index 8629bc954ae6143ed88e380cd3bc76795289b448..b7d217b159a306c27aadb399139786a38fead474 100644 (file)
--- a/src/game/g_monsters.pas
+++ b/src/game/g_monsters.pas
interface
uses
+ SysUtils, Classes,
mempool,
g_basic, e_graphics, g_phys, g_textures, g_grid,
- g_saveload, BinEditor, g_panel, xprofiler;
+ g_saveload, g_panel, xprofiler;
const
MONSTATE_SLEEP = 0;
FMaxHealth: Integer;
FState: Byte;
FCurAnim: Byte;
- FAnim: Array of Array [D_LEFT..D_RIGHT] of TAnimation;
+ FAnim: Array of Array [TDirection.D_LEFT..TDirection.D_RIGHT] of TAnimation;
FTargetUID: Word;
FTargetTime: Integer;
FBehaviour: Byte;
procedure AddTrigger(t: Integer);
procedure ClearTriggers();
procedure Respawn();
- procedure SaveState(var Mem: TBinMemoryWriter);
- procedure LoadState(var Mem: TBinMemoryReader);
+ procedure SaveState (st: TStream);
+ procedure LoadState (st: TStream);
procedure SetState(State: Byte; ForceAnim: Byte = 255);
procedure MakeBloodVector(Count: Word; VelX, VelY: Integer);
procedure MakeBloodSimple(Count: Word);
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);
+procedure g_Monsters_SaveState (st: TStream);
+procedure g_Monsters_LoadState (st: TStream);
-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_SpawnAt (monType: Integer; x, y: Integer; dir: TDirection=TDirection.D_LEFT): TMonster; overload;
+function g_Mons_SpawnAt (const typeName: AnsiString; x, y: Integer; dir: TDirection=TDirection.D_LEFT): TMonster; overload;
function g_Mons_TypeLo (): Integer; inline;
function g_Mons_TypeHi (): Integer; inline;
uses
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;
+ g_console, g_map, Math, g_menu, wadreader,
+ g_language, g_netmsg, idpool, utils, xstreams;
procedure g_Monsters_LoadData();
begin
- e_WriteLog('Loading monsters data...', MSG_NOTIFY);
+ e_WriteLog('Loading monsters data...', TMsgType.Notify);
g_Game_SetLoadingText(_lc[I_LOAD_MONSTER_TEXTURES]+' 0%', 0, False);
g_Frames_CreateWAD(nil, 'FRAMES_MONSTER_BARREL_SLEEP', GameWAD+':MTEXTURES\BARREL_SLEEP', 64, 64, 3);
procedure g_Monsters_FreeData();
begin
- e_WriteLog('Releasing monsters data...', MSG_NOTIFY);
+ e_WriteLog('Releasing monsters data...', TMsgType.Notify);
g_Frames_DeleteByName('FRAMES_MONSTER_BARREL_SLEEP');
g_Frames_DeleteByName('FRAMES_MONSTER_BARREL_PAIN');
result := uidMap[UID];
end;
-procedure g_Monsters_SaveState(var Mem: TBinMemoryWriter);
+procedure g_Monsters_SaveState (st: TStream);
var
count, i: Integer;
- b: Byte;
begin
-// Ñ÷èòàåì êîëè÷åñòâî ñóùåñòâóþùèõ ìîíñòðîâ:
+ // Ñ÷èòàåì êîëè÷åñòâî ñóùåñòâóþùèõ ìîíñòðîâ
count := 0;
- if (gMonsters <> nil) then
+ for i := 0 to High(gMonsters) do
begin
- for i := 0 to High(gMonsters) do
- begin
- if (gMonsters[i] <> nil) then
- begin
- if (gMonsters[i].FMonsterType <> MONSTER_NONE) then count += 1;
- end;
- end;
+ if (gMonsters[i] <> nil) and (gMonsters[i].FMonsterType <> MONSTER_NONE) then count += 1;
end;
- Mem := TBinMemoryWriter.Create((count+1) * 350);
+ // Ñîõðàíÿåì èíôîðìàöèþ öåëåóêàçàòåëÿ
+ utils.writeInt(st, LongInt(pt_x));
+ utils.writeInt(st, LongInt(pt_xs));
+ utils.writeInt(st, LongInt(pt_y));
+ utils.writeInt(st, LongInt(pt_ys));
-// Ñîõðàíÿåì èíôîðìàöèþ öåëåóêàçàòåëÿ:
- Mem.WriteInt(pt_x);
- Mem.WriteInt(pt_xs);
- Mem.WriteInt(pt_y);
- Mem.WriteInt(pt_ys);
+ // Êîëè÷åñòâî ìîíñòðîâ
+ utils.writeInt(st, LongInt(count));
-// Êîëè÷åñòâî ìîíñòðîâ:
- Mem.WriteInt(count);
+ if (count = 0) then exit;
- if count = 0 then
- Exit;
-
-// Ñîõðàíÿåì ìîíñòðîâ:
+ // Ñîõðàíÿåì ìîíñòðîâ
for i := 0 to High(gMonsters) do
begin
- if (gMonsters[i] <> nil) then
+ if (gMonsters[i] <> nil) and (gMonsters[i].FMonsterType <> MONSTER_NONE) then
begin
- if (gMonsters[i].FMonsterType <> MONSTER_NONE) then
- begin
- // Òèï ìîíñòðà:
- b := gMonsters[i].MonsterType;
- Mem.WriteByte(b);
- // Ñîõðàíÿåì äàííûå ìîíñòðà:
- gMonsters[i].SaveState(Mem);
- end;
+ // Òèï ìîíñòðà
+ utils.writeInt(st, Byte(gMonsters[i].MonsterType));
+ // Ñîõðàíÿåì äàííûå ìîíñòðà:
+ gMonsters[i].SaveState(st);
end;
end;
end;
-procedure g_Monsters_LoadState(var Mem: TBinMemoryReader);
+
+procedure g_Monsters_LoadState (st: TStream);
var
count, a: Integer;
b: Byte;
mon: TMonster;
begin
- if Mem = nil then exit;
+ assert(st <> nil);
g_Monsters_Free(false);
// Çàãðóæàåì èíôîðìàöèþ öåëåóêàçàòåëÿ
- Mem.ReadInt(pt_x);
- Mem.ReadInt(pt_xs);
- Mem.ReadInt(pt_y);
- Mem.ReadInt(pt_ys);
+ pt_x := utils.readLongInt(st);
+ pt_xs := utils.readLongInt(st);
+ pt_y := utils.readLongInt(st);
+ pt_ys := utils.readLongInt(st);
// Êîëè÷åñòâî ìîíñòðîâ
- Mem.ReadInt(count);
+ count := utils.readLongInt(st);
- if count = 0 then exit;
+ if (count = 0) then exit;
+ if (count < 0) or (count > 1024*1024) then raise XStreamError.Create('invalid monster count');
// Çàãðóæàåì ìîíñòðîâ
for a := 0 to count-1 do
begin
// Òèï ìîíñòðà
- Mem.ReadByte(b);
+ b := utils.readByte(st);
// Ñîçäàåì ìîíñòðà
- mon := g_Monsters_Create(b, 0, 0, D_LEFT);
- if mon = nil then raise EBinSizeError.Create('g_Monsters_LoadState: ID = -1 (Can''t create)');
+ mon := g_Monsters_Create(b, 0, 0, TDirection.D_LEFT);
+ if (mon = nil) then raise XStreamError.Create('g_Monsters_LoadState: ID = -1 (can''t create)');
// Çàãðóæàåì äàííûå ìîíñòðà
- mon.LoadState(Mem);
+ mon.LoadState(st);
end;
end;
// ////////////////////////////////////////////////////////////////////////// //
-function g_Mons_SpawnAt (monType: Integer; x, y: Integer; dir: TDirection=D_LEFT): TMonster; overload;
+function g_Mons_SpawnAt (monType: Integer; x, y: Integer; dir: TDirection=TDirection.D_LEFT): TMonster; overload;
begin
result := nil;
if (monType >= MONSTER_DEMON) and (monType <= MONSTER_MAN) then
end;
-function g_Mons_SpawnAt (const typeName: AnsiString; x, y: Integer; dir: TDirection=D_LEFT): TMonster; overload;
+function g_Mons_SpawnAt (const typeName: AnsiString; x, y: Integer; dir: TDirection=TDirection.D_LEFT): TMonster; overload;
begin
result := g_Mons_SpawnAt(g_Mons_TypeIdByName(typeName), x, y, dir);
end;
for a := 0 to High(FAnim) do
begin
- FAnim[a, D_LEFT] := nil;
- FAnim[a, D_RIGHT] := nil;
+ FAnim[a, TDirection.D_LEFT] := nil;
+ FAnim[a, TDirection.D_RIGHT] := nil;
end;
for a := ANIM_SLEEP to ANIM_PAIN do
if g_Frames_Get(FramesID, 'FRAMES_MONSTER_'+MONSTERTABLE[MonsterType].Name+
'_'+ANIMTABLE[ANIM_DIE].name) then
begin
- FAnim[a, D_RIGHT] := TAnimation.Create(FramesID, ANIMTABLE[ANIM_DIE].loop,
+ FAnim[a, TDirection.D_RIGHT] := TAnimation.Create(FramesID, ANIMTABLE[ANIM_DIE].loop,
MONSTER_ANIMTABLE[MonsterType].AnimSpeed[ANIM_DIE]);
- FAnim[a, D_LEFT] := TAnimation.Create(FramesID, ANIMTABLE[ANIM_DIE].loop,
+ FAnim[a, TDirection.D_LEFT] := TAnimation.Create(FramesID, ANIMTABLE[ANIM_DIE].loop,
MONSTER_ANIMTABLE[MonsterType].AnimSpeed[ANIM_DIE]);
Continue;
end;
end;
- FAnim[a, D_RIGHT] := TAnimation.Create(FramesID, ANIMTABLE[a].loop,
+ FAnim[a, TDirection.D_RIGHT] := TAnimation.Create(FramesID, ANIMTABLE[a].loop,
MONSTER_ANIMTABLE[MonsterType].AnimSpeed[a]);
// Åñëè åñòü îòäåëüíàÿ ëåâàÿ àíèìàöèÿ - çàãðóæàåì:
g_Frames_Get(FramesID, s);
end;
- FAnim[a, D_LEFT] := TAnimation.Create(FramesID, ANIMTABLE[a].loop,
+ FAnim[a, TDirection.D_LEFT] := TAnimation.Create(FramesID, ANIMTABLE[a].loop,
MONSTER_ANIMTABLE[MonsterType].AnimSpeed[a]);
end;
if (t = HIT_ELECTRO) and (FMonsterType = MONSTER_FISH) and g_Game_IsServer then
begin
FSleep := 20;
- if Random(2) = 0 then
- FDirection := D_RIGHT
- else
- FDirection := D_LEFT;
+ if Random(2) = 0 then FDirection := TDirection.D_RIGHT else FDirection := TDirection.D_LEFT;
Result := True;
SetState(MONSTATE_RUN);
Exit;
it := g_Items_Create(FObj.X + (FObj.Rect.Width div 2),
FObj.Y + (FObj.Rect.Height div 2),
c, True, False);
+ g_Items_SetDrop(it); // mark it as monster drop
g_Obj_Push(g_Items_ObjByIdx(it), (FObj.Vel.X div 2)-3+Random(7),
(FObj.Vel.Y div 2)-Random(4));
- positionChanged(); // this updates spatial accelerators
+ //positionChanged(); // this updates spatial accelerators
if g_Game_IsServer and g_Game_IsNet then
MH_SEND_ItemSpawn(True, it);
end;
begin
for a := 0 to High(FAnim) do
begin
- FAnim[a, D_LEFT].Free();
- FAnim[a, D_RIGHT].Free();
+ FAnim[a, TDirection.D_LEFT].Free();
+ FAnim[a, TDirection.D_RIGHT].Free();
end;
vilefire.Free();
if FState = MONSTATE_SHOOT then
if GetPos(FTargetUID, @o) then
vilefire.Draw(o.X+o.Rect.X+(o.Rect.Width div 2)-32,
- o.Y+o.Rect.Y+o.Rect.Height-128, M_NONE);
+ o.Y+o.Rect.Y+o.Rect.Height-128, TMirrorType.None);
// Íå â îáëàñòè ðèñîâàíèÿ íå ðåñóåì:
//FIXME!
if FAnim[FCurAnim, FDirection] <> nil then
begin
// Åñëè íåò ëåâîé àíèìàöèè èëè îíà ñîâïàäàåò ñ ïðàâîé => îòðàæàåì ïðàâóþ:
- if (FDirection = D_LEFT) and
+ if (FDirection = TDirection.D_LEFT) and
((not MONSTER_ANIMTABLE[FMonsterType].LeftAnim) or
- (FAnim[FCurAnim, D_LEFT].FramesID = FAnim[FCurAnim, D_RIGHT].FramesID)) and
+ (FAnim[FCurAnim, TDirection.D_LEFT].FramesID = FAnim[FCurAnim, TDirection.D_RIGHT].FramesID)) and
(FMonsterType <> MONSTER_BARREL) then
- m := M_HORIZONTAL
+ m := TMirrorType.Horizontal
else
- m := M_NONE;
+ m := TMirrorType.None;
// Ëåâàÿ àíèìàöèÿ => ìåíÿåì ñìåùåíèå îòíîñèòåëüíî öåíòðà:
- if (FDirection = D_LEFT) and
+ if (FDirection = TDirection.D_LEFT) and
(FMonsterType <> MONSTER_BARREL) then
begin
dx := MONSTER_ANIMTABLE[FMonsterType].AnimDeltaLeft[FCurAnim].X;
dy := MONSTER_ANIMTABLE[FMonsterType].AnimDeltaLeft[FCurAnim].Y;
- if m = M_HORIZONTAL then
+ if m = TMirrorType.Horizontal then
begin // Íåò îòäåëüíîé ëåâîé àíèìàöèè
// Ðàññòîÿíèå îò êðàÿ òåêñòóðû äî êðàÿ âèçóàëüíîãî ïîëîæåíèÿ îáúåêòà íà òåêñòóðå:
c := (MONSTERTABLE[FMonsterType].Rect.X - dx) + MONSTERTABLE[FMonsterType].Rect.Width;
positionChanged();
if dir = 1 then
- FDirection := D_LEFT
+ FDirection := TDirection.D_LEFT
else
if dir = 2 then
- FDirection := D_RIGHT
+ FDirection := TDirection.D_RIGHT
else
if dir = 3 then
begin // îáðàòíîå
- if FDirection = D_RIGHT then
- FDirection := D_LEFT
+ if FDirection = TDirection.D_RIGHT then
+ FDirection := TDirection.D_LEFT
else
- FDirection := D_RIGHT;
+ FDirection := TDirection.D_RIGHT;
end;
// Ýôôåêò òåëåïîðòà â òî÷êå íàçíà÷åíèÿ:
// Ïîâîðà÷èâàåìñÿ â ñòîðîíó öåëè:
if sx > 0 then
- FDirection := D_RIGHT
+ FDirection := TDirection.D_RIGHT
else
- FDirection := D_LEFT;
+ FDirection := TDirection.D_LEFT;
// Åñëè ìîíñòð óìååò ñòðåëÿòü è åñòü ïî êîìó - ñòðåëÿåì:
if canShoot(FMonsterType) and (FTargetUID <> 0) then
FSleep := 15;
SetState(MONSTATE_RUN);
if Random(2) = 0 then
- FDirection := D_LEFT
+ FDirection := TDirection.D_LEFT
else
- FDirection := D_RIGHT;
+ FDirection := TDirection.D_RIGHT;
goto _end;
end;
FObj.Vel.Y := 0;
// Ïëàâàåì òóäà-ñþäà:
if Random(2) = 0 then
- FDirection := D_LEFT
+ FDirection := TDirection.D_LEFT
else
- FDirection := D_RIGHT;
+ FDirection := TDirection.D_RIGHT;
FSleep := 20;
SetState(MONSTATE_RUN);
end;
end;
// Áåæèì â âûáðàííóþ ñòîðîíó:
- if FDirection = D_RIGHT then
+ if FDirection = TDirection.D_RIGHT then
FObj.Vel.X := MONSTERTABLE[FMonsterType].RunVel
else
FObj.Vel.X := -MONSTERTABLE[FMonsterType].RunVel;
end;
// Áåæèì â âûáðàííóþ ñòîðîíó:
- if FDirection = D_RIGHT then
+ if FDirection = TDirection.D_RIGHT then
FObj.Vel.X := MONSTERTABLE[FMonsterType].RunVel
else
FObj.Vel.X := -MONSTERTABLE[FMonsterType].RunVel;
end;
// Áåæèì â âûáðàííóþ ñòîðîíó:
- if FDirection = D_RIGHT then
+ if FDirection = TDirection.D_RIGHT then
FObj.Vel.X := MONSTERTABLE[FMonsterType].RunVel
else
FObj.Vel.X := -MONSTERTABLE[FMonsterType].RunVel;
end;
// Áåæèì â âûáðàííóþ ñòîðîíó:
- if FDirection = D_RIGHT then
+ if FDirection = TDirection.D_RIGHT then
FObj.Vel.X := MONSTERTABLE[FMonsterType].RunVel
else
FObj.Vel.X := -MONSTERTABLE[FMonsterType].RunVel;
if (FMonsterType = MONSTER_PAIN) then
begin
mon := g_Monsters_Create(MONSTER_SOUL, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2)-30,
- FObj.Y+FObj.Rect.Y+20, D_LEFT);
+ FObj.Y+FObj.Rect.Y+20, TDirection.D_LEFT);
if mon <> nil then
begin
mon.SetState(MONSTATE_GO);
end;
mon := g_Monsters_Create(MONSTER_SOUL, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2),
- FObj.Y+FObj.Rect.Y+20, D_RIGHT);
+ FObj.Y+FObj.Rect.Y+20, TDirection.D_RIGHT);
if mon <> nil then
begin
mon.SetState(MONSTATE_GO);
end;
mon := g_Monsters_Create(MONSTER_SOUL, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2)-15,
- FObj.Y+FObj.Rect.Y, D_RIGHT);
+ FObj.Y+FObj.Rect.Y, TDirection.D_RIGHT);
if mon <> nil then
begin
mon.SetState(MONSTATE_GO);
if FCurAnim = ANIM_ATTACK2 then
begin
o := FObj;
- o.Vel.X := IfThen(FDirection = D_RIGHT, 1, -1)*IfThen(FMonsterType = MONSTER_CYBER, 60, 50);
+ o.Vel.X := IfThen(FDirection = TDirection.D_RIGHT, 1, -1)*IfThen(FMonsterType = MONSTER_CYBER, 60, 50);
if g_Weapon_Hit(@o, IfThen(FMonsterType = MONSTER_CYBER, 33, 50), FUID, HIT_SOME) <> 0 then
g_Sound_PlayExAt('SOUND_MONSTER_SKEL_HIT', FObj.X, FObj.Y);
end;
// Âû÷èñëÿåì êîîðäèíàòû, îòêóäà âûëåòèò ïóëÿ:
wx := MONSTER_ANIMTABLE[FMonsterType].wX;
- if FDirection = D_LEFT then
+ if FDirection = TDirection.D_LEFT then
begin
wx := MONSTER_ANIMTABLE[FMonsterType].wX-(MONSTERTABLE[FMonsterType].Rect.X+(MONSTERTABLE[FMonsterType].Rect.Width div 2));
wx := MONSTERTABLE[FMonsterType].Rect.X+(MONSTERTABLE[FMonsterType].Rect.Width div 2)-wx;
end;
// Áåæèì â âûáðàííóþ ñòîðîíó:
- if FDirection = D_RIGHT then
+ if FDirection = TDirection.D_RIGHT then
FObj.Vel.X := MONSTERTABLE[FMonsterType].RunVel
else
FObj.Vel.X := -MONSTERTABLE[FMonsterType].RunVel;
end;
// Áåæèì â âûáðàííóþ ñòîðîíó:
- if FDirection = D_RIGHT then
+ if FDirection = TDirection.D_RIGHT then
FObj.Vel.X := MONSTERTABLE[FMonsterType].RunVel
else
FObj.Vel.X := -MONSTERTABLE[FMonsterType].RunVel;
end;
// Áåæèì â âûáðàííóþ ñòîðîíó:
- if FDirection = D_RIGHT then
+ if FDirection = TDirection.D_RIGHT then
FObj.Vel.X := MONSTERTABLE[FMonsterType].RunVel
else
FObj.Vel.X := -MONSTERTABLE[FMonsterType].RunVel;
end;
// Áåæèì â âûáðàííóþ ñòîðîíó:
- if FDirection = D_RIGHT then
+ if FDirection = TDirection.D_RIGHT then
FObj.Vel.X := MONSTERTABLE[FMonsterType].RunVel
else
FObj.Vel.X := -MONSTERTABLE[FMonsterType].RunVel;
if FCurAnim = ANIM_ATTACK2 then
begin
o := FObj;
- o.Vel.X := IfThen(FDirection = D_RIGHT, 1, -1)*IfThen(FMonsterType = MONSTER_CYBER, 60, 50);
+ o.Vel.X := IfThen(FDirection = TDirection.D_RIGHT, 1, -1)*IfThen(FMonsterType = MONSTER_CYBER, 60, 50);
g_Weapon_Hit(@o, IfThen(FMonsterType = MONSTER_CYBER, 33, 50), FUID, HIT_SOME);
end;
procedure TMonster.Turn();
begin
// Ðàçâîðà÷èâàåìñÿ:
- if FDirection = D_LEFT then
- FDirection := D_RIGHT
- else
- FDirection := D_LEFT;
+ if FDirection = TDirection.D_LEFT then FDirection := TDirection.D_RIGHT else FDirection := TDirection.D_LEFT;
// Áåæèì â âûáðàííóþ ñòîðîíó:
- if FDirection = D_RIGHT then
+ if FDirection = TDirection.D_RIGHT then
FObj.Vel.X := MONSTERTABLE[FMonsterType].RunVel
else
FObj.Vel.X := -MONSTERTABLE[FMonsterType].RunVel;
WakeUpSound();
end;
-procedure TMonster.SaveState(var Mem: TBinMemoryWriter);
+procedure TMonster.SaveState (st: TStream);
var
i: Integer;
- sig: DWORD;
b: Byte;
anim: Boolean;
begin
- if Mem = nil then
- Exit;
-
-// Ñèãíàòóðà ìîíñòðà:
- sig := MONSTER_SIGNATURE; // 'MONS'
- Mem.WriteDWORD(sig);
-// UID ìîíñòðà:
- Mem.WriteWord(FUID);
-// Íàïðàâëåíèå:
- if FDirection = D_LEFT then
- b := 1
- else // D_RIGHT
- b := 2;
- Mem.WriteByte(b);
-// Íàäî ëè óäàëèòü åãî:
- Mem.WriteBoolean(FRemoved);
-// Îñòàëîñü çäîðîâüÿ:
- Mem.WriteInt(FHealth);
-// Ñîñòîÿíèå:
- Mem.WriteByte(FState);
-// Òåêóùàÿ àíèìàöèÿ:
- Mem.WriteByte(FCurAnim);
-// UID öåëè:
- Mem.WriteWord(FTargetUID);
-// Âðåìÿ ïîñëå ïîòåðè öåëè:
- Mem.WriteInt(FTargetTime);
-// Ïîâåäåíèå ìîíñòðà:
- Mem.WriteByte(FBehaviour);
-// Ãîòîâíîñòü ê âûñòðåëó:
- Mem.WriteInt(FAmmo);
-// Áîëü:
- Mem.WriteInt(FPain);
-// Âðåìÿ îæèäàíèÿ:
- Mem.WriteInt(FSleep);
-// Îçâó÷èâàòü ëè áîëü:
- Mem.WriteBoolean(FPainSound);
-// Áûëà ëè àòàêà âî âðåìÿ àíèìàöèè àòàêè:
- Mem.WriteBoolean(FWaitAttackAnim);
-// Íàäî ëè ñòðåëÿòü íà ñëåäóþùåì øàãå:
- Mem.WriteBoolean(FChainFire);
-// Ïîäëåæèò ëè ðåñïàâíó:
- Mem.WriteBoolean(FNoRespawn);
-// Êîîðäèíàòû öåëè:
- Mem.WriteInt(tx);
- Mem.WriteInt(ty);
-// ID ìîíñòðà ïðè ñòàðòå êàðòû:
- Mem.WriteInt(FStartID);
-// Èíäåêñ òðèããåðà, ñîçäàâøåãî ìîíñòðà:
- Mem.WriteInt(FSpawnTrigger);
-// Îáúåêò ìîíñòðà:
- Obj_SaveState(@FObj, Mem);
-// Åñòü ëè àíèìàöèÿ îãíÿ êîëäóíà:
- anim := vilefire <> nil;
- Mem.WriteBoolean(anim);
-// Åñëè åñòü - ñîõðàíÿåì:
- if anim then
- vilefire.SaveState(Mem);
-// Àíèìàöèè:
+ assert(st <> nil);
+
+ // Ñèãíàòóðà ìîíñòðà:
+ utils.writeSign(st, 'MONS');
+ utils.writeInt(st, Byte(0)); // version
+ // UID ìîíñòðà:
+ utils.writeInt(st, Word(FUID));
+ // Íàïðàâëåíèå
+ if FDirection = TDirection.D_LEFT then b := 1 else b := 2; // D_RIGHT
+ utils.writeInt(st, Byte(b));
+ // Íàäî ëè óäàëèòü åãî
+ utils.writeBool(st, FRemoved);
+ // Îñòàëîñü çäîðîâüÿ
+ utils.writeInt(st, LongInt(FHealth));
+ // Ñîñòîÿíèå
+ utils.writeInt(st, Byte(FState));
+ // Òåêóùàÿ àíèìàöèÿ
+ utils.writeInt(st, Byte(FCurAnim));
+ // UID öåëè
+ utils.writeInt(st, Word(FTargetUID));
+ // Âðåìÿ ïîñëå ïîòåðè öåëè
+ utils.writeInt(st, LongInt(FTargetTime));
+ // Ïîâåäåíèå ìîíñòðà
+ utils.writeInt(st, Byte(FBehaviour));
+ // Ãîòîâíîñòü ê âûñòðåëó
+ utils.writeInt(st, LongInt(FAmmo));
+ // Áîëü
+ utils.writeInt(st, LongInt(FPain));
+ // Âðåìÿ îæèäàíèÿ
+ utils.writeInt(st, LongInt(FSleep));
+ // Îçâó÷èâàòü ëè áîëü
+ utils.writeBool(st, FPainSound);
+ // Áûëà ëè àòàêà âî âðåìÿ àíèìàöèè àòàêè
+ utils.writeBool(st, FWaitAttackAnim);
+ // Íàäî ëè ñòðåëÿòü íà ñëåäóþùåì øàãå
+ utils.writeBool(st, FChainFire);
+ // Ïîäëåæèò ëè ðåñïàâíó
+ utils.writeBool(st, FNoRespawn);
+ // Êîîðäèíàòû öåëè
+ utils.writeInt(st, LongInt(tx));
+ utils.writeInt(st, LongInt(ty));
+ // ID ìîíñòðà ïðè ñòàðòå êàðòû
+ utils.writeInt(st, LongInt(FStartID));
+ // Èíäåêñ òðèããåðà, ñîçäàâøåãî ìîíñòðà
+ utils.writeInt(st, LongInt(FSpawnTrigger));
+ // Îáúåêò ìîíñòðà
+ Obj_SaveState(st, @FObj);
+ // Åñòü ëè àíèìàöèÿ îãíÿ êîëäóíà
+ anim := (vilefire <> nil);
+ utils.writeBool(st, anim);
+ // Åñëè åñòü - ñîõðàíÿåì:
+ if anim then vilefire.SaveState(st);
+ // Àíèìàöèè
for i := ANIM_SLEEP to ANIM_PAIN do
begin
- // Åñòü ëè ëåâàÿ àíèìàöèÿ:
- anim := FAnim[i, D_LEFT] <> nil;
- Mem.WriteBoolean(anim);
- // Åñëè åñòü - ñîõðàíÿåì:
- if anim then
- FAnim[i, D_LEFT].SaveState(Mem);
- // Åñòü ëè ïðàâàÿ àíèìàöèÿ:
- anim := FAnim[i, D_RIGHT] <> nil;
- Mem.WriteBoolean(anim);
- // Åñëè åñòü - ñîõðàíÿåì:
- if anim then
- FAnim[i, D_RIGHT].SaveState(Mem);
+ // Åñòü ëè ëåâàÿ àíèìàöèÿ
+ anim := (FAnim[i, TDirection.D_LEFT] <> nil);
+ utils.writeBool(st, anim);
+ // Åñëè åñòü - ñîõðàíÿåì
+ if anim then FAnim[i, TDirection.D_LEFT].SaveState(st);
+ // Åñòü ëè ïðàâàÿ àíèìàöèÿ
+ anim := (FAnim[i, TDirection.D_RIGHT] <> nil);
+ utils.writeBool(st, anim);
+ // Åñëè åñòü - ñîõðàíÿåì
+ if anim then FAnim[i, TDirection.D_RIGHT].SaveState(st);
end;
end;
-procedure TMonster.LoadState(var Mem: TBinMemoryReader);
+procedure TMonster.LoadState (st: TStream);
var
i: Integer;
- sig: DWORD;
b: Byte;
anim: Boolean;
begin
- if Mem = nil then
- Exit;
+ assert(st <> nil);
-// Ñèãíàòóðà ìîíñòðà:
- Mem.ReadDWORD(sig);
- if sig <> MONSTER_SIGNATURE then // 'MONS'
- begin
- raise EBinSizeError.Create('TMonster.LoadState: Wrong Monster Signature');
- end;
+ // Ñèãíàòóðà ìîíñòðà:
+ if not utils.checkSign(st, 'MONS') then raise XStreamError.Create('invalid monster signature');
+ if (utils.readByte(st) <> 0) then raise XStreamError.Create('invalid monster version');
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);
+ // UID ìîíñòðà:
+ FUID := utils.readWord(st);
//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
- FDirection := D_LEFT
- else // b = 2
- FDirection := D_RIGHT;
-// Íàäî ëè óäàëèòü åãî:
- Mem.ReadBoolean(FRemoved);
-// Îñòàëîñü çäîðîâüÿ:
- Mem.ReadInt(FHealth);
-// Ñîñòîÿíèå:
- Mem.ReadByte(FState);
-// Òåêóùàÿ àíèìàöèÿ:
- Mem.ReadByte(FCurAnim);
-// UID öåëè:
- Mem.ReadWord(FTargetUID);
-// Âðåìÿ ïîñëå ïîòåðè öåëè:
- Mem.ReadInt(FTargetTime);
-// Ïîâåäåíèå ìîíñòðà:
- Mem.ReadByte(FBehaviour);
-// Ãîòîâíîñòü ê âûñòðåëó:
- Mem.ReadInt(FAmmo);
-// Áîëü:
- Mem.ReadInt(FPain);
-// Âðåìÿ îæèäàíèÿ:
- Mem.ReadInt(FSleep);
-// Îçâó÷èâàòü ëè áîëü:
- Mem.ReadBoolean(FPainSound);
-// Áûëà ëè àòàêà âî âðåìÿ àíèìàöèè àòàêè:
- Mem.ReadBoolean(FWaitAttackAnim);
-// Íàäî ëè ñòðåëÿòü íà ñëåäóþùåì øàãå:
- Mem.ReadBoolean(FChainFire);
-// Ïîäëåæèò ëè ðåñïàâíó
- Mem.ReadBoolean(FNoRespawn);
-// Êîîðäèíàòû öåëè:
- Mem.ReadInt(tx);
- Mem.ReadInt(ty);
-// ID ìîíñòðà ïðè ñòàðòå êàðòû:
- Mem.ReadInt(FStartID);
-// Èíäåêñ òðèããåðà, ñîçäàâøåãî ìîíñòðà:
- Mem.ReadInt(FSpawnTrigger);
-// Îáúåêò ìîíñòðà:
- Obj_LoadState(@FObj, Mem);
-// Åñòü ëè àíèìàöèÿ îãíÿ êîëäóíà:
- Mem.ReadBoolean(anim);
-// Åñëè åñòü - çàãðóæàåì:
+ // Íàïðàâëåíèå
+ b := utils.readByte(st);
+ if b = 1 then FDirection := TDirection.D_LEFT else FDirection := TDirection.D_RIGHT; // b = 2
+ // Íàäî ëè óäàëèòü åãî
+ FRemoved := utils.readBool(st);
+ // Îñòàëîñü çäîðîâüÿ
+ FHealth := utils.readLongInt(st);
+ // Ñîñòîÿíèå
+ FState := utils.readByte(st);
+ // Òåêóùàÿ àíèìàöèÿ
+ FCurAnim := utils.readByte(st);
+ // UID öåëè
+ FTargetUID := utils.readWord(st);
+ // Âðåìÿ ïîñëå ïîòåðè öåëè
+ FTargetTime := utils.readLongInt(st);
+ // Ïîâåäåíèå ìîíñòðà
+ FBehaviour := utils.readByte(st);
+ // Ãîòîâíîñòü ê âûñòðåëó
+ FAmmo := utils.readLongInt(st);
+ // Áîëü
+ FPain := utils.readLongInt(st);
+ // Âðåìÿ îæèäàíèÿ
+ FSleep := utils.readLongInt(st);
+ // Îçâó÷èâàòü ëè áîëü
+ FPainSound := utils.readBool(st);
+ // Áûëà ëè àòàêà âî âðåìÿ àíèìàöèè àòàêè
+ FWaitAttackAnim := utils.readBool(st);
+ // Íàäî ëè ñòðåëÿòü íà ñëåäóþùåì øàãå
+ FChainFire := utils.readBool(st);
+ // Ïîäëåæèò ëè ðåñïàâíó
+ FNoRespawn := utils.readBool(st);
+ // Êîîðäèíàòû öåëè
+ tx := utils.readLongInt(st);
+ ty := utils.readLongInt(st);
+ // ID ìîíñòðà ïðè ñòàðòå êàðòû
+ FStartID := utils.readLongInt(st);
+ // Èíäåêñ òðèããåðà, ñîçäàâøåãî ìîíñòðà
+ FSpawnTrigger := utils.readLongInt(st);
+ // Îáúåêò ìîíñòðà
+ Obj_LoadState(@FObj, st);
+ // Åñòü ëè àíèìàöèÿ îãíÿ êîëäóíà
+ anim := utils.readBool(st);
+ // Åñëè åñòü - çàãðóæàåì:
if anim then
begin
Assert(vilefire <> nil, 'TMonster.LoadState: no vilefire anim');
- vilefire.LoadState(Mem);
+ vilefire.LoadState(st);
end;
-// Àíèìàöèè:
+ // Àíèìàöèè
for i := ANIM_SLEEP to ANIM_PAIN do
begin
- // Åñòü ëè ëåâàÿ àíèìàöèÿ:
- Mem.ReadBoolean(anim);
- // Åñëè åñòü - çàãðóæàåì:
+ // Åñòü ëè ëåâàÿ àíèìàöèÿ
+ anim := utils.readBool(st);
+ // Åñëè åñòü - çàãðóæàåì
if anim then
begin
- Assert(FAnim[i, D_LEFT] <> nil,
- 'TMonster.LoadState: no '+IntToStr(i)+'_left anim');
- FAnim[i, D_LEFT].LoadState(Mem);
+ Assert(FAnim[i, TDirection.D_LEFT] <> nil, 'TMonster.LoadState: no '+IntToStr(i)+'_left anim');
+ FAnim[i, TDirection.D_LEFT].LoadState(st);
end;
- // Åñòü ëè ïðàâàÿ àíèìàöèÿ:
- Mem.ReadBoolean(anim);
- // Åñëè åñòü - çàãðóæàåì:
+ // Åñòü ëè ïðàâàÿ àíèìàöèÿ
+ anim := utils.readBool(st);
+ // Åñëè åñòü - çàãðóæàåì
if anim then
begin
- Assert(FAnim[i, D_RIGHT] <> nil,
- 'TMonster.LoadState: no '+IntToStr(i)+'_right anim');
- FAnim[i, D_RIGHT].LoadState(Mem);
+ Assert(FAnim[i, TDirection.D_RIGHT] <> nil, 'TMonster.LoadState: no '+IntToStr(i)+'_right anim');
+ FAnim[i, TDirection.D_RIGHT].LoadState(st);
end;
end;
end;
+
procedure TMonster.ActivateTriggers();
var
a: Integer;