diff --git a/src/game/g_player.pas b/src/game/g_player.pas
index 551b9c6ab89c90cf3eabfb9a27ae8fc4f39001e4..68bee9a40a786e8f1f3470eb74f072bcd6d38427 100644 (file)
--- a/src/game/g_player.pas
+++ b/src/game/g_player.pas
uses
SysUtils, Classes,
{$IFDEF USE_MEMPOOL}mempool,{$ENDIF}
- r_graphics, g_playermodel, g_basic, g_textures,
+ g_base, g_playermodel, g_basic, g_textures,
g_weapons, g_phys, g_sound, g_saveload, MAPDEF,
g_panel;
FSavedStateNum: Integer;
FModel: TPlayerModel;
- FPunchAnim: TAnimation;
+ FPunchAnim: TAnimationState;
FActionPrior: Byte;
FActionAnim: Byte;
FActionForce: Boolean;
property Berserk: Integer read FBerserk;
property Pain: Integer read FPain;
property Pickup: Integer read FPickup;
- property PunchAnim: TAnimation read FPunchAnim write FPunchAnim;
+ property PunchAnim: TAnimationState read FPunchAnim write FPunchAnim;
property SpawnInvul: Integer read FSpawnInvul;
property Ghost: Boolean read FGhost;
procedure LoadState (st: TStream); override;
end;
- PGib = ^TGib;
- TGib = record
- alive: Boolean;
- ID: DWORD;
- MaskID: DWORD;
- RAngle: Integer;
- Color: TRGB;
- Obj: TObj;
-
- procedure getMapBox (out x, y, w, h: Integer); inline;
- procedure moveBy (dx, dy: Integer); inline;
-
- procedure positionChanged (); inline; //WARNING! call this after entity position was changed, or coldet will not work right!
- end;
-
-
PShell = ^TShell;
TShell = record
- SpriteID: DWORD;
- alive: Boolean;
+ alive: Boolean;
SType: Byte;
RAngle: Integer;
Timeout: Cardinal;
- CX, CY: Integer;
Obj: TObj;
procedure getMapBox (out x, y, w, h: Integer); inline;
TCorpse = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
private
- FModelName: String;
FMess: Boolean;
FState: Byte;
FDamage: Byte;
- FColor: TRGB;
FObj: TObj;
FPlayerUID: Word;
- FAnimation: TAnimation;
- FAnimationMask: TAnimation;
+ FModel: TPlayerModel;
public
constructor Create(X, Y: Integer; ModelName: String; aMess: Boolean);
property Obj: TObj read FObj; // copies object
property State: Byte read FState;
property Mess: Boolean read FMess;
-
- (* internal state *)
- property Color: TRGB read FColor;
- property Animation: TAnimation read FAnimation;
- property AnimationMask: TAnimation read FAnimationMask;
+ property Model: TPlayerModel read FModel;
end;
TTeamStat = Array [TEAM_RED..TEAM_BLUE] of
var
gPlayers: Array of TPlayer;
gCorpses: Array of TCorpse;
- gGibs: Array of TGib;
gShells: Array of TShell;
gTeamStat: TTeamStat;
gFly: Boolean = False;
function Lerp(X, Y, Factor: Integer): Integer;
-procedure g_Gibs_SetMax(Count: Word);
-function g_Gibs_GetMax(): Word;
procedure g_Corpses_SetMax(Count: Word);
function g_Corpses_GetMax(): Word;
procedure g_Shells_SetMax(Count: Word);
function g_Player_GetStats(): TPlayerStatArray;
function g_Player_ValidName(Name: String): Boolean;
function g_Player_CreateCorpse(Player: TPlayer): Integer;
-procedure g_Player_CreateGibs(fX, fY: Integer; ModelName: String; fColor: TRGB);
procedure g_Player_CreateShell(fX, fY, dX, dY: Integer; T: Byte);
procedure g_Player_UpdatePhysicalObjects();
procedure g_Player_RemoveAllCorpses();
implementation
uses
-{$IFDEF ENABLE_HOLMES}
- g_holmes,
-{$ENDIF}
- e_log, g_map, g_items, g_console, g_gfx, Math,
- g_options, g_triggers, g_menu, g_game, g_grid, e_res,
- wadreader, g_main, g_monsters, CONFIG, g_language,
- g_net, g_netmsg, g_window,
+ {$IFDEF ENABLE_HOLMES}
+ g_holmes,
+ {$ENDIF}
+ {$IFDEF ENABLE_MENU}
+ g_menu,
+ {$ENDIF}
+ {$IFNDEF HEADLESS}
+ r_render,
+ {$ENDIF}
+ {$IFDEF ENABLE_GFX}
+ g_gfx,
+ {$ENDIF}
+ {$IFDEF ENABLE_GIBS}
+ g_gibs,
+ {$ENDIF}
+ e_log, g_map, g_items, g_console, Math,
+ g_options, g_triggers, g_game, g_grid, e_res,
+ wadreader, g_monsters, CONFIG, g_language,
+ g_net, g_netmsg,
utils, xstreams;
const PLR_SAVE_VERSION = 0;
BOTLIST_FILENAME = 'botlist.txt';
var
- MaxGibs: Word = 150;
MaxCorpses: Word = 20;
MaxShells: Word = 300;
- CurrentGib: Integer = 0;
CurrentShell: Integer = 0;
BotNames: Array of String;
BotList: Array of TBotProfile;
Result := g_Player_Get(UID1).FTeam = g_Player_Get(UID2).FTeam;
end;
-procedure g_Gibs_SetMax(Count: Word);
-begin
- MaxGibs := Count;
- SetLength(gGibs, Count);
-
- if CurrentGib >= Count then
- CurrentGib := 0;
-end;
-
-function g_Gibs_GetMax(): Word;
-begin
- Result := MaxGibs;
-end;
-
procedure g_Shells_SetMax(Count: Word);
begin
MaxShells := Count;
with Player do
begin
- if (FHealth >= -50) or (gGibsCount = 0) then
+{$IFDEF ENABLE_GIBS}
+ if (FHealth < -50) and (gGibsCount > 0) then
+ begin
+ g_Gibs_Create(FObj.X + PLAYER_RECT_CX, FObj.Y + PLAYER_RECT_CY, FModel.id, FModel.Color);
+ end
+ else
+{$ENDIF}
begin
if (gCorpses = nil) or (Length(gCorpses) = 0) then
Exit;
if not ok then
find_id := Random(Length(gCorpses));
- gCorpses[find_id] := TCorpse.Create(FObj.X, FObj.Y, FModel.Name, FHealth < -20);
- gCorpses[find_id].FColor := FModel.Color;
+ gCorpses[find_id] := TCorpse.Create(FObj.X, FObj.Y, FModel.GetName(), FHealth < -20);
+ gCorpses[find_id].FModel.Color := FModel.Color;
gCorpses[find_id].FObj.Vel := FObj.Vel;
gCorpses[find_id].FObj.Accel := FObj.Accel;
gCorpses[find_id].FPlayerUID := FUID;
Result := find_id;
end
- else
- g_Player_CreateGibs(FObj.X + PLAYER_RECT_CX,
- FObj.Y + PLAYER_RECT_CY,
- FModel.Name, FModel.Color);
end;
end;
procedure g_Player_CreateShell(fX, fY, dX, dY: Integer; T: Byte);
-var
- SID: DWORD;
begin
if (gShells = nil) or (Length(gShells) = 0) then
Exit;
with gShells[CurrentShell] do
begin
- SpriteID := 0;
g_Obj_Init(@Obj);
Obj.Rect.X := 0;
Obj.Rect.Y := 0;
if T = SHELL_BULLET then
begin
- if g_Texture_Get('TEXTURE_SHELL_BULLET', SID) then
- SpriteID := SID;
- CX := 2;
- CY := 1;
Obj.Rect.Width := 4;
Obj.Rect.Height := 2;
end
else
begin
- if g_Texture_Get('TEXTURE_SHELL_SHELL', SID) then
- SpriteID := SID;
- CX := 4;
- CY := 2;
Obj.Rect.Width := 7;
Obj.Rect.Height := 3;
end;
end;
end;
-procedure g_Player_CreateGibs(fX, fY: Integer; ModelName: string; fColor: TRGB);
-var
- a: Integer;
- GibsArray: TGibsArray;
- Blood: TModelBlood;
-begin
- if (gGibs = nil) or (Length(gGibs) = 0) then
- Exit;
- if not g_PlayerModel_GetGibs(ModelName, GibsArray) then
- Exit;
- Blood := g_PlayerModel_GetBlood(ModelName);
-
- for a := 0 to High(GibsArray) do
- with gGibs[CurrentGib] do
- begin
- Color := fColor;
- ID := GibsArray[a].ID;
- MaskID := GibsArray[a].MaskID;
- alive := True;
- g_Obj_Init(@Obj);
- Obj.Rect := GibsArray[a].Rect;
- Obj.X := fX-GibsArray[a].Rect.X-(GibsArray[a].Rect.Width div 2);
- Obj.Y := fY-GibsArray[a].Rect.Y-(GibsArray[a].Rect.Height div 2);
- g_Obj_PushA(@Obj, 25 + Random(10), Random(361));
- positionChanged(); // this updates spatial accelerators
- RAngle := Random(360);
-
- if gBloodCount > 0 then
- g_GFX_Blood(fX, fY, 16*gBloodCount+Random(5*gBloodCount), -16+Random(33), -16+Random(33),
- Random(48), Random(48), Blood.R, Blood.G, Blood.B, Blood.Kind);
-
- if CurrentGib >= High(gGibs) then
- CurrentGib := 0
- else
- Inc(CurrentGib);
- end;
-end;
-
procedure g_Player_UpdatePhysicalObjects();
var
i: Integer;
end;
begin
-// Куски мяса:
- if gGibs <> nil then
- for i := 0 to High(gGibs) do
- if gGibs[i].alive then
- with gGibs[i] do
- begin
- Obj.oldX := Obj.X;
- Obj.oldY := Obj.Y;
-
- vel := Obj.Vel;
- mr := g_Obj_Move(@Obj, True, False, True);
- positionChanged(); // this updates spatial accelerators
-
- if WordBool(mr and MOVE_FALLOUT) then
- begin
- alive := False;
- Continue;
- end;
-
- // Отлетает от удара о стену/потолок/пол:
- if WordBool(mr and MOVE_HITWALL) then
- Obj.Vel.X := -(vel.X div 2);
- if WordBool(mr and (MOVE_HITCEIL or MOVE_HITLAND)) then
- Obj.Vel.Y := -(vel.Y div 2);
-
- if (Obj.Vel.X >= 0) then
- begin // Clockwise
- RAngle := RAngle + Abs(Obj.Vel.X)*6 + Abs(Obj.Vel.Y);
- if RAngle >= 360 then
- RAngle := RAngle mod 360;
- end else begin // Counter-clockwise
- RAngle := RAngle - Abs(Obj.Vel.X)*6 - Abs(Obj.Vel.Y);
- if RAngle < 0 then
- RAngle := (360 - (Abs(RAngle) mod 360)) mod 360;
- end;
-
- // Сопротивление воздуха для куска трупа:
- if gTime mod (GAME_TICK*3) = 0 then
- Obj.Vel.X := z_dec(Obj.Vel.X, 1);
- end;
-
// Трупы:
if gCorpses <> nil then
for i := 0 to High(gCorpses) do
end;
end;
-
-procedure TGib.getMapBox (out x, y, w, h: Integer); inline;
-begin
- x := Obj.X+Obj.Rect.X;
- y := Obj.Y+Obj.Rect.Y;
- w := Obj.Rect.Width;
- h := Obj.Rect.Height;
-end;
-
-procedure TGib.moveBy (dx, dy: Integer); inline;
-begin
- if (dx <> 0) or (dy <> 0) then
- begin
- Obj.X += dx;
- Obj.Y += dy;
- positionChanged();
- end;
-end;
-
-
procedure TShell.getMapBox (out x, y, w, h: Integer); inline;
begin
x := Obj.X;
end;
end;
-
-procedure TGib.positionChanged (); inline; begin end;
procedure TShell.positionChanged (); inline; begin end;
procedure g_Player_RemoveAllCorpses();
-var
- i: Integer;
-begin
- gGibs := nil;
+ var i: Integer;
+ {$IFDEF ENABLE_GIBS}
+ var maxgibs: Integer;
+ {$ENDIF}
+begin
+ {$IFDEF ENABLE_GIBS}
+ maxgibs := g_Gibs_GetMax();
+ g_Gibs_SetMax(0);
+ g_Gibs_SetMax(maxgibs);
+ {$ENDIF}
gShells := nil;
- SetLength(gGibs, MaxGibs);
- SetLength(gShells, MaxGibs);
- CurrentGib := 0;
+ SetLength(gShells, MaxShells);
CurrentShell := 0;
if gCorpses <> nil then
if gCorpses[i] <> nil then
begin
// Название модели
- utils.writeStr(st, gCorpses[i].FModelName);
+ utils.writeStr(st, gCorpses[i].FModel.GetName());
// Тип смерти
utils.writeBool(st, gCorpses[i].Mess);
// Сохраняем данные трупа:
FNetTime := 0;
FWaitForFirstSpawn := false;
+ FPunchAnim := TAnimationState.Create(False, 1, 4);
+ FPunchAnim.Disable;
resetWeaponQueue();
end;
HIT_BFG, HIT_ROCKET, HIT_SOME: MakeBloodVector(c, vx, vy);
end;
- if t = HIT_WATER then
- g_GFX_Bubbles(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2),
- FObj.Y+PLAYER_RECT.Y-4, value div 2, 8, 4);
+ {$IFDEF ENABLE_GFX}
+ if t = HIT_WATER then
+ begin
+ g_GFX_Bubbles(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2),
+ FObj.Y+PLAYER_RECT.Y-4, value div 2, 8, 4);
+ end;
+ {$ENDIF}
end;
// Буфер урона:
FJetSoundOn.Free();
FJetSoundOff.Free();
FModel.Free();
- if FPunchAnim <> nil then
- FPunchAnim.Free();
+ FPunchAnim.Free();
inherited;
end;
procedure TPlayer.DoPunch();
-var
- id: DWORD;
- st: String;
begin
- if FPunchAnim <> nil then begin
- FPunchAnim.reset();
- FPunchAnim.Free;
- FPunchAnim := nil;
- end;
- st := 'FRAMES_PUNCH';
- if R_BERSERK in FRulez then
- st := st + '_BERSERK';
- if FKeys[KEY_UP].Pressed then
- st := st + '_UP'
- else if FKeys[KEY_DOWN].Pressed then
- st := st + '_DN';
- g_Frames_Get(id, st);
- FPunchAnim := TAnimation.Create(id, False, 1);
+ FPunchAnim.Reset;
+ FPunchAnim.Enable;
end;
procedure TPlayer.Fire();
end;
procedure TPlayer.MakeBloodSimple(Count: Word);
-begin
- g_GFX_Blood(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)+8,
- FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2),
- Count div 2, 3, -1, 16, (PLAYER_RECT.Height*2 div 3),
- FModel.Blood.R, FModel.Blood.G, FModel.Blood.B, FModel.Blood.Kind);
- g_GFX_Blood(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)-8,
- FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2),
- Count div 2, -3, -1, 16, (PLAYER_RECT.Height*2) div 3,
- FModel.Blood.R, FModel.Blood.G, FModel.Blood.B, FModel.Blood.Kind);
+ {$IFDEF ENABLE_GFX}
+ var Blood: TModelBlood;
+ {$ENDIF}
+begin
+ {$IFDEF ENABLE_GFX}
+ Blood := SELF.FModel.GetBlood();
+ g_GFX_Blood(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)+8,
+ FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2),
+ Count div 2, 3, -1, 16, (PLAYER_RECT.Height*2 div 3),
+ Blood.R, Blood.G, Blood.B, Blood.Kind);
+ g_GFX_Blood(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)-8,
+ FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2),
+ Count div 2, -3, -1, 16, (PLAYER_RECT.Height*2) div 3,
+ Blood.R, Blood.G, Blood.B, Blood.Kind);
+ {$ENDIF}
end;
procedure TPlayer.MakeBloodVector(Count: Word; VelX, VelY: Integer);
+ {$IFDEF ENABLE_GFX}
+ var Blood: TModelBlood;
+ {$ENDIF}
begin
- g_GFX_Blood(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2),
- FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2),
- Count, VelX, VelY, 16, (PLAYER_RECT.Height*2) div 3,
- FModel.Blood.R, FModel.Blood.G, FModel.Blood.B, FModel.Blood.Kind);
+ {$IFDEF ENABLE_GFX}
+ Blood := SELF.FModel.GetBlood();
+ g_GFX_Blood(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2),
+ FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2),
+ Count, VelX, VelY, 16, (PLAYER_RECT.Height*2) div 3,
+ Blood.R, Blood.G, Blood.B, Blood.Kind);
+ {$ENDIF}
end;
procedure TPlayer.QueueWeaponSwitch(Weapon: Byte);
var
RespawnPoint: TRespawnPoint;
a, b, c: Byte;
- Anim: TAnimation;
- ID: DWORD;
begin
FSlopeOld := 0;
FIncCamOld := 0;
FFirePainTime := 0;
FFireAttacker := 0;
-// Анимация возрождения:
- if (not gLoadGameMode) and (not Silent) then
- if g_Frames_Get(ID, 'FRAMES_TELEPORT') then
+ {$IFDEF ENABLE_GFX}
+ // Анимация возрождения:
+ if (not gLoadGameMode) and (not Silent) then
begin
- Anim := TAnimation.Create(ID, False, 3);
- g_GFX_OnceAnim(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)-32,
- FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2)-32, Anim);
- Anim.Free();
+ g_GFX_QueueEffect(
+ R_GFX_TELEPORT_FAST,
+ FObj.X + PLAYER_RECT.X + (PLAYER_RECT.Width div 2) - 32,
+ FObj.Y + PLAYER_RECT.Y + (PLAYER_RECT.Height div 2) - 32
+ );
end;
+ {$ENDIF}
FSpectator := False;
FGhost := False;
end;
procedure TPlayer.Run(Direction: TDirection);
-var
- a, b: Integer;
+ {$IFDEF ENABLE_GIBS}
+ var a, b: Integer;
+ {$ENDIF}
begin
if MAX_RUNVEL > 8 then
FlySmoke();
if FObj.Vel.X < MAX_RUNVEL then
FObj.Vel.X := FObj.Vel.X + (MAX_RUNVEL shr 3);
-// Возможно, пинаем куски:
- if (FObj.Vel.X <> 0) and (gGibs <> nil) then
- begin
- b := Abs(FObj.Vel.X);
- if b > 1 then b := b * (Random(8 div b) + 1);
- for a := 0 to High(gGibs) do
+ {$IFDEF ENABLE_GIBS}
+ // Возможно, пинаем куски:
+ if (FObj.Vel.X <> 0) and (gGibs <> nil) then
begin
- if gGibs[a].alive 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
+ 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 FObj.Vel.X < 0 then
- begin
- g_Obj_PushA(@gGibs[a].Obj, b, Random(61)+120) // налево
- end
- else
+ if gGibs[a].alive 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
- g_Obj_PushA(@gGibs[a].Obj, b, Random(61)); // направо
+ // Пинаем куски
+ if FObj.Vel.X < 0 then
+ begin
+ g_Obj_PushA(@gGibs[a].Obj, b, Random(61)+120) // налево
+ end
+ else
+ begin
+ g_Obj_PushA(@gGibs[a].Obj, b, Random(61)); // направо
+ end;
+ gGibs[a].positionChanged(); // this updates spatial accelerators
end;
- gGibs[a].positionChanged(); // this updates spatial accelerators
end;
end;
- end;
+ {$ENDIF}
SetAction(A_WALK);
end;
end;
function TPlayer.TeleportTo(X, Y: Integer; silent: Boolean; dir: Byte): Boolean;
-var
- Anim: TAnimation;
- ID: DWORD;
begin
Result := False;
FJustTeleported := True;
- Anim := nil;
if not silent then
begin
- if g_Frames_Get(ID, 'FRAMES_TELEPORT') then
- begin
- Anim := TAnimation.Create(ID, False, 3);
- end;
-
g_Sound_PlayExAt('SOUND_GAME_TELEPORT', FObj.X, FObj.Y);
- g_GFX_OnceAnim(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)-32,
- FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2)-32, Anim);
+ {$IFDEF ENABLE_GFX}
+ g_GFX_QueueEffect(
+ R_GFX_TELEPORT_FAST,
+ FObj.X + PLAYER_RECT.X + (PLAYER_RECT.Width div 2) - 32,
+ FObj.Y + PLAYER_RECT.Y + (PLAYER_RECT.Height div 2) - 32
+ );
+ {$ENDIF}
if g_Game_IsServer and g_Game_IsNet then
MH_SEND_Effect(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)-32,
FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2)-32, 1,
end;
end;
- if not silent and (Anim <> nil) then
+ if not silent then
begin
- g_GFX_OnceAnim(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)-32,
- FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2)-32, Anim);
- Anim.Free();
-
+ {$IFDEF ENABLE_GFX}
+ g_GFX_QueueEffect(
+ R_GFX_TELEPORT_FAST,
+ FObj.X + PLAYER_RECT.X + (PLAYER_RECT.Width div 2) - 32,
+ FObj.Y + PLAYER_RECT.Y + (PLAYER_RECT.Height div 2) - 32
+ );
+ {$ENDIF}
if g_Game_IsServer and g_Game_IsNet then
MH_SEND_Effect(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2)-32,
FObj.Y+PLAYER_RECT.Y+(PLAYER_RECT.Height div 2)-32, 0,
FLoss := 0;
end;
- if FAlive and (FPunchAnim <> nil) then
- FPunchAnim.Update();
+ if FAlive then
+ FPunchAnim.Update;
+ if FPunchAnim.played then
+ FPunchAnim.Disable;
if FAlive and (gFly or FJetpack) then
FlySmoke();
end
else if (FAir mod 31 = 0) and not blockmon then
begin
- g_GFX_Bubbles(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2), FObj.Y+PLAYER_RECT.Y-4, 5+Random(6), 8, 4);
+ {$IFDEF ENABLE_GFX}
+ g_GFX_Bubbles(FObj.X+PLAYER_RECT.X+(PLAYER_RECT.Width div 2), FObj.Y+PLAYER_RECT.Y-4, 5+Random(6), 8, 4);
+ {$ENDIF}
if Random(2) = 0 then
g_Sound_PlayExAt('SOUND_GAME_BUBBLE1', FObj.X, FObj.Y)
else
if (FActionAnim = A_PAIN) and (FModel.Animation <> A_PAIN) then
begin
FModel.ChangeAnimation(FActionAnim, FActionForce);
- FModel.GetCurrentAnimation.MinLength := i;
- FModel.GetCurrentAnimationMask.MinLength := i;
+ FModel.AnimState.MinLength := i;
end else FModel.ChangeAnimation(FActionAnim, FActionForce and (FModel.Animation <> A_STAND));
- if (FModel.GetCurrentAnimation.Played or ((not FActionChanged) and (FModel.Animation = A_WALK)))
+ if (FModel.AnimState.Played or ((not FActionChanged) and (FModel.Animation = A_WALK)))
then SetAction(A_STAND, True);
- if not ((FModel.Animation = A_WALK) and (Abs(FObj.Vel.X) < 4) and not FModel.Fire) then FModel.Update;
+ if not ((FModel.Animation = A_WALK) and (Abs(FObj.Vel.X) < 4) and not FModel.GetFire()) then FModel.Update;
for b := Low(FKeys) to High(FKeys) do
if FKeys[b].Time = 0 then FKeys[b].Pressed := False else Dec(FKeys[b].Time);
// Время до повторного респауна, смены оружия, исользования, захвата флага
for i := T_RESPAWN to T_FLAGCAP do utils.writeInt(st, LongWord(FTime[i]));
// Название модели
- utils.writeStr(st, FModel.Name);
+ utils.writeStr(st, FModel.GetName());
// Цвет модели
utils.writeInt(st, Byte(FColor.R));
utils.writeInt(st, Byte(FColor.G));
end;
procedure TPlayer.FlySmoke(Times: DWORD = 1);
-var
- id, i: DWORD;
- Anim: TAnimation;
+ var i: DWORD;
begin
if (Random(5) = 1) and (Times = 1) then
Exit;
if BodyInLiquid(0, 0) then
begin
- g_GFX_Bubbles(Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2)+Random(3)-1,
- Obj.Y+Obj.Rect.Height+8, 1, 8, 4);
+ {$IFDEF ENABLE_GFX}
+ g_GFX_Bubbles(Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2)+Random(3)-1,
+ Obj.Y+Obj.Rect.Height+8, 1, 8, 4);
+ {$ENDIF}
if Random(2) = 0 then
g_Sound_PlayExAt('SOUND_GAME_BUBBLE1', FObj.X, FObj.Y)
else
Exit;
end;
- if g_Frames_Get(id, 'FRAMES_SMOKE') then
+ for i := 1 to Times do
begin
- for i := 1 to Times do
- begin
- Anim := TAnimation.Create(id, False, 3);
- Anim.Alpha := 150;
- g_GFX_OnceAnim(Obj.X+Obj.Rect.X+Random(Obj.Rect.Width+Times*2)-(Anim.Width div 2),
- Obj.Y+Obj.Rect.Height-4+Random(8+Times*2), Anim, ONCEANIM_SMOKE);
- Anim.Free();
- end;
+ {$IFDEF ENABLE_GFX}
+ g_GFX_QueueEffect(
+ R_GFX_SMOKE_TRANS,
+ Obj.X+Obj.Rect.X+Random(Obj.Rect.Width+Times*2)-(R_GFX_SMOKE_WIDTH div 2),
+ Obj.Y+Obj.Rect.Height-4+Random(8+Times*2)
+ );
+ {$ENDIF}
end;
end;
procedure TPlayer.OnFireFlame(Times: DWORD = 1);
-var
- id, i: DWORD;
- Anim: TAnimation;
+ var i: DWORD;
begin
if (Random(10) = 1) and (Times = 1) then
Exit;
- if g_Frames_Get(id, 'FRAMES_FLAME') then
+ for i := 1 to Times do
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;
+ {$IFDEF ENABLE_GFX}
+ g_GFX_QueueEffect(
+ R_GFX_FLAME,
+ Obj.X+Obj.Rect.X+Random(Obj.Rect.Width+Times*2)-(R_GFX_FLAME_WIDTH div 2),
+ Obj.Y+8+Random(8+Times*2)
+ );
+ {$ENDIF}
end;
end;
FObj.X := X;
FObj.Y := Y;
FObj.Rect := PLAYER_CORPSERECT;
- FModelName := ModelName;
FMess := aMess;
+ FModel := g_PlayerModel_Get(ModelName);
if FMess then
- begin
- FState := CORPSE_STATE_MESS;
- g_PlayerModel_GetAnim(ModelName, A_DIE2, FAnimation, FAnimationMask);
- end
+ begin
+ FState := CORPSE_STATE_MESS;
+ FModel.ChangeAnimation(A_DIE2);
+ end
else
- begin
- FState := CORPSE_STATE_NORMAL;
- g_PlayerModel_GetAnim(ModelName, A_DIE1, FAnimation, FAnimationMask);
- end;
+ begin
+ FState := CORPSE_STATE_NORMAL;
+ FModel.ChangeAnimation(A_DIE1);
+ end;
end;
destructor TCorpse.Destroy();
begin
- FAnimation.Free();
-
+ FModel.Free;
inherited;
end;
procedure TCorpse.Damage(Value: Word; SpawnerUID: Word; vx, vy: Integer);
-var
- pm: TPlayerModel;
- Blood: TModelBlood;
+ {$IFDEF ENABLE_GFX}
+ var Blood: TModelBlood;
+ {$ENDIF}
begin
if FState = CORPSE_STATE_REMOVEME then
Exit;
FDamage := FDamage + Value;
+{$IFDEF ENABLE_GIBS}
if FDamage > 150 then
+ begin
+ if FModel <> nil then
begin
- if FAnimation <> nil then
- begin
- FAnimation.Free();
- FAnimation := nil;
-
- FState := CORPSE_STATE_REMOVEME;
-
- g_Player_CreateGibs(FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2),
- FObj.Y+FObj.Rect.Y+(FObj.Rect.Height div 2),
- FModelName, FColor);
- // Звук мяса от трупа:
- pm := g_PlayerModel_Get(FModelName);
- pm.PlaySound(MODELSOUND_DIE, 5, FObj.X, FObj.Y);
- pm.Free;
-
- // Зловещий смех:
- if (gBodyKillEvent <> -1)
- and gDelayedEvents[gBodyKillEvent].Pending then
- gDelayedEvents[gBodyKillEvent].Pending := False;
- gBodyKillEvent := g_Game_DelayEvent(DE_BODYKILL, 1050, SpawnerUID);
- end;
+ FState := CORPSE_STATE_REMOVEME;
+
+ g_Gibs_Create(
+ FObj.X + FObj.Rect.X + (FObj.Rect.Width div 2),
+ FObj.Y + FObj.Rect.Y + (FObj.Rect.Height div 2),
+ FModel.id,
+ FModel.Color
+ );
+
+ // Звук мяса от трупа:
+ FModel.PlaySound(MODELSOUND_DIE, 5, FObj.X, FObj.Y);
+
+ // Зловещий смех:
+ if (gBodyKillEvent <> -1) and gDelayedEvents[gBodyKillEvent].Pending then
+ gDelayedEvents[gBodyKillEvent].Pending := False;
+ gBodyKillEvent := g_Game_DelayEvent(DE_BODYKILL, 1050, SpawnerUID);
+
+ FModel.Free;
+ FModel := nil;
end
+ end
else
- begin
- Blood := g_PlayerModel_GetBlood(FModelName);
- FObj.Vel.X := FObj.Vel.X + vx;
- FObj.Vel.Y := FObj.Vel.Y + vy;
+{$ENDIF}
+ begin
+ FObj.Vel.X := FObj.Vel.X + vx;
+ FObj.Vel.Y := FObj.Vel.Y + vy;
+ {$IFDEF ENABLE_GFX}
+ Blood := FModel.GetBlood();
g_GFX_Blood(FObj.X+PLAYER_CORPSERECT.X+(PLAYER_CORPSERECT.Width div 2),
FObj.Y+PLAYER_CORPSERECT.Y+(PLAYER_CORPSERECT.Height div 2),
Value, vx, vy, 16, (PLAYER_CORPSERECT.Height*2) div 3,
Blood.R, Blood.G, Blood.B, Blood.Kind);
- end;
+ {$ENDIF}
+ end;
end;
procedure TCorpse.Update();
Exit;
end;
- if FAnimation <> nil then
- FAnimation.Update();
- if FAnimationMask <> nil then
- FAnimationMask.Update();
+ if FModel <> nil then
+ FModel.Update;
end;
procedure TCorpse.SaveState (st: TStream);
-var
- anim: Boolean;
+ var anim: Boolean;
begin
assert(st <> nil);
// Накопленный урон
utils.writeInt(st, Byte(FDamage));
// Цвет
- utils.writeInt(st, Byte(FColor.R));
- utils.writeInt(st, Byte(FColor.G));
- utils.writeInt(st, Byte(FColor.B));
+ utils.writeInt(st, Byte(FModel.Color.R));
+ utils.writeInt(st, Byte(FModel.Color.G));
+ utils.writeInt(st, Byte(FModel.Color.B));
// Объект трупа
Obj_SaveState(st, @FObj);
utils.writeInt(st, Word(FPlayerUID));
- // Есть ли анимация
- anim := (FAnimation <> nil);
+ // animation
+ anim := (FModel <> nil);
utils.writeBool(st, anim);
- // Если есть - сохраняем
- if anim then FAnimation.SaveState(st);
- // Есть ли маска анимации
- anim := (FAnimationMask <> nil);
+ if anim then FModel.AnimState.SaveState(st, 0, False);
+ // animation for mask (same as animation, compat with older saves)
+ anim := (FModel <> nil);
utils.writeBool(st, anim);
- // Если есть - сохраняем
- if anim then FAnimationMask.SaveState(st);
+ if anim then FModel.AnimState.SaveState(st, 0, False);
end;
procedure TCorpse.LoadState (st: TStream);
-var
- anim: Boolean;
+ var anim, blending: Boolean; r, g, b, alpha: Byte; stub: TAnimationState;
begin
assert(st <> nil);
// Накопленный урон
FDamage := utils.readByte(st);
// Цвет
- FColor.R := utils.readByte(st);
- FColor.G := utils.readByte(st);
- FColor.B := utils.readByte(st);
+ r := utils.readByte(st);
+ g := utils.readByte(st);
+ b := utils.readByte(st);
+ FModel.SetColor(r, g, b);
// Объект трупа
Obj_LoadState(@FObj, st);
FPlayerUID := utils.readWord(st);
- // Есть ли анимация
+ // animation
+ stub := TAnimationState.Create(False, 0, 0);
anim := utils.readBool(st);
- // Если есть - загружаем
if anim then
begin
- Assert(FAnimation <> nil, 'TCorpse.LoadState: no FAnimation');
- FAnimation.LoadState(st);
- end;
- // Есть ли маска анимации
- anim := utils.readBool(st);
- // Если есть - загружаем
- if anim then
+ stub.LoadState(st, alpha, blending);
+ FModel.AnimState.CurrentFrame := Min(stub.CurrentFrame, FModel.AnimState.Length);
+ end
+ else
begin
- Assert(FAnimationMask <> nil, 'TCorpse.LoadState: no FAnimationMask');
- FAnimationMask.LoadState(st);
+ FModel.Free;
+ FModel := nil
end;
+ // animation for mask (same as animation, compat with older saves)
+ anim := utils.readBool(st);
+ if anim then stub.LoadState(st, alpha, blending);
+ stub.Free;
end;
{ T B o t : }