index 62686cd4409d24785029888d2809c4feba7e467b..8629bc954ae6143ed88e380cd3bc76795289b448 100644 (file)
--- a/src/game/g_monsters.pas
+++ b/src/game/g_monsters.pas
interface
uses
+ mempool,
g_basic, e_graphics, g_phys, g_textures, g_grid,
g_saveload, BinEditor, g_panel, xprofiler;
MONSTATE_REVIVE = 10;
MONSTATE_RUNOUT = 11;
+{ in mapdef now
BH_NORMAL = 0;
BH_KILLER = 1;
BH_MANIAC = 2;
BH_INSANE = 3;
BH_CANNIBAL = 4;
BH_GOOD = 5;
+}
type
- TMonster = Class (TObject)
+ TMonster = class(TPoolObject)
private
FMonsterType: Byte;
FUID: Word;
FDieTriggers: Array of Integer;
FSpawnTrigger: Integer;
+ mNeedSend: Boolean; // for network
+
+ mEDamageType: Integer;
+
procedure Turn();
function findNewPrey(): Boolean;
procedure ActivateTriggers();
procedure setGameX (v: Integer); inline;
procedure setGameY (v: Integer); inline;
+ procedure doDamage (v: Integer);
+
public
FNoRespawn: Boolean;
FFireTime: Integer;
trapCheckFrameId: DWord; // for `g_weapons.CheckTrap()`
+ mplatCheckFrameId: LongWord;
constructor Create(MonsterType: Byte; aID: Integer; ForcedUID: Integer = -1);
destructor Destroy(); override;
procedure positionChanged (); //WARNING! call this after monster position was changed, or coldet will not work right!
procedure setPosition (ax, ay: Integer; callPosChanged: Boolean=true); inline;
+ procedure moveBy (dx, dy: Integer); inline;
procedure getMapBox (out x, y, w, h: Integer); inline;
+ // get-and-clear
+ function gncNeedSend (): Boolean; inline;
+ procedure setDirty (); inline; // why `dirty`? 'cause i may introduce property `needSend` later
+
public
property Obj: TObj read FObj;
property proxyId: Integer read mProxyId;
property arrIdx: Integer read mArrIdx;
- published
property MonsterType: Byte read FMonsterType;
property MonsterHealth: Integer read FHealth write FHealth;
property MonsterAmmo: Integer read FAmmo write FAmmo;
property GameDirection: TDirection read FDirection write FDirection;
property StartID: Integer read FStartID;
+
+ published
+ property eMonsterType: Byte read FMonsterType;
+ property eMonsterHealth: Integer read FHealth write FHealth;
+ property eMonsterAmmo: Integer read FAmmo write FAmmo;
+ property eMonsterTargetUID: Word read FTargetUID write FTargetUID;
+ property eMonsterTargetTime: Integer read FTargetTime write FTargetTime;
+ property eMonsterBehaviour: Byte read FBehaviour write FBehaviour;
+ property eMonsterSleep: Integer read FSleep write FSleep;
+ property eMonsterState: Byte read FState write FState;
+ property eMonsterRemoved: Boolean read FRemoved;
+ property eMonsterPain: Integer read FPain write FPain;
+ property eMonsterAnim: Byte read FCurAnim;
+
+ property eUID: Word read FUID;
+ property eSpawnTrigger: Integer read FSpawnTrigger;
+
+ property eGameX: Integer read FObj.X write setGameX;
+ property eGameY: Integer read FObj.Y write setGameY;
+ property eGameVelX: Integer read FObj.Vel.X write FObj.Vel.X;
+ property eGameVelY: Integer read FObj.Vel.Y write FObj.Vel.Y;
+ property eGameAccelX: Integer read FObj.Accel.X write FObj.Accel.X;
+ property eGameAccelY: Integer read FObj.Accel.Y write FObj.Accel.Y;
+ property eGameDirection: TDirection read FDirection write FDirection;
+
+ property eStartID: Integer read FStartID;
+
+ // set this before assigning something to `eDamage`
+ property eDamageType: Integer read mEDamageType write mEDamageType;
+ property eDamage: Integer write doDamage;
end;
function g_Mons_ForEachAt (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;
+function g_Mons_getNewTrapFrameId (): DWord; inline;
+function g_Mons_getNewMPlatFrameId (): LongWord; inline;
type
implementation
uses
- e_log, g_main, g_sound, g_gfx, g_player, g_game,
+ e_log, e_texture, 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, idpool;
// ////////////////////////////////////////////////////////////////////////// //
var
- monCheckTrapLastFrameId: DWord;
+ monCheckTrapLastFrameId: DWord = 0;
+ monCheckMPlatLastFrameId: LongWord = 0;
procedure TMonster.getMapBox (out x, y, w, h: Integer); inline;
h := FObj.Rect.Height;
end;
+function TMonster.gncNeedSend (): Boolean; inline; begin result := mNeedSend; mNeedSend := false; end;
+
+procedure TMonster.setDirty (); inline; begin mNeedSend := true; end;
+
// ////////////////////////////////////////////////////////////////////////// //
function g_Mons_AlongLine (x0, y0, x1, y1: Integer; cb: TMonsAlongLineCB; log: Boolean=false): TMonster;
{$ENDIF}
if (mProxyId = -1) then
begin
+ //mNeedSend := true;
mProxyId := monsGrid.insertBody(self, FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y, FObj.Rect.Width, FObj.Rect.Height);
{$IF DEFINED(D2F_DEBUG_MONS_MOVE)}
monsGrid.getBodyXY(mProxyId, x, y);
if (w <> nw) or (h <> nh) then
begin
+ //mNeedSend := true;
{$IF DEFINED(D2F_DEBUG_MONS_MOVE)}
e_WriteLog(Format('monster #%d:(%u): resized; mProxyid=%d; gx=%d; gy=%d', [mArrIdx, UID, mProxyId, x-monsGrid.gridX0, y-monsGrid.gridY0]), MSG_NOTIFY);
{$ENDIF}
end
else if (x <> nx) or (y <> ny) then
begin
+ //mNeedSend := true;
{$IF DEFINED(D2F_DEBUG_MONS_MOVE)}
e_WriteLog(Format('monster #%d:(%u): updating grid; mProxyid=%d; gx=%d; gy=%d', [mArrIdx, UID, mProxyId, x-monsGrid.gridX0, y-monsGrid.gridY0]), MSG_NOTIFY);
{$ENDIF}
end;
-function g_Mons_getNewTrapFrameId (): DWord;
+function g_Mons_getNewTrapFrameId (): DWord; inline;
var
f: Integer;
begin
Inc(monCheckTrapLastFrameId);
- if monCheckTrapLastFrameId = 0 then
+ if (monCheckTrapLastFrameId = 0) then
begin
// wraparound
monCheckTrapLastFrameId := 1;
end;
+function g_Mons_getNewMPlatFrameId (): LongWord; inline;
+var
+ f: Integer;
+begin
+ Inc(monCheckMPlatLastFrameId);
+ if (monCheckMPlatLastFrameId = 0) then
+ begin
+ // wraparound
+ monCheckMPlatLastFrameId := 1;
+ for f := 0 to High(gMonsters) do
+ begin
+ if (gMonsters[f] <> nil) then gMonsters[f].mplatCheckFrameId := 0;
+ end;
+ end;
+ result := monCheckMPlatLastFrameId;
+end;
+
+
var
pt_x: Integer = 0;
pt_xs: Integer = 1;
freeInds := TIdPool.Create();
clearUidMap();
monCheckTrapLastFrameId := 0;
+ monCheckMPlatLastFrameId := 0;
end;
procedure g_Monsters_FreeData();
gMonsters := nil;
clearUidMap();
monCheckTrapLastFrameId := 0;
+ monCheckMPlatLastFrameId := 0;
end;
procedure TMonster.setGameX (v: Integer); inline; begin FObj.X := v; positionChanged(); end;
procedure TMonster.setGameY (v: Integer); inline; begin FObj.Y := v; positionChanged(); end;
+
procedure TMonster.setPosition (ax, ay: Integer; callPosChanged: Boolean=true); inline; begin FObj.X := ax; FObj.Y := ay; if callPosChanged then positionChanged(); end;
+procedure TMonster.moveBy (dx, dy: Integer); inline;
+begin
+ if (dx <> 0) or (dy <> 0) then
+ begin
+ FObj.X += dx;
+ FObj.Y += dy;
+ positionChanged();
+ end;
+end;
+
+procedure TMonster.doDamage (v: Integer);
+begin
+ if (v <= 0) then exit;
+ if (v > 32767) then v := 32767;
+ Damage(v, 0, 0, 0, mEDamageType);
+end;
procedure TMonster.ActionSound();
begin
FFireTime := 0;
FFirePainTime := 0;
FFireAttacker := 0;
+ mEDamageType := HIT_SOME;
mProxyId := -1;
mArrIdx := -1;
trapCheckFrameId := 0;
+ mplatCheckFrameId := 0;
+ mNeedSend := false;
if FMonsterType in [MONSTER_ROBO, MONSTER_BARREL] then
FBloodKind := BLOOD_SPARKS
o.Y+o.Rect.Y+o.Rect.Height-128, M_NONE);
// Íå â îáëàñòè ðèñîâàíèÿ íå ðåñóåì:
+//FIXME!
if (g_dbg_scale = 1.0) then
begin
if not g_Collide(FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y, FObj.Rect.Width, FObj.Rect.Height,