X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_weapons.pas;h=5505731729eb497613804cd78aa72d00886d96c8;hb=281969a1bea9afbf36babebcf9208549929a96f4;hp=5ba00a7ad526f3a3e025954efc7dbd20510eefa1;hpb=2e74c901511298e44d168948d85e9cff009fcb7e;p=d2df-sdl.git diff --git a/src/game/g_weapons.pas b/src/game/g_weapons.pas index 5ba00a7..5505731 100644 --- a/src/game/g_weapons.pas +++ b/src/game/g_weapons.pas @@ -1,4 +1,4 @@ -(* Copyright (C) DooM 2D:Forever Developers +(* Copyright (C) Doom 2D: Forever Developers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,22 +20,9 @@ unit g_weapons; interface uses - g_textures, g_basic, e_graphics, g_phys, BinEditor, xprofiler; + SysUtils, Classes, mempool, + g_textures, g_basic, e_graphics, g_phys, xprofiler; -{ -const - HIT_SOME = 0; - HIT_ROCKET = 1; - HIT_BFG = 2; - HIT_TRAP = 3; - HIT_FALL = 4; - HIT_WATER = 5; - HIT_ACID = 6; - HIT_ELECTRO = 7; - HIT_FLAME = 8; - HIT_SELF = 9; - HIT_DISCON = 10; -} type TShot = record @@ -91,8 +78,8 @@ procedure g_Weapon_Draw(); function g_Weapon_Danger(UID: Word; X, Y: Integer; Width, Height: Word; Time: Byte): Boolean; procedure g_Weapon_DestroyShot(I: Integer; X, Y: Integer; Loud: Boolean = True); -procedure g_Weapon_SaveState(var Mem: TBinMemoryWriter); -procedure g_Weapon_LoadState(var Mem: TBinMemoryReader); +procedure g_Weapon_SaveState (st: TStream); +procedure g_Weapon_LoadState (st: TStream); procedure g_Weapon_AddDynLights(); @@ -128,10 +115,10 @@ implementation uses Math, g_map, g_player, g_gfx, g_sound, g_main, g_panel, - g_console, SysUtils, g_options, g_game, + g_console, g_options, g_game, g_triggers, MAPDEF, e_log, g_monsters, g_saveload, g_language, g_netmsg, g_grid, - binheap, hashtable; + geom, binheap, hashtable, utils, xstreams; type TWaterPanel = record @@ -170,8 +157,13 @@ type x, y: Integer; end; + TBinHeapKeyHitTime = class + public + class function less (const a, b: Integer): Boolean; inline; + end; + // indicies in `wgunHitTime` array - TBinaryHeapHitTimes = specialize TBinaryHeapBase; + TBinaryHeapHitTimes = specialize TBinaryHeapBase; var WaterMap: array of array of DWORD = nil; @@ -181,7 +173,7 @@ var wgunHitTimeUsed: Integer = 0; -function hitTimeLess (a, b: Integer): Boolean; +class function TBinHeapKeyHitTime.less (const a, b: Integer): Boolean; var hta, htb: PHitTime; begin @@ -1107,7 +1099,7 @@ end; procedure g_Weapon_LoadData(); begin - e_WriteLog('Loading weapons data...', MSG_NOTIFY); + e_WriteLog('Loading weapons data...', TMsgType.Notify); g_Sound_CreateWADEx('SOUND_WEAPON_HITPUNCH', GameWAD+':SOUNDS\HITPUNCH'); g_Sound_CreateWADEx('SOUND_WEAPON_MISSPUNCH', GameWAD+':SOUNDS\MISSPUNCH'); @@ -1134,6 +1126,9 @@ begin g_Sound_CreateWADEx('SOUND_WEAPON_FIREBALL', GameWAD+':SOUNDS\FIREBALL'); g_Sound_CreateWADEx('SOUND_WEAPON_EXPLODEBALL', GameWAD+':SOUNDS\EXPLODEBALL'); g_Sound_CreateWADEx('SOUND_WEAPON_FIREREV', GameWAD+':SOUNDS\FIREREV'); + g_Sound_CreateWADEx('SOUND_WEAPON_FLAMEON', GameWAD+':SOUNDS\STARTFLM'); + g_Sound_CreateWADEx('SOUND_WEAPON_FLAMEOFF', GameWAD+':SOUNDS\STOPFLM'); + g_Sound_CreateWADEx('SOUND_WEAPON_FLAMEWORK', GameWAD+':SOUNDS\WORKFLM'); g_Sound_CreateWADEx('SOUND_PLAYER_JETFLY', GameWAD+':SOUNDS\WORKJETPACK'); g_Sound_CreateWADEx('SOUND_PLAYER_JETON', GameWAD+':SOUNDS\STARTJETPACK'); g_Sound_CreateWADEx('SOUND_PLAYER_JETOFF', GameWAD+':SOUNDS\STOPJETPACK'); @@ -1168,12 +1163,12 @@ begin g_Texture_CreateWADEx('TEXTURE_SHELL_SHELL', GameWAD+':TEXTURES\ESHELL'); //wgunMonHash := hashNewIntInt(); - wgunHitHeap := TBinaryHeapHitTimes.Create(hitTimeLess); + wgunHitHeap := TBinaryHeapHitTimes.Create(); end; procedure g_Weapon_FreeData(); begin - e_WriteLog('Releasing weapons data...', MSG_NOTIFY); + e_WriteLog('Releasing weapons data...', TMsgType.Notify); g_Sound_Delete('SOUND_WEAPON_HITPUNCH'); g_Sound_Delete('SOUND_WEAPON_MISSPUNCH'); @@ -1200,6 +1195,9 @@ begin g_Sound_Delete('SOUND_WEAPON_FIREBALL'); g_Sound_Delete('SOUND_WEAPON_EXPLODEBALL'); g_Sound_Delete('SOUND_WEAPON_FIREREV'); + g_Sound_Delete('SOUND_WEAPON_FLAMEON'); + g_Sound_Delete('SOUND_WEAPON_FLAMEOFF'); + g_Sound_Delete('SOUND_WEAPON_FLAMEWORK'); g_Sound_Delete('SOUND_PLAYER_JETFLY'); g_Sound_Delete('SOUND_PLAYER_JETON'); g_Sound_Delete('SOUND_PLAYER_JETOFF'); @@ -1321,7 +1319,7 @@ begin //vy := (dy*10 div d)*yi; {$IF DEFINED(D2F_DEBUG)} - stt := curTimeMicro(); + stt := getTimeMicro(); {$ENDIF} xx := x; @@ -1352,7 +1350,7 @@ begin begin _collide := True; {$IF DEFINED(D2F_DEBUG)} - stt := curTimeMicro()-stt; + stt := getTimeMicro()-stt; e_WriteLog(Format('*** old trace time: %u microseconds', [LongWord(stt)]), MSG_NOTIFY); showTime := false; {$ENDIF} @@ -1372,7 +1370,7 @@ begin {$IF DEFINED(D2F_DEBUG)} if showTime then begin - stt := curTimeMicro()-stt; + stt := getTimeMicro()-stt; e_WriteLog(Format('*** old trace time: %u microseconds', [LongWord(stt)]), MSG_NOTIFY); end; {$ENDIF} @@ -1448,13 +1446,12 @@ var end; end; - function sqchecker (mon: TMonster; tag: Integer): Boolean; + procedure sqchecker (mon: TMonster); var mx, my, mw, mh: Integer; inx, iny: Integer; distSq: Integer; begin - result := false; // don't stop mon.getMapBox(mx, my, mw, mh); if lineAABBIntersects(x0, y0, x2, y2, mx, my, mw, mh, inx, iny) then begin @@ -1476,6 +1473,8 @@ var {$IF DEFINED(D2F_DEBUG)} stt: UInt64; {$ENDIF} + mit: PMonster; + it: TMonsterGrid.Iter; begin (* if not gwep_debug_fast_trace then @@ -1510,8 +1509,8 @@ begin if (dy > 0) then yi := 1 else if (dy < 0) then yi := -1 else yi := 0; {$IF DEFINED(D2F_DEBUG)} - e_WriteLog(Format('GUN TRACE: (%d,%d) to (%d,%d)', [x, y, x2, y2]), MSG_NOTIFY); - stt := curTimeMicro(); + e_WriteLog(Format('GUN TRACE: (%d,%d) to (%d,%d)', [x, y, x2, y2]), TMsgType.Notify); + stt := getTimeMicro(); {$ENDIF} wallHitFlag := (g_Map_traceToNearestWall(x, y, x2, y2, @wallHitX, @wallHitY) <> nil); @@ -1530,7 +1529,11 @@ begin if playerPossibleHit() then exit; // instant hit // collect monsters - g_Mons_AlongLine(x, y, x2, y2, sqchecker); + //g_Mons_AlongLine(x, y, x2, y2, sqchecker); + + it := monsGrid.forEachAlongLine(x, y, x2, y2, -1); + for mit in it do sqchecker(mit^); + it.release(); // here, we collected all monsters and players in `wgunHitHeap` and `wgunHitTime` // also, if `wallWasHit` is `true`, then `wallHitX` and `wallHitY` contains spark coords @@ -1565,8 +1568,8 @@ begin if wallHitFlag then begin {$IF DEFINED(D2F_DEBUG)} - stt := curTimeMicro()-stt; - e_WriteLog(Format('*** new trace time: %u microseconds', [LongWord(stt)]), MSG_NOTIFY); + stt := getTimeMicro()-stt; + e_WriteLog(Format('*** new trace time: %u microseconds', [LongWord(stt)]), TMsgType.Notify); {$ENDIF} g_GFX_Spark(wallHitX, wallHitY, 2+Random(2), 180+a, 0, 0); if g_Game_IsServer and g_Game_IsNet then MH_SEND_Effect(wallHitX, wallHitY, 180+a, NET_GFX_SPARK); @@ -1574,8 +1577,8 @@ begin else begin {$IF DEFINED(D2F_DEBUG)} - stt := curTimeMicro()-stt; - e_WriteLog(Format('*** new trace time: %u microseconds', [LongWord(stt)]), MSG_NOTIFY); + stt := getTimeMicro()-stt; + e_WriteLog(Format('*** new trace time: %u microseconds', [LongWord(stt)]), TMsgType.Notify); {$ENDIF} end; @@ -2154,7 +2157,7 @@ begin if Stopped = 0 then begin - st := g_Obj_Move(@Obj, False, spl); + st := g_Obj_Move_Projectile(@Obj, False, spl); end else begin @@ -2524,14 +2527,14 @@ begin if (Shots[i].ShotType = WEAPON_BARON_FIRE) or (Shots[i].ShotType = WEAPON_MANCUB_FIRE) or (Shots[i].ShotType = WEAPON_SKEL_FIRE) then - Animation.DrawEx(Obj.X, Obj.Y, M_NONE, p, a) + Animation.DrawEx(Obj.X, Obj.Y, TMirrorType.None, p, a) else - Animation.Draw(Obj.X, Obj.Y, M_NONE); + Animation.Draw(Obj.X, Obj.Y, TMirrorType.None); end else if TextureID <> 0 then begin if (Shots[i].ShotType = WEAPON_ROCKETLAUNCHER) then - e_DrawAdv(TextureID, Obj.X, Obj.Y, 0, True, False, a, @p, M_NONE) + e_DrawAdv(TextureID, Obj.X, Obj.Y, 0, True, False, a, @p, TMirrorType.None) else if (Shots[i].ShotType <> WEAPON_FLAMETHROWER) then e_Draw(TextureID, Obj.X, Obj.Y, 0, True, False); end; @@ -2570,93 +2573,82 @@ begin end; end; -procedure g_Weapon_SaveState(var Mem: TBinMemoryWriter); +procedure g_Weapon_SaveState (st: TStream); var count, i, j: Integer; - dw: DWORD; begin -// Ñ÷èòàåì êîëè÷åñòâî ñóùåñòâóþùèõ ñíàðÿäîâ: + // Ñ÷èòàåì êîëè÷åñòâî ñóùåñòâóþùèõ ñíàðÿäîâ count := 0; - if Shots <> nil then - for i := 0 to High(Shots) do - if Shots[i].ShotType <> 0 then - count := count + 1; + for i := 0 to High(Shots) do if (Shots[i].ShotType <> 0) then Inc(count); - Mem := TBinMemoryWriter.Create((count+1) * 80); + // Êîëè÷åñòâî ñíàðÿäîâ + utils.WriteInt(st, count); -// Êîëè÷åñòâî ñíàðÿäîâ: - Mem.WriteInt(count); - - if count = 0 then - Exit; + if (count = 0) then exit; for i := 0 to High(Shots) do + begin if Shots[i].ShotType <> 0 then begin - // Ñèãíàòóðà ñíàðÿäà: - dw := SHOT_SIGNATURE; // 'SHOT' - Mem.WriteDWORD(dw); - // Òèï ñíàðÿäà: - Mem.WriteByte(Shots[i].ShotType); - // Öåëü: - Mem.WriteWord(Shots[i].Target); - // UID ñòðåëÿâøåãî: - Mem.WriteWord(Shots[i].SpawnerUID); - // Ðàçìåð ïîëÿ Triggers: - dw := Length(Shots[i].Triggers); - Mem.WriteDWORD(dw); - // Òðèããåðû, àêòèâèðîâàííûå âûñòðåëîì: - for j := 0 to Integer(dw)-1 do - Mem.WriteDWORD(Shots[i].Triggers[j]); - // Îáúåêò ñíàðÿäà: - Obj_SaveState(@Shots[i].Obj, Mem); - // Êîñòûëèíà åáàíàÿ: - Mem.WriteByte(Shots[i].Stopped); + // Ñèãíàòóðà ñíàðÿäà + utils.writeSign(st, 'SHOT'); + utils.writeInt(st, Byte(0)); // version + // Òèï ñíàðÿäà + utils.writeInt(st, Byte(Shots[i].ShotType)); + // Öåëü + utils.writeInt(st, Word(Shots[i].Target)); + // UID ñòðåëÿâøåãî + utils.writeInt(st, Word(Shots[i].SpawnerUID)); + // Ðàçìåð ïîëÿ Triggers + utils.writeInt(st, Integer(Length(Shots[i].Triggers))); + // Òðèããåðû, àêòèâèðîâàííûå âûñòðåëîì + for j := 0 to Length(Shots[i].Triggers)-1 do utils.writeInt(st, LongWord(Shots[i].Triggers[j])); + // Îáúåêò ñíàðÿäà + Obj_SaveState(st, @Shots[i].Obj); + // Êîñòûëèíà åáàíàÿ + utils.writeInt(st, Byte(Shots[i].Stopped)); end; + end; end; -procedure g_Weapon_LoadState(var Mem: TBinMemoryReader); +procedure g_Weapon_LoadState (st: TStream); var - count, i, j: Integer; - dw: DWORD; + count, tc, i, j: Integer; + dw: LongWord; begin - if Mem = nil then - Exit; + if (st = nil) then exit; -// Êîëè÷åñòâî ñíàðÿäîâ: - Mem.ReadInt(count); + // Êîëè÷åñòâî ñíàðÿäîâ + count := utils.readLongInt(st); + if (count < 0) or (count > 1024*1024) then raise XStreamError.Create('invalid shots counter'); SetLength(Shots, count); - if count = 0 then - Exit; + if (count = 0) then exit; for i := 0 to count-1 do begin - // Ñèãíàòóðà ñíàðÿäà: - Mem.ReadDWORD(dw); - if dw <> SHOT_SIGNATURE then // 'SHOT' - begin - raise EBinSizeError.Create('g_Weapons_LoadState: Wrong Shot Signature'); - end; - // Òèï ñíàðÿäà: - Mem.ReadByte(Shots[i].ShotType); - // Öåëü: - Mem.ReadWord(Shots[i].Target); - // UID ñòðåëÿâøåãî: - Mem.ReadWord(Shots[i].SpawnerUID); - // Ðàçìåð ïîëÿ Triggers: - Mem.ReadDWORD(dw); - SetLength(Shots[i].Triggers, dw); - // Òðèããåðû, àêòèâèðîâàííûå âûñòðåëîì: - for j := 0 to Integer(dw)-1 do - Mem.ReadDWORD(Shots[i].Triggers[j]); - // Îáúåêò ïðåäìåòà: - Obj_LoadState(@Shots[i].Obj, Mem); - // Êîñòûëèíà åáàíàÿ: - Mem.ReadByte(Shots[i].Stopped); - - // Óñòàíîâêà òåêñòóðû èëè àíèìàöèè: + // Ñèãíàòóðà ñíàðÿäà + if not utils.checkSign(st, 'SHOT') then raise XStreamError.Create('invalid shot signature'); + if (utils.readByte(st) <> 0) then raise XStreamError.Create('invalid shot version'); + // Òèï ñíàðÿäà: + Shots[i].ShotType := utils.readByte(st); + // Öåëü + Shots[i].Target := utils.readWord(st); + // UID ñòðåëÿâøåãî + Shots[i].SpawnerUID := utils.readWord(st); + // Ðàçìåð ïîëÿ Triggers + tc := utils.readLongInt(st); + if (tc < 0) or (tc > 1024*1024) then raise XStreamError.Create('invalid shot triggers counter'); + SetLength(Shots[i].Triggers, tc); + // Òðèããåðû, àêòèâèðîâàííûå âûñòðåëîì + for j := 0 to tc-1 do Shots[i].Triggers[j] := utils.readLongWord(st); + // Îáúåêò ïðåäìåòà + Obj_LoadState(@Shots[i].Obj, st); + // Êîñòûëèíà åáàíàÿ + Shots[i].Stopped := utils.readByte(st); + + // Óñòàíîâêà òåêñòóðû èëè àíèìàöèè Shots[i].TextureID := DWORD(-1); Shots[i].Animation := nil;