Rev 90 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 90 | Rev 94 | ||
---|---|---|---|
1 | unit LevMain; |
1 | unit LevMain; |
2 | 2 | ||
3 | interface |
3 | interface |
4 | 4 | ||
5 | uses |
5 | uses |
6 | Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, MMSystem, |
6 | Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, MMSystem, |
7 | Dialogs, StdCtrls, ExtCtrls, Menus, DIB, DXClass, DXSprite, DXDraws, |
7 | Dialogs, StdCtrls, ExtCtrls, Menus, DIB, DXClass, DXSprite, DXDraws, |
8 | DXSounds, Spin, ComCtrls{$IF CompilerVersion >= 23.0}, System.UITypes, |
8 | DXSounds, Spin, ComCtrls{$IF CompilerVersion >= 23.0}, System.UITypes, |
9 | WinAPI.DirectDraw{$ENDIF}, DirectX, ComLevelReader, Global, IOUtils; |
9 | WinAPI.DirectDraw{$ENDIF}, DirectX, ComLevelReader, Global, IOUtils; |
10 | 10 | ||
11 | type |
11 | type |
12 | TMainForm = class(TDXForm) |
12 | TMainForm = class(TDXForm) |
13 | MainMenu: TMainMenu; |
13 | MainMenu: TMainMenu; |
14 | Spiel: TMenuItem; |
14 | Spiel: TMenuItem; |
15 | Beenden: TMenuItem; |
15 | Beenden: TMenuItem; |
16 | Hilfe: TMenuItem; |
16 | Hilfe: TMenuItem; |
17 | Leer1: TMenuItem; |
17 | Leer1: TMenuItem; |
18 | Level: TMenuItem; |
18 | Level: TMenuItem; |
19 | Informationen: TMenuItem; |
19 | Informationen: TMenuItem; |
20 | Enemy1: TRadioButton; |
20 | Enemy1: TRadioButton; |
21 | Enemy2: TRadioButton; |
21 | Enemy2: TRadioButton; |
22 | Enemy3: TRadioButton; |
22 | Enemy3: TRadioButton; |
23 | Enemy4: TRadioButton; |
23 | Enemy4: TRadioButton; |
24 | Enemy5: TRadioButton; |
24 | Enemy5: TRadioButton; |
25 | Enemy6: TRadioButton; |
25 | Enemy6: TRadioButton; |
26 | Enemy7: TRadioButton; |
26 | Enemy7: TRadioButton; |
27 | ScrollBar: TScrollBar; |
27 | ScrollBar: TScrollBar; |
28 | Bevel1: TBevel; |
28 | Bevel1: TBevel; |
29 | Bevel2: TBevel; |
29 | Bevel2: TBevel; |
30 | SelLabel: TLabel; |
30 | SelLabel: TLabel; |
31 | SelPanel: TPanel; |
31 | SelPanel: TPanel; |
32 | Bevel3: TBevel; |
32 | Bevel3: TBevel; |
33 | SLabel1a: TLabel; |
33 | SLabel1a: TLabel; |
34 | SLabel2a: TLabel; |
34 | SLabel2a: TLabel; |
35 | SLabel1b: TLabel; |
35 | SLabel1b: TLabel; |
36 | SLabel2b: TLabel; |
36 | SLabel2b: TLabel; |
37 | SLabel0: TLabel; |
37 | SLabel0: TLabel; |
38 | Neu: TMenuItem; |
38 | Neu: TMenuItem; |
39 | Image1: TImage; |
39 | Image1: TImage; |
40 | SLabel3a: TLabel; |
40 | SLabel3a: TLabel; |
41 | SLabel3b: TLabel; |
41 | SLabel3b: TLabel; |
42 | SLabel4a: TLabel; |
42 | SLabel4a: TLabel; |
43 | SLabel4b: TLabel; |
43 | SLabel4b: TLabel; |
44 | LivesLabel: TLabel; |
44 | LivesLabel: TLabel; |
45 | StatusBar: TStatusBar; |
45 | StatusBar: TStatusBar; |
46 | N1: TMenuItem; |
46 | N1: TMenuItem; |
47 | Spielfelderweitern1: TMenuItem; |
47 | Spielfelderweitern1: TMenuItem; |
48 | SidePanel: TPanel; |
48 | SidePanel: TPanel; |
49 | LivesEdit: TSpinEdit; |
49 | LivesEdit: TSpinEdit; |
50 | AlleLeveldateienaktualisieren1: TMenuItem; |
50 | AlleLeveldateienaktualisieren1: TMenuItem; |
51 | N2: TMenuItem; |
51 | N2: TMenuItem; |
52 | Leveltesten1: TMenuItem; |
52 | Leveltesten1: TMenuItem; |
53 | Hilfe1: TMenuItem; |
53 | Hilfe1: TMenuItem; |
54 | N3: TMenuItem; |
54 | N3: TMenuItem; |
55 | AufUpdatesprfen1: TMenuItem; |
55 | AufUpdatesprfen1: TMenuItem; |
56 | N4: TMenuItem; |
56 | N4: TMenuItem; |
57 | WasgibtesNeues1: TMenuItem; |
57 | WasgibtesNeues1: TMenuItem; |
58 | Enemy8: TRadioButton; |
58 | Enemy8: TRadioButton; |
59 | procedure DXDrawFinalize(Sender: TObject); |
59 | procedure DXDrawFinalize(Sender: TObject); |
60 | procedure DXDrawInitialize(Sender: TObject); |
60 | procedure DXDrawInitialize(Sender: TObject); |
61 | procedure FormCreate(Sender: TObject); |
61 | procedure FormCreate(Sender: TObject); |
62 | procedure DXTimerTimer(Sender: TObject; LagCount: Integer); |
62 | procedure DXTimerTimer(Sender: TObject; LagCount: Integer); |
63 | procedure BeendenClick(Sender: TObject); |
63 | procedure BeendenClick(Sender: TObject); |
64 | procedure FormDestroy(Sender: TObject); |
64 | procedure FormDestroy(Sender: TObject); |
65 | procedure LevelClick(Sender: TObject); |
65 | procedure LevelClick(Sender: TObject); |
66 | procedure FormShow(Sender: TObject); |
66 | procedure FormShow(Sender: TObject); |
67 | procedure InformationenClick(Sender: TObject); |
67 | procedure InformationenClick(Sender: TObject); |
68 | procedure FormClose(Sender: TObject; var Action: TCloseAction); |
68 | procedure FormClose(Sender: TObject; var Action: TCloseAction); |
69 | procedure DXDrawMouseDown(Sender: TObject; Button: TMouseButton; |
69 | procedure DXDrawMouseDown(Sender: TObject; Button: TMouseButton; |
70 | Shift: TShiftState; X, Y: Integer); |
70 | Shift: TShiftState; X, Y: Integer); |
71 | procedure EnemyClick(Sender: TObject); |
71 | procedure EnemyClick(Sender: TObject); |
72 | procedure NeuClick(Sender: TObject); |
72 | procedure NeuClick(Sender: TObject); |
73 | procedure DXDrawMouseMove(Sender: TObject; Shift: TShiftState; X, |
73 | procedure DXDrawMouseMove(Sender: TObject; Shift: TShiftState; X, |
74 | Y: Integer); |
74 | Y: Integer); |
75 | procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); |
75 | procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); |
76 | procedure Spielfelderweitern1Click(Sender: TObject); |
76 | procedure Spielfelderweitern1Click(Sender: TObject); |
77 | procedure ScrollBarScroll(Sender: TObject; ScrollCode: TScrollCode; |
77 | procedure ScrollBarScroll(Sender: TObject; ScrollCode: TScrollCode; |
78 | var ScrollPos: Integer); |
78 | var ScrollPos: Integer); |
79 | procedure AlleLeveldateienaktualisieren1Click(Sender: TObject); |
79 | procedure AlleLeveldateienaktualisieren1Click(Sender: TObject); |
80 | procedure Leveltesten1Click(Sender: TObject); |
80 | procedure Leveltesten1Click(Sender: TObject); |
81 | procedure HilfeTopicClick(Sender: TObject); |
81 | procedure HilfeTopicClick(Sender: TObject); |
82 | procedure AufUpdatesprfen1Click(Sender: TObject); |
82 | procedure AufUpdatesprfen1Click(Sender: TObject); |
83 | private |
83 | private |
84 | function GetTestlevelFilename: string; |
84 | function GetTestlevelFilename: string; |
85 | public |
85 | public |
86 | { VCL-Ersatz } |
86 | { VCL-Ersatz } |
87 | spriteengine: tdxspriteengine; |
87 | spriteengine: tdxspriteengine; |
88 | dxtimer: tdxtimer; |
88 | dxtimer: tdxtimer; |
89 | imagelist: tdximagelist; |
89 | imagelist: tdximagelist; |
90 | dxdraw: tdxdraw; |
90 | dxdraw: tdxdraw; |
91 | { Variablen } |
91 | { Variablen } |
92 | FMenuItem: integer; |
92 | FMenuItem: integer; |
93 | LevData: TLevelData; |
93 | LevData: TLevelData; |
94 | ScrollP: integer; |
94 | ScrollP: integer; |
95 | AltScrollPos: integer; |
95 | AltScrollPos: integer; |
96 | Boss: boolean; |
96 | Boss: boolean; |
97 | LevChanged: boolean; |
97 | LevChanged: boolean; |
98 | NumEnemys: integer; |
98 | NumEnemys: integer; |
99 | function SelectedEnemyType: TEnemyType; |
99 | function SelectedEnemyType: TEnemyType; |
100 | { Grafik-Routinen } |
100 | { Grafik-Routinen } |
101 | function GetSpriteGraphic(Sprite: TSpaceMissionGraphicSprite): TPictureCollectionItem; |
101 | function GetSpriteGraphic(Sprite: TSpaceMissionGraphicSprite): TPictureCollectionItem; |
102 | { Level-Routinen } |
102 | { Level-Routinen } |
103 | procedure EnemyCreateSprite(x, y: integer; AEnemyType: TEnemyType; ALives: integer); |
103 | procedure EnemyCreateSprite(x, y: integer; AEnemyType: TEnemyType; ALives: integer); |
104 | procedure DestroyLevel; |
104 | procedure DestroyLevel; |
105 | procedure RefreshFromLevData; |
105 | procedure RefreshFromLevData; |
106 | procedure AnzeigeAct; |
106 | procedure AnzeigeAct; |
107 | { Initialisiations-Routinen } |
107 | { Initialisiations-Routinen } |
108 | procedure DXInit; |
108 | procedure DXInit; |
109 | procedure ProgramInit; |
109 | procedure ProgramInit; |
110 | { Farb-Routinen } |
110 | { Farb-Routinen } |
111 | function ComposeColor(Dest, Src: TRGBQuad; Percent: Integer): TRGBQuad; |
111 | function ComposeColor(Dest, Src: TRGBQuad; Percent: Integer): TRGBQuad; |
112 | procedure PalleteAnim(Col: TRGBQuad; Time: Integer); |
112 | procedure PalleteAnim(Col: TRGBQuad; Time: Integer); |
113 | end; |
113 | end; |
114 | 114 | ||
115 | var |
115 | var |
116 | MainForm: TMainForm; |
116 | MainForm: TMainForm; |
117 | 117 | ||
118 | implementation |
118 | implementation |
119 | 119 | ||
120 | uses |
120 | uses |
121 | LevSplash, LevSpeicherung, ComInfo, LevOptions, ShellAPI, ComHilfe; |
121 | LevSplash, LevSpeicherung, ComInfo, LevOptions, ShellAPI, ComHilfe; |
122 | 122 | ||
123 | {$R *.DFM} |
123 | {$R *.DFM} |
124 | 124 | ||
125 | resourcestring |
125 | resourcestring |
126 | status_info = 'Zeigen Sie mit dem Mauszeiger auf eine Einheit, um deren Eigenschaften anzuzeigen...'; |
126 | status_info = 'Zeigen Sie mit dem Mauszeiger auf eine Einheit, um deren Eigenschaften anzuzeigen...'; |
127 | 127 | ||
128 | type |
128 | type |
129 | TBackground = class(TBackgroundSprite) |
129 | TBackground = class(TBackgroundSprite) |
130 | strict protected |
130 | strict protected |
131 | procedure DoMove(MoveCount: Integer); override; |
131 | procedure DoMove(MoveCount: Integer); override; |
132 | end; |
132 | end; |
133 | 133 | ||
134 | TEnemyOrItem = class(TImageSprite) |
134 | TEnemyOrItem = class(TImageSprite) |
135 | strict private |
135 | strict private |
136 | FLives: integer; |
136 | FLives: integer; |
137 | FEnemyType: TEnemyType; |
137 | FEnemyType: TEnemyType; |
138 | FXCor: integer; |
138 | FXCor: integer; |
139 | FCorInit: boolean; |
139 | FCorInit: boolean; |
140 | strict protected |
140 | strict protected |
141 | procedure DoMove(MoveCount: Integer); override; |
141 | procedure DoMove(MoveCount: Integer); override; |
142 | public |
142 | public |
143 | constructor Create(AParent: TSprite; AEnemyType: TEnemyType; ALives: Integer); reintroduce; |
143 | constructor Create(AParent: TSprite; AEnemyType: TEnemyType; ALives: Integer); reintroduce; |
144 | end; |
144 | end; |
145 | 145 | ||
146 | { TBackground } |
146 | { TBackground } |
147 | 147 | ||
148 | procedure TBackground.DoMove(MoveCount: Integer); |
148 | procedure TBackground.DoMove(MoveCount: Integer); |
149 | begin |
149 | begin |
150 | X := -(MainForm.ScrollP * LevEditRasterW); |
150 | X := -(MainForm.ScrollP * LevEditRasterW); |
151 | end; |
151 | end; |
152 | 152 | ||
153 | { TEnemy } |
153 | { TEnemy } |
154 | 154 | ||
155 | procedure TEnemyOrItem.DoMove(MoveCount: Integer); |
155 | procedure TEnemyOrItem.DoMove(MoveCount: Integer); |
156 | begin |
156 | begin |
157 | if not FCorInit then |
157 | if not FCorInit then |
158 | begin |
158 | begin |
159 | FXCor := trunc(x) + (MainForm.ScrollP * LevEditRasterW); |
159 | FXCor := trunc(x) + (MainForm.ScrollP * LevEditRasterW); |
160 | FCorInit := true; |
160 | FCorInit := true; |
161 | end; |
161 | end; |
162 | if MainForm.LevData.IndexOfEnemy(FXCor, integer(round(Y)), FEnemyType, FLives) = -1 then dead; |
162 | if MainForm.LevData.IndexOfEnemy(FXCor, integer(round(Y)), FEnemyType, FLives) = -1 then dead; |
163 | X := FXCor - (MainForm.ScrollP * LevEditRasterW); |
163 | X := FXCor - (MainForm.ScrollP * LevEditRasterW); |
164 | end; |
164 | end; |
165 | 165 | ||
166 | constructor TEnemyOrItem.Create(AParent: TSprite; AEnemyType: TEnemyType; ALives: Integer); |
166 | constructor TEnemyOrItem.Create(AParent: TSprite; AEnemyType: TEnemyType; ALives: Integer); |
167 | begin |
167 | begin |
168 | inherited Create(AParent); |
168 | inherited Create(AParent); |
169 | if AEnemyType = etEnemyAttacker then Image := MainForm.GetSpriteGraphic(smgEnemyAttacker); |
169 | if AEnemyType = etEnemyAttacker then Image := MainForm.GetSpriteGraphic(smgEnemyAttacker); |
170 | if AEnemyType = etEnemyAttacker2 then Image := MainForm.GetSpriteGraphic(smgEnemyAttacker2); |
170 | if AEnemyType = etEnemyAttacker2 then Image := MainForm.GetSpriteGraphic(smgEnemyAttacker2); |
171 | if AEnemyType = etEnemyAttacker3 then Image := MainForm.GetSpriteGraphic(smgEnemyAttacker3); |
171 | if AEnemyType = etEnemyAttacker3 then Image := MainForm.GetSpriteGraphic(smgEnemyAttacker3); |
172 | if AEnemyType = etEnemyMeteor then Image := MainForm.GetSpriteGraphic(smgEnemyMeteor); |
172 | if AEnemyType = etEnemyMeteor then Image := MainForm.GetSpriteGraphic(smgEnemyMeteor); |
173 | if AEnemyType = etEnemyUFO then Image := MainForm.GetSpriteGraphic(smgEnemyDisk); |
173 | if AEnemyType = etEnemyUFO then Image := MainForm.GetSpriteGraphic(smgEnemyDisk); |
174 | if AEnemyType = etEnemyUFO2 then Image := MainForm.GetSpriteGraphic(smgEnemyDisk2); |
174 | if AEnemyType = etEnemyUFO2 then Image := MainForm.GetSpriteGraphic(smgEnemyDisk2); |
175 | if AEnemyType = etEnemyBoss then Image := MainForm.GetSpriteGraphic(smgEnemyBoss); |
175 | if AEnemyType = etEnemyBoss then Image := MainForm.GetSpriteGraphic(smgEnemyBoss); |
176 | if AEnemyType = etItemMedikit then Image := MainForm.GetSpriteGraphic(smgItemMedikit); |
176 | if AEnemyType = etItemMedikit then Image := MainForm.GetSpriteGraphic(smgItemMedikit); |
177 | 177 | ||
178 | if not EnemyTypeHasLives(AEnemyType) then |
178 | if not EnemyTypeHasLives(AEnemyType) then |
179 | FLives := 0 |
179 | FLives := 0 |
180 | else |
180 | else |
181 | FLives := ALives; |
181 | FLives := ALives; |
182 | FEnemyType := AEnemyType; |
182 | FEnemyType := AEnemyType; |
183 | Width := Image.Width; |
183 | Width := Image.Width; |
184 | Height := Image.Height; |
184 | Height := Image.Height; |
185 | PixelCheck := True; |
185 | PixelCheck := True; |
186 | end; |
186 | end; |
187 | 187 | ||
188 | { TMainForm } |
188 | { TMainForm } |
189 | 189 | ||
190 | procedure TMainForm.DXInit; |
190 | procedure TMainForm.DXInit; |
191 | begin |
191 | begin |
192 | Imagelist.Items.LoadFromFile(OwnDirectory+DxgFile); |
192 | Imagelist.Items.LoadFromFile(OwnDirectory+DxgFile); |
193 | ImageList.Items.MakeColorTable; |
193 | ImageList.Items.MakeColorTable; |
194 | DXDraw.ColorTable := ImageList.Items.ColorTable; |
194 | DXDraw.ColorTable := ImageList.Items.ColorTable; |
195 | DXDraw.DefColorTable := ImageList.Items.ColorTable; |
195 | DXDraw.DefColorTable := ImageList.Items.ColorTable; |
196 | DXDraw.UpdatePalette; |
196 | DXDraw.UpdatePalette; |
197 | DXDraw.Initialize; |
197 | DXDraw.Initialize; |
198 | end; |
198 | end; |
199 | 199 | ||
200 | procedure TMainForm.FormCreate(Sender: TObject); |
200 | procedure TMainForm.FormCreate(Sender: TObject); |
201 | resourcestring |
201 | resourcestring |
202 | SFileError = 'Die Datei kann von SpaceMission nicht geöffnet werden!'; |
202 | SFileError = 'Die Datei kann von SpaceMission nicht geöffnet werden!'; |
203 | SCaption = 'SpaceMission %s - Leveleditor'; |
203 | SCaption = 'SpaceMission %s - Level-Editor'; |
204 | begin |
204 | begin |
205 | { VCL-Ersatz start } |
205 | { VCL-Ersatz start } |
206 | dxtimer := tdxtimer.create(self); |
206 | dxtimer := tdxtimer.create(self); |
207 | dxtimer.Interval := 100; |
207 | dxtimer.Interval := 100; |
208 | dxtimer.ActiveOnly := false; |
208 | dxtimer.ActiveOnly := false; |
209 | dxtimer.Enabled := false; |
209 | dxtimer.Enabled := false; |
210 | dxtimer.OnTimer := DxTimerTimer; |
210 | dxtimer.OnTimer := DxTimerTimer; |
211 | 211 | ||
212 | dxdraw := tdxdraw.Create(self); |
212 | dxdraw := tdxdraw.Create(self); |
213 | dxdraw.Parent := self; |
213 | dxdraw.Parent := self; |
214 | dxdraw.Left := 0; |
214 | dxdraw.Left := 0; |
215 | dxdraw.Top := 0; |
215 | dxdraw.Top := 0; |
216 | dxdraw.Width := SidePanel.Left; |
216 | dxdraw.Width := SidePanel.Left; |
217 | dxdraw.Height := ScrollBar.Top; |
217 | dxdraw.Height := ScrollBar.Top; |
218 | dxdraw.AutoInitialize := False; |
218 | dxdraw.AutoInitialize := False; |
219 | dxdraw.AutoSize := False; |
219 | dxdraw.AutoSize := False; |
220 | dxdraw.Color := clBlack; |
220 | dxdraw.Color := clBlack; |
221 | (* |
221 | (* |
222 | dxdraw.Display.BitCount := 24; |
222 | dxdraw.Display.BitCount := 24; |
223 | dxdraw.Display.FixedBitCount := False; |
223 | dxdraw.Display.FixedBitCount := False; |
224 | dxdraw.Display.FixedRatio := False; |
224 | dxdraw.Display.FixedRatio := False; |
225 | dxdraw.Display.FixedSize := False; |
225 | dxdraw.Display.FixedSize := False; |
226 | dxdraw.Display.Height := 600; |
226 | dxdraw.Display.Height := 600; |
227 | dxdraw.Display.Width := 800; |
227 | dxdraw.Display.Width := 800; |
228 | *) |
228 | *) |
229 | dxdraw.Options := [doAllowReboot, doWaitVBlank, doAllowPalette256, doCenter, {doRetainedMode,} doHardware, doSelectDriver]; |
229 | dxdraw.Options := [doAllowReboot, doWaitVBlank, doAllowPalette256, doCenter, {doRetainedMode,} doHardware, doSelectDriver]; |
230 | dxdraw.OnFinalize := DXDrawFinalize; |
230 | dxdraw.OnFinalize := DXDrawFinalize; |
231 | dxdraw.OnInitialize := DXDrawInitialize; |
231 | dxdraw.OnInitialize := DXDrawInitialize; |
232 | dxdraw.ParentShowHint := False; |
232 | dxdraw.ParentShowHint := False; |
233 | dxdraw.ShowHint := False; |
233 | dxdraw.ShowHint := False; |
234 | dxdraw.TabOrder := 0; |
234 | dxdraw.TabOrder := 0; |
235 | dxdraw.OnMouseDown := DXDrawMouseDown; |
235 | dxdraw.OnMouseDown := DXDrawMouseDown; |
236 | dxdraw.OnMouseMove := DXDrawMouseMove; |
236 | dxdraw.OnMouseMove := DXDrawMouseMove; |
237 | 237 | ||
238 | spriteengine := tdxspriteengine.create(self); |
238 | spriteengine := tdxspriteengine.create(self); |
239 | spriteengine.DXDraw := dxdraw; |
239 | spriteengine.DXDraw := dxdraw; |
240 | 240 | ||
241 | imagelist := tdximagelist.create(self); |
241 | imagelist := tdximagelist.create(self); |
242 | imagelist.DXDraw := dxdraw; |
242 | imagelist.DXDraw := dxdraw; |
243 | 243 | ||
244 | { VCL-Ersatz ende } |
244 | { VCL-Ersatz ende } |
245 | 245 | ||
246 | StatusBar.SimpleText := ' ' + status_info; |
246 | StatusBar.SimpleText := ' ' + status_info; |
247 | 247 | ||
248 | LivesEdit.MinValue := 1; |
248 | LivesEdit.MinValue := 1; |
249 | LivesEdit.MaxValue := MaxPossibleEnemyLives; |
249 | LivesEdit.MaxValue := MaxPossibleEnemyLives; |
250 | LivesEdit.Value := 1; |
250 | LivesEdit.Value := 1; |
251 | 251 | ||
252 | Enemy1.Checked := true; |
252 | Enemy1.Checked := true; |
253 | EnemyClick(Enemy1); |
253 | EnemyClick(Enemy1); |
254 | // Leeres Level am Anfang braucht keine Beenden-Bestätigung. |
254 | // Leeres Level am Anfang braucht keine Beenden-Bestätigung. |
255 | // LevChanged := true; |
255 | // LevChanged := true; |
256 | 256 | ||
257 | //Application.Title := Format(SCaption, [ProgramVersion]); |
257 | //Application.Title := Format(SCaption, [ProgramVersion]); |
258 | Caption := Format(SCaption, [ProgramVersion]); |
258 | Caption := Format(SCaption, [ProgramVersion]); |
259 | DXInit; |
259 | DXInit; |
260 | LevData := TLevelData.create; |
260 | LevData := TLevelData.create; |
261 | ProgramInit; |
261 | ProgramInit; |
262 | DestroyLevel; |
262 | DestroyLevel; |
263 | if (paramcount > 0) and (fileexists(paramstr(1))) and (ExtractFileExt(paramstr(1)).ToLower = '.lev') then |
263 | if (paramcount > 0) and (fileexists(paramstr(1))) and (ExtractFileExt(paramstr(1)).ToLower = '.lev') then |
264 | begin |
264 | begin |
265 | try |
265 | try |
266 | LevData.RasterErzwingen := true; |
266 | LevData.RasterErzwingen := true; |
267 | LevData.LoadFromFile(paramstr(1)); |
267 | LevData.LoadFromFile(paramstr(1)); |
268 | except |
268 | except |
269 | on E: Exception do |
269 | on E: Exception do |
270 | begin |
270 | begin |
271 | showmessage(SFileError + ' ' +E.Message); |
271 | showmessage(SFileError + ' ' +E.Message); |
272 | DestroyLevel; |
272 | DestroyLevel; |
273 | end; |
273 | end; |
274 | end; |
274 | end; |
275 | RefreshFromLevData; |
275 | RefreshFromLevData; |
276 | LevChanged := false; |
276 | LevChanged := false; |
277 | AnzeigeAct; |
277 | AnzeigeAct; |
278 | end; |
278 | end; |
279 | end; |
279 | end; |
280 | 280 | ||
281 | procedure TMainForm.FormDestroy(Sender: TObject); |
281 | procedure TMainForm.FormDestroy(Sender: TObject); |
282 | var |
282 | var |
283 | tmp: string; |
283 | tmp: string; |
284 | begin |
284 | begin |
285 | FreeAndNil(dxdraw); |
285 | FreeAndNil(dxdraw); |
286 | FreeAndNil(LevData); |
286 | FreeAndNil(LevData); |
287 | //FreeAndNil(spriteengine); |
287 | //FreeAndNil(spriteengine); |
288 | FreeAndNil(dxtimer); |
288 | FreeAndNil(dxtimer); |
289 | FreeAndNil(imagelist); |
289 | FreeAndNil(imagelist); |
290 | tmp := GetTestlevelFilename; |
290 | tmp := GetTestlevelFilename; |
291 | 291 | ||
292 | // SpaceMission.exe only loads a file once, so we can delete any test level |
292 | // SpaceMission.exe only loads a file once, so we can delete any test level |
293 | if FileExists(tmp) then DeleteFile(GetTestlevelFilename); |
293 | if FileExists(tmp) then DeleteFile(GetTestlevelFilename); |
294 | end; |
294 | end; |
295 | 295 | ||
296 | procedure TMainForm.BeendenClick(Sender: TObject); |
296 | procedure TMainForm.BeendenClick(Sender: TObject); |
297 | begin |
297 | begin |
298 | close; |
298 | close; |
299 | end; |
299 | end; |
300 | 300 | ||
301 | procedure TMainForm.DXDrawInitialize(Sender: TObject); |
301 | procedure TMainForm.DXDrawInitialize(Sender: TObject); |
302 | begin |
302 | begin |
303 | if Assigned(DXTimer) then DXTimer.Enabled := True; |
303 | if Assigned(DXTimer) then DXTimer.Enabled := True; |
304 | end; |
304 | end; |
305 | 305 | ||
306 | procedure TMainForm.DXDrawFinalize(Sender: TObject); |
306 | procedure TMainForm.DXDrawFinalize(Sender: TObject); |
307 | begin |
307 | begin |
308 | if Assigned(DXTimer) then DXTimer.Enabled := False; |
308 | if Assigned(DXTimer) then DXTimer.Enabled := False; |
309 | end; |
309 | end; |
310 | 310 | ||
311 | procedure TMainForm.DXTimerTimer(Sender: TObject; LagCount: Integer); |
311 | procedure TMainForm.DXTimerTimer(Sender: TObject; LagCount: Integer); |
312 | begin |
312 | begin |
313 | if not DXDraw.CanDraw then exit; |
313 | if not DXDraw.CanDraw then exit; |
314 | LagCount := 1000 div 60; |
314 | LagCount := 1000 div 60; |
315 | SpriteEngine.Move(LagCount); |
315 | SpriteEngine.Move(LagCount); |
316 | SpriteEngine.Dead; |
316 | SpriteEngine.Dead; |
317 | DxDraw.Surface.Fill(0); |
317 | DxDraw.Surface.Fill(0); |
318 | SpriteEngine.Draw; |
318 | SpriteEngine.Draw; |
319 | DXDraw.Flip; |
319 | DXDraw.Flip; |
320 | end; |
320 | end; |
321 | 321 | ||
322 | function TMainForm.ComposeColor(Dest, Src: TRGBQuad; Percent: Integer): TRGBQuad; |
322 | function TMainForm.ComposeColor(Dest, Src: TRGBQuad; Percent: Integer): TRGBQuad; |
323 | begin |
323 | begin |
324 | with Result do |
324 | with Result do |
325 | begin |
325 | begin |
326 | rgbRed := Src.rgbRed+((Dest.rgbRed-Src.rgbRed)*Percent div 256); |
326 | rgbRed := Src.rgbRed+((Dest.rgbRed-Src.rgbRed)*Percent div 256); |
327 | rgbGreen := Src.rgbGreen+((Dest.rgbGreen-Src.rgbGreen)*Percent div 256); |
327 | rgbGreen := Src.rgbGreen+((Dest.rgbGreen-Src.rgbGreen)*Percent div 256); |
328 | rgbBlue := Src.rgbBlue+((Dest.rgbBlue-Src.rgbBlue)*Percent div 256); |
328 | rgbBlue := Src.rgbBlue+((Dest.rgbBlue-Src.rgbBlue)*Percent div 256); |
329 | rgbReserved := 0; |
329 | rgbReserved := 0; |
330 | end; |
330 | end; |
331 | end; |
331 | end; |
332 | 332 | ||
333 | procedure TMainForm.PalleteAnim(Col: TRGBQuad; Time: Integer); |
333 | procedure TMainForm.PalleteAnim(Col: TRGBQuad; Time: Integer); |
334 | var |
334 | var |
335 | i: Integer; |
335 | i: Integer; |
336 | t, t2: DWORD; |
336 | t, t2: DWORD; |
337 | ChangePalette: Boolean; |
337 | ChangePalette: Boolean; |
338 | c: Integer; |
338 | c: Integer; |
339 | begin |
339 | begin |
340 | if DXDraw.Initialized then |
340 | if DXDraw.Initialized then |
341 | begin |
341 | begin |
342 | c := DXDraw.Surface.ColorMatch(RGB(Col.rgbRed, Col.rgbGreen, Col.rgbBlue)); |
342 | c := DXDraw.Surface.ColorMatch(RGB(Col.rgbRed, Col.rgbGreen, Col.rgbBlue)); |
343 | ChangePalette := False; |
343 | ChangePalette := False; |
344 | if DXDraw.CanPaletteAnimation then |
344 | if DXDraw.CanPaletteAnimation then |
345 | begin |
345 | begin |
346 | t := GetTickCount; |
346 | t := GetTickCount; |
347 | while Abs(GetTickCount-t)<Time do |
347 | while Abs(GetTickCount-t)<Time do |
348 | begin |
348 | begin |
349 | t2 := Trunc(Abs(GetTickCount-t)/Time*255); |
349 | t2 := Trunc(Abs(GetTickCount-t)/Time*255); |
350 | for i := 0 to 255 do |
350 | for i := 0 to 255 do |
351 | DXDraw.ColorTable[i] := ComposeColor(Col, DXDraw.DefColorTable[i], t2); |
351 | DXDraw.ColorTable[i] := ComposeColor(Col, DXDraw.DefColorTable[i], t2); |
352 | DXDraw.UpdatePalette; |
352 | DXDraw.UpdatePalette; |
353 | ChangePalette := True; |
353 | ChangePalette := True; |
354 | end; |
354 | end; |
355 | end else |
355 | end else |
356 | Sleep(Time); |
356 | Sleep(Time); |
357 | for i := 0 to 4 do |
357 | for i := 0 to 4 do |
358 | begin |
358 | begin |
359 | DXDraw.Surface.Fill(c); |
359 | DXDraw.Surface.Fill(c); |
360 | DXDraw.Flip; |
360 | DXDraw.Flip; |
361 | end; |
361 | end; |
362 | if ChangePalette then |
362 | if ChangePalette then |
363 | begin |
363 | begin |
364 | DXDraw.ColorTable := DXDraw.DefColorTable; |
364 | DXDraw.ColorTable := DXDraw.DefColorTable; |
365 | DXDraw.UpdatePalette; |
365 | DXDraw.UpdatePalette; |
366 | end; |
366 | end; |
367 | DXDraw.Surface.Fill(c); |
367 | DXDraw.Surface.Fill(c); |
368 | DXDraw.Flip; |
368 | DXDraw.Flip; |
369 | end; |
369 | end; |
370 | end; |
370 | end; |
371 | 371 | ||
372 | procedure TMainForm.ProgramInit; |
372 | procedure TMainForm.ProgramInit; |
373 | {var |
373 | {var |
374 | i, j: Integer;} |
374 | i, j: Integer;} |
375 | begin |
375 | begin |
376 | sleep(500); |
376 | sleep(500); |
377 | //PlayerSprite |
377 | //PlayerSprite |
378 | with TBackground.Create(SpriteEngine.Engine) do |
378 | with TBackground.Create(SpriteEngine.Engine) do |
379 | begin |
379 | begin |
380 | SetMapSize(1, 1); |
380 | SetMapSize(1, 1); |
381 | Image := MainForm.GetSpriteGraphic(smgStar3); |
381 | Image := MainForm.GetSpriteGraphic(smgStar3); |
382 | Z := -13; |
382 | Z := -13; |
383 | Y := 40; |
383 | Y := 40; |
384 | Tile := True; |
384 | Tile := True; |
385 | end; |
385 | end; |
386 | with TBackground.Create(SpriteEngine.Engine) do |
386 | with TBackground.Create(SpriteEngine.Engine) do |
387 | begin |
387 | begin |
388 | SetMapSize(1, 1); |
388 | SetMapSize(1, 1); |
389 | Image := MainForm.GetSpriteGraphic(smgStar2); |
389 | Image := MainForm.GetSpriteGraphic(smgStar2); |
390 | Z := -12; |
390 | Z := -12; |
391 | Y := 30; |
391 | Y := 30; |
392 | Tile := True; |
392 | Tile := True; |
393 | end; |
393 | end; |
394 | with TBackground.Create(SpriteEngine.Engine) do |
394 | with TBackground.Create(SpriteEngine.Engine) do |
395 | begin |
395 | begin |
396 | SetMapSize(1, 1); |
396 | SetMapSize(1, 1); |
397 | Image := MainForm.GetSpriteGraphic(smgStar1); |
397 | Image := MainForm.GetSpriteGraphic(smgStar1); |
398 | Z := -11; |
398 | Z := -11; |
399 | Y := 10; |
399 | Y := 10; |
400 | Tile := True; |
400 | Tile := True; |
401 | end; |
401 | end; |
402 | with TBackground.Create(SpriteEngine.Engine) do |
402 | with TBackground.Create(SpriteEngine.Engine) do |
403 | begin |
403 | begin |
404 | SetMapSize(1, 1); |
404 | SetMapSize(1, 1); |
405 | Image := MainForm.GetSpriteGraphic(smgMatrix); |
405 | Image := MainForm.GetSpriteGraphic(smgMatrix); |
406 | Z := -10; |
406 | Z := -10; |
407 | Tile := True; |
407 | Tile := True; |
408 | end; |
408 | end; |
409 | {with TBackground.Create(SpriteEngine.Engine) do |
409 | {with TBackground.Create(SpriteEngine.Engine) do |
410 | begin |
410 | begin |
411 | SetMapSize(200, 10); |
411 | SetMapSize(200, 10); |
412 | Y := 10; |
412 | Y := 10; |
413 | Z := -13; |
413 | Z := -13; |
414 | FSpeed := 1 / 2; |
414 | FSpeed := 1 / 2; |
415 | Tile := True; |
415 | Tile := True; |
416 | for i := 0 to MapHeight-1 do |
416 | for i := 0 to MapHeight-1 do |
417 | begin |
417 | begin |
418 | for j := 0 to MapWidth-1 do |
418 | for j := 0 to MapWidth-1 do |
419 | begin |
419 | begin |
420 | Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 8); |
420 | Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 8); |
421 | if Random(100)<95 then Chips[j, i] := -1; |
421 | if Random(100)<95 then Chips[j, i] := -1; |
422 | end; |
422 | end; |
423 | end; |
423 | end; |
424 | end; |
424 | end; |
425 | with TBackground.Create(SpriteEngine.Engine) do |
425 | with TBackground.Create(SpriteEngine.Engine) do |
426 | begin |
426 | begin |
427 | SetMapSize(200, 10); |
427 | SetMapSize(200, 10); |
428 | Y := 30; |
428 | Y := 30; |
429 | Z := -12; |
429 | Z := -12; |
430 | FSpeed := 1; |
430 | FSpeed := 1; |
431 | Tile := True; |
431 | Tile := True; |
432 | for i := 0 to MapHeight-1 do |
432 | for i := 0 to MapHeight-1 do |
433 | begin |
433 | begin |
434 | for j := 0 to MapWidth-1 do |
434 | for j := 0 to MapWidth-1 do |
435 | begin |
435 | begin |
436 | Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 4); |
436 | Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 4); |
437 | if Random(100)<95 then Chips[j, i] := -1; |
437 | if Random(100)<95 then Chips[j, i] := -1; |
438 | end; |
438 | end; |
439 | end; |
439 | end; |
440 | end; |
440 | end; |
441 | with TBackground.Create(SpriteEngine.Engine) do |
441 | with TBackground.Create(SpriteEngine.Engine) do |
442 | begin |
442 | begin |
443 | SetMapSize(200, 10); |
443 | SetMapSize(200, 10); |
444 | Y := 40; |
444 | Y := 40; |
445 | Z := -11; |
445 | Z := -11; |
446 | FSpeed := 2; |
446 | FSpeed := 2; |
447 | Tile := True; |
447 | Tile := True; |
448 | for i := 0 to MapHeight-1 do |
448 | for i := 0 to MapHeight-1 do |
449 | begin |
449 | begin |
450 | for j := 0 to MapWidth-1 do |
450 | for j := 0 to MapWidth-1 do |
451 | begin |
451 | begin |
452 | Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 2); |
452 | Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 2); |
453 | if Random(100)<95 then Chips[j, i] := -1; |
453 | if Random(100)<95 then Chips[j, i] := -1; |
454 | end; |
454 | end; |
455 | end; |
455 | end; |
456 | end;} |
456 | end;} |
457 | PalleteAnim(RGBQuad(0, 0, 0), 300); |
457 | PalleteAnim(RGBQuad(0, 0, 0), 300); |
458 | mainform.Visible := true; |
458 | mainform.Visible := true; |
459 | end; |
459 | end; |
460 | 460 | ||
461 | procedure TMainForm.RefreshFromLevData; |
461 | procedure TMainForm.RefreshFromLevData; |
462 | var |
462 | var |
463 | i: integer; |
463 | i: integer; |
464 | begin |
464 | begin |
465 | MainForm.ScrollBar.Max := MainForm.LevData.LevelEditorLength; |
465 | MainForm.ScrollBar.Max := MainForm.LevData.LevelEditorLength; |
466 | for i := 0 to MainForm.LevData.CountEnemies - 1 do |
466 | for i := 0 to MainForm.LevData.CountEnemies - 1 do |
467 | begin |
467 | begin |
468 | MainForm.EnemyCreateSprite( |
468 | MainForm.EnemyCreateSprite( |
469 | MainForm.LevData.EnemyAdventTable[i].x, |
469 | MainForm.LevData.EnemyAdventTable[i].x, |
470 | MainForm.LevData.EnemyAdventTable[i].y, |
470 | MainForm.LevData.EnemyAdventTable[i].y, |
471 | MainForm.LevData.EnemyAdventTable[i].enemyType, |
471 | MainForm.LevData.EnemyAdventTable[i].enemyType, |
472 | MainForm.LevData.EnemyAdventTable[i].lifes |
472 | MainForm.LevData.EnemyAdventTable[i].lifes |
473 | ); |
473 | ); |
474 | end; |
474 | end; |
475 | MainForm.NumEnemys := MainForm.LevData.CountEnemies; |
475 | MainForm.NumEnemys := MainForm.LevData.CountEnemies; |
476 | MainForm.Boss := MainForm.LevData.HasBoss; |
476 | MainForm.Boss := MainForm.LevData.HasBoss; |
477 | AnzeigeAct; |
477 | AnzeigeAct; |
478 | end; |
478 | end; |
479 | 479 | ||
480 | procedure TMainForm.LevelClick(Sender: TObject); |
480 | procedure TMainForm.LevelClick(Sender: TObject); |
481 | begin |
481 | begin |
482 | speicherungform.showmodal; |
482 | speicherungform.showmodal; |
483 | end; |
483 | end; |
484 | 484 | ||
485 | procedure TMainForm.Leveltesten1Click(Sender: TObject); |
485 | procedure TMainForm.Leveltesten1Click(Sender: TObject); |
486 | var |
486 | var |
487 | sav: TSaveData; |
487 | sav: TSaveData; |
488 | tmp: string; |
488 | tmp: string; |
489 | begin |
489 | begin |
490 | KillTask(SpaceMissionExe); |
490 | KillTask(SpaceMissionExe); |
491 | 491 | ||
492 | sav := TSaveData.Create; |
492 | sav := TSaveData.Create; |
493 | try |
493 | try |
494 | sav.Score := 0; |
494 | sav.Score := 0; |
495 | sav.Life := 6; |
495 | sav.Life := 6; |
496 | if Assigned(SpeicherungForm) then |
496 | if Assigned(SpeicherungForm) then |
497 | sav.Level := SpeicherungForm.LevelNumber.Value |
497 | sav.Level := SpeicherungForm.LevelNumber.Value |
498 | else |
498 | else |
499 | sav.Level := 1; |
499 | sav.Level := 1; |
500 | sav.GameMode := gmLevels; |
500 | sav.GameMode := gmLevels; |
501 | sav.LevelData := TlevelData.Create; |
501 | sav.LevelData := TlevelData.Create; |
502 | sav.LevelData.Assign(LevData); |
502 | sav.LevelData.Assign(LevData); |
503 | tmp := GetTestlevelFilename; |
503 | tmp := GetTestlevelFilename; |
504 | sav.SaveToFile(tmp); |
504 | sav.SaveToFile(tmp); |
505 | ShellExecute(Handle, 'open', PChar(OwnDirectory+SpaceMissionExe), PChar('"'+tmp+'"'), PChar(OwnDirectory), SW_NORMAL); // do not localize |
505 | ShellExecute(Handle, 'open', PChar(OwnDirectory+SpaceMissionExe), PChar('"'+tmp+'"'), PChar(OwnDirectory), SW_NORMAL); // do not localize |
506 | finally |
506 | finally |
507 | FreeAndNil(sav); |
507 | FreeAndNil(sav); |
508 | end; |
508 | end; |
509 | end; |
509 | end; |
510 | 510 | ||
511 | procedure TMainForm.FormShow(Sender: TObject); |
511 | procedure TMainForm.FormShow(Sender: TObject); |
512 | begin |
512 | begin |
513 | if Assigned(SplashForm) then |
513 | if Assigned(SplashForm) then |
514 | begin |
514 | begin |
515 | SplashForm.Hide; |
515 | SplashForm.Hide; |
516 | FreeAndNil(SplashForm); |
516 | FreeAndNil(SplashForm); |
517 | end; |
517 | end; |
518 | 518 | ||
519 | dxtimer.Enabled := true; |
519 | dxtimer.Enabled := true; |
520 | dxtimer.ActiveOnly := true; |
520 | dxtimer.ActiveOnly := true; |
521 | end; |
521 | end; |
522 | 522 | ||
523 | function TMainForm.GetSpriteGraphic( |
523 | function TMainForm.GetSpriteGraphic( |
524 | Sprite: TSpaceMissionGraphicSprite): TPictureCollectionItem; |
524 | Sprite: TSpaceMissionGraphicSprite): TPictureCollectionItem; |
525 | begin |
525 | begin |
526 | if (Sprite<>smgNone) and (imagelist.Items.Count >= Ord(Sprite)) then |
526 | if (Sprite<>smgNone) and (imagelist.Items.Count >= Ord(Sprite)) then |
527 | result := imagelist.Items.Items[Ord(Sprite)-1] |
527 | result := imagelist.Items.Items[Ord(Sprite)-1] |
528 | else |
528 | else |
529 | result := nil; |
529 | result := nil; |
530 | end; |
530 | end; |
531 | 531 | ||
532 | function TMainForm.GetTestlevelFilename: string; |
532 | function TMainForm.GetTestlevelFilename: string; |
533 | begin |
533 | begin |
534 | result := IncludeTrailingPathDelimiter(TPath.GetTempPath) + 'SpaceMissionTest.sav'; // do not localize |
534 | result := IncludeTrailingPathDelimiter(TPath.GetTempPath) + 'SpaceMissionTest.sav'; // do not localize |
535 | end; |
535 | end; |
536 | 536 | ||
537 | procedure TMainForm.HilfeTopicClick(Sender: TObject); |
537 | procedure TMainForm.HilfeTopicClick(Sender: TObject); |
538 | // Please keep this code in-sync with GamMain.pas |
538 | // Please keep this code in-sync with GamMain.pas |
539 | var |
539 | var |
540 | bakTimerEnabled: boolean; |
540 | bakTimerEnabled: boolean; |
541 | begin |
541 | begin |
542 | bakTimerEnabled := dxtimer.Enabled; |
542 | bakTimerEnabled := dxtimer.Enabled; |
543 | try |
543 | try |
544 | dxtimer.Enabled := false; |
544 | dxtimer.Enabled := false; |
545 | HilfeForm.Caption := TMenuItem(Sender).Caption; |
545 | HilfeForm.Caption := TMenuItem(Sender).Caption; |
546 | HilfeForm.Caption := StringReplace(HilfeForm.Caption, '&&', #1, [rfReplaceAll]); |
546 | HilfeForm.Caption := StringReplace(HilfeForm.Caption, '&&', #1, [rfReplaceAll]); |
547 | HilfeForm.Caption := StringReplace(HilfeForm.Caption, '&', '', [rfReplaceAll]); |
547 | HilfeForm.Caption := StringReplace(HilfeForm.Caption, '&', '', [rfReplaceAll]); |
548 | HilfeForm.Caption := StringReplace(HilfeForm.Caption, #1, '&', [rfReplaceAll]); |
548 | HilfeForm.Caption := StringReplace(HilfeForm.Caption, #1, '&', [rfReplaceAll]); |
549 | HilfeForm.ShowMarkDownHelp(OwnDirectory+TMenuItem(Sender).Hint); |
549 | HilfeForm.ShowMarkDownHelp(OwnDirectory+TMenuItem(Sender).Hint); |
550 | HilfeForm.ShowModal; |
550 | HilfeForm.ShowModal; |
551 | finally |
551 | finally |
552 | dxtimer.Enabled := bakTimerEnabled; |
552 | dxtimer.Enabled := bakTimerEnabled; |
553 | end; |
553 | end; |
554 | end; |
554 | end; |
555 | 555 | ||
556 | procedure TMainForm.InformationenClick(Sender: TObject); |
556 | procedure TMainForm.InformationenClick(Sender: TObject); |
557 | begin |
557 | begin |
558 | mainform.dxtimer.enabled := false; |
558 | mainform.dxtimer.enabled := false; |
559 | InfoForm.showmodal; |
559 | InfoForm.showmodal; |
560 | mainform.dxtimer.enabled := true; |
560 | mainform.dxtimer.enabled := true; |
561 | end; |
561 | end; |
562 | 562 | ||
563 | procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction); |
563 | procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction); |
564 | begin |
564 | begin |
565 | SpriteEngine.Engine.Clear; |
565 | SpriteEngine.Engine.Clear; |
566 | DXTimer.Enabled := False; |
566 | DXTimer.Enabled := False; |
567 | end; |
567 | end; |
568 | 568 | ||
569 | procedure TMainForm.DXDrawMouseDown(Sender: TObject; Button: TMouseButton; |
569 | procedure TMainForm.DXDrawMouseDown(Sender: TObject; Button: TMouseButton; |
570 | Shift: TShiftState; X, Y: Integer); |
570 | Shift: TShiftState; X, Y: Integer); |
571 | var |
571 | var |
572 | i: TEnemyType; |
572 | i: TEnemyType; |
573 | j, k, l, ex, ey: integer; |
573 | j, k, l, ex, ey: integer; |
574 | ok, breaked: boolean; |
574 | ok, breaked: boolean; |
575 | begin |
575 | begin |
576 | ex := trunc(x/LevEditRasterW) * LevEditRasterW; |
576 | ex := trunc(x/LevEditRasterW) * LevEditRasterW; |
577 | ey := trunc(y/LevEditRasterH) * LevEditRasterH; |
577 | ey := trunc(y/LevEditRasterH) * LevEditRasterH; |
578 | EnemyCreateSprite(ex, ey, SelectedEnemyType, LivesEdit.Value); |
578 | EnemyCreateSprite(ex, ey, SelectedEnemyType, LivesEdit.Value); |
579 | breaked := false; |
579 | breaked := false; |
580 | { Setzen } |
580 | { Setzen } |
581 | if Button = mbLeft then |
581 | if Button = mbLeft then |
582 | begin |
582 | begin |
583 | ok := true; |
583 | ok := true; |
584 | if (SelectedEnemyType = etEnemyBoss) and boss then |
584 | if (SelectedEnemyType = etEnemyBoss) and boss then |
585 | ok := false // boss already exists |
585 | ok := false // boss already exists |
586 | else |
586 | else |
587 | begin |
587 | begin |
588 | for i := Low(TEnemyType) to High(TEnemyType) do |
588 | for i := Low(TEnemyType) to High(TEnemyType) do |
589 | begin |
589 | begin |
590 | for j := 0 to MaxPossibleEnemyLives do |
590 | for j := 0 to MaxPossibleEnemyLives do |
591 | begin |
591 | begin |
592 | if boss then |
592 | if boss then |
593 | begin |
593 | begin |
594 | for k := 0 to BossWidth-1 do |
594 | for k := 0 to BossWidth-1 do |
595 | begin |
595 | begin |
596 | for l := 0 to BossHeight-2 do |
596 | for l := 0 to BossHeight-2 do |
597 | begin |
597 | begin |
598 | if LevData.IndexOfEnemy(ex + ((ScrollP - k) * LevEditRasterW), ey - (LevEditRasterH * l), etEnemyBoss, j) <> -1 then |
598 | if LevData.IndexOfEnemy(ex + ((ScrollP - k) * LevEditRasterW), ey - (LevEditRasterH * l), etEnemyBoss, j) <> -1 then |
599 | begin |
599 | begin |
600 | ok := false; |
600 | ok := false; |
601 | break; |
601 | break; |
602 | end; |
602 | end; |
603 | end; |
603 | end; |
604 | if not ok then break; |
604 | if not ok then break; |
605 | end; |
605 | end; |
606 | if not ok then break; |
606 | if not ok then break; |
607 | end; |
607 | end; |
608 | if LevData.IndexOfEnemy(ex + (ScrollP * LevEditRasterW), ey, i, j) <> -1 then |
608 | if LevData.IndexOfEnemy(ex + (ScrollP * LevEditRasterW), ey, i, j) <> -1 then |
609 | begin |
609 | begin |
610 | ok := false; |
610 | ok := false; |
611 | break; |
611 | break; |
612 | end; |
612 | end; |
613 | end; |
613 | end; |
614 | if not ok then break; |
614 | if not ok then break; |
615 | end; |
615 | end; |
616 | end; |
616 | end; |
617 | if ok then |
617 | if ok then |
618 | begin |
618 | begin |
619 | if EnemyTypeHasLives(SelectedEnemyType) then |
619 | if EnemyTypeHasLives(SelectedEnemyType) then |
620 | LevData.AddEnemy(ex + (ScrollP * LevEditRasterW), ey, SelectedEnemyType, LivesEdit.Value) |
620 | LevData.AddEnemy(ex + (ScrollP * LevEditRasterW), ey, SelectedEnemyType, LivesEdit.Value) |
621 | else |
621 | else |
622 | LevData.AddEnemy(ex + (ScrollP * LevEditRasterW), ey, SelectedEnemyType, 0); |
622 | LevData.AddEnemy(ex + (ScrollP * LevEditRasterW), ey, SelectedEnemyType, 0); |
623 | inc(NumEnemys); |
623 | inc(NumEnemys); |
624 | if SelectedEnemyType = etEnemyBoss then boss := true; |
624 | if SelectedEnemyType = etEnemyBoss then boss := true; |
625 | end |
625 | end |
626 | else beep; |
626 | else beep; |
627 | end |
627 | end |
628 | { Löschen } |
628 | { Löschen } |
629 | else if Button = mbRight then |
629 | else if Button = mbRight then |
630 | begin |
630 | begin |
631 | for i := Low(TEnemyType) to High(TEnemyType) do |
631 | for i := Low(TEnemyType) to High(TEnemyType) do |
632 | begin |
632 | begin |
633 | for j := 0 to MaxPossibleEnemyLives do |
633 | for j := 0 to MaxPossibleEnemyLives do |
634 | begin |
634 | begin |
635 | if boss and (i = etEnemyBoss) then |
635 | if boss and (i = etEnemyBoss) then |
636 | begin |
636 | begin |
637 | for k := 0 to BossWidth - 1 do |
637 | for k := 0 to BossWidth - 1 do |
638 | begin |
638 | begin |
639 | for l := 0 to BossHeight - 1 do |
639 | for l := 0 to BossHeight - 1 do |
640 | begin |
640 | begin |
641 | if LevData.IndexOfEnemy(ex + ((ScrollP - k) * LevEditRasterW), ey - (LevEditRasterH * l), i, j) <> -1 then |
641 | if LevData.IndexOfEnemy(ex + ((ScrollP - k) * LevEditRasterW), ey - (LevEditRasterH * l), i, j) <> -1 then |
642 | begin |
642 | begin |
643 | LevData.DeleteEnemy(ex + ((ScrollP - k) * LevEditRasterW), ey - (LevEditRasterH * l), i, j); |
643 | LevData.DeleteEnemy(ex + ((ScrollP - k) * LevEditRasterW), ey - (LevEditRasterH * l), i, j); |
644 | Boss := false; |
644 | Boss := false; |
645 | dec(NumEnemys); |
645 | dec(NumEnemys); |
646 | breaked := true; |
646 | breaked := true; |
647 | break; |
647 | break; |
648 | end; |
648 | end; |
649 | end; |
649 | end; |
650 | if breaked then break; |
650 | if breaked then break; |
651 | end; |
651 | end; |
652 | end; |
652 | end; |
653 | if LevData.IndexOfEnemy(ex + (ScrollP * LevEditRasterW), ey, i, j) <> -1 then |
653 | if LevData.IndexOfEnemy(ex + (ScrollP * LevEditRasterW), ey, i, j) <> -1 then |
654 | begin |
654 | begin |
655 | LevData.DeleteEnemy(ex + (ScrollP * LevEditRasterW), ey, i, j); |
655 | LevData.DeleteEnemy(ex + (ScrollP * LevEditRasterW), ey, i, j); |
656 | if i = etEnemyBoss then Boss := false; |
656 | if i = etEnemyBoss then Boss := false; |
657 | dec(NumEnemys); |
657 | dec(NumEnemys); |
658 | breaked := true; |
658 | breaked := true; |
659 | break; |
659 | break; |
660 | end; |
660 | end; |
661 | end; |
661 | end; |
662 | if breaked then break; |
662 | if breaked then break; |
663 | end; |
663 | end; |
664 | end; |
664 | end; |
665 | LevChanged := true; |
665 | LevChanged := true; |
666 | AnzeigeAct; |
666 | AnzeigeAct; |
667 | end; |
667 | end; |
668 | 668 | ||
669 | procedure TMainForm.EnemyClick(Sender: TObject); |
669 | procedure TMainForm.EnemyClick(Sender: TObject); |
670 | var |
670 | var |
671 | et: TEnemyType; |
671 | et: TEnemyType; |
672 | begin |
672 | begin |
673 | et := SelectedEnemyType; |
673 | et := SelectedEnemyType; |
674 | Image1.Left := -(87 * (Ord(et) - 1)) + 1; |
674 | Image1.Left := -(87 * (Ord(et) - 1)) + 1; |
675 | LivesEdit.Enabled := EnemyTypeHasLives(et); |
675 | LivesEdit.Enabled := EnemyTypeHasLives(et); |
676 | LivesLabel.Enabled := EnemyTypeHasLives(et); |
676 | LivesLabel.Enabled := EnemyTypeHasLives(et); |
677 | end; |
677 | end; |
678 | 678 | ||
679 | procedure TMainForm.EnemyCreateSprite(x, y: integer; AEnemyType: TEnemyType; ALives: integer); |
679 | procedure TMainForm.EnemyCreateSprite(x, y: integer; AEnemyType: TEnemyType; ALives: integer); |
680 | var |
680 | var |
681 | Enemy: TSprite; |
681 | Enemy: TSprite; |
682 | begin |
682 | begin |
683 | Enemy := TEnemyOrItem.Create(SpriteEngine.Engine, AEnemyType, ALives); |
683 | Enemy := TEnemyOrItem.Create(SpriteEngine.Engine, AEnemyType, ALives); |
684 | Enemy.x := x; |
684 | Enemy.x := x; |
685 | Enemy.y := y; |
685 | Enemy.y := y; |
686 | end; |
686 | end; |
687 | 687 | ||
688 | procedure TMainForm.DestroyLevel; |
688 | procedure TMainForm.DestroyLevel; |
689 | begin |
689 | begin |
690 | ScrollBar.Position := 0; // this doesn't call ScrollBarScroll() |
690 | ScrollBar.Position := 0; // this doesn't call ScrollBarScroll() |
691 | ScrollP := 0; |
691 | ScrollP := 0; |
692 | LevData.Clear; |
692 | LevData.Clear; |
693 | ScrollBar.Max := LevData.LevelEditorLength; |
693 | ScrollBar.Max := LevData.LevelEditorLength; |
694 | NumEnemys := 0; |
694 | NumEnemys := 0; |
695 | Boss := false; |
695 | Boss := false; |
696 | LevChanged := true; |
696 | LevChanged := true; |
697 | LivesEdit.Value := 1; |
697 | LivesEdit.Value := 1; |
698 | Enemy1.Checked := true; |
698 | Enemy1.Checked := true; |
699 | EnemyClick(Enemy1); |
699 | EnemyClick(Enemy1); |
700 | AnzeigeAct; |
700 | AnzeigeAct; |
701 | end; |
701 | end; |
702 | 702 | ||
703 | procedure TMainForm.AlleLeveldateienaktualisieren1Click(Sender: TObject); |
703 | procedure TMainForm.AlleLeveldateienaktualisieren1Click(Sender: TObject); |
704 | var |
704 | var |
705 | i: integer; |
705 | i: integer; |
706 | begin |
706 | begin |
707 | // Just for internal/development purposes |
707 | // Just for internal/development purposes |
708 | for i := 1 to MaxPossibleLevels do |
708 | for i := 1 to MaxPossibleLevels do |
709 | begin |
709 | begin |
710 | if FileExists('Levels\Level '+IntToStr(i)+'.lev') then |
710 | if FileExists('Levels\Level '+IntToStr(i)+'.lev') then |
711 | begin |
711 | begin |
712 | LevData.RasterErzwingen := true; |
712 | LevData.RasterErzwingen := true; |
713 | LevData.LoadFromFile('Levels\Level '+IntToStr(i)+'.lev'); |
713 | LevData.LoadFromFile('Levels\Level '+IntToStr(i)+'.lev'); |
714 | LevData.SaveToFile('Levels\Level '+IntToStr(i)+'.lev'); |
714 | LevData.SaveToFile('Levels\Level '+IntToStr(i)+'.lev'); |
715 | end; |
715 | end; |
716 | end; |
716 | end; |
717 | end; |
717 | end; |
718 | 718 | ||
719 | procedure TMainForm.AnzeigeAct; |
719 | procedure TMainForm.AnzeigeAct; |
720 | resourcestring |
720 | resourcestring |
721 | SYes = 'Ja'; |
721 | SYes = 'Ja'; |
722 | SNo = 'Nein'; |
722 | SNo = 'Nein'; |
723 | begin |
723 | begin |
724 | SLabel1b.Caption := inttostr(NumEnemys); |
724 | SLabel1b.Caption := inttostr(NumEnemys); |
725 | if Boss then SLabel2b.Caption := SYes else SLabel2b.Caption := SNo; |
725 | if Boss then SLabel2b.Caption := SYes else SLabel2b.Caption := SNo; |
726 | SLabel3b.Caption := inttostr(ScrollBar.Max); |
726 | SLabel3b.Caption := inttostr(ScrollBar.Max); |
727 | if LevChanged then |
727 | if LevChanged then |
728 | begin |
728 | begin |
729 | SLabel4a.Font.Color := $00000096; |
729 | SLabel4a.Font.Color := $00000096; |
730 | SLabel4b.Font.Color := $00000096; |
730 | SLabel4b.Font.Color := $00000096; |
731 | SLabel4b.Caption := SNo; |
731 | SLabel4b.Caption := SNo; |
732 | end |
732 | end |
733 | else |
733 | else |
734 | begin |
734 | begin |
735 | SLabel4a.Font.Color := $00009600; |
735 | SLabel4a.Font.Color := $00009600; |
736 | SLabel4b.Font.Color := $00009600; |
736 | SLabel4b.Font.Color := $00009600; |
737 | SLabel4b.Caption := SYes; |
737 | SLabel4b.Caption := SYes; |
738 | end; |
738 | end; |
739 | end; |
739 | end; |
740 | 740 | ||
741 | procedure TMainForm.AufUpdatesprfen1Click(Sender: TObject); |
741 | procedure TMainForm.AufUpdatesprfen1Click(Sender: TObject); |
742 | begin |
742 | begin |
743 | CheckForUpdates('spacemission', ProgramVersion); // do not localize |
743 | CheckForUpdates('spacemission', ProgramVersion); // do not localize |
744 | end; |
744 | end; |
745 | 745 | ||
746 | procedure TMainForm.NeuClick(Sender: TObject); |
746 | procedure TMainForm.NeuClick(Sender: TObject); |
747 | resourcestring |
747 | resourcestring |
748 | SReallyDeleteLevel = 'Level wirklich löschen?'; |
748 | SReallyDeleteLevel = 'Level wirklich löschen?'; |
749 | begin |
749 | begin |
750 | if MessageDlg(SReallyDeleteLevel, mtConfirmation, mbYesNoCancel, 0) = mrYes then |
750 | if MessageDlg(SReallyDeleteLevel, mtConfirmation, mbYesNoCancel, 0) = mrYes then |
751 | DestroyLevel; |
751 | DestroyLevel; |
752 | end; |
752 | end; |
753 | 753 | ||
754 | procedure TMainForm.DXDrawMouseMove(Sender: TObject; Shift: TShiftState; X, |
754 | procedure TMainForm.DXDrawMouseMove(Sender: TObject; Shift: TShiftState; X, |
755 | Y: Integer); |
755 | Y: Integer); |
756 | resourcestring |
756 | resourcestring |
757 | status_lives = 'Leben: '; |
757 | status_lives = 'Leben: '; |
758 | status_nolives = 'Einheit hat keine Lebensangabe'; |
758 | status_nolives = 'Einheit hat keine Lebensangabe'; |
759 | SUnknownEnemyType = '???'; |
759 | SUnknownEnemyType = '???'; |
760 | var |
760 | var |
761 | i: TEnemyType; |
761 | i: TEnemyType; |
762 | ex, ey, j, k, l: integer; |
762 | ex, ey, j, k, l: integer; |
763 | lifes: integer; |
763 | lifes: integer; |
764 | enemyType: TEnemyType; |
764 | enemyType: TEnemyType; |
765 | enemyName: string; |
765 | enemyName: string; |
766 | breaked: boolean; |
766 | breaked: boolean; |
767 | begin |
767 | begin |
768 | if sender <> DxDraw then |
768 | if sender <> DxDraw then |
769 | begin |
769 | begin |
770 | StatusBar.SimpleText := ' ' + status_info; |
770 | StatusBar.SimpleText := ' ' + status_info; |
771 | exit; |
771 | exit; |
772 | end; |
772 | end; |
773 | ex := trunc(x/LevEditRasterW) * LevEditRasterW; |
773 | ex := trunc(x/LevEditRasterW) * LevEditRasterW; |
774 | ey := trunc(y/LevEditRasterH) * LevEditRasterH; |
774 | ey := trunc(y/LevEditRasterH) * LevEditRasterH; |
775 | lifes := -1; |
775 | lifes := -1; |
776 | enemyType := etUnknown; |
776 | enemyType := etUnknown; |
777 | breaked := false; |
777 | breaked := false; |
778 | for i := Low(TEnemyType) to High(TEnemyType) do |
778 | for i := Low(TEnemyType) to High(TEnemyType) do |
779 | begin |
779 | begin |
780 | for j := 0 to MaxPossibleEnemyLives do |
780 | for j := 0 to MaxPossibleEnemyLives do |
781 | begin |
781 | begin |
782 | if boss and (i = etEnemyBoss) then |
782 | if boss and (i = etEnemyBoss) then |
783 | begin |
783 | begin |
784 | for k := 0 to BossWidth - 1 do |
784 | for k := 0 to BossWidth - 1 do |
785 | begin |
785 | begin |
786 | for l := 0 to BossHeight - 1 do |
786 | for l := 0 to BossHeight - 1 do |
787 | begin |
787 | begin |
788 | if LevData.IndexOfEnemy(ex + ((ScrollP - k) * LevEditRasterW), ey - (LevEditRasterH * l), i, j) <> -1 then |
788 | if LevData.IndexOfEnemy(ex + ((ScrollP - k) * LevEditRasterW), ey - (LevEditRasterH * l), i, j) <> -1 then |
789 | begin |
789 | begin |
790 | lifes := j; |
790 | lifes := j; |
791 | breaked := true; |
791 | breaked := true; |
792 | break; |
792 | break; |
793 | end; |
793 | end; |
794 | end; |
794 | end; |
795 | if breaked then break; |
795 | if breaked then break; |
796 | end; |
796 | end; |
797 | end; |
797 | end; |
798 | if (breaked = false) and (LevData.IndexOfEnemy(ex + (ScrollP * LevEditRasterW), ey, i, j) <> -1) then |
798 | if (breaked = false) and (LevData.IndexOfEnemy(ex + (ScrollP * LevEditRasterW), ey, i, j) <> -1) then |
799 | begin |
799 | begin |
800 | lifes := j; |
800 | lifes := j; |
801 | enemyType := i; |
801 | enemyType := i; |
802 | breaked := true; |
802 | breaked := true; |
803 | break; |
803 | break; |
804 | end; |
804 | end; |
805 | end; |
805 | end; |
806 | if breaked then break; |
806 | if breaked then break; |
807 | end; |
807 | end; |
808 | if lifes <> -1 then |
808 | if lifes <> -1 then |
809 | begin |
809 | begin |
810 | if Ord(enemyType) = 1 then enemyName := Enemy1.Caption |
810 | if Ord(enemyType) = 1 then enemyName := Enemy1.Caption |
811 | else if Ord(enemyType) = 2 then enemyName := Enemy2.Caption |
811 | else if Ord(enemyType) = 2 then enemyName := Enemy2.Caption |
812 | else if Ord(enemyType) = 3 then enemyName := Enemy3.Caption |
812 | else if Ord(enemyType) = 3 then enemyName := Enemy3.Caption |
813 | else if Ord(enemyType) = 4 then enemyName := Enemy4.Caption |
813 | else if Ord(enemyType) = 4 then enemyName := Enemy4.Caption |
814 | else if Ord(enemyType) = 5 then enemyName := Enemy5.Caption |
814 | else if Ord(enemyType) = 5 then enemyName := Enemy5.Caption |
815 | else if Ord(enemyType) = 6 then enemyName := Enemy6.Caption |
815 | else if Ord(enemyType) = 6 then enemyName := Enemy6.Caption |
816 | else if Ord(enemyType) = 7 then enemyName := Enemy7.Caption |
816 | else if Ord(enemyType) = 7 then enemyName := Enemy7.Caption |
817 | else if Ord(enemyType) = 8 then enemyName := Enemy8.Caption |
817 | else if Ord(enemyType) = 8 then enemyName := Enemy8.Caption |
818 | else enemyName := SUnknownEnemyType; |
818 | else enemyName := SUnknownEnemyType; |
819 | if lifes > 0 then |
819 | if lifes > 0 then |
820 | StatusBar.SimpleText := ' ' + enemyName + ' - ' + status_lives + inttostr(lifes) |
820 | StatusBar.SimpleText := ' ' + enemyName + ' - ' + status_lives + inttostr(lifes) |
821 | else |
821 | else |
822 | StatusBar.SimpleText := ' ' + enemyName + ' - ' + status_nolives; |
822 | StatusBar.SimpleText := ' ' + enemyName + ' - ' + status_nolives; |
823 | end |
823 | end |
824 | else |
824 | else |
825 | StatusBar.SimpleText := ' ' + status_info; |
825 | StatusBar.SimpleText := ' ' + status_info; |
826 | end; |
826 | end; |
827 | 827 | ||
828 | procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); |
828 | procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); |
829 | resourcestring |
829 | resourcestring |
830 | SExitWithoutSave = 'Beenden ohne abspeichern?'; |
830 | SExitWithoutSave = 'Beenden ohne abspeichern?'; |
831 | begin |
831 | begin |
832 | if Assigned(LevData) and LevChanged and (LevData.CountEnemies>0) then |
832 | if Assigned(LevData) and LevChanged and (LevData.CountEnemies>0) then |
833 | CanClose := MessageDlg(SExitWithoutSave, mtConfirmation, mbYesNoCancel, 0) = mrYes; |
833 | CanClose := MessageDlg(SExitWithoutSave, mtConfirmation, mbYesNoCancel, 0) = mrYes; |
834 | end; |
834 | end; |
835 | 835 | ||
836 | procedure TMainForm.Spielfelderweitern1Click(Sender: TObject); |
836 | procedure TMainForm.Spielfelderweitern1Click(Sender: TObject); |
837 | begin |
837 | begin |
838 | LevelForm.Aktualisieren; |
838 | LevelForm.Aktualisieren; |
839 | LevelForm.showmodal; |
839 | LevelForm.showmodal; |
840 | end; |
840 | end; |
841 | 841 | ||
842 | procedure TMainForm.ScrollBarScroll(Sender: TObject; |
842 | procedure TMainForm.ScrollBarScroll(Sender: TObject; |
843 | ScrollCode: TScrollCode; var ScrollPos: Integer); |
843 | ScrollCode: TScrollCode; var ScrollPos: Integer); |
844 | begin |
844 | begin |
845 | ScrollP := ScrollPos; |
845 | ScrollP := ScrollPos; |
846 | end; |
846 | end; |
847 | 847 | ||
848 | function TMainForm.SelectedEnemyType: TEnemyType; |
848 | function TMainForm.SelectedEnemyType: TEnemyType; |
849 | begin |
849 | begin |
850 | if Enemy1.Checked then result := etEnemyAttacker |
850 | if Enemy1.Checked then result := etEnemyAttacker |
851 | else if Enemy2.Checked then result := etEnemyAttacker2 |
851 | else if Enemy2.Checked then result := etEnemyAttacker2 |
852 | else if Enemy3.Checked then result := etEnemyAttacker3 |
852 | else if Enemy3.Checked then result := etEnemyAttacker3 |
853 | else if Enemy4.Checked then result := etEnemyMeteor |
853 | else if Enemy4.Checked then result := etEnemyMeteor |
854 | else if Enemy5.Checked then result := etEnemyUFO |
854 | else if Enemy5.Checked then result := etEnemyUFO |
855 | else if Enemy6.Checked then result := etEnemyUFO2 |
855 | else if Enemy6.Checked then result := etEnemyUFO2 |
856 | else if Enemy7.Checked then result := etEnemyBoss |
856 | else if Enemy7.Checked then result := etEnemyBoss |
857 | else if Enemy8.Checked then result := etItemMedikit |
857 | else if Enemy8.Checked then result := etItemMedikit |
858 | else result := etUnknown; |
858 | else result := etUnknown; |
859 | end; |
859 | end; |
860 | 860 | ||
861 | end. |
861 | end. |
862 | 862 | ||
863 | 863 |