X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_monsters.pas;h=f5f69a93d5eea3b621a153db5d821dd334c49545;hb=a9c0a618b01fb1e51cc953ff8295f888890cc967;hp=59b5506a5ee732d02bde51f54f49820dedc7a1c2;hpb=829537fc7b2b29baaab7287e54fba2cdd8d00b5c;p=d2df-sdl.git diff --git a/src/game/g_monsters.pas b/src/game/g_monsters.pas index 59b5506..f5f69a9 100644 --- a/src/game/g_monsters.pas +++ b/src/game/g_monsters.pas @@ -93,6 +93,7 @@ type public FNoRespawn: Boolean; FFireTime: Integer; + trapCheckFrameId: DWord; // for `g_weapons.CheckTrap()` constructor Create(MonsterType: Byte; aID: Integer; ForcedUID: Integer = -1); destructor Destroy(); override; @@ -160,22 +161,23 @@ type property StartID: Integer read FStartID; end; -procedure g_Monsters_LoadData(); -procedure g_Monsters_FreeData(); -procedure g_Monsters_Init(); -procedure g_Monsters_Free(); -function g_Monsters_Create(MonsterType: Byte; X, Y: Integer; - Direction: TDirection; AdjCoord: Boolean = False; ForcedUID: Integer = -1): TMonster; -procedure g_Monsters_Update(); -procedure g_Monsters_Draw(); -procedure g_Monsters_DrawHealth(); -function g_Monsters_Get(UID: Word): TMonster; -procedure g_Monsters_killedp(); -procedure g_Monsters_SaveState(var Mem: TBinMemoryWriter); -procedure g_Monsters_LoadState(var Mem: TBinMemoryReader); -function g_Monsters_GetIDByName(name: String): Integer; -function g_Monsters_GetNameByID(MonsterType: Byte): String; -function g_Monsters_GetKilledBy(MonsterType: Byte): String; + +procedure g_Monsters_LoadData (); +procedure g_Monsters_FreeData (); +procedure g_Monsters_Init (); +procedure g_Monsters_Free (); +function g_Monsters_Create (MonsterType: Byte; X, Y: Integer; Direction: TDirection; + AdjCoord: Boolean = False; ForcedUID: Integer = -1): TMonster; +procedure g_Monsters_Update (); +procedure g_Monsters_Draw (); +procedure g_Monsters_DrawHealth (); +function g_Monsters_ByUID (UID: Word): TMonster; +procedure g_Monsters_killedp (); +procedure g_Monsters_SaveState (var Mem: TBinMemoryWriter); +procedure g_Monsters_LoadState (var Mem: TBinMemoryReader); +function g_Monsters_GetIDByName (name: String): Integer; +function g_Monsters_GetNameByID (MonsterType: Byte): String; +function g_Monsters_GetKilledBy (MonsterType: Byte): String; type @@ -194,6 +196,8 @@ function g_Mons_IsAnyAliveAt (x, y: Integer; width, height: Integer): Boolean; function g_Mons_ForEachAt (x, y: Integer; width, height: Integer; cb: TEachMonsterCB): Boolean; function g_Mons_ForEachAtAlive (x, y: Integer; width, height: Integer; cb: TEachMonsterCB): Boolean; +function g_Mons_getNewTrapFrameId (): DWord; + var gmon_debug_use_sqaccel: Boolean = true; @@ -208,6 +212,11 @@ uses g_language, g_netmsg, z_aabbtree; +// ////////////////////////////////////////////////////////////////////////// // +var + monCheckTrapLastFrameId: DWord; + + // ////////////////////////////////////////////////////////////////////////// // type TDynAABBTreeMonsBase = specialize TDynAABBTreeBase; @@ -472,6 +481,34 @@ const var gMonsters: array of TMonster; + uidMap: array [0..65535] of TMonster; // monster knows it's index + + +procedure clearUidMap (); +var + idx: Integer; +begin + for idx := 0 to High(uidMap) do uidMap[idx] := nil; +end; + + +function g_Mons_getNewTrapFrameId (): DWord; +var + f: Integer; +begin + Inc(monCheckTrapLastFrameId); + if monCheckTrapLastFrameId = 0 then + begin + // wraparound + monCheckTrapLastFrameId := 1; + for f := 0 to High(gMonsters) do + begin + if (gMonsters[f] <> nil) then gMonsters[f].trapCheckFrameId := 0; + end; + end; + result := monCheckTrapLastFrameId; +end; + var pt_x: Integer = 0; @@ -546,7 +583,7 @@ begin UIDType := g_GetUIDType(SpawnerUID); if UIDType = UID_MONSTER then begin - m := g_Monsters_Get(SpawnerUID); + m := g_Monsters_ByUID(SpawnerUID); if m = nil then Exit; MonsterType := m.FMonsterType; end; @@ -866,6 +903,8 @@ begin g_Sound_CreateWADEx('SOUND_MONSTER_FISH_ATTACK', GameWAD+':MSOUNDS\FISH_ATTACK'); monsTree := TDynAABBTreeMons.Create(); + clearUidMap(); + monCheckTrapLastFrameId := 0; end; procedure g_Monsters_FreeData(); @@ -1095,12 +1134,11 @@ procedure g_Monsters_Free(); var a: Integer; begin - if gMonsters <> nil then - for a := 0 to High(gMonsters) do - gMonsters[a].Free(); - monsTree.reset(); + for a := 0 to High(gMonsters) do gMonsters[a].Free(); gMonsters := nil; + clearUidMap(); + monCheckTrapLastFrameId := 0; end; function g_Monsters_Create(MonsterType: Byte; X, Y: Integer; @@ -1128,6 +1166,8 @@ begin mon.arrIdx := find_id; mon.treeNode := -1; + uidMap[mon.FUID] := mon; + // Íàñòðàèâàåì ïîëîæåíèå with mon do begin @@ -1179,34 +1219,33 @@ procedure g_Monsters_Update(); var a: Integer; begin -// Öåëåóêàçàòåëü: + // Öåëåóêàçàòåëü if gTime mod (GAME_TICK*2) = 0 then begin pt_x := pt_x+pt_xs; pt_y := pt_y+pt_ys; - if Abs(pt_x) > 246 then - pt_xs := -pt_xs; - if Abs(pt_y) > 100 then - pt_ys := -pt_ys; + if abs(pt_x) > 246 then pt_xs := -pt_xs; + if abs(pt_y) > 100 then pt_ys := -pt_ys; end; gMon := True; // Äëÿ ðàáîòû BlockMon'à - if gMonsters <> nil then - for a := 0 to High(gMonsters) do - if (gMonsters[a] <> nil) then - if not gMonsters[a].FRemoved then - begin - if g_Game_IsClient then - gMonsters[a].ClientUpdate() - else - gMonsters[a].Update(); - end - else - begin - gMonsters[a].Free(); - gMonsters[a] := nil; - end; + for a := 0 to High(gMonsters) do + begin + if (gMonsters[a] = nil) then continue; + if not gMonsters[a].FRemoved then + begin + if g_Game_IsClient then + gMonsters[a].ClientUpdate() + else + gMonsters[a].Update(); + end + else + begin + gMonsters[a].Free(); + gMonsters[a] := nil; + end; + end; gMon := False; end; @@ -1238,12 +1277,12 @@ begin end; end; -function g_Monsters_Get(UID: Word): TMonster; -var - a: Integer; +function g_Monsters_ByUID (UID: Word): TMonster; +//var a: Integer; begin + result := uidMap[UID]; + { Result := nil; - if gMonsters <> nil then for a := 0 to High(gMonsters) do if (gMonsters[a] <> nil) and @@ -1252,6 +1291,7 @@ begin Result := gMonsters[a]; Break; end; + } end; procedure g_Monsters_SaveState(var Mem: TBinMemoryWriter); @@ -1613,6 +1653,7 @@ begin treeNode := -1; arrIdx := -1; + trapCheckFrameId := 0; if FMonsterType in [MONSTER_ROBO, MONSTER_BARREL] then FBloodKind := BLOOD_SPARKS @@ -1763,8 +1804,7 @@ begin end; // Òåïåðü öåëü - óäàðèâøèé, åñëè òîëüêî íå ñàì ñåáÿ: - if (SpawnerUID <> FUID) and - (BehaviourDamage(SpawnerUID, FBehaviour, FMonsterType)) then + if (SpawnerUID <> FUID) and (BehaviourDamage(SpawnerUID, FBehaviour, FMonsterType)) then begin FTargetUID := SpawnerUID; FTargetTime := 0; @@ -1870,8 +1910,7 @@ begin if FHealth < FMaxHealth then begin IncMax(FHealth, Value, FMaxHealth); - if g_Game_IsServer and g_Game_IsNet then - MH_SEND_MonsterState(FUID); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_MonsterState(FUID); Result := True; end; end; @@ -1890,12 +1929,22 @@ begin if (treeNode <> -1) then begin - {$IF DEFINED(D2F_DEBUG)} - e_WriteLog(Format('monster #%d(%u): removed from tree; nodeid=%d', [arrIdx, UID, treeNode]), MSG_NOTIFY); - {$ENDIF} - monsTree.removeObject(treeNode); + if monsTree.isValidId(treeNode) then + begin + {$IF DEFINED(D2F_DEBUG)} + e_WriteLog(Format('monster #%d(%u): removed from tree; nodeid=%d', [arrIdx, UID, treeNode]), MSG_NOTIFY); + {$ENDIF} + monsTree.removeObject(treeNode); + end; end; + if (arrIdx <> -1) then + begin + gMonsters[arrIdx] := nil; + end; + + uidMap[FUID] := nil; + inherited Destroy(); end; @@ -2000,8 +2049,7 @@ procedure TMonster.Push(vx, vy: Integer); begin FObj.Accel.X := FObj.Accel.X + vx; FObj.Accel.Y := FObj.Accel.Y + vy; - if g_Game_IsServer and g_Game_IsNet then - MH_SEND_MonsterPos(FUID); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_MonsterPos(FUID); end; procedure TMonster.SetState(State: Byte; ForceAnim: Byte = 255); @@ -2125,8 +2173,7 @@ begin NET_GFX_TELE); end; - if g_Game_IsServer and g_Game_IsNet then - MH_SEND_MonsterPos(FUID); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_MonsterPos(FUID); Result := True; end; @@ -4344,8 +4391,7 @@ procedure TMonster.CatchFire(Attacker: Word); begin FFireTime := 100; FFireAttacker := Attacker; - if g_Game_IsNet and g_Game_IsServer then - MH_SEND_MonsterState(FUID); + if g_Game_IsNet and g_Game_IsServer then MH_SEND_MonsterState(FUID); end; procedure TMonster.OnFireFlame(Times: DWORD = 1);