X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_monsters.pas;h=ca7ec00e32e8be568d538f6020515c42dbfcc9e6;hb=9a8ac2323ba1c23f248ff5effe2747135ecc14f6;hp=f5f69a93d5eea3b621a153db5d821dd334c49545;hpb=2281a9384c7d29ae85f32a746fa748e000a7870f;p=d2df-sdl.git diff --git a/src/game/g_monsters.pas b/src/game/g_monsters.pas index f5f69a9..ca7ec00 100644 --- a/src/game/g_monsters.pas +++ b/src/game/g_monsters.pas @@ -20,7 +20,7 @@ interface uses g_basic, e_graphics, g_phys, g_textures, - g_saveload, BinEditor, g_panel; + g_saveload, BinEditor, g_panel, z_aabbtree; const MONSTATE_SLEEP = 0; @@ -90,6 +90,8 @@ type function findNewPrey(): Boolean; procedure ActivateTriggers(); + function getMapAABB (): AABB2D; inline; + public FNoRespawn: Boolean; FFireTime: Integer; @@ -158,6 +160,8 @@ type property GameAccelY: Integer read FObj.Accel.Y write FObj.Accel.Y; property GameDirection: TDirection read FDirection write FDirection; + property mapAABB: AABB2D read getMapAABB; + property StartID: Integer read FStartID; end; @@ -181,9 +185,7 @@ function g_Monsters_GetKilledBy (MonsterType: Byte): String; type - TEachMonsterCB = function (monidx: Integer; mon: TMonster): Boolean is nested; // return `true` to stop - -function g_Mons_ForEach (cb: TEachMonsterCB): Boolean; + TEachMonsterCB = function (mon: TMonster): Boolean is nested; // return `true` to stop // throws on invalid uid function g_Mons_ByIdx (uid: Integer): TMonster; inline; @@ -193,8 +195,11 @@ function g_Mons_ByIdx_NC (uid: Integer): TMonster; inline; function g_Mons_IsAnyAliveAt (x, y: Integer; width, height: Integer): Boolean; +function g_Mons_ForEach (cb: TEachMonsterCB): Boolean; +function g_Mons_ForEachAlive (cb: TEachMonsterCB): 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_ForEachAliveAt (x, y: Integer; width, height: Integer; cb: TEachMonsterCB): Boolean; function g_Mons_getNewTrapFrameId (): DWord; @@ -209,7 +214,7 @@ uses e_log, g_main, g_sound, g_gfx, g_player, g_game, g_weapons, g_triggers, MAPDEF, g_items, g_options, g_console, g_map, Math, SysUtils, g_menu, wadreader, - g_language, g_netmsg, z_aabbtree; + g_language, g_netmsg; // ////////////////////////////////////////////////////////////////////////// // @@ -217,6 +222,12 @@ var monCheckTrapLastFrameId: DWord; +function TMonster.getMapAABB (): AABB2D; inline; +begin + result := AABB2D.CreateWH(FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y, FObj.Rect.Width, FObj.Rect.Height); +end; + + // ////////////////////////////////////////////////////////////////////////// // type TDynAABBTreeMonsBase = specialize TDynAABBTreeBase; @@ -230,7 +241,8 @@ begin result := false; if (flesh = nil) then raise Exception.Create('DynTree: trying to get dimensions of inexistant monsters'); if (flesh.Obj.Rect.Width < 1) or (flesh.Obj.Rect.Height < 1) then raise Exception.Create('DynTree: monster without size, wtf?!'); - aabb := AABB2D.CreateWH(flesh.Obj.X+flesh.Obj.Rect.X, flesh.Obj.Y+flesh.Obj.Rect.Y, flesh.Obj.Rect.Width, flesh.Obj.Rect.Height); + //aabb := AABB2D.CreateWH(flesh.Obj.X+flesh.Obj.Rect.X, flesh.Obj.Y+flesh.Obj.Rect.Y, flesh.Obj.Rect.Width, flesh.Obj.Rect.Height); + aabb := flesh.getMapAABB(); if not aabb.valid then raise Exception.Create('wutafuuuuuuu?!'); result := true; end; @@ -572,6 +584,7 @@ begin Result := False; end; + function BehaviourDamage(SpawnerUID: Word; BH, SelfType: Byte): Boolean; var m: TMonster; @@ -601,6 +614,7 @@ begin end; end; + function canShoot(m: Byte): Boolean; begin Result := False; @@ -613,7 +627,8 @@ begin end; end; -function isCorpse(o: PObj; immediately: Boolean): Integer; + +function isCorpse (o: PObj; immediately: Boolean): Integer; function monsCollCheck (mon: TMonster; atag: Integer): Boolean; begin @@ -2866,7 +2881,7 @@ _end: mon.SetState(STATE_GO); mon.FNoRespawn := True; Inc(gTotalMonsters); - if g_Game_IsNet then MH_SEND_MonsterSpawn(gMonsters[sx].UID); + if g_Game_IsNet then MH_SEND_MonsterSpawn(mon.UID); end; mon := g_Monsters_Create(MONSTER_SOUL, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2), @@ -2876,7 +2891,7 @@ _end: mon.SetState(STATE_GO); mon.FNoRespawn := True; Inc(gTotalMonsters); - if g_Game_IsNet then MH_SEND_MonsterSpawn(gMonsters[sx].UID); + if g_Game_IsNet then MH_SEND_MonsterSpawn(mon.UID); end; mon := g_Monsters_Create(MONSTER_SOUL, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2)-15, @@ -2886,9 +2901,10 @@ _end: mon.SetState(STATE_GO); mon.FNoRespawn := True; Inc(gTotalMonsters); - if g_Game_IsNet then MH_SEND_MonsterSpawn(gMonsters[sx].UID); + if g_Game_IsNet then MH_SEND_MonsterSpawn(mon.UID); end; - if g_Game_IsNet then MH_SEND_CoopStats(gMonsters[sx].UID); + + if g_Game_IsNet then MH_SEND_CoopStats(); end; // Ó ýòèõ ìîíñòðîâ íåò òðóïîâ: @@ -3061,7 +3077,7 @@ _end: mon.shoot(@o, True); Inc(gTotalMonsters); - if g_Game_IsNet then MH_SEND_MonsterSpawn(gMonsters[sx].UID); + if g_Game_IsNet then MH_SEND_MonsterSpawn(mon.UID); end; end; end; @@ -4417,36 +4433,57 @@ end; // ////////////////////////////////////////////////////////////////////////// // +// throws on invalid uid +function g_Mons_ByIdx (uid: Integer): TMonster; inline; +begin + result := g_Mons_ByIdx_NC(uid); + if (result = nil) then raise Exception.Create('g_Mons_ByIdx: invalid monster id'); +end; + + +// can return null +function g_Mons_ByIdx_NC (uid: Integer): TMonster; inline; +begin + if (uid < 0) or (uid > High(gMonsters)) then begin result := nil; exit; end; + result := gMonsters[uid]; +end; + + function g_Mons_ForEach (cb: TEachMonsterCB): Boolean; var idx: Integer; + mon: TMonster; begin result := false; if (gMonsters = nil) or not assigned(cb) then exit; for idx := 0 to High(gMonsters) do begin - if (gMonsters[idx] <> nil) then + mon := gMonsters[idx]; + if (mon <> nil) then begin - result := cb(idx, gMonsters[idx]); + result := cb(mon); if result then exit; end; end; end; -// throws on invalid uid -function g_Mons_ByIdx (uid: Integer): TMonster; inline; -begin - result := g_Mons_ByIdx_NC(uid); - if (result = nil) then raise Exception.Create('g_Mons_ByIdx: invalid monster id'); -end; - - -// can return null -function g_Mons_ByIdx_NC (uid: Integer): TMonster; inline; +function g_Mons_ForEachAlive (cb: TEachMonsterCB): Boolean; +var + idx: Integer; + mon: TMonster; begin - if (uid < 0) or (uid > High(gMonsters)) then begin result := nil; exit; end; - result := gMonsters[uid]; + result := false; + if (gMonsters = nil) or not assigned(cb) then exit; + for idx := 0 to High(gMonsters) do + begin + mon := gMonsters[idx]; + if (mon <> nil) and mon.Live then + begin + result := cb(mon); + if result then exit; + end; + end; end; @@ -4459,10 +4496,10 @@ function g_Mons_IsAnyAliveAt (x, y: Integer; width, height: Integer): Boolean; var idx: Integer; + mon: TMonster; begin result := false; if (width < 1) or (height < 1) then exit; - if gmon_debug_use_sqaccel then begin result := (monsTree.aabbQuery(x, y, width, height, monsCollCheck) <> nil); @@ -4471,9 +4508,10 @@ begin begin for idx := 0 to High(gMonsters) do begin - if (gMonsters[idx] <> nil) and gMonsters[idx].Live then + mon := gMonsters[idx]; + if (mon <> nil) and mon.Live then begin - if g_Obj_Collide(x, y, width, height, @gMonsters[idx].Obj) then + if g_Obj_Collide(x, y, width, height, @mon.Obj) then begin result := true; exit; @@ -4489,15 +4527,15 @@ function g_Mons_ForEachAt (x, y: Integer; width, height: Integer; cb: TEachMonst function monsCollCheck (mon: TMonster; atag: Integer): Boolean; begin result := false; - if g_Obj_Collide(x, y, width, height, @mon.Obj) then result := cb(mon.arrIdx, mon); + if g_Obj_Collide(x, y, width, height, @mon.Obj) then result := cb(mon); end; var idx: Integer; + mon: TMonster; begin result := false; if (width < 1) or (height < 1) then exit; - if gmon_debug_use_sqaccel then begin result := (monsTree.aabbQuery(x, y, width, height, monsCollCheck) <> nil); @@ -4506,11 +4544,12 @@ begin begin for idx := 0 to High(gMonsters) do begin - if (gMonsters[idx] <> nil) and gMonsters[idx].Live then + mon := gMonsters[idx]; + if (mon <> nil) and mon.Live then begin - if g_Obj_Collide(x, y, width, height, @gMonsters[idx].Obj) then + if g_Obj_Collide(x, y, width, height, @mon.Obj) then begin - result := cb(idx, gMonsters[idx]); + result := cb(mon); if result then exit; end; end; @@ -4519,20 +4558,20 @@ begin end; -function g_Mons_ForEachAtAlive (x, y: Integer; width, height: Integer; cb: TEachMonsterCB): Boolean; +function g_Mons_ForEachAliveAt (x, y: Integer; width, height: Integer; cb: TEachMonsterCB): Boolean; function monsCollCheck (mon: TMonster; atag: Integer): Boolean; begin result := false; - if mon.Live and g_Obj_Collide(x, y, width, height, @mon.Obj) then result := cb(mon.arrIdx, mon); + if mon.Live and g_Obj_Collide(x, y, width, height, @mon.Obj) then result := cb(mon); end; var idx: Integer; + mon: TMonster; begin result := false; if (width < 1) or (height < 1) then exit; - if gmon_debug_use_sqaccel then begin if (width = 1) and (height = 1) then @@ -4548,11 +4587,12 @@ begin begin for idx := 0 to High(gMonsters) do begin - if (gMonsters[idx] <> nil) and gMonsters[idx].Live then + mon := gMonsters[idx]; + if (mon <> nil) and mon.Live then begin - if g_Obj_Collide(x, y, width, height, @gMonsters[idx].Obj) then + if g_Obj_Collide(x, y, width, height, @mon.Obj) then begin - result := cb(idx, gMonsters[idx]); + result := cb(mon); if result then exit; end; end;