summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: f0c98dc)
raw | patch | inline | side by side (parent: f0c98dc)
author | fgsfds <pvt.fgsfds@gmail.com> | |
Sat, 12 Aug 2017 15:21:46 +0000 (18:21 +0300) | ||
committer | fgsfds <pvt.fgsfds@gmail.com> | |
Sat, 12 Aug 2017 15:21:46 +0000 (18:21 +0300) |
index cde1aad4dff139c91b8ffdf65997fa9ce4ba1a3e..cc4926a3135a2a5a97cfa4a3e06e71907eea6008 100644 (file)
--- a/src/game/g_monsters.pas
+++ b/src/game/g_monsters.pas
FBloodKind: Byte;
FShellTimer: Integer;
FShellType: Byte;
+ FFirePainTime: Integer;
vilefire: TAnimation;
FDieTriggers: Array of Integer;
public
FNoRespawn: Boolean;
+ FFireTime: Integer;
constructor Create(MonsterType: Byte; aID: Integer; ForcedUID: Integer = -1);
destructor Destroy(); override;
function AnimIsReverse: Boolean;
function shoot(o: PObj; immediately: Boolean): Boolean;
function kick(o: PObj): Boolean;
+ procedure CatchFire();
+ procedure OnFireFlame(Times: DWORD = 1);
property MonsterType: Byte read FMonsterType;
property MonsterHealth: Integer read FHealth write FHealth;
FNoRespawn := False;
FShellTimer := -1;
FBehaviour := BH_NORMAL;
+ FFireTime := 0;
+ FFirePainTime := 0;
if FMonsterType in [MONSTER_ROBO, MONSTER_BARREL] then
FBloodKind := BLOOD_SPARKS
if (FState = STATE_DIE) or (FState = STATE_DEAD) then
FObj.Vel.X := z_dec(FObj.Vel.X, 1);
+ if FFireTime > 0 then
+ begin
+ if WordBool(st and MOVE_INWATER) then
+ FFireTime := 0
+ else
+ begin
+ OnFireFlame(1);
+ FFireTime := FFireTime - 1;
+ if (FState <> STATE_DIE) and (FState <> STATE_DEAD) then
+ if FFirePainTime = 0 then
+ begin
+ Damage(5, 0, 0, 0, HIT_FLAME);
+ FFirePainTime := 18;
+ end
+ else
+ FFirePainTime := FFirePainTime - 1;
+ end;
+ end;
+
// Ìåðòâûé íè÷åãî íå äåëàåò:
if (FState = STATE_DEAD) then
goto _end;
if (FState = STATE_DIE) or (FState = STATE_DEAD) then
FObj.Vel.X := z_dec(FObj.Vel.X, 1);
+ if FFireTime > 0 then
+ begin
+ if WordBool(st and MOVE_INWATER) then
+ FFireTime := 0
+ else
+ begin
+ OnFireFlame(1);
+ FFireTime := FFireTime - 1;
+ end;
+ end;
+
// Ìåðòâûé íè÷åãî íå äåëàåò:
if (FState = STATE_DEAD) then
goto _end;
SetLength(FDieTriggers, 0);
end;
+procedure TMonster.CatchFire();
+begin
+ FFireTime := 360;
+ if g_Game_IsNet and g_Game_IsServer then
+ MH_SEND_MonsterState(FUID);
+end;
+
+procedure TMonster.OnFireFlame(Times: DWORD = 1);
+var
+ id, i: DWORD;
+ Anim: TAnimation;
+begin
+ if (Random(10) = 1) and (Times = 1) then
+ Exit;
+
+ if g_Frames_Get(id, 'FRAMES_FLAME') then
+ begin
+ for i := 1 to Times do
+ begin
+ Anim := TAnimation.Create(id, False, 3);
+ Anim.Alpha := 0;
+ g_GFX_OnceAnim(Obj.X+Obj.Rect.X+Random(Obj.Rect.Width+Times*2)-(Anim.Width div 2),
+ Obj.Y+8+Random(8+Times*2)+IfThen(FState = STATE_DEAD, 16, 0), Anim, ONCEANIM_SMOKE);
+ Anim.Free();
+ end;
+ end;
+end;
+
end.
diff --git a/src/game/g_net.pas b/src/game/g_net.pas
index 0ea107b875028752a826f3043227275af8a834c5..c9e40400fea7511762dee5f673a05b820b13d776 100644 (file)
--- a/src/game/g_net.pas
+++ b/src/game/g_net.pas
e_log, e_fixedbuffer, ENet, Classes;
const
- NET_PROTOCOL_VER = 170;
+ NET_PROTOCOL_VER = 171;
NET_MAXCLIENTS = 24;
NET_CHANS = 11;
diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas
index f8ec00a801c09757c9ed897566a53ff116beba7e..a5bd880c0e817a6c91756c18377b6d94699c26f7 100644 (file)
--- a/src/game/g_netmsg.pas
+++ b/src/game/g_netmsg.pas
e_Buffer_Write(@NetOut, Byte(FPhysics));
e_Buffer_Write(@NetOut, Byte(FNoRespawn));
e_Buffer_Write(@NetOut, Byte(FJetpack));
+ e_Buffer_Write(@NetOut, FFireTime);
end;
g_Net_Host_Send(ID, True, NET_CHAN_PLAYER);
e_Buffer_Write(@NetOut, MonsterAmmo);
e_Buffer_Write(@NetOut, MonsterPain);
e_Buffer_Write(@NetOut, Byte(AnimIsReverse));
+ e_Buffer_Write(@NetOut, FFireTime);
end;
g_Net_Host_Send(ID, True, NET_CHAN_MONSTER);
FNoRespawn := e_Raw_Read_Byte(P) <> 0;
OldJet := FJetpack;
FJetpack := e_Raw_Read_Byte(P) <> 0;
+ FFireTime := e_Raw_Read_LongInt(P);
if OldJet and not FJetpack then
JetpackOff
else if not OldJet and FJetpack then
MonsterAmmo := e_Raw_Read_LongInt(P);
MonsterPain := e_Raw_Read_LongInt(P);
AnimRevert := e_Raw_Read_Byte(P) <> 0;
+ FFireTime := e_Raw_Read_LongInt(P);
RevertAnim(AnimRevert);
if MonsterState <> MState then
diff --git a/src/game/g_player.pas b/src/game/g_player.pas
index d03247cdc5e4e3f2505078aa28ccd5f165f70f55..a0496da85e63e8314c938bcea0aa18bd7a957495 100644 (file)
--- a/src/game/g_player.pas
+++ b/src/game/g_player.pas
FObj: TObj;
FXTo, FYTo: Integer;
FSpectatePlayer: Integer;
+ FFirePainTime: Integer;
FSavedState: TPlayerSavedState;
function FullInLift(XInc, YInc: Integer): Integer;
{procedure CollideItem();}
procedure FlySmoke(Times: DWORD = 1);
+ procedure OnFireFlame(Times: DWORD = 1);
function GetAmmoByWeapon(Weapon: Byte): Word;
procedure SetAction(Action: Byte; Force: Boolean = False);
procedure OnDamage(Angle: SmallInt); virtual;
FPing: Word;
FLoss: Byte;
FDummy: Boolean;
+ FFireTime: Integer;
constructor Create(); virtual;
destructor Destroy(); override;
procedure RealizeCurrentWeapon();
procedure JetpackOn;
procedure JetpackOff;
+ procedure CatchFire();
property Name: String read FName write FName;
property Model: TPlayerModel read FModel;
FLoss := 0;
FSavedState.WaitRecall := False;
FShellTimer := -1;
+ FFireTime := 0;
+ FFirePainTime := 0;
FActualModelName := 'doomer';
WEAPON_FLAMETHROWER:
if FAmmo[A_FUEL] > 0 then
begin
+ g_Weapon_flame(wx, wy, xd, yd, FUID);
FReloading[FCurrWeap] := WEAPON_RELOAD[FCurrWeap];
Dec(FAmmo[A_FUEL]);
FFireAngle := FAngle;
FJetSoundOff.PlayAt(FObj.X, FObj.Y);
end;
+procedure TPlayer.CatchFire();
+begin
+ FFireTime := 360;
+ if g_Game_IsNet and g_Game_IsServer then
+ MH_SEND_PlayerStats(FUID);
+end;
+
procedure TPlayer.Jump();
begin
if gFly or FJetpack then
end else if FAir < AIR_DEF then
FAir := AIR_DEF;
+ if FFireTime > 0 then
+ begin
+ if BodyInLiquid(0, 0) then
+ begin
+ FFireTime := 0;
+ FFirePainTime := 0;
+ end
+ else
+ begin
+ OnFireFlame(1);
+ if FFirePainTime <= 0 then
+ begin
+ if g_Game_IsServer then
+ Damage(5, 0, 0, 0, HIT_FLAME);
+ FFirePainTime := 18;
+ end;
+ FFirePainTime := FFirePainTime - 1;
+ FFireTime := FFireTime - 1;
+ if (FFireTime = 0) and g_Game_IsNet and g_Game_IsServer then
+ MH_SEND_PlayerStats(FUID);
+ end;
+ end;
+
if FDamageBuffer > 0 then
begin
if FDamageBuffer >= 9 then
WEAPON_FLAMETHROWER:
begin
+ g_Weapon_flame(wx, wy, xd, yd, FUID, WID);
FFireAngle := FAngle;
f := True;
end;
end;
end;
+procedure TPlayer.OnFireFlame(Times: DWORD = 1);
+var
+ id, i: DWORD;
+ Anim: TAnimation;
+begin
+ if (Random(10) = 1) and (Times = 1) then
+ Exit;
+
+ if g_Frames_Get(id, 'FRAMES_FLAME') then
+ begin
+ for i := 1 to Times do
+ begin
+ Anim := TAnimation.Create(id, False, 3);
+ Anim.Alpha := 0;
+ g_GFX_OnceAnim(Obj.X+Obj.Rect.X+Random(Obj.Rect.Width+Times*2)-(Anim.Width div 2),
+ Obj.Y+8+Random(8+Times*2), Anim, ONCEANIM_SMOKE);
+ Anim.Free();
+ end;
+ end;
+end;
+
procedure TPlayer.PauseSounds(Enable: Boolean);
begin
FSawSound.Pause(Enable);
diff --git a/src/game/g_weapons.pas b/src/game/g_weapons.pas
index 38d33e3b5c713244a7c978857c816d1d39d2f35a..6021daff58ecda40d6a0aceb210d69520ae25395 100644 (file)
--- a/src/game/g_weapons.pas
+++ b/src/game/g_weapons.pas
Animation: TAnimation;
TextureID: DWORD;
Timeout: DWORD;
+ Stopped: Byte;
end;
var
function g_Weapon_chainsaw(x, y: Integer; d, SpawnerUID: Word): Integer;
procedure g_Weapon_rocket(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
procedure g_Weapon_revf(x, y, xd, yd: Integer; SpawnerUID, TargetUID: Word; WID: Integer = -1; Silent: Boolean = False);
+procedure g_Weapon_flame(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
procedure g_Weapon_plasma(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
procedure g_Weapon_ball1(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
procedure g_Weapon_ball2(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
SHOT_BFG_DAMAGE = 100;
SHOT_BFG_RADIUS = 256;
+ SHOT_FLAME_WIDTH = 4;
+ SHOT_FLAME_HEIGHT = 4;
+ SHOT_FLAME_LIFETIME = 360;
+
SHOT_SIGNATURE = $544F4853; // 'SHOT'
var
end;
if g_Game_IsServer then
- Result := m.Damage(d, vx, vy, SpawnerUID, t)
+ begin
+ if (t <> HIT_FLAME) or (m.FFireTime = 0) or (vx <> 0) or (vy <> 0) then
+ Result := m.Damage(d, vx, vy, SpawnerUID, t)
+ else
+ Result := True;
+ if t = HIT_FLAME then
+ m.CatchFire();
+ end
else
Result := True;
end;
if (p.UID = SpawnerUID) and (t <> HIT_ROCKET) and (t <> HIT_ELECTRO) then
Exit;
- if g_Game_IsServer then p.Damage(d, SpawnerUID, vx, vy, t);
+ if g_Game_IsServer then
+ begin
+ if (t <> HIT_FLAME) or (p.FFireTime = 0) or (vx <> 0) or (vy <> 0) then
+ p.Damage(d, SpawnerUID, vx, vy, t);
+ if (t = HIT_FLAME) then
+ p.CatchFire();
+ end;
Result := True;
end;
end;
end;
+ WEAPON_FLAMETHROWER:
+ begin
+ with Shots[find_id] do
+ begin
+ g_Obj_Init(@Obj);
+
+ Obj.Rect.Width := SHOT_FLAME_WIDTH;
+ Obj.Rect.Height := SHOT_FLAME_HEIGHT;
+
+ Triggers := nil;
+ ShotType := WEAPON_FLAMETHROWER;
+ Animation := nil;
+ TextureID := 0;
+ Stopped := 0;
+ end;
+ end;
+
WEAPON_IMP_FIRE:
begin
with Shots[find_id] do
Shots[i].Obj.Accel.Y := 0;
if Shots[i].ShotType in [WEAPON_ROCKETLAUNCHER, WEAPON_BFG] then
Shots[i].Timeout := 900 // ~25 sec
+ else if Shots[i].ShotType = WEAPON_FLAMETHROWER then
+ Shots[i].Timeout := SHOT_FLAME_LIFETIME
else
Shots[i].Timeout := 550 // ~15 sec
end;
g_Frames_CreateWAD(nil, 'FRAMES_EXPLODE_IMPFIRE', GameWAD+':TEXTURES\EIMPFIRE', 64, 64, 3);
g_Frames_CreateWAD(nil, 'FRAMES_BFGHIT', GameWAD+':TEXTURES\BFGHIT', 64, 64, 4);
g_Frames_CreateWAD(nil, 'FRAMES_FIRE', GameWAD+':TEXTURES\FIRE', 64, 128, 8);
+ g_Frames_CreateWAD(nil, 'FRAMES_FLAME', GameWAD+':TEXTURES\FLAME', 32, 32, 11);
g_Frames_CreateWAD(nil, 'FRAMES_EXPLODE_PLASMA', GameWAD+':TEXTURES\EPLASMA', 32, 32, 4, True);
g_Frames_CreateWAD(nil, 'FRAMES_EXPLODE_BSPFIRE', GameWAD+':TEXTURES\EBSPFIRE', 32, 32, 5);
g_Frames_CreateWAD(nil, 'FRAMES_EXPLODE_CACOFIRE', GameWAD+':TEXTURES\ECACOFIRE', 64, 64, 3);
g_Sound_PlayExAt('SOUND_WEAPON_FIREPLASMA', x, y);
end;
+procedure g_Weapon_flame(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1;
+ Silent: Boolean = False);
+var
+ find_id, FramesID: DWORD;
+ dx, dy: Integer;
+begin
+ if WID < 0 then
+ find_id := FindShot()
+ else
+ begin
+ find_id := WID;
+ if Integer(find_id) >= High(Shots) then
+ SetLength(Shots, find_id + 64);
+ end;
+
+ with Shots[find_id] do
+ begin
+ g_Obj_Init(@Obj);
+
+ Obj.Rect.Width := SHOT_FLAME_WIDTH;
+ Obj.Rect.Height := SHOT_FLAME_HEIGHT;
+
+ dx := IfThen(xd>x, -Obj.Rect.Width, 0);
+ dy := -(Obj.Rect.Height div 2);
+ throw(find_id, x+dx, y+dy, xd+dx, yd+dy, 16);
+
+ triggers := nil;
+ ShotType := WEAPON_FLAMETHROWER;
+ Animation := nil;
+ TextureID := 0;
+ Stopped := 0;
+ end;
+
+ Shots[find_id].SpawnerUID := SpawnerUID;
+
+ // if not Silent then
+ // g_Sound_PlayExAt('SOUND_WEAPON_FIREPLASMA', x, y);
+end;
+
procedure g_Weapon_ball1(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1;
Silent: Boolean = False);
var
end;
end;
+ WEAPON_FLAMETHROWER: // Îãíåìåò
+ begin
+ // Ïîä âîäîé íå ñòðåëÿåò, ñî âðåìåíåì óìèðàåò
+ if (Timeout < 1) or WordBool(st and (MOVE_INWATER)) then
+ begin
+ ShotType := 0;
+ Continue;
+ end;
+
+ // Ãðàâèòàöèÿ
+ if Stopped = 0 then
+ Obj.Accel.Y := Obj.Accel.Y + 1;
+ // Ïîïàëè â ñòåíó èëè â âîäó:
+ if WordBool(st and (MOVE_HITWALL or MOVE_HITLAND or MOVE_HITCEIL or MOVE_HITWATER)) then
+ begin
+ // Ïðèëèïàåì:
+ Obj.Vel.X := 0;
+ Obj.Vel.Y := 0;
+ Obj.Accel.Y := 0;
+ if WordBool(st and (MOVE_HITWALL or MOVE_HITWATER)) then
+ Stopped := 1
+ else
+ Stopped := 2;
+ end;
+
+ a := IfThen(Stopped = 0, 2, 1);
+ // Åñëè â êîãî-òî ïîïàëè
+ if g_Weapon_Hit(@Obj, a, SpawnerUID, HIT_FLAME, False) <> 0 then
+ begin
+ // HIT_FLAME ñàì ïîäîææåò
+ // Åñëè â ïîëåòå ïîïàëè, èñ÷åçàåì
+ if Stopped = 0 then
+ ShotType := 0;
+ end;
+
+ if g_Frames_Get(_id, 'FRAMES_FLAME') then
+ begin
+ Anim := TAnimation.Create(_id, False, 3);
+ Anim.Alpha := 0;
+ case Stopped of
+ 0: g_GFX_OnceAnim(cx-4+Random(8)-(Anim.Width div 2),
+ cy-4+Random(8)-(Anim.Height div 2),
+ Anim, ONCEANIM_SMOKE);
+ 1: g_GFX_OnceAnim(cx-4+Random(8)-(Anim.Width div 2),
+ cy-12+Random(24)-(Anim.Height div 2),
+ Anim, ONCEANIM_SMOKE);
+ 2: g_GFX_OnceAnim(cx-12+Random(24)-(Anim.Width div 2),
+ cy-4+Random(8)-(Anim.Height div 2),
+ Anim, ONCEANIM_SMOKE);
+ end;
+ Anim.Free();
+ end;
+ end;
+
WEAPON_BFG: // BFG
begin
// Ïîïàëà â âîäó - ýëåêòðîøîê ïî âîäå:
begin
if gGameSettings.GameType = GT_SERVER then
MH_SEND_DeleteShot(i, Obj.X, Obj.Y, Loud);
- Animation.Free();
- Animation := nil;
+ if Animation <> nil then
+ begin
+ Animation.Free();
+ Animation := nil;
+ end;
end
- else if (oldvx <> Obj.Vel.X) or (oldvy <> Obj.Vel.Y) then
+ else if (ShotType <> WEAPON_FLAMETHROWER) and ((oldvx <> Obj.Vel.X) or (oldvy <> Obj.Vel.Y)) then
if gGameSettings.GameType = GT_SERVER then
MH_SEND_UpdateShot(i);
end;
else
Animation.Draw(Obj.X, Obj.Y, M_NONE);
end
- else
+ else if TextureID <> 0 then
begin
if (Shots[i].ShotType = WEAPON_ROCKETLAUNCHER) then
e_DrawAdv(TextureID, Obj.X, Obj.Y, 0, True, False, a, @p, M_NONE)
Mem.WriteDWORD(Shots[i].Triggers[j]);
// Îáúåêò ñíàðÿäà:
Obj_SaveState(@Shots[i].Obj, Mem);
+ // Êîñòûëèíà åáàíàÿ:
+ Mem.WriteByte(Shots[i].Stopped);
end;
end;
Mem.ReadDWORD(Shots[i].Triggers[j]);
// Îáúåêò ïðåäìåòà:
Obj_LoadState(@Shots[i].Obj, Mem);
+ // Êîñòûëèíà åáàíàÿ:
+ Mem.ReadByte(Shots[i].Stopped);
// Óñòàíîâêà òåêñòóðû èëè àíèìàöèè:
Shots[i].TextureID := DWORD(-1);