X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_monsters.pas;h=d982204b256927b22a1f2c24666397c5739d7a87;hb=db9e913bebcfba6251351e97118db8ee01c76cc0;hp=79e3be36312924e30b4de321a8777ba82efdb716;hpb=2a9dada1550aeeb1ca055fb9f88952c930a64760;p=d2df-sdl.git diff --git a/src/game/g_monsters.pas b/src/game/g_monsters.pas index 79e3be3..d982204 100644 --- a/src/game/g_monsters.pas +++ b/src/game/g_monsters.pas @@ -14,6 +14,7 @@ * along with this program. If not, see . *) {$INCLUDE ../shared/a_modes.inc} +{$M+} {.$DEFINE D2F_DEBUG_MONS_MOVE} unit g_monsters; @@ -37,12 +38,14 @@ const 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) @@ -86,14 +89,20 @@ type FDieTriggers: Array of Integer; FSpawnTrigger: Integer; + mNeedSend: Boolean; // for network + procedure Turn(); function findNewPrey(): Boolean; procedure ActivateTriggers(); + procedure setGameX (v: Integer); inline; + procedure setGameY (v: Integer); inline; + 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; @@ -101,7 +110,7 @@ type function Collide(Panel: TPanel): Boolean; overload; function Collide(X, Y: Integer): Boolean; overload; function TeleportTo(X, Y: Integer; silent: Boolean; dir: Byte): Boolean; - function Live(): Boolean; + function alive(): Boolean; procedure SetHealth(aH: Integer); procedure Push(vx, vy: Integer); function Damage(aDamage: Word; VelX, VelY: Integer; SpawnerUID: Word; t: Byte): Boolean; @@ -134,8 +143,22 @@ type 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; @@ -148,12 +171,11 @@ type property MonsterPain: Integer read FPain write FPain; property MonsterAnim: Byte read FCurAnim write FCurAnim; - property Obj: TObj read FObj; property UID: Word read FUID write FUID; property SpawnTrigger: Integer read FSpawnTrigger write FSpawnTrigger; - property GameX: Integer read FObj.X write FObj.X; - property GameY: Integer read FObj.Y write FObj.Y; + property GameX: Integer read FObj.X write setGameX; + property GameY: Integer read FObj.Y write setGameY; property GameVelX: Integer read FObj.Vel.X write FObj.Vel.X; property GameVelY: Integer read FObj.Vel.Y write FObj.Vel.Y; property GameAccelX: Integer read FObj.Accel.X write FObj.Accel.X; @@ -161,9 +183,6 @@ type property GameDirection: TDirection read FDirection write FDirection; property StartID: Integer read FStartID; - - property proxyId: Integer read mProxyId; - property arrIdx: Integer read mArrIdx; end; @@ -183,9 +202,16 @@ 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; + +function g_Mons_SpawnAt (monType: Integer; x, y: Integer; dir: TDirection=D_LEFT): TMonster; overload; +function g_Mons_SpawnAt (const typeName: AnsiString; x, y: Integer; dir: TDirection=D_LEFT): TMonster; overload; + +function g_Mons_TypeLo (): Integer; inline; +function g_Mons_TypeHi (): Integer; inline; + +function g_Mons_TypeIdByName (const name: AnsiString): Integer; +function g_Mons_NameByTypeId (monType: Integer): AnsiString; +function g_Mons_GetKilledByTypeId (monType: Integer): AnsiString; type @@ -207,7 +233,8 @@ function g_Mons_ForEachAlive (cb: TEachMonsterCB): Boolean; 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 @@ -252,6 +279,7 @@ uses g_language, g_netmsg, idpool; + // ////////////////////////////////////////////////////////////////////////// // procedure g_Mons_ProfilersBegin (); begin @@ -282,7 +310,8 @@ end; // ////////////////////////////////////////////////////////////////////////// // var - monCheckTrapLastFrameId: DWord; + monCheckTrapLastFrameId: DWord = 0; + monCheckMPlatLastFrameId: LongWord = 0; procedure TMonster.getMapBox (out x, y, w, h: Integer); inline; @@ -293,6 +322,10 @@ begin 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; @@ -313,6 +346,7 @@ begin {$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); @@ -326,6 +360,7 @@ begin 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} @@ -333,6 +368,7 @@ begin 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} @@ -539,6 +575,7 @@ const MAX_SOUL = 512; // Îãðàíè÷åíèå Lost_Soul'îâ +// ////////////////////////////////////////////////////////////////////////// // var gMonsters: array of TMonster; uidMap: array [0..65535] of TMonster; // monster knows it's index @@ -554,12 +591,12 @@ begin 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; @@ -572,6 +609,24 @@ begin 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; @@ -958,6 +1013,7 @@ begin freeInds := TIdPool.Create(); clearUidMap(); monCheckTrapLastFrameId := 0; + monCheckMPlatLastFrameId := 0; end; procedure g_Monsters_FreeData(); @@ -1198,6 +1254,7 @@ begin gMonsters := nil; clearUidMap(); monCheckTrapLastFrameId := 0; + monCheckMPlatLastFrameId := 0; end; @@ -1450,43 +1507,87 @@ begin end; end; -function g_Monsters_GetIDByName(name: String): Integer; + +// ////////////////////////////////////////////////////////////////////////// // +function g_Mons_SpawnAt (monType: Integer; x, y: Integer; dir: TDirection=D_LEFT): TMonster; overload; +begin + result := nil; + if (monType >= MONSTER_DEMON) and (monType <= MONSTER_MAN) then + begin + result := g_Monsters_Create(monType, x, y, dir); + end; +end; + + +function g_Mons_SpawnAt (const typeName: AnsiString; x, y: Integer; dir: TDirection=D_LEFT): TMonster; overload; +begin + result := g_Mons_SpawnAt(g_Mons_TypeIdByName(typeName), x, y, dir); +end; + + + +// ////////////////////////////////////////////////////////////////////////// // +function g_Mons_TypeLo (): Integer; inline; begin result := Low(MONSTERTABLE); end; +function g_Mons_TypeHi (): Integer; inline; begin result := High(MONSTERTABLE); end; + + +function g_Mons_TypeIdByName (const name: String): Integer; var i: Integer; begin - name := UpperCase(name); i := MONSTER_DEMON; while (i <= MONSTER_MAN) do begin - if name = MONSTERTABLE[i].Name then + if (CompareText(name, MONSTERTABLE[i].Name) = 0) then begin - Result := i; - Exit; + result := i; + exit; end; Inc(i); end; - - Result := -1; + result := -1; + // HACK! + if (CompareText(name, 'zombie') = 0) then result := MONSTER_ZOMBY; end; -function g_Monsters_GetNameByID(MonsterType: Byte): String; + +function g_Mons_NameByTypeId (monType: Integer): AnsiString; begin - if MonsterType in [MONSTER_DEMON..MONSTER_MAN] then - Result := MONSTERTABLE[MonsterType].Name + if (monType >= MONSTER_DEMON) and (monType <= MONSTER_MAN) then + result := MONSTERTABLE[monType].Name else - Result := '?'; + result := '?'; end; -function g_Monsters_GetKilledBy(MonsterType: Byte): String; + +function g_Mons_GetKilledByTypeId (monType: Integer): AnsiString; begin - if MonsterType in [MONSTER_DEMON..MONSTER_MAN] then - Result := KilledByMonster[MonsterType] + if (monType >= MONSTER_DEMON) and (monType <= MONSTER_MAN) then + Result := KilledByMonster[monType] else Result := '?'; end; + +// ////////////////////////////////////////////////////////////////////////// // { T M o n s t e r : } +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.ActionSound(); begin case FMonsterType of @@ -1675,8 +1776,8 @@ begin FObj.Accel.X := 0; FObj.Accel.Y := 0; FDirection := FStartDirection; - GameX := FStartX; - GameY := FStartY; + {GameX}FObj.X := FStartX; + {GameY}FObj.Y := FStartY; FObj.Rect := MONSTERTABLE[FMonsterType].Rect; FHealth := MONSTERTABLE[FMonsterType].Health; FAmmo := 0; @@ -1736,6 +1837,8 @@ begin mProxyId := -1; mArrIdx := -1; trapCheckFrameId := 0; + mplatCheckFrameId := 0; + mNeedSend := false; if FMonsterType in [MONSTER_ROBO, MONSTER_BARREL] then FBloodKind := BLOOD_SPARKS @@ -1987,7 +2090,7 @@ begin Result := False; if g_Game_IsClient then Exit; - if not Live then + if not alive then Exit; if FHealth < FMaxHealth then @@ -2051,7 +2154,7 @@ begin o.Y+o.Rect.Y+o.Rect.Height-128, M_NONE); // Íå â îáëàñòè ðèñîâàíèÿ íå ðåñóåì: - if not g_dbg_scale_05 then + 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, sX-128, sY-128, sWidth+256, sHeight+256) then @@ -2314,7 +2417,7 @@ begin (FObj.X > gMapInfo.Width+1000) or (FObj.Y < -1000) then begin FRemoved := True; - if Live and (gLMSRespawn = LMS_RESPAWN_NONE) then + if alive and (gLMSRespawn = LMS_RESPAWN_NONE) then begin Inc(gCoopMonstersKilled); if g_Game_IsNet then @@ -2477,7 +2580,7 @@ begin // Åñëè åñòü èãðîê ðÿäîì, ïðîñûïàåìñÿ è èäåì ê íåìó: if (gPlayers <> nil) then for a := 0 to High(gPlayers) do - if (gPlayers[a] <> nil) and (gPlayers[a].Live) + if (gPlayers[a] <> nil) and (gPlayers[a].alive) and (not gPlayers[a].NoTarget) and (gPlayers[a].FMegaRulez[MR_INVIS] < gTime) then with gPlayers[a] do if g_Look(@FObj, @Obj, FDirection) then @@ -2495,7 +2598,7 @@ begin // Åñëè åñòü ïîäõîäÿùèé ìîíñòð ðÿäîì: if gMonsters <> nil then for a := 0 to High(gMonsters) do - if (gMonsters[a] <> nil) and (gMonsters[a].Live) and + if (gMonsters[a] <> nil) and (gMonsters[a].alive) and (gMonsters[a].FUID <> FUID) then begin // Ìàíüÿêè íàïàäàþò íà âñåõ ìîíñòðîâ, êðîìå äðóçåé @@ -2697,7 +2800,7 @@ begin if b > 1 then b := b * (Random(8 div b) + 1); for a := 0 to High(gGibs) do begin - if gGibs[a].Live and + if gGibs[a].alive and g_Obj_Collide(FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y+FObj.Rect.Height-4, FObj.Rect.Width, 8, @gGibs[a].Obj) and (Random(3) = 0) then begin @@ -3529,7 +3632,7 @@ begin if b > 1 then b := b * (Random(8 div b) + 1); for a := 0 to High(gGibs) do begin - if gGibs[a].Live and + if gGibs[a].alive and g_Obj_Collide(FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y+FObj.Rect.Height-4, FObj.Rect.Width, 8, @gGibs[a].Obj) and (Random(3) = 0) then begin @@ -3981,7 +4084,7 @@ begin if (gPlayers <> nil) and (FBehaviour <> BH_INSANE) and (FBehaviour <> BH_CANNIBAL) and (FBehaviour <> BH_GOOD) then for a := 0 to High(gPlayers) do - if (gPlayers[a] <> nil) and (gPlayers[a].Live) + if (gPlayers[a] <> nil) and (gPlayers[a].alive) and (not gPlayers[a].NoTarget) and (gPlayers[a].FMegaRulez[MR_INVIS] < gTime) then begin if g_Look(@FObj, @gPlayers[a].Obj, FDirection) then @@ -4001,7 +4104,7 @@ begin // Êèëëåðû è äîáðûå íå òðîãàþò ìîíñòðîâ if (gMonsters <> nil) and (FBehaviour <> BH_KILLER) and (FBehaviour <> BH_GOOD) then for a := 0 to High(gMonsters) do - if (gMonsters[a] <> nil) and (gMonsters[a].Live) and + if (gMonsters[a] <> nil) and (gMonsters[a].alive) and (gMonsters[a].FUID <> FUID) then begin if (FBehaviour = BH_CANNIBAL) and (gMonsters[a].FMonsterType <> FMonsterType) then @@ -4254,7 +4357,7 @@ begin Result := True; end; -function TMonster.Live(): Boolean; +function TMonster.alive(): Boolean; begin Result := (FState <> MONSTATE_DIE) and (FState <> MONSTATE_DEAD) and (FHealth > 0); end; @@ -4562,7 +4665,7 @@ begin for idx := 0 to High(gMonsters) do begin mon := gMonsters[idx]; - if (mon <> nil) and mon.Live then + if (mon <> nil) and mon.alive then begin result := cb(mon); if result then exit; @@ -4575,7 +4678,7 @@ function g_Mons_IsAnyAliveAt (x, y: Integer; width, height: Integer): Boolean; function monsCollCheck (mon: TMonster; atag: Integer): Boolean; begin - result := mon.Live;// and g_Obj_Collide(x, y, width, height, @mon.Obj)); + result := mon.alive;// and g_Obj_Collide(x, y, width, height, @mon.Obj)); end; var @@ -4593,7 +4696,7 @@ begin for idx := 0 to High(gMonsters) do begin mon := gMonsters[idx]; - if (mon <> nil) and mon.Live then + if (mon <> nil) and mon.alive then begin if g_Obj_Collide(x, y, width, height, @mon.Obj) then begin @@ -4628,7 +4731,7 @@ begin for idx := 0 to High(gMonsters) do begin mon := gMonsters[idx]; - if (mon <> nil) and mon.Live then + if (mon <> nil) and mon.alive then begin if g_Obj_Collide(x, y, width, height, @mon.Obj) then begin @@ -4646,8 +4749,8 @@ function g_Mons_ForEachAliveAt (x, y: Integer; width, height: Integer; cb: TEach 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); - if mon.Live then result := cb(mon) else result := false; + //if mon.alive and g_Obj_Collide(x, y, width, height, @mon.Obj) then result := cb(mon); + if mon.alive then result := cb(mon) else result := false; end; var @@ -4672,7 +4775,7 @@ begin for idx := 0 to High(gMonsters) do begin mon := gMonsters[idx]; - if (mon <> nil) and mon.Live then + if (mon <> nil) and mon.alive then begin if g_Obj_Collide(x, y, width, height, @mon.Obj) then begin