index cc4926a3135a2a5a97cfa4a3e06e71907eea6008..690626078d17713d17936ec942a69007ca21ae1d 100644 (file)
--- a/src/game/g_monsters.pas
+++ b/src/game/g_monsters.pas
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*)
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*)
-{$MODE DELPHI}
+{$INCLUDE ../shared/a_modes.inc}
unit g_monsters;
interface
unit g_monsters;
interface
FShellTimer: Integer;
FShellType: Byte;
FFirePainTime: Integer;
FShellTimer: Integer;
FShellType: Byte;
FFirePainTime: Integer;
+ FFireAttacker: Word;
vilefire: TAnimation;
FDieTriggers: Array of Integer;
vilefire: TAnimation;
FDieTriggers: Array of Integer;
function Live(): Boolean;
procedure SetHealth(aH: Integer);
procedure Push(vx, vy: Integer);
function Live(): Boolean;
procedure SetHealth(aH: Integer);
procedure Push(vx, vy: Integer);
- function Damage(Damage: Word; VelX, VelY: Integer; SpawnerUID: Word; t: Byte): Boolean;
+ function Damage(aDamage: Word; VelX, VelY: Integer; SpawnerUID: Word; t: Byte): Boolean;
function Heal(Value: Word): Boolean;
procedure BFGHit();
procedure Update();
procedure ClientUpdate();
function Heal(Value: Word): Boolean;
procedure BFGHit();
procedure Update();
procedure ClientUpdate();
- procedure ClientAttack(wx, wy, tx, ty: Integer);
+ procedure ClientAttack(wx, wy, atx, aty: Integer);
procedure SetDeadAnim;
procedure Draw();
procedure WakeUp();
procedure SetDeadAnim;
procedure Draw();
procedure WakeUp();
function AnimIsReverse: Boolean;
function shoot(o: PObj; immediately: Boolean): Boolean;
function kick(o: PObj): Boolean;
function AnimIsReverse: Boolean;
function shoot(o: PObj; immediately: Boolean): Boolean;
function kick(o: PObj): Boolean;
- procedure CatchFire();
+ procedure CatchFire(Attacker: Word);
procedure OnFireFlame(Times: DWORD = 1);
procedure OnFireFlame(Times: DWORD = 1);
+ procedure positionChanged (); //WARNING! call this after monster position was changed, or coldet will not work right!
+
property MonsterType: Byte read FMonsterType;
property MonsterHealth: Integer read FHealth write FHealth;
property MonsterAmmo: Integer read FAmmo write FAmmo;
property MonsterType: Byte read FMonsterType;
property MonsterHealth: Integer read FHealth write FHealth;
property MonsterAmmo: Integer read FAmmo write FAmmo;
FState := STATE_SLEEP;
FCurAnim := ANIM_SLEEP;
FState := STATE_SLEEP;
FCurAnim := ANIM_SLEEP;
+ positionChanged(); // this updates spatial accelerators
+
if g_Game_IsNet and g_Game_IsServer then
begin
MH_SEND_MonsterPos(FUID);
if g_Game_IsNet and g_Game_IsServer then
begin
MH_SEND_MonsterPos(FUID);
FBehaviour := BH_NORMAL;
FFireTime := 0;
FFirePainTime := 0;
FBehaviour := BH_NORMAL;
FFireTime := 0;
FFirePainTime := 0;
+ FFireAttacker := 0;
if FMonsterType in [MONSTER_ROBO, MONSTER_BARREL] then
FBloodKind := BLOOD_SPARKS
if FMonsterType in [MONSTER_ROBO, MONSTER_BARREL] then
FBloodKind := BLOOD_SPARKS
vilefire := nil;
end;
vilefire := nil;
end;
-function TMonster.Damage(Damage: Word; VelX, VelY: Integer; SpawnerUID: Word; t: Byte): Boolean;
+function TMonster.Damage(aDamage: Word; VelX, VelY: Integer; SpawnerUID: Word; t: Byte): Boolean;
var
c, it: Integer;
p: TPlayer;
var
c, it: Integer;
p: TPlayer;
// Ðîáîòó óðîíà íåò:
if FMonsterType = MONSTER_ROBO then
// Ðîáîòó óðîíà íåò:
if FMonsterType = MONSTER_ROBO then
- Damage := 0;
+ aDamage := 0;
// Íàíîñèì óðîí:
// Íàíîñèì óðîí:
- if g_Game_IsServer then Dec(FHealth, Damage);
+ if g_Game_IsServer then Dec(FHealth, aDamage);
// Óñèëèâàåì áîëü ìîíñòðà îò óðîíà:
if FPain = 0 then
FPain := 3;
// Óñèëèâàåì áîëü ìîíñòðà îò óðîíà:
if FPain = 0 then
FPain := 3;
- FPain := FPain+Damage;
+ FPain := FPain+aDamage;
// Åñëè áîëü ñóùåñòâåííàÿ, òî ìåíÿåì ñîñòîÿíèå íà áîëåâîå:
if FState <> STATE_PAIN then
// Åñëè áîëü ñóùåñòâåííàÿ, òî ìåíÿåì ñîñòîÿíèå íà áîëåâîå:
if FState <> STATE_PAIN then
// Åñëè ðàçðåøåíà êðîâü - ñîçäàåì áðûçãè êðîâè:
if (gBloodCount > 0) then
begin
// Åñëè ðàçðåøåíà êðîâü - ñîçäàåì áðûçãè êðîâè:
if (gBloodCount > 0) then
begin
- c := Min(Damage, 200);
- c := c*gBloodCount - (Damage div 4) + Random(c div 2);
+ c := Min(aDamage, 200);
+ c := c*gBloodCount - (aDamage div 4) + Random(c div 2);
if (VelX = 0) and (VelY = 0) then
MakeBloodSimple(c)
if (VelX = 0) and (VelY = 0) then
MakeBloodSimple(c)
it := g_Items_Create(FObj.X + (FObj.Rect.Width div 2),
FObj.Y + (FObj.Rect.Height div 2),
c, True, False);
it := g_Items_Create(FObj.X + (FObj.Rect.Width div 2),
FObj.Y + (FObj.Rect.Height div 2),
c, True, False);
- g_Obj_Push(@gItems[it].Obj, (FObj.Vel.X div 2)-3+Random(7),
- (FObj.Vel.Y div 2)-Random(4));
+ g_Obj_Push(g_ItemObjByIdx(it), (FObj.Vel.X div 2)-3+Random(7),
+ (FObj.Vel.Y div 2)-Random(4));
+ positionChanged(); // this updates spatial accelerators
if g_Game_IsServer and g_Game_IsNet then
MH_SEND_ItemSpawn(True, it);
end;
if g_Game_IsServer and g_Game_IsNet then
MH_SEND_ItemSpawn(True, it);
end;
if gTime mod (GAME_TICK*2) <> 0 then
begin
g_Obj_Move(@FObj, fall, True, True);
if gTime mod (GAME_TICK*2) <> 0 then
begin
g_Obj_Move(@FObj, fall, True, True);
+ positionChanged(); // this updates spatial accelerators
Exit;
end;
Exit;
end;
// Äâèãàåìñÿ:
st := g_Obj_Move(@FObj, fall, True, True);
// Äâèãàåìñÿ:
st := g_Obj_Move(@FObj, fall, True, True);
+ positionChanged(); // this updates spatial accelerators
// Âûëåòåë çà êàðòó - óäàëÿåì è çàïóñêàåì òðèããåðû:
if WordBool(st and MOVE_FALLOUT) or (FObj.X < -1000) or
// Âûëåòåë çà êàðòó - óäàëÿåì è çàïóñêàåì òðèããåðû:
if WordBool(st and MOVE_FALLOUT) or (FObj.X < -1000) or
if (FState <> STATE_DIE) and (FState <> STATE_DEAD) then
if FFirePainTime = 0 then
begin
if (FState <> STATE_DIE) and (FState <> STATE_DEAD) then
if FFirePainTime = 0 then
begin
- Damage(5, 0, 0, 0, HIT_FLAME);
+ Damage(5, FFireAttacker, 0, 0, HIT_FLAME);
FFirePainTime := 18;
end
else
FFirePainTime := 18;
end
else
b := Abs(FObj.Vel.X);
if b > 1 then b := b * (Random(8 div b) + 1);
for a := 0 to High(gGibs) do
b := Abs(FObj.Vel.X);
if b > 1 then b := b * (Random(8 div b) + 1);
for a := 0 to High(gGibs) do
+ begin
if gGibs[a].Live 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
if gGibs[a].Live 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
// Ïèíàåì êóñêè
if FObj.Vel.X < 0 then
// Ïèíàåì êóñêè
if FObj.Vel.X < 0 then
- g_Obj_PushA(@gGibs[a].Obj, b, Random(61)+120) // íàëåâî
+ begin
+ g_Obj_PushA(@gGibs[a].Obj, b, Random(61)+120); // íàëåâî
+ end
else
else
+ begin
g_Obj_PushA(@gGibs[a].Obj, b, Random(61)); // íàïðàâî
g_Obj_PushA(@gGibs[a].Obj, b, Random(61)); // íàïðàâî
+ end;
+ positionChanged(); // this updates spatial accelerators
+ end;
+ end;
end;
// Áîññû ìîãóò ïèíàòü òðóïû:
if (FMonsterType in [MONSTER_CYBER, MONSTER_SPIDER, MONSTER_ROBO]) and
end;
// Áîññû ìîãóò ïèíàòü òðóïû:
if (FMonsterType in [MONSTER_CYBER, MONSTER_SPIDER, MONSTER_ROBO]) and
if gTime mod (GAME_TICK*2) <> 0 then
begin
g_Obj_Move(@FObj, fall, True, True);
if gTime mod (GAME_TICK*2) <> 0 then
begin
g_Obj_Move(@FObj, fall, True, True);
+ positionChanged(); // this updates spatial accelerators
Exit;
end;
Exit;
end;
// Äâèãàåìñÿ:
st := g_Obj_Move(@FObj, fall, True, True);
// Äâèãàåìñÿ:
st := g_Obj_Move(@FObj, fall, True, True);
+ positionChanged(); // this updates spatial accelerators
// Âûëåòåë çà êàðòó - óäàëÿåì è çàïóñêàåì òðèããåðû:
if WordBool(st and MOVE_FALLOUT) or (FObj.X < -1000) or
// Âûëåòåë çà êàðòó - óäàëÿåì è çàïóñêàåì òðèããåðû:
if WordBool(st and MOVE_FALLOUT) or (FObj.X < -1000) or
b := Abs(FObj.Vel.X);
if b > 1 then b := b * (Random(8 div b) + 1);
for a := 0 to High(gGibs) do
b := Abs(FObj.Vel.X);
if b > 1 then b := b * (Random(8 div b) + 1);
for a := 0 to High(gGibs) do
+ begin
if gGibs[a].Live 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
if gGibs[a].Live 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
// Ïèíàåì êóñêè
if FObj.Vel.X < 0 then
// Ïèíàåì êóñêè
if FObj.Vel.X < 0 then
- g_Obj_PushA(@gGibs[a].Obj, b, Random(61)+120) // íàëåâî
+ begin
+ g_Obj_PushA(@gGibs[a].Obj, b, Random(61)+120); // íàëåâî
+ end
else
else
+ begin
g_Obj_PushA(@gGibs[a].Obj, b, Random(61)); // íàïðàâî
g_Obj_PushA(@gGibs[a].Obj, b, Random(61)); // íàïðàâî
+ end;
+ positionChanged(); // this updates spatial accelerators
+ end;
+ end;
end;
// Áîññû ìîãóò ïèíàòü òðóïû:
if (FMonsterType in [MONSTER_CYBER, MONSTER_SPIDER, MONSTER_ROBO]) and
end;
// Áîññû ìîãóò ïèíàòü òðóïû:
if (FMonsterType in [MONSTER_CYBER, MONSTER_SPIDER, MONSTER_ROBO]) and
FAnim[FCurAnim, FDirection].Update();
end;
FAnim[FCurAnim, FDirection].Update();
end;
-procedure TMonster.ClientAttack(wx, wy, tx, ty: Integer);
+procedure TMonster.ClientAttack(wx, wy, atx, aty: Integer);
begin
case FMonsterType of
MONSTER_ZOMBY:
begin
case FMonsterType of
MONSTER_ZOMBY:
g_Player_CreateShell(wx, wy, 0, -2, SHELL_BULLET);
end;
MONSTER_IMP:
g_Player_CreateShell(wx, wy, 0, -2, SHELL_BULLET);
end;
MONSTER_IMP:
- g_Weapon_ball1(wx, wy, tx, ty, FUID);
+ g_Weapon_ball1(wx, wy, atx, aty, FUID);
MONSTER_CYBER:
MONSTER_CYBER:
- g_Weapon_rocket(wx, wy, tx, ty, FUID);
+ g_Weapon_rocket(wx, wy, atx, aty, FUID);
MONSTER_SKEL:
MONSTER_SKEL:
- g_Weapon_revf(wx, wy, tx, ty, FUID, FTargetUID);
+ g_Weapon_revf(wx, wy, atx, aty, FUID, FTargetUID);
MONSTER_BSP:
MONSTER_BSP:
- g_Weapon_aplasma(wx, wy, tx, ty, FUID);
+ g_Weapon_aplasma(wx, wy, atx, aty, FUID);
MONSTER_ROBO:
MONSTER_ROBO:
- g_Weapon_plasma(wx, wy, tx, ty, FUID);
+ g_Weapon_plasma(wx, wy, atx, aty, FUID);
MONSTER_MANCUB:
MONSTER_MANCUB:
- g_Weapon_manfire(wx, wy, tx, ty, FUID);
+ g_Weapon_manfire(wx, wy, atx, aty, FUID);
MONSTER_BARON, MONSTER_KNIGHT:
MONSTER_BARON, MONSTER_KNIGHT:
- g_Weapon_ball7(wx, wy, tx, ty, FUID);
+ g_Weapon_ball7(wx, wy, atx, aty, FUID);
MONSTER_CACO:
MONSTER_CACO:
- g_Weapon_ball2(wx, wy, tx, ty, FUID);
+ g_Weapon_ball2(wx, wy, atx, aty, FUID);
end;
end;
end;
end;
SetLength(FDieTriggers, 0);
end;
SetLength(FDieTriggers, 0);
end;
-procedure TMonster.CatchFire();
+procedure TMonster.CatchFire(Attacker: Word);
begin
begin
- FFireTime := 360;
+ FFireTime := 100;
+ FFireAttacker := Attacker;
if g_Game_IsNet and g_Game_IsServer then
MH_SEND_MonsterState(FUID);
end;
if g_Game_IsNet and g_Game_IsServer then
MH_SEND_MonsterState(FUID);
end;
end;
end;
end;
end;
+//WARNING! call this after monster position was changed, or coldet will not work right!
+procedure TMonster.positionChanged ();
+begin
+end;
+
end.
end.