X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_monsters.pas;h=a437ff9bdcd13e7c1ea72bc56b75efe61c4a72cb;hb=66d9ad247935e99fe7161849b71ed952cbb85508;hp=7b22e56dfcc3cffee624d01a965ac6dfa208e31f;hpb=de7f5ee74b7584e08e587929069b17800b5d2eb6;p=d2df-sdl.git diff --git a/src/game/g_monsters.pas b/src/game/g_monsters.pas index 7b22e56..a437ff9 100644 --- a/src/game/g_monsters.pas +++ b/src/game/g_monsters.pas @@ -14,6 +14,8 @@ * along with this program. If not, see . *) {$INCLUDE ../shared/a_modes.inc} +{$M+} +{.$DEFINE D2F_DEBUG_MONS_MOVE} unit g_monsters; interface @@ -89,6 +91,9 @@ type function findNewPrey(): Boolean; procedure ActivateTriggers(); + procedure setGameX (v: Integer); inline; + procedure setGameY (v: Integer); inline; + public FNoRespawn: Boolean; FFireTime: Integer; @@ -133,8 +138,17 @@ 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 getMapBox (out x, y, w, h: Integer); inline; + 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; @@ -147,12 +161,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; @@ -160,9 +173,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; @@ -172,7 +182,7 @@ procedure g_Mons_InitTree (x, y, w, h: Integer); procedure g_Monsters_LoadData (); procedure g_Monsters_FreeData (); procedure g_Monsters_Init (); -procedure g_Monsters_Free (); +procedure g_Monsters_Free (clearGrid: Boolean=true); function g_Monsters_Create (MonsterType: Byte; X, Y: Integer; Direction: TDirection; AdjCoord: Boolean = False; ForcedUID: Integer = -1): TMonster; procedure g_Monsters_Update (); @@ -234,7 +244,7 @@ type TMonsterGrid = specialize TBodyGridBase; var - monsGrid: TMonsterGrid = nil; + monsGrid: TMonsterGrid = nil; // DO NOT USE! public for debugging only! var @@ -248,7 +258,8 @@ 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; + g_language, g_netmsg, idpool; + // ////////////////////////////////////////////////////////////////////////// // @@ -304,7 +315,8 @@ end; //WARNING! call this after monster position was changed, or coldet will not work right! procedure TMonster.positionChanged (); var - x, y: Integer; + x, y, w, h: Integer; + nx, ny, nw, nh: Integer; begin {$IF DEFINED(D2F_DEBUG_MONS_MOVE)} //e_WriteLog(Format('monster #%d(%u): pos=(%d,%d); rpos=(%d,%d)', [mArrIdx, UID, FObj.X, FObj.Y, FObj.Rect.X, FObj.Rect.Y]), MSG_NOTIFY); @@ -314,25 +326,35 @@ begin 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); - e_WriteLog(Format('monster #%d(%u): inserted into the grid; mProxyid=%d; x=%d; y=%d', [mArrIdx, UID, mProxyId, x, y]), MSG_NOTIFY); + e_WriteLog(Format('monster #%d:(%u): inserted into the grid; mProxyid=%d; gx=%d; gy=%d', [mArrIdx, UID, mProxyId, x-monsGrid.gridX0, y-monsGrid.gridY0]), MSG_NOTIFY); {$ENDIF} end else begin - monsGrid.getBodyXY(mProxyId, x, y); - if (FObj.X+FObj.Rect.X = x) and (FObj.Y+FObj.Rect.Y = y) then exit; // nothing to do - {$IF DEFINED(D2F_DEBUG_MONS_MOVE)}e_WriteLog(Format('monster #%d(%u): updating tree; mProxyid=%d; x=%d; y=%d', [mArrIdx, UID, mProxyId, x, y]), MSG_NOTIFY);{$ENDIF} - - {$IF TRUE} - monsGrid.moveBody(mProxyId, FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y); - {$ELSE} - monsGrid.removeBody(mProxyId); - mProxyId := monsGrid.insertBody(self, FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y, FObj.Rect.Width, FObj.Rect.Height); - {$ENDIF} + monsGrid.getBodyDims(mProxyId, x, y, w, h); + getMapBox(nx, ny, nw, nh); + if (w <> nw) or (h <> nh) then + begin + {$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} + monsGrid.moveResizeBody(mProxyId, nx, ny, nw, nh); + end + else if (x <> nx) or (y <> ny) then + begin + {$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} + monsGrid.moveBody(mProxyId, nx, ny); + end + else + begin + exit; // nothing to do + end; {$IF DEFINED(D2F_DEBUG_MONS_MOVE)} monsGrid.getBodyXY(mProxyId, x, y); - e_WriteLog(Format('monster #%d(%u): updated tree; mProxyid=%d; x=%d; y=%d', [mArrIdx, UID, mProxyId, x, y]), MSG_NOTIFY); + e_WriteLog(Format('monster #%d:(%u): updated grid; mProxyid=%d; gx=%d; gy=%d', [mArrIdx, UID, mProxyId, x-monsGrid.gridX0, y-monsGrid.gridY0]), MSG_NOTIFY); {$ENDIF} end; end; @@ -440,8 +462,8 @@ const LeftAnim: Boolean; wX, wY: Integer; // Îòêóäà âûëåòèò ïóëÿ AnimSpeed: Array [ANIM_SLEEP..ANIM_PAIN] of Byte; - AnimDeltaRight: Array [ANIM_SLEEP..ANIM_PAIN] of TPoint; - AnimDeltaLeft: Array [ANIM_SLEEP..ANIM_PAIN] of TPoint; + AnimDeltaRight: Array [ANIM_SLEEP..ANIM_PAIN] of TDFPoint; + AnimDeltaLeft: Array [ANIM_SLEEP..ANIM_PAIN] of TDFPoint; end = // SLEEP GO DIE MESS ATTACK ATTACK2 PAIN ((LeftAnim: False; wX: 54; wY: 32; AnimSpeed:(3, 2, 3, 2, 3, 0, 4); //DEMON AnimDeltaRight: ((X: 1; Y: 4), (X: 1; Y: 4), (X: 0; Y: 4), (X: 0; Y: 4), (X: 2; Y: 6), (X: 2; Y: 6), (X: 2; Y: 5)); @@ -530,6 +552,7 @@ const var gMonsters: array of TMonster; uidMap: array [0..65535] of TMonster; // monster knows it's index + freeInds: TIdPool = nil; procedure clearUidMap (); @@ -537,6 +560,7 @@ var idx: Integer; begin for idx := 0 to High(uidMap) do uidMap[idx] := nil; + freeInds.clear(); end; @@ -566,29 +590,16 @@ var soulcount: Integer = 0; -function allocMonster(): DWORD; +function allocMonster (): DWORD; var - i, olen: Integer; + f, olen: Integer; begin - for i := 0 to High(gMonsters) do + result := freeInds.alloc(); + if (result > High(gMonsters)) then begin - if (gMonsters[i] = nil) then - begin - result := i; - exit; - end; - end; - - olen := Length(gMonsters); - if (olen = 0) then - begin - SetLength(gMonsters, 64); - result := 0; - end - else - begin - result := olen; - SetLength(gMonsters, Length(gMonsters)+32); + olen := Length(gMonsters); + SetLength(gMonsters, result+64); + for f := olen to High(gMonsters) do gMonsters[f] := nil; end; end; @@ -954,6 +965,7 @@ begin g_Sound_CreateWADEx('SOUND_MONSTER_FISH_ATTACK', GameWAD+':MSOUNDS\FISH_ATTACK'); + freeInds := TIdPool.Create(); clearUidMap(); monCheckTrapLastFrameId := 0; end; @@ -1172,6 +1184,9 @@ begin g_Sound_Delete('SOUND_MONSTER_SPIDER_WALK'); g_Sound_Delete('SOUND_MONSTER_FISH_ATTACK'); + + freeInds.Free(); + freeInds := nil; end; procedure g_Monsters_Init(); @@ -1179,12 +1194,16 @@ begin soulcount := 0; end; -procedure g_Monsters_Free(); +procedure g_Monsters_Free (clearGrid: Boolean=true); var a: Integer; begin - monsGrid.Free(); - monsGrid := nil; + e_LogWritefln('Cleared monster data (clearGrid=%s)', [clearGrid]); + if (clearGrid) then + begin + monsGrid.Free(); + monsGrid := nil; + end; for a := 0 to High(gMonsters) do gMonsters[a].Free(); gMonsters := nil; clearUidMap(); @@ -1197,6 +1216,8 @@ procedure g_Mons_InitTree (x, y, w, h: Integer); begin monsGrid.Free(); monsGrid := TMonsterGrid.Create(x, y, w, h); + //clearUidMap(); // why not? + e_LogWritefln('%s', ['Recreated monster tree']); end; @@ -1259,11 +1280,14 @@ begin if gMonsters = nil then Exit; -// Ïðèêîëèñò ñìååòñÿ íàä ñìåðòüþ èãðîêà: + // Ïðèêîëèñò ñìååòñÿ íàä ñìåðòüþ èãðîêà: h := High(gMonsters); for a := 0 to h do + begin if (gMonsters[a] <> nil) then + begin with gMonsters[a] do + begin if (FMonsterType = MONSTER_MAN) and (FState <> MONSTATE_DEAD) and (FState <> MONSTATE_SLEEP) and @@ -1272,6 +1296,9 @@ begin g_Sound_PlayExAt('SOUND_MONSTER_TRUP', FObj.X, FObj.Y); Exit; end; + end; + end; + end; end; procedure g_Monsters_Update(); @@ -1318,9 +1345,12 @@ var a: Integer; begin if gMonsters <> nil then + begin for a := 0 to High(gMonsters) do - if gMonsters[a] <> nil then - gMonsters[a].Draw(); + begin + if (gMonsters[a] <> nil) then gMonsters[a].Draw(); + end; + end; end; procedure g_Monsters_DrawHealth(); @@ -1332,29 +1362,19 @@ begin e_TextureFontGetSize(gStdFont, fW, fH); for a := 0 to High(gMonsters) do + begin if gMonsters[a] <> nil then begin e_TextureFontPrint(gMonsters[a].FObj.X + gMonsters[a].FObj.Rect.X, gMonsters[a].FObj.Y + gMonsters[a].FObj.Rect.Y + gMonsters[a].FObj.Rect.Height - fH, IntToStr(gMonsters[a].FHealth), gStdFont); end; + end; end; 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 - (gMonsters[a].FUID = UID) then - begin - Result := gMonsters[a]; - Break; - end; - } end; procedure g_Monsters_SaveState(var Mem: TBinMemoryWriter); @@ -1364,11 +1384,16 @@ var begin // Ñ÷èòàåì êîëè÷åñòâî ñóùåñòâóþùèõ ìîíñòðîâ: count := 0; - if gMonsters <> nil then + if (gMonsters <> nil) then + begin for i := 0 to High(gMonsters) do - if gMonsters[i] <> nil then - if gMonsters[i].FMonsterType <> MONSTER_NONE then - count := count + 1; + begin + if (gMonsters[i] <> nil) then + begin + if (gMonsters[i].FMonsterType <> MONSTER_NONE) then count += 1; + end; + end; + end; Mem := TBinMemoryWriter.Create((count+1) * 350); @@ -1386,15 +1411,19 @@ begin // Ñîõðàíÿåì ìîíñòðîâ: for i := 0 to High(gMonsters) do - if gMonsters[i] <> nil then - if gMonsters[i].FMonsterType <> MONSTER_NONE then + begin + if (gMonsters[i] <> nil) then + begin + if (gMonsters[i].FMonsterType <> MONSTER_NONE) then begin - // Òèï ìîíñòðà: + // Òèï ìîíñòðà: b := gMonsters[i].MonsterType; Mem.WriteByte(b); - // Ñîõðàíÿåì äàííûå ìîíñòðà: + // Ñîõðàíÿåì äàííûå ìîíñòðà: gMonsters[i].SaveState(Mem); end; + end; + end; end; procedure g_Monsters_LoadState(var Mem: TBinMemoryReader); @@ -1405,7 +1434,7 @@ var begin if Mem = nil then exit; - g_Monsters_Free(); + g_Monsters_Free(false); // Çàãðóæàåì èíôîðìàöèþ öåëåóêàçàòåëÿ Mem.ReadInt(pt_x); @@ -1468,6 +1497,11 @@ 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.ActionSound(); begin case FMonsterType of @@ -1656,8 +1690,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; @@ -1997,13 +2031,17 @@ begin begin monsGrid.removeBody(mProxyId); {$IF DEFINED(D2F_DEBUG_MONS_MOVE)} - e_WriteLog(Format('monster #%d(%u): removed from tree; mProxyid=%d', [mArrIdx, UID, mProxyId]), MSG_NOTIFY); + e_WriteLog(Format('monster #%d:(%u): removed from grid; mProxyid=%d', [mArrIdx, UID, mProxyId]), MSG_NOTIFY); {$ENDIF} end; mProxyId := -1; end; - if (mArrIdx <> -1) and (mArrIdx < Length(gMonsters)) then gMonsters[mArrIdx] := nil; + if (mArrIdx <> -1) and (mArrIdx < Length(gMonsters)) then + begin + freeInds.release(mArrIdx); + gMonsters[mArrIdx] := nil; + end; mArrIdx := -1; uidMap[FUID] := nil; @@ -2028,9 +2066,12 @@ begin o.Y+o.Rect.Y+o.Rect.Height-128, M_NONE); // Íå â îáëàñòè ðèñîâàíèÿ íå ðåñóåì: - 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 - Exit; + 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 + Exit; + end; // Ýòè ìîíñòðû, óìèðàÿ, íå îñòàâëÿþò òðóïîâ: if FState = MONSTATE_DEAD then @@ -4333,6 +4374,7 @@ begin end; end; + procedure TMonster.LoadState(var Mem: TBinMemoryReader); var i: Integer; @@ -4349,8 +4391,13 @@ begin begin raise EBinSizeError.Create('TMonster.LoadState: Wrong Monster Signature'); end; + if (uidMap[FUID] <> nil) and (uidMap[FUID] <> self) then raise Exception.Create('internal error in monster loader (0)'); + uidMap[FUID] := nil; // UID ìîíñòðà: Mem.ReadWord(FUID); + //if (arrIdx = -1) then raise Exception.Create('internal error in monster loader'); + if (uidMap[FUID] <> nil) then raise Exception.Create('internal error in monster loader (1)'); + uidMap[FUID] := self; // Íàïðàâëåíèå: Mem.ReadByte(b); if b = 1 then