DEADSOFTWARE

moved compiler options to shared/a_modes.inc; turned on advanced records
[d2df-sdl.git] / src / game / g_items.pas
1 (* Copyright (C) DooM 2D:Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$INCLUDE ../shared/a_modes.inc}
17 unit g_items;
19 interface
21 uses
22 g_textures, g_phys, g_saveload, BinEditor, MAPDEF;
24 Type
25 TItem = record
26 ItemType: Byte;
27 Respawnable: Boolean;
28 InitX, InitY: Integer;
29 RespawnTime: Word;
30 Live: Boolean;
31 Fall: Boolean;
32 QuietRespawn: Boolean;
33 SpawnTrigger: Integer;
34 Obj: TObj;
35 Animation: TAnimation;
36 end;
38 procedure g_Items_LoadData();
39 procedure g_Items_FreeData();
40 procedure g_Items_Init();
41 procedure g_Items_Free();
42 function g_Items_Create(X, Y: Integer; ItemType: Byte;
43 Fall, Respawnable: Boolean; AdjCoord: Boolean = False; ForcedID: Integer = -1): DWORD;
44 procedure g_Items_Update();
45 procedure g_Items_Draw();
46 procedure g_Items_Pick(ID: DWORD);
47 procedure g_Items_Remove(ID: DWORD);
48 procedure g_Items_SaveState(var Mem: TBinMemoryWriter);
49 procedure g_Items_LoadState(var Mem: TBinMemoryReader);
51 var
52 gItems: Array of TItem = nil;
53 gItemsTexturesID: Array [1..ITEM_MAX] of DWORD;
54 gMaxDist: Integer = 1;
55 ITEM_RESPAWNTIME: Integer = 60 * 36;
57 implementation
59 uses
60 g_basic, e_graphics, g_sound, g_main, g_gfx, g_map,
61 Math, g_game, g_triggers, g_console, SysUtils, g_player, g_net, g_netmsg,
62 e_log;
64 const
65 ITEM_SIGNATURE = $4D455449; // 'ITEM'
67 ITEMSIZE: Array [ITEM_MEDKIT_SMALL..ITEM_MAX] of Array [0..1] of Byte =
68 (((14), (15)), // MEDKIT_SMALL
69 ((28), (19)), // MEDKIT_LARGE
70 ((28), (19)), // MEDKIT_BLACK
71 ((31), (16)), // ARMOR_GREEN
72 ((31), (16)), // ARMOR_BLUE
73 ((25), (25)), // SPHERE_BLUE
74 ((25), (25)), // SPHERE_WHITE
75 ((24), (47)), // SUIT
76 ((14), (27)), // OXYGEN
77 ((25), (25)), // INVUL
78 ((62), (24)), // WEAPON_SAW
79 ((63), (12)), // WEAPON_SHOTGUN1
80 ((54), (13)), // WEAPON_SHOTGUN2
81 ((54), (16)), // WEAPON_CHAINGUN
82 ((62), (16)), // WEAPON_ROCKETLAUNCHER
83 ((54), (16)), // WEAPON_PLASMA
84 ((61), (36)), // WEAPON_BFG
85 ((54), (16)), // WEAPON_SUPERPULEMET
86 (( 9), (11)), // AMMO_BULLETS
87 ((28), (16)), // AMMO_BULLETS_BOX
88 ((15), ( 7)), // AMMO_SHELLS
89 ((32), (12)), // AMMO_SHELLS_BOX
90 ((12), (27)), // AMMO_ROCKET
91 ((54), (21)), // AMMO_ROCKET_BOX
92 ((15), (12)), // AMMO_CELL
93 ((32), (21)), // AMMO_CELL_BIG
94 ((22), (29)), // AMMO_BACKPACK
95 ((16), (16)), // KEY_RED
96 ((16), (16)), // KEY_GREEN
97 ((16), (16)), // KEY_BLUE
98 (( 1), ( 1)), // WEAPON_KASTET
99 ((43), (16)), // WEAPON_PISTOL
100 ((14), (18)), // BOTTLE
101 ((16), (15)), // HELMET
102 ((32), (24)), // JETPACK
103 ((25), (25)), // INVIS
104 ((53), (20)), // WEAPON_FLAMETHROWER
105 ((13), (20))); // AMMO_FUELCAN
107 procedure InitTextures();
108 begin
109 g_Texture_Get('ITEM_MEDKIT_SMALL', gItemsTexturesID[ITEM_MEDKIT_SMALL]);
110 g_Texture_Get('ITEM_MEDKIT_LARGE', gItemsTexturesID[ITEM_MEDKIT_LARGE]);
111 g_Texture_Get('ITEM_MEDKIT_BLACK', gItemsTexturesID[ITEM_MEDKIT_BLACK]);
112 g_Texture_Get('ITEM_SUIT', gItemsTexturesID[ITEM_SUIT]);
113 g_Texture_Get('ITEM_OXYGEN', gItemsTexturesID[ITEM_OXYGEN]);
114 g_Texture_Get('ITEM_WEAPON_SAW', gItemsTexturesID[ITEM_WEAPON_SAW]);
115 g_Texture_Get('ITEM_WEAPON_SHOTGUN1', gItemsTexturesID[ITEM_WEAPON_SHOTGUN1]);
116 g_Texture_Get('ITEM_WEAPON_SHOTGUN2', gItemsTexturesID[ITEM_WEAPON_SHOTGUN2]);
117 g_Texture_Get('ITEM_WEAPON_CHAINGUN', gItemsTexturesID[ITEM_WEAPON_CHAINGUN]);
118 g_Texture_Get('ITEM_WEAPON_ROCKETLAUNCHER', gItemsTexturesID[ITEM_WEAPON_ROCKETLAUNCHER]);
119 g_Texture_Get('ITEM_WEAPON_PLASMA', gItemsTexturesID[ITEM_WEAPON_PLASMA]);
120 g_Texture_Get('ITEM_WEAPON_BFG', gItemsTexturesID[ITEM_WEAPON_BFG]);
121 g_Texture_Get('ITEM_WEAPON_SUPERPULEMET', gItemsTexturesID[ITEM_WEAPON_SUPERPULEMET]);
122 g_Texture_Get('ITEM_WEAPON_FLAMETHROWER', gItemsTexturesID[ITEM_WEAPON_FLAMETHROWER]);
123 g_Texture_Get('ITEM_AMMO_BULLETS', gItemsTexturesID[ITEM_AMMO_BULLETS]);
124 g_Texture_Get('ITEM_AMMO_BULLETS_BOX', gItemsTexturesID[ITEM_AMMO_BULLETS_BOX]);
125 g_Texture_Get('ITEM_AMMO_SHELLS', gItemsTexturesID[ITEM_AMMO_SHELLS]);
126 g_Texture_Get('ITEM_AMMO_SHELLS_BOX', gItemsTexturesID[ITEM_AMMO_SHELLS_BOX]);
127 g_Texture_Get('ITEM_AMMO_ROCKET', gItemsTexturesID[ITEM_AMMO_ROCKET]);
128 g_Texture_Get('ITEM_AMMO_ROCKET_BOX', gItemsTexturesID[ITEM_AMMO_ROCKET_BOX]);
129 g_Texture_Get('ITEM_AMMO_CELL', gItemsTexturesID[ITEM_AMMO_CELL]);
130 g_Texture_Get('ITEM_AMMO_CELL_BIG', gItemsTexturesID[ITEM_AMMO_CELL_BIG]);
131 g_Texture_Get('ITEM_AMMO_FUELCAN', gItemsTexturesID[ITEM_AMMO_FUELCAN]);
132 g_Texture_Get('ITEM_AMMO_BACKPACK', gItemsTexturesID[ITEM_AMMO_BACKPACK]);
133 g_Texture_Get('ITEM_KEY_RED', gItemsTexturesID[ITEM_KEY_RED]);
134 g_Texture_Get('ITEM_KEY_GREEN', gItemsTexturesID[ITEM_KEY_GREEN]);
135 g_Texture_Get('ITEM_KEY_BLUE', gItemsTexturesID[ITEM_KEY_BLUE]);
136 g_Texture_Get('ITEM_WEAPON_KASTET', gItemsTexturesID[ITEM_WEAPON_KASTET]);
137 g_Texture_Get('ITEM_WEAPON_PISTOL', gItemsTexturesID[ITEM_WEAPON_PISTOL]);
138 g_Texture_Get('ITEM_JETPACK', gItemsTexturesID[ITEM_JETPACK]);
139 end;
141 procedure g_Items_LoadData();
142 begin
143 e_WriteLog('Loading items data...', MSG_NOTIFY);
145 g_Sound_CreateWADEx('SOUND_ITEM_RESPAWNITEM', GameWAD+':SOUNDS\RESPAWNITEM');
146 g_Sound_CreateWADEx('SOUND_ITEM_GETRULEZ', GameWAD+':SOUNDS\GETRULEZ');
147 g_Sound_CreateWADEx('SOUND_ITEM_GETWEAPON', GameWAD+':SOUNDS\GETWEAPON');
148 g_Sound_CreateWADEx('SOUND_ITEM_GETITEM', GameWAD+':SOUNDS\GETITEM');
150 g_Frames_CreateWAD(nil, 'FRAMES_ITEM_BLUESPHERE', GameWAD+':TEXTURES\SBLUE', 32, 32, 4, True);
151 g_Frames_CreateWAD(nil, 'FRAMES_ITEM_WHITESPHERE', GameWAD+':TEXTURES\SWHITE', 32, 32, 4, True);
152 g_Frames_CreateWAD(nil, 'FRAMES_ITEM_ARMORGREEN', GameWAD+':TEXTURES\ARMORGREEN', 32, 16, 3, True);
153 g_Frames_CreateWAD(nil, 'FRAMES_ITEM_ARMORBLUE', GameWAD+':TEXTURES\ARMORBLUE', 32, 16, 3, True);
154 g_Frames_CreateWAD(nil, 'FRAMES_ITEM_INVUL', GameWAD+':TEXTURES\INVUL', 32, 32, 4, True);
155 g_Frames_CreateWAD(nil, 'FRAMES_ITEM_INVIS', GameWAD+':TEXTURES\INVIS', 32, 32, 4, True);
156 g_Frames_CreateWAD(nil, 'FRAMES_ITEM_RESPAWN', GameWAD+':TEXTURES\ITEMRESPAWN', 32, 32, 5, True);
157 g_Frames_CreateWAD(nil, 'FRAMES_ITEM_BOTTLE', GameWAD+':TEXTURES\BOTTLE', 16, 32, 4, True);
158 g_Frames_CreateWAD(nil, 'FRAMES_ITEM_HELMET', GameWAD+':TEXTURES\HELMET', 16, 16, 4, True);
159 g_Frames_CreateWAD(nil, 'FRAMES_FLAG_RED', GameWAD+':TEXTURES\FLAGRED', 64, 64, 5, False);
160 g_Frames_CreateWAD(nil, 'FRAMES_FLAG_BLUE', GameWAD+':TEXTURES\FLAGBLUE', 64, 64, 5, False);
161 g_Frames_CreateWAD(nil, 'FRAMES_FLAG_DOM', GameWAD+':TEXTURES\FLAGDOM', 64, 64, 5, False);
162 g_Texture_CreateWADEx('ITEM_MEDKIT_SMALL', GameWAD+':TEXTURES\MED1');
163 g_Texture_CreateWADEx('ITEM_MEDKIT_LARGE', GameWAD+':TEXTURES\MED2');
164 g_Texture_CreateWADEx('ITEM_WEAPON_SAW', GameWAD+':TEXTURES\SAW');
165 g_Texture_CreateWADEx('ITEM_WEAPON_PISTOL', GameWAD+':TEXTURES\PISTOL');
166 g_Texture_CreateWADEx('ITEM_WEAPON_KASTET', GameWAD+':TEXTURES\KASTET');
167 g_Texture_CreateWADEx('ITEM_WEAPON_SHOTGUN1', GameWAD+':TEXTURES\SHOTGUN1');
168 g_Texture_CreateWADEx('ITEM_WEAPON_SHOTGUN2', GameWAD+':TEXTURES\SHOTGUN2');
169 g_Texture_CreateWADEx('ITEM_WEAPON_CHAINGUN', GameWAD+':TEXTURES\MGUN');
170 g_Texture_CreateWADEx('ITEM_WEAPON_ROCKETLAUNCHER', GameWAD+':TEXTURES\RLAUNCHER');
171 g_Texture_CreateWADEx('ITEM_WEAPON_PLASMA', GameWAD+':TEXTURES\PGUN');
172 g_Texture_CreateWADEx('ITEM_WEAPON_BFG', GameWAD+':TEXTURES\BFG');
173 g_Texture_CreateWADEx('ITEM_WEAPON_SUPERPULEMET', GameWAD+':TEXTURES\SPULEMET');
174 g_Texture_CreateWADEx('ITEM_WEAPON_FLAMETHROWER', GameWAD+':TEXTURES\FLAMETHROWER');
175 g_Texture_CreateWADEx('ITEM_AMMO_BULLETS', GameWAD+':TEXTURES\CLIP');
176 g_Texture_CreateWADEx('ITEM_AMMO_BULLETS_BOX', GameWAD+':TEXTURES\AMMO');
177 g_Texture_CreateWADEx('ITEM_AMMO_SHELLS', GameWAD+':TEXTURES\SHELL1');
178 g_Texture_CreateWADEx('ITEM_AMMO_SHELLS_BOX', GameWAD+':TEXTURES\SHELL2');
179 g_Texture_CreateWADEx('ITEM_AMMO_ROCKET', GameWAD+':TEXTURES\ROCKET');
180 g_Texture_CreateWADEx('ITEM_AMMO_ROCKET_BOX', GameWAD+':TEXTURES\ROCKETS');
181 g_Texture_CreateWADEx('ITEM_AMMO_CELL', GameWAD+':TEXTURES\CELL');
182 g_Texture_CreateWADEx('ITEM_AMMO_CELL_BIG', GameWAD+':TEXTURES\CELL2');
183 g_Texture_CreateWADEx('ITEM_AMMO_FUELCAN', GameWAD+':TEXTURES\FUELCAN');
184 g_Texture_CreateWADEx('ITEM_AMMO_BACKPACK', GameWAD+':TEXTURES\BPACK');
185 g_Texture_CreateWADEx('ITEM_KEY_RED', GameWAD+':TEXTURES\KEYR');
186 g_Texture_CreateWADEx('ITEM_KEY_GREEN', GameWAD+':TEXTURES\KEYG');
187 g_Texture_CreateWADEx('ITEM_KEY_BLUE', GameWAD+':TEXTURES\KEYB');
188 g_Texture_CreateWADEx('ITEM_OXYGEN', GameWAD+':TEXTURES\OXYGEN');
189 g_Texture_CreateWADEx('ITEM_SUIT', GameWAD+':TEXTURES\SUIT');
190 g_Texture_CreateWADEx('ITEM_WEAPON_KASTET', GameWAD+':TEXTURES\KASTET');
191 g_Texture_CreateWADEx('ITEM_MEDKIT_BLACK', GameWAD+':TEXTURES\BMED');
192 g_Texture_CreateWADEx('ITEM_JETPACK', GameWAD+':TEXTURES\JETPACK');
194 InitTextures();
195 end;
197 procedure g_Items_FreeData();
198 begin
199 e_WriteLog('Releasing items data...', MSG_NOTIFY);
201 g_Sound_Delete('SOUND_ITEM_RESPAWNITEM');
202 g_Sound_Delete('SOUND_ITEM_GETRULEZ');
203 g_Sound_Delete('SOUND_ITEM_GETWEAPON');
204 g_Sound_Delete('SOUND_ITEM_GETITEM');
206 g_Frames_DeleteByName('FRAMES_ITEM_BLUESPHERE');
207 g_Frames_DeleteByName('FRAMES_ITEM_WHITESPHERE');
208 g_Frames_DeleteByName('FRAMES_ITEM_ARMORGREEN');
209 g_Frames_DeleteByName('FRAMES_ITEM_ARMORBLUE');
210 g_Frames_DeleteByName('FRAMES_ITEM_INVUL');
211 g_Frames_DeleteByName('FRAMES_ITEM_INVIS');
212 g_Frames_DeleteByName('FRAMES_ITEM_RESPAWN');
213 g_Frames_DeleteByName('FRAMES_ITEM_BOTTLE');
214 g_Frames_DeleteByName('FRAMES_ITEM_HELMET');
215 g_Frames_DeleteByName('FRAMES_FLAG_RED');
216 g_Frames_DeleteByName('FRAMES_FLAG_BLUE');
217 g_Frames_DeleteByName('FRAMES_FLAG_DOM');
218 g_Texture_Delete('ITEM_MEDKIT_SMALL');
219 g_Texture_Delete('ITEM_MEDKIT_LARGE');
220 g_Texture_Delete('ITEM_WEAPON_SAW');
221 g_Texture_Delete('ITEM_WEAPON_PISTOL');
222 g_Texture_Delete('ITEM_WEAPON_KASTET');
223 g_Texture_Delete('ITEM_WEAPON_SHOTGUN1');
224 g_Texture_Delete('ITEM_WEAPON_SHOTGUN2');
225 g_Texture_Delete('ITEM_WEAPON_CHAINGUN');
226 g_Texture_Delete('ITEM_WEAPON_ROCKETLAUNCHER');
227 g_Texture_Delete('ITEM_WEAPON_PLASMA');
228 g_Texture_Delete('ITEM_WEAPON_BFG');
229 g_Texture_Delete('ITEM_WEAPON_SUPERPULEMET');
230 g_Texture_Delete('ITEM_WEAPON_FLAMETHROWER');
231 g_Texture_Delete('ITEM_AMMO_BULLETS');
232 g_Texture_Delete('ITEM_AMMO_BULLETS_BOX');
233 g_Texture_Delete('ITEM_AMMO_SHELLS');
234 g_Texture_Delete('ITEM_AMMO_SHELLS_BOX');
235 g_Texture_Delete('ITEM_AMMO_ROCKET');
236 g_Texture_Delete('ITEM_AMMO_ROCKET_BOX');
237 g_Texture_Delete('ITEM_AMMO_CELL');
238 g_Texture_Delete('ITEM_AMMO_CELL_BIG');
239 g_Texture_Delete('ITEM_AMMO_FUELCAN');
240 g_Texture_Delete('ITEM_AMMO_BACKPACK');
241 g_Texture_Delete('ITEM_KEY_RED');
242 g_Texture_Delete('ITEM_KEY_GREEN');
243 g_Texture_Delete('ITEM_KEY_BLUE');
244 g_Texture_Delete('ITEM_OXYGEN');
245 g_Texture_Delete('ITEM_SUIT');
246 g_Texture_Delete('ITEM_WEAPON_KASTET');
247 g_Texture_Delete('ITEM_MEDKIT_BLACK');
248 g_Texture_Delete('ITEM_JETPACK');
249 end;
251 function FindItem(): DWORD;
252 var
253 i: Integer;
254 begin
255 if gItems <> nil then
256 for i := 0 to High(gItems) do
257 if gItems[i].ItemType = ITEM_NONE then
258 begin
259 Result := i;
260 Exit;
261 end;
263 if gItems = nil then
264 begin
265 SetLength(gItems, 32);
266 Result := 0;
267 end
268 else
269 begin
270 Result := High(gItems) + 1;
271 SetLength(gItems, Length(gItems) + 32);
272 end;
273 end;
275 procedure g_Items_Init();
276 var
277 a, b: Integer;
278 begin
279 if gMapInfo.Height > gPlayerScreenSize.Y then
280 a := gMapInfo.Height - gPlayerScreenSize.Y
281 else
282 a := gMapInfo.Height;
284 if gMapInfo.Width > gPlayerScreenSize.X then
285 b := gMapInfo.Width - gPlayerScreenSize.X
286 else
287 b := gMapInfo.Width;
289 gMaxDist := Trunc(Hypot(a, b));
290 end;
292 procedure g_Items_Free();
293 var
294 i: Integer;
295 begin
296 if gItems <> nil then
297 begin
298 for i := 0 to High(gItems) do
299 gItems[i].Animation.Free();
300 gItems := nil;
301 end;
302 end;
304 function g_Items_Create(X, Y: Integer; ItemType: Byte;
305 Fall, Respawnable: Boolean; AdjCoord: Boolean = False; ForcedID: Integer = -1): DWORD;
306 var
307 find_id: DWORD;
308 ID: DWORD;
309 begin
310 if ForcedID < 0 then
311 find_id := FindItem()
312 else
313 begin
314 find_id := ForcedID;
315 if Integer(find_id) > High(gItems) then
316 SetLength(gItems, find_id + 32);
317 end;
319 gItems[find_id].ItemType := ItemType;
320 gItems[find_id].Respawnable := Respawnable;
321 if g_Game_IsServer and (ITEM_RESPAWNTIME = 0) then
322 gItems[find_id].Respawnable := False;
323 gItems[find_id].InitX := X;
324 gItems[find_id].InitY := Y;
325 gItems[find_id].RespawnTime := 0;
326 gItems[find_id].Fall := Fall;
327 gItems[find_id].Live := True;
328 gItems[find_id].QuietRespawn := False;
330 g_Obj_Init(@gItems[find_id].Obj);
331 gItems[find_id].Obj.X := X;
332 gItems[find_id].Obj.Y := Y;
333 gItems[find_id].Obj.Rect.Width := ITEMSIZE[ItemType][0];
334 gItems[find_id].Obj.Rect.Height := ITEMSIZE[ItemType][1];
336 gItems[find_id].Animation := nil;
337 gItems[find_id].SpawnTrigger := -1;
339 // Êîîðäèíàòû îòíîñèòåëüíî öåíòðà íèæíåãî ðåáðà:
340 if AdjCoord then
341 with gItems[find_id] do
342 begin
343 Obj.X := X - (Obj.Rect.Width div 2);
344 Obj.Y := Y - Obj.Rect.Height;
345 InitX := Obj.X;
346 InitY := Obj.Y;
347 end;
349 // Óñòàíîâêà àíèìàöèè:
350 with gItems[find_id] do
351 begin
352 case ItemType of
353 ITEM_ARMOR_GREEN:
354 if g_Frames_Get(ID, 'FRAMES_ITEM_ARMORGREEN') then
355 Animation := TAnimation.Create(ID, True, 20);
356 ITEM_ARMOR_BLUE:
357 if g_Frames_Get(ID, 'FRAMES_ITEM_ARMORBLUE') then
358 Animation := TAnimation.Create(ID, True, 20);
359 ITEM_SPHERE_BLUE:
360 if g_Frames_Get(ID, 'FRAMES_ITEM_BLUESPHERE') then
361 Animation := TAnimation.Create(ID, True, 15);
362 ITEM_SPHERE_WHITE:
363 if g_Frames_Get(ID, 'FRAMES_ITEM_WHITESPHERE') then
364 Animation := TAnimation.Create(ID, True, 20);
365 ITEM_INVUL:
366 if g_Frames_Get(ID, 'FRAMES_ITEM_INVUL') then
367 Animation := TAnimation.Create(ID, True, 20);
368 ITEM_INVIS:
369 if g_Frames_Get(ID, 'FRAMES_ITEM_INVIS') then
370 Animation := TAnimation.Create(ID, True, 20);
371 ITEM_BOTTLE:
372 if g_Frames_Get(ID, 'FRAMES_ITEM_BOTTLE') then
373 Animation := TAnimation.Create(ID, True, 20);
374 ITEM_HELMET:
375 if g_Frames_Get(ID, 'FRAMES_ITEM_HELMET') then
376 Animation := TAnimation.Create(ID, True, 20);
377 end;
378 end;
380 Result := find_id;
381 end;
383 procedure g_Items_Update();
384 var
385 i, j, k: Integer;
386 ID: DWORD;
387 Anim: TAnimation;
388 m: Word;
389 r, nxt: Boolean;
390 begin
391 if gItems <> nil then
392 for i := 0 to High(gItems) do
393 if gItems[i].ItemType <> ITEM_NONE then
394 with gItems[i] do
395 begin
396 nxt := False;
398 if Live then
399 begin
400 if Fall then
401 begin
402 m := g_Obj_Move(@Obj, True, True);
404 // Ñîïðîòèâëåíèå âîçäóõà:
405 if gTime mod (GAME_TICK*2) = 0 then
406 Obj.Vel.X := z_dec(Obj.Vel.X, 1);
407 // Åñëè âûïàë çà êàðòó:
408 if WordBool(m and MOVE_FALLOUT) then
409 begin
410 if SpawnTrigger = -1 then
411 g_Items_Pick(i)
412 else begin
413 g_Items_Remove(i);
414 if g_Game_IsServer and g_Game_IsNet then MH_SEND_ItemDestroy(True, i);
415 end;
416 Continue;
417 end;
418 end;
420 // Åñëè èãðîêè ïîáëèçîñòè:
421 if gPlayers <> nil then
422 begin
423 j := Random(Length(gPlayers)) - 1;
425 for k := 0 to High(gPlayers) do
426 begin
427 Inc(j);
428 if j > High(gPlayers) then
429 j := 0;
431 if (gPlayers[j] <> nil) and gPlayers[j].Live and
432 g_Obj_Collide(@gPlayers[j].Obj, @Obj) then
433 begin
434 if g_Game_IsClient then Continue;
436 if not gPlayers[j].PickItem(ItemType, Respawnable, r) then
437 Continue;
439 if g_Game_IsNet then MH_SEND_PlayerStats(gPlayers[j].UID);
442 Doom 2D: Original:
443 1. I_NONE,I_CLIP,I_SHEL,I_ROCKET,I_CELL,I_AMMO,I_SBOX,I_RBOX,I_CELP,I_BPACK,I_CSAW,I_SGUN,I_SGUN2,I_MGUN,I_LAUN,I_PLAS,I_BFG,I_GUN2
444 +2. I_MEGA,I_INVL,I_SUPER
445 3. I_STIM,I_MEDI,I_ARM1,I_ARM2,I_AQUA,I_KEYR,I_KEYG,I_KEYB,I_SUIT,I_RTORCH,I_GTORCH,I_BTORCH,I_GOR1,I_FCAN
448 if gSoundEffectsDF then
449 begin
450 if ItemType in [ITEM_SPHERE_BLUE, ITEM_SPHERE_WHITE, ITEM_INVUL,
451 ITEM_INVIS, ITEM_MEDKIT_BLACK, ITEM_JETPACK] then
452 g_Sound_PlayExAt('SOUND_ITEM_GETRULEZ',
453 gPlayers[j].Obj.X, gPlayers[j].Obj.Y)
454 else
455 if ItemType in [ITEM_WEAPON_SAW, ITEM_WEAPON_PISTOL, ITEM_WEAPON_SHOTGUN1, ITEM_WEAPON_SHOTGUN2,
456 ITEM_WEAPON_CHAINGUN, ITEM_WEAPON_ROCKETLAUNCHER, ITEM_WEAPON_PLASMA,
457 ITEM_WEAPON_BFG, ITEM_WEAPON_SUPERPULEMET, ITEM_WEAPON_FLAMETHROWER,
458 ITEM_AMMO_BACKPACK] then
459 g_Sound_PlayExAt('SOUND_ITEM_GETWEAPON',
460 gPlayers[j].Obj.X, gPlayers[j].Obj.Y)
461 else
462 g_Sound_PlayExAt('SOUND_ITEM_GETITEM',
463 gPlayers[j].Obj.X, gPlayers[j].Obj.Y);
464 end
465 else
466 begin
467 if ItemType in [ITEM_SPHERE_BLUE, ITEM_SPHERE_WHITE, ITEM_SUIT,
468 ITEM_MEDKIT_BLACK, ITEM_INVUL, ITEM_INVIS, ITEM_JETPACK] then
469 g_Sound_PlayExAt('SOUND_ITEM_GETRULEZ',
470 gPlayers[j].Obj.X, gPlayers[j].Obj.Y)
471 else
472 if ItemType in [ITEM_WEAPON_SAW, ITEM_WEAPON_PISTOL, ITEM_WEAPON_SHOTGUN1, ITEM_WEAPON_SHOTGUN2,
473 ITEM_WEAPON_CHAINGUN, ITEM_WEAPON_ROCKETLAUNCHER, ITEM_WEAPON_PLASMA,
474 ITEM_WEAPON_BFG, ITEM_WEAPON_SUPERPULEMET, ITEM_WEAPON_FLAMETHROWER] then
475 g_Sound_PlayExAt('SOUND_ITEM_GETWEAPON',
476 gPlayers[j].Obj.X, gPlayers[j].Obj.Y)
477 else
478 g_Sound_PlayExAt('SOUND_ITEM_GETITEM',
479 gPlayers[j].Obj.X, gPlayers[j].Obj.Y);
480 end;
482 // Íàäî óáðàòü ñ êàðòû, åñëè ýòî íå êëþ÷, êîòîðûì íóæíî ïîäåëèòüñÿ ñ äðóãèì èãðîêîì:
483 if r then
484 begin
485 if not Respawnable then
486 g_Items_Remove(i)
487 else
488 g_Items_Pick(i);
490 if g_Game_IsNet then MH_SEND_ItemDestroy(False, i);
491 nxt := True;
492 Break;
493 end;
494 end;
495 end;
496 end;
498 if nxt then
499 Continue;
500 end;
502 if Respawnable and g_Game_IsServer then
503 begin
504 DecMin(RespawnTime, 0);
505 if (RespawnTime = 0) and (not Live) then
506 begin
507 if not QuietRespawn then
508 g_Sound_PlayExAt('SOUND_ITEM_RESPAWNITEM', InitX, InitY);
510 if g_Frames_Get(ID, 'FRAMES_ITEM_RESPAWN') then
511 begin
512 Anim := TAnimation.Create(ID, False, 4);
513 g_GFX_OnceAnim(InitX+(Obj.Rect.Width div 2)-16, InitY+(Obj.Rect.Height div 2)-16, Anim);
514 Anim.Free();
515 end;
517 Obj.X := InitX;
518 Obj.Y := InitY;
519 Obj.Vel.X := 0;
520 Obj.Vel.Y := 0;
521 Obj.Accel.X := 0;
522 Obj.Accel.Y := 0;
524 Live := True;
526 if g_Game_IsNet then MH_SEND_ItemSpawn(QuietRespawn, i);
527 QuietRespawn := False;
528 end;
529 end;
531 if Animation <> nil then
532 Animation.Update();
533 end;
534 end;
536 procedure g_Items_Draw();
537 var
538 i: Integer;
539 begin
540 if gItems <> nil then
541 for i := 0 to High(gItems) do
542 if gItems[i].Live then
543 with gItems[i] do
544 if g_Collide(Obj.X, Obj.Y, Obj.Rect.Width, Obj.Rect.Height,
545 sX, sY, sWidth, sHeight) then
546 begin
547 if Animation = nil then
548 e_Draw(gItemsTexturesID[ItemType], Obj.X, Obj.Y, 0, True, False)
549 else
550 Animation.Draw(Obj.X, Obj.Y, M_NONE);
552 if g_debug_Frames then
553 begin
554 e_DrawQuad(Obj.X+Obj.Rect.X,
555 Obj.Y+Obj.Rect.Y,
556 Obj.X+Obj.Rect.X+Obj.Rect.Width-1,
557 Obj.Y+Obj.Rect.Y+Obj.Rect.Height-1,
558 0, 255, 0);
559 end;
560 end;
561 end;
563 procedure g_Items_Pick(ID: DWORD);
564 begin
565 gItems[ID].Live := False;
566 gItems[ID].RespawnTime := ITEM_RESPAWNTIME;
567 end;
569 procedure g_Items_Remove(ID: DWORD);
570 begin
571 gItems[ID].ItemType := ITEM_NONE;
573 if gItems[ID].Animation <> nil then
574 begin
575 gItems[ID].Animation.Free();
576 gItems[ID].Animation := nil;
577 end;
579 gItems[ID].Live := False;
581 if gItems[ID].SpawnTrigger > -1 then
582 begin
583 g_Triggers_DecreaseSpawner(gItems[ID].SpawnTrigger);
584 gItems[ID].SpawnTrigger := -1;
585 end;
586 end;
588 procedure g_Items_SaveState(var Mem: TBinMemoryWriter);
589 var
590 count, i: Integer;
591 sig: DWORD;
592 begin
593 // Ñ÷èòàåì êîëè÷åñòâî ñóùåñòâóþùèõ ïðåäìåòîâ:
594 count := 0;
595 if gItems <> nil then
596 for i := 0 to High(gItems) do
597 if gItems[i].ItemType <> ITEM_NONE then
598 count := count + 1;
600 Mem := TBinMemoryWriter.Create((count+1) * 60);
602 // Êîëè÷åñòâî ïðåäìåòîâ:
603 Mem.WriteInt(count);
605 if count = 0 then
606 Exit;
608 for i := 0 to High(gItems) do
609 if gItems[i].ItemType <> ITEM_NONE then
610 begin
611 // Ñèãíàòóðà ïðåäìåòà:
612 sig := ITEM_SIGNATURE; // 'ITEM'
613 Mem.WriteDWORD(sig);
614 // Òèï ïðåäìåòà:
615 Mem.WriteByte(gItems[i].ItemType);
616 // Åñòü ëè ðåñïàóí:
617 Mem.WriteBoolean(gItems[i].Respawnable);
618 // Êîîðäèíàòû ðåñïóíà:
619 Mem.WriteInt(gItems[i].InitX);
620 Mem.WriteInt(gItems[i].InitY);
621 // Âðåìÿ äî ðåñïàóíà:
622 Mem.WriteWord(gItems[i].RespawnTime);
623 // Ñóùåñòâóåò ëè ýòîò ïðåäìåò:
624 Mem.WriteBoolean(gItems[i].Live);
625 // Ìîæåò ëè îí ïàäàòü:
626 Mem.WriteBoolean(gItems[i].Fall);
627 // Èíäåêñ òðèããåðà, ñîçäàâøåãî ïðåäìåò:
628 Mem.WriteInt(gItems[i].SpawnTrigger);
629 // Îáúåêò ïðåäìåòà:
630 Obj_SaveState(@gItems[i].Obj, Mem);
631 end;
632 end;
634 procedure g_Items_LoadState(var Mem: TBinMemoryReader);
635 var
636 count, i, a: Integer;
637 sig: DWORD;
638 b: Byte;
639 begin
640 if Mem = nil then
641 Exit;
643 g_Items_Free();
645 // Êîëè÷åñòâî ïðåäìåòîâ:
646 Mem.ReadInt(count);
648 if count = 0 then
649 Exit;
651 for a := 0 to count-1 do
652 begin
653 // Ñèãíàòóðà ïðåäìåòà:
654 Mem.ReadDWORD(sig);
655 if sig <> ITEM_SIGNATURE then // 'ITEM'
656 begin
657 raise EBinSizeError.Create('g_Items_LoadState: Wrong Item Signature');
658 end;
659 // Òèï ïðåäìåòà:
660 Mem.ReadByte(b);
661 // Ñîçäàåì ïðåäìåò:
662 i := g_Items_Create(0, 0, b, False, False);
663 // Åñòü ëè ðåñïàóí:
664 Mem.ReadBoolean(gItems[i].Respawnable);
665 // Êîîðäèíàòû ðåñïóíà:
666 Mem.ReadInt(gItems[i].InitX);
667 Mem.ReadInt(gItems[i].InitY);
668 // Âðåìÿ äî ðåñïàóíà:
669 Mem.ReadWord(gItems[i].RespawnTime);
670 // Ñóùåñòâóåò ëè ýòîò ïðåäìåò:
671 Mem.ReadBoolean(gItems[i].Live);
672 // Ìîæåò ëè îí ïàäàòü:
673 Mem.ReadBoolean(gItems[i].Fall);
674 // Èíäåêñ òðèããåðà, ñîçäàâøåãî ïðåäìåò:
675 Mem.ReadInt(gItems[i].SpawnTrigger);
676 // Îáúåêò ïðåäìåòà:
677 Obj_LoadState(@gItems[i].Obj, Mem);
678 end;
679 end;
681 end.