X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_monsters.pas;h=a6e39d1f07215ddf0ac526be15ad345df66bd787;hb=52c1edc4aba4aa850742200a391845a91f3451ef;hp=e496521d4485a3ada649639ff4b7ebec96ae0bcf;hpb=331297e82162a6acd3e9e07605368e329ce66105;p=d2df-sdl.git diff --git a/src/game/g_monsters.pas b/src/game/g_monsters.pas index e496521..a6e39d1 100644 --- a/src/game/g_monsters.pas +++ b/src/game/g_monsters.pas @@ -2,8 +2,7 @@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * the Free Software Foundation, version 3 of the License ONLY. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -40,6 +39,8 @@ const MONSTATE_REVIVE = 10; MONSTATE_RUNOUT = 11; + MON_BURN_TIME = 100; + { in mapdef now BH_NORMAL = 0; BH_KILLER = 1; @@ -123,6 +124,7 @@ type function Damage(aDamage: Word; VelX, VelY: Integer; SpawnerUID: Word; t: Byte): Boolean; function Heal(Value: Word): Boolean; procedure BFGHit(); + procedure PreUpdate(); procedure Update(); procedure ClientUpdate(); procedure ClientAttack(wx, wy, atx, aty: Integer); @@ -145,7 +147,7 @@ type function AnimIsReverse: Boolean; function shoot(o: PObj; immediately: Boolean): Boolean; function kick(o: PObj): Boolean; - procedure CatchFire(Attacker: Word); + procedure CatchFire(Attacker: Word; Timeout: Integer = MON_BURN_TIME); procedure OnFireFlame(Times: DWORD = 1); procedure positionChanged (); //WARNING! call this after monster position was changed, or coldet will not work right! @@ -231,6 +233,7 @@ procedure g_Monsters_Init (); 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_PreUpdate (); procedure g_Monsters_Update (); procedure g_Monsters_Draw (); procedure g_Monsters_DrawHealth (); @@ -1376,6 +1379,8 @@ begin FStartDirection := Direction; FStartX := GameX; FStartY := GameY; + FObj.oldX := FObj.X; + FObj.oldY := FObj.Y; end; mon.positionChanged(); @@ -1411,6 +1416,16 @@ begin end; end; +procedure g_Monsters_PreUpdate(); +var + a: Integer; +begin + if gMonsters = nil then Exit; + for a := 0 to High(gMonsters) do + if (gMonsters[a] <> nil) and (not gMonsters[a].FRemoved) then + gMonsters[a].PreUpdate(); +end; + procedure g_Monsters_Update(); var a: Integer; @@ -1992,6 +2007,9 @@ var begin Result := False; +// Ìîíñòð ñòàòè÷åí ïîêà èäåò warmup + if (gLMSRespawn > LMS_RESPAWN_NONE) then exit; + // Óìèðàåò, óìåð èëè âîñêðåøàåòñÿ => óðîí äåëàòü íåêîìó: if (FState = MONSTATE_DEAD) or (FState = MONSTATE_DIE) or (FState = MONSTATE_REVIVE) then Exit; @@ -2006,6 +2024,15 @@ begin Exit; end; +// Àð÷è íå ãîðÿò, ÷åðåïà óæå ãîðÿò + if (t = HIT_FLAME) and (FMonsterType in [MONSTER_VILE, MONSTER_SOUL]) then + begin + // Ïðîñíóòüñÿ âñå-òàêè ñòîèò + if FState = MONSTATE_SLEEP then + SetState(MONSTATE_GO); + Exit; + end; + // Ëîâóøêà óáèâàåò ñðàçó: if t = HIT_TRAP then FHealth := -100; @@ -2196,12 +2223,14 @@ end; procedure TMonster.Draw(); var m: TMirrorType; - dx, dy, c: Integer; + dx, dy, c, fX, fY: Integer; o: TObj; begin //e_CharFont_Print(gMenuSmallFont, Obj.X+Obj.Rect.X, Obj.Y+Obj.Rect.Y, 'TYPE: '+IntToStr(FMonsterType)); //e_CharFont_Print(gMenuSmallFont, Obj.X+Obj.Rect.X, Obj.Y+Obj.Rect.Y+16, 'STATE: '+IntToStr(FState)); + FObj.lerp(gLerpFactor, fX, fY); + // Åñëè êîëäóí ñòðåëÿåò, òî ðèñóåì îãîíü: if FMonsterType = MONSTER_VILE then if FState = MONSTATE_SHOOT then @@ -2261,7 +2290,7 @@ begin end; // Ðèñóåì: - FAnim[FCurAnim, FDirection].Draw(Obj.X+dx, Obj.Y+dy, m); + FAnim[FCurAnim, FDirection].Draw(fX+dx, fY+dy, m); end; if g_debug_Frames then @@ -2393,6 +2422,8 @@ begin FObj.X := X - FObj.Rect.X; FObj.Y := Y - FObj.Rect.Y; + FObj.oldX := FObj.X; // don't interpolate after teleport + FObj.oldY := FObj.Y; positionChanged(); if dir = 1 then @@ -2426,6 +2457,12 @@ begin Result := True; end; +procedure TMonster.PreUpdate(); +begin + FObj.oldX := FObj.X; + FObj.oldY := FObj.Y; +end; + procedure TMonster.Update(); var a, b, sx, sy, wx, wy, oldvelx: Integer; @@ -2433,11 +2470,16 @@ var o, co: TObj; fall: Boolean; mon: TMonster; + mit: PMonster; + it: TMonsterGrid.Iter; label _end; begin fall := True; +// Ìîíñòð ñòàòè÷åí ïîêà èäåò warmup + if (gLMSRespawn > LMS_RESPAWN_NONE) then exit; + // Ðûáû "ëåòàþò" òîëüêî â âîäå: if FMonsterType = MONSTER_FISH then if g_Obj_CollidePanel(@FObj, 0, 0, PANEL_WATER or PANEL_ACID1 or PANEL_ACID2) then @@ -2469,6 +2511,15 @@ begin st := g_Obj_Move(@FObj, fall, True, True); positionChanged(); // this updates spatial accelerators +// Åñëè ãîðèì - ïîäæèãàåì äðóãèõ ìîíñòðîâ, íî íå íà 100 òèêîâ êàæäûé ðàç: + if FFireTime > 0 then + begin + it := monsGrid.forEachInAABB(FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y, FObj.Rect.Width, FObj.Rect.Height); + for mit in it do + if mit.UID <> FUID then + mit.CatchFire(FFireAttacker, FFireTime); + end; + // Âûëåòåë çà êàðòó - óäàëÿåì è çàïóñêàåì òðèããåðû: if WordBool(st and MOVE_FALLOUT) or (FObj.X < -1000) or (FObj.X > gMapInfo.Width+1000) or (FObj.Y < -1000) then @@ -2825,7 +2876,7 @@ begin // Ðûáà ïëûâåò ââåðõ: if FObj.Vel.Y < 0 then - if not g_Obj_CollideWater(@FObj, 0, -16) then + if not g_Obj_CollideLiquid(@FObj, 0, -16) then begin // Âñïëûëè äî ïîâåðõíîñòè - ñòîï: FObj.Vel.Y := 0; @@ -2887,9 +2938,9 @@ begin FObj.Rect.Width, 8, @co) and (Random(3) = 0) then // Ïèíàåì òðóïû if FObj.Vel.X < 0 then - gCorpses[a].Damage(b*2, -b, Random(7)) // íàëåâî + gCorpses[a].Damage(b*2, FUID, -b, Random(7)) // íàëåâî else - gCorpses[a].Damage(b*2, b, Random(7)); // íàïðàâî + gCorpses[a].Damage(b*2, FUID, b, Random(7)); // íàïðàâî end; end; // Åñëè öåëü âûñîêî, òî, âîçìîæíî, ïðûãàåì: @@ -3243,6 +3294,19 @@ _end: wx := FObj.X + wx; wy := FObj.Y + MONSTER_ANIMTABLE[FMonsterType].wY; + // Ìîíñòð íå ìîæåò öåëèòüñÿ â îáúåêò çà ñïèíîé, ñòðåëÿÿ âëåâî: + if (FDirection = TDirection.D_LEFT) and (tx > wx) then + begin + tx := wx - 32; + ty := wy + Random(11) - 5; + end; + // È àíàëîãè÷íî, ñòðåëÿÿ âïðàâî: + if (FDirection = TDirection.D_RIGHT) and (tx < wx) then + begin + tx := wx + 32; + ty := wy + Random(11) - 5; + end; + // Äåëàåì âûñòðåë íóæíûì îðóæèåì: case FMonsterType of MONSTER_IMP: @@ -3405,6 +3469,10 @@ begin sx := 0; // SHUT UP COMPILER sy := 0; fall := True; + +// Ìîíñòð ñòàòè÷åí ïîêà èäåò warmup + if (gLMSRespawn > LMS_RESPAWN_NONE) then exit; + // Ðûáû "ëåòàþò" òîëüêî â âîäå: if FMonsterType = MONSTER_FISH then if g_Obj_CollidePanel(@FObj, 0, 0, PANEL_WATER or PANEL_ACID1 or PANEL_ACID2) then @@ -3661,7 +3729,7 @@ begin // Ðûáà ïëûâåò ââåðõ: if FObj.Vel.Y < 0 then - if not g_Obj_CollideWater(@FObj, 0, -16) then + if not g_Obj_CollideLiquid(@FObj, 0, -16) then begin // Âñïëûëè äî ïîâåðõíîñòè - ñòîï: FObj.Vel.Y := 0; @@ -3720,9 +3788,9 @@ begin FObj.Rect.Width, 8, @co) and (Random(3) = 0) then // Ïèíàåì òðóïû if FObj.Vel.X < 0 then - gCorpses[a].Damage(b*2, -b, Random(7)) // íàëåâî + gCorpses[a].Damage(b*2, FUID, -b, Random(7)) // íàëåâî else - gCorpses[a].Damage(b*2, b, Random(7)); // íàïðàâî + gCorpses[a].Damage(b*2, FUID, b, Random(7)); // íàïðàâî end; end; end; @@ -4623,9 +4691,16 @@ begin SetLength(FDieTriggers, 0); end; -procedure TMonster.CatchFire(Attacker: Word); +procedure TMonster.CatchFire(Attacker: Word; Timeout: Integer = MON_BURN_TIME); begin - FFireTime := 100; + if FMonsterType in [MONSTER_SOUL, MONSTER_VILE] then + exit; // àð÷è íå ãîðÿò, ÷åðåïà óæå ãîðÿò + if Timeout <= 0 then exit; + if g_Obj_CollidePanel(@FObj, 0, 0, PANEL_WATER or PANEL_ACID1 or PANEL_ACID2) then + exit; // íå ïîäãîðàåì â âîäå íà âñÿêèé ñëó÷àé + if FFireTime <= 0 then + g_Sound_PlayExAt('SOUND_IGNITE', FObj.X, FObj.Y); + FFireTime := Timeout; FFireAttacker := Attacker; if g_Game_IsNet and g_Game_IsServer then MH_SEND_MonsterState(FUID); end;