From: Ketmar Dark Date: Sun, 20 Aug 2017 04:54:57 +0000 (+0300) Subject: uidmap for monsters, so we don't have to do linear searches X-Git-Url: http://deadsoftware.ru/gitweb?p=d2df-sdl.git;a=commitdiff_plain;h=1b0f87b9a64f04be222df8d8d2de059cb139c98d uidmap for monsters, so we don't have to do linear searches --- diff --git a/src/game/g_basic.pas b/src/game/g_basic.pas index 626596b..98cebcc 100644 --- a/src/game/g_basic.pas +++ b/src/game/g_basic.pas @@ -226,7 +226,7 @@ begin while true do begin result := UID_MAX_PLAYER+$1+Random(UID_MAX_MONSTER-UID_MAX_GAME-UID_MAX_PLAYER+$1); - if (g_Monsters_Get(result) = nil) then break; + if (g_Monsters_ByUID(result) = nil) then break; end; end; end; @@ -947,7 +947,7 @@ begin UID_MONSTER: begin - m := g_Monsters_Get(UID); + m := g_Monsters_ByUID(UID); if m = nil then Exit; if not m.Live then Exit; diff --git a/src/game/g_monsters.pas b/src/game/g_monsters.pas index 59b5506..4a20c48 100644 --- a/src/game/g_monsters.pas +++ b/src/game/g_monsters.pas @@ -160,22 +160,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 @@ -472,6 +473,16 @@ 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; + var pt_x: Integer = 0; @@ -546,7 +557,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 +877,7 @@ begin g_Sound_CreateWADEx('SOUND_MONSTER_FISH_ATTACK', GameWAD+':MSOUNDS\FISH_ATTACK'); monsTree := TDynAABBTreeMons.Create(); + clearUidMap(); end; procedure g_Monsters_FreeData(); @@ -1095,12 +1107,10 @@ procedure g_Monsters_Free(); var a: Integer; begin - if gMonsters <> nil then - for a := 0 to High(gMonsters) do - gMonsters[a].Free(); - + for a := 0 to High(gMonsters) do gMonsters[a].Free(); monsTree.reset(); gMonsters := nil; + clearUidMap(); end; function g_Monsters_Create(MonsterType: Byte; X, Y: Integer; @@ -1128,6 +1138,8 @@ begin mon.arrIdx := find_id; mon.treeNode := -1; + uidMap[mon.FUID] := mon; + // Íàñòðàèâàåì ïîëîæåíèå with mon do begin @@ -1179,34 +1191,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 +1249,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 +1263,7 @@ begin Result := gMonsters[a]; Break; end; + } end; procedure g_Monsters_SaveState(var Mem: TBinMemoryWriter); @@ -1763,8 +1775,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 +1881,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; @@ -1896,6 +1906,13 @@ begin monsTree.removeObject(treeNode); end; + if (arrIdx <> -1) then + begin + gMonsters[arrIdx] := nil; + end; + + uidMap[FUID] := nil; + inherited Destroy(); end; @@ -2000,8 +2017,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 +2141,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 +4359,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); diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas index 9432628..213669e 100644 --- a/src/game/g_netmsg.pas +++ b/src/game/g_netmsg.pas @@ -1321,7 +1321,7 @@ procedure MH_SEND_MonsterSpawn(UID: Word; ID: Integer = NET_EVERYONE); var M: TMonster; begin - M := g_Monsters_Get(UID); + M := g_Monsters_ByUID(UID); if M = nil then Exit; @@ -1352,7 +1352,7 @@ procedure MH_SEND_MonsterPos(UID: Word; ID: Integer = NET_EVERYONE); var M: TMonster; begin - M := g_Monsters_Get(UID); + M := g_Monsters_ByUID(UID); if M = nil then Exit; NetOut.Write(Byte(NET_MSG_MPOS)); @@ -1374,7 +1374,7 @@ procedure MH_SEND_MonsterState(UID: Word; ForcedAnim: Byte = 255; ID: Integer = var M: TMonster; begin - M := g_Monsters_Get(UID); + M := g_Monsters_ByUID(UID); if M = nil then Exit; NetOut.Write(Byte(NET_MSG_MSTATE)); @@ -1413,7 +1413,7 @@ procedure MH_SEND_MonsterDelete(UID: Word; ID: Integer = NET_EVERYONE); var M: TMonster; begin - M := g_Monsters_Get(UID); + M := g_Monsters_ByUID(UID); if M = nil then Exit; NetOut.Write(Byte(NET_MSG_MDEL)); @@ -2566,7 +2566,7 @@ var Mon: TMonster; begin ID := M.ReadWord(); - Mon := g_Monsters_Get(ID); + Mon := g_Monsters_ByUID(ID); if Mon <> nil then Exit; @@ -2587,7 +2587,7 @@ begin MDir := M.ReadByte(); g_Monsters_Create(MType, X, Y, TDirection(MDir), False, ID); - Mon := g_Monsters_Get(ID); + Mon := g_Monsters_ByUID(ID); if Mon = nil then Exit; @@ -2618,7 +2618,7 @@ var ID: Word; begin ID := M.ReadWord(); - Mon := g_Monsters_Get(ID); + Mon := g_Monsters_ByUID(ID); if Mon = nil then Exit; @@ -2641,7 +2641,7 @@ var AnimRevert: Boolean; begin ID := M.ReadWord(); - Mon := g_Monsters_Get(ID); + Mon := g_Monsters_ByUID(ID); if Mon = nil then Exit; MState := M.ReadByte(); @@ -2685,7 +2685,7 @@ var begin ID := M.ReadWord(); - Mon := g_Monsters_Get(ID); + Mon := g_Monsters_ByUID(ID); if Mon = nil then Exit; X := M.ReadLongInt(); @@ -2702,7 +2702,7 @@ var Mon: TMonster; begin ID := M.ReadWord(); - Mon := g_Monsters_Get(ID); + Mon := g_Monsters_ByUID(ID); if Mon = nil then Exit; Mon.SetState(5); Mon.MonsterRemoved := True; diff --git a/src/game/g_player.pas b/src/game/g_player.pas index c1b7c08..612a4fb 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -3121,7 +3121,7 @@ begin end else if g_GetUIDType(SpawnerUID) = UID_MONSTER then begin // Óáèò ìîíñòðîì - mon := g_Monsters_Get(SpawnerUID); + mon := g_Monsters_ByUID(SpawnerUID); if mon = nil then s := '?' else @@ -6393,7 +6393,7 @@ begin if (g_GetUIDType(Target.UID) = UID_MONSTER) and vsMonster then begin // Ìîíñòð - mon := g_Monsters_Get(Target.UID); + mon := g_Monsters_ByUID(Target.UID); if mon <> nil then begin Target.X := mon.Obj.X; @@ -6626,7 +6626,7 @@ begin end else begin // Öåëü - ìîíñòð - mon := g_Monsters_Get(Target.UID); + mon := g_Monsters_ByUID(Target.UID); if (mon = nil) or (not mon.Live) then Target.UID := 0; // òî çàáûòü öåëü end; @@ -7378,7 +7378,7 @@ begin if (g_GetUIDType(FLastSpawnerUID) = UID_MONSTER) and LongBool(gGameSettings.Options and GAME_OPTION_BOTVSMONSTER) then begin // Ìîíñòð - mon := g_Monsters_Get(FLastSpawnerUID); + mon := g_Monsters_ByUID(FLastSpawnerUID); ok := not TargetOnScreen(mon.Obj.X + mon.Obj.Rect.X, mon.Obj.Y + mon.Obj.Rect.Y); end; diff --git a/src/game/g_triggers.pas b/src/game/g_triggers.pas index 4fefb5d..29ea42e 100644 --- a/src/game/g_triggers.pas +++ b/src/game/g_triggers.pas @@ -755,7 +755,7 @@ begin UID_MONSTER: begin - m := g_Monsters_Get(ActivateUID); + m := g_Monsters_ByUID(ActivateUID); if m = nil then Exit; @@ -801,7 +801,7 @@ begin UID_MONSTER: begin - m := g_Monsters_Get(ActivateUID); + m := g_Monsters_ByUID(ActivateUID); if m = nil then Exit; @@ -1880,7 +1880,7 @@ begin UID_MONSTER: begin - m := g_Monsters_Get(ActivateUID); + m := g_Monsters_ByUID(ActivateUID); if m = nil then Exit; diff --git a/src/game/g_weapons.pas b/src/game/g_weapons.pas index f8028ee..f3accc6 100644 --- a/src/game/g_weapons.pas +++ b/src/game/g_weapons.pas @@ -244,11 +244,11 @@ begin end; procedure CheckTrap(ID: DWORD; dm: Integer; t: Byte); - var a, b, c, d, i1, i2: Integer; pl, mn: WArray; + { function monsWaterCheck (monidx: Integer; mon: TMonster): Boolean; begin result := false; // don't stop @@ -258,6 +258,17 @@ var mn[i2] := monidx; end; end; + } + + function monsWaterCheck (monidx: Integer; mon: TMonster): Boolean; + begin + result := false; // don't stop + if (not InWArray(monidx, mn)) and (i2 < 1023) then //FIXME + begin + i2 += 1; + mn[i2] := monidx; + end; + end; begin if (gWater = nil) or (WaterMap = nil) then Exit; @@ -292,16 +303,22 @@ begin end; end; - g_Mons_ForEach(monsWaterCheck); + //g_Mons_ForEach(monsWaterCheck); + g_Mons_ForEachAtAlive( + gWater[WaterMap[a][c]].X, gWater[WaterMap[a][c]].Y, + gWater[WaterMap[a][c]].Width, gWater[WaterMap[a][c]].Height, + monsWaterCheck); end; if i1 <> -1 then - for d := 0 to i1 do - gPlayers[pl[d]].Damage(dm, Shots[ID].SpawnerUID, 0, 0, t); + begin + for d := 0 to i1 do gPlayers[pl[d]].Damage(dm, Shots[ID].SpawnerUID, 0, 0, t); + end; if i2 <> -1 then - for d := 0 to i2 do - g_Mons_ByIdx(mn[d]).Damage(dm, 0, 0, Shots[ID].SpawnerUID, t); + begin + for d := 0 to i2 do g_Mons_ByIdx(mn[d]).Damage(dm, 0, 0, Shots[ID].SpawnerUID, t); + end; end; pl := nil; @@ -318,9 +335,9 @@ begin tt := g_GetUIDType(SpawnerUID); if tt = UID_MONSTER then begin - mon := g_Monsters_Get(SpawnerUID); + mon := g_Monsters_ByUID(SpawnerUID); if mon <> nil then - mt := g_Monsters_Get(SpawnerUID).MonsterType + mt := g_Monsters_ByUID(SpawnerUID).MonsterType else mt := 0; end @@ -876,7 +893,7 @@ begin case g_GetUIDType(UID) of UID_PLAYER: Result := HitPlayer(g_Player_Get(UID), d, 0, 0, SpawnerUID, t); - UID_MONSTER: Result := HitMonster(g_Monsters_Get(UID), d, 0, 0, SpawnerUID, t); + UID_MONSTER: Result := HitMonster(g_Monsters_ByUID(UID), d, 0, 0, SpawnerUID, t); else Exit; end; end;