DEADSOFTWARE

render: remove flag animation from player model state
[d2df-sdl.git] / src / game / opengl / r_playermodel.pas
1 (* Copyright (C) Doom 2D: Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License ONLY.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *)
15 {$INCLUDE ../../shared/a_modes.inc}
16 unit r_playermodel;
18 interface
20 uses g_playermodel; // TPlayerModel
22 procedure r_PlayerModel_Initialize;
23 procedure r_PlayerModel_Finalize;
24 procedure r_PlayerModel_Load;
25 procedure r_PlayerModel_Free;
26 procedure r_PlayerModel_Update;
27 procedure r_PlayerModel_Draw (pm: TPlayerModel; X, Y: Integer; Alpha: Byte = 0);
29 implementation
31 uses
32 SysUtils, Classes, Math,
33 MAPDEF, utils,
34 ImagingTypes, Imaging, ImagingUtility,
35 r_graphics, g_options, r_animations, r_textures,
36 g_base, g_basic, g_map, g_weapons, g_textures
37 ;
39 const
40 WeapNames: Array [WP_FIRST + 1..WP_LAST] of String = ('csaw', 'hgun', 'sg', 'ssg', 'mgun', 'rkt', 'plz', 'bfg', 'spl', 'flm');
42 type
43 TDirIdx = TDirection.D_LEFT..TDirection.D_RIGHT;
44 TAnimIdx = A_STAND..A_LAST;
46 var
47 WeaponID: Array [WP_FIRST + 1..WP_LAST, W_POS_NORMAL..W_POS_DOWN, W_ACT_NORMAL..W_ACT_FIRE] of DWORD;
48 Models: Array of record
49 Frames: Array [TDirIdx, TAnimIdx] of record
50 base: DWORD;
51 mask: DWORD;
52 end;
53 end;
54 RedFlagFrames: DWORD;
55 BlueFlagFrames: DWORD;
56 FlagAnimState: TAnimationState;
58 procedure r_PlayerModel_Initialize;
59 begin
60 FlagAnimState := TAnimationState.Create(True, 8, 5);
61 end;
63 procedure r_PlayerModel_Finalize;
64 begin
65 FlagAnimState.Free;
66 FlagAnimState := nil;
67 end;
69 procedure ExtAnimFromBaseAnim(MName: String; AIdx: Integer);
70 const
71 CopyAnim: array [A_LASTBASE+1..A_LASTEXT] of Integer = (
72 A_WALK, A_WALK, A_WALK, A_WALK, A_WALK,
73 A_STAND, A_WALK, A_ATTACK, A_WALK, A_SEEUP, A_SEEDOWN,
74 A_ATTACKUP, A_ATTACKDOWN
75 );
76 var
77 OIdx: Integer;
78 AName, OName: String;
79 begin
80 // HACK: shitty workaround to duplicate base animations
81 // in place of extended, replace with something better later
83 Assert((AIdx > A_LASTBASE) and (AIdx <= A_LASTEXT));
84 OIdx := CopyAnim[AIdx];
86 AName := MName + '_RIGHTANIM' + IntToStr(AIdx);
87 OName := MName + '_RIGHTANIM' + IntToStr(OIdx);
88 Assert(g_Frames_Dup(AName, OName));
89 Assert(g_Frames_Dup(AName + '_MASK', OName + '_MASK'));
90 AName := MName + '_LEFTANIM' + IntToStr(AIdx);
91 OName := MName + '_LEFTANIM' + IntToStr(OIdx);
92 if g_Frames_Exists(AName) then
93 begin
94 g_Frames_Dup(AName, OName);
95 g_Frames_Dup(AName + '_MASK', OName + '_MASK');
96 end;
97 end;
99 procedure r_PlayerModel_Load;
100 var ID1, ID2: DWORD; i, a, b: Integer; prefix, aname: String;
101 begin
102 g_Frames_CreateWAD(@RedFlagFrames, 'FRAMES_FLAG_RED', GameWAD + ':TEXTURES\FLAGRED', 64, 64, 5, False);
103 g_Frames_CreateWAD(@BlueFlagFrames, 'FRAMES_FLAG_BLUE', GameWAD + ':TEXTURES\FLAGBLUE', 64, 64, 5, False);
104 for a := WP_FIRST + 1 to WP_LAST do
105 begin
106 g_Texture_CreateWAD(WeaponID[a][W_POS_NORMAL][W_ACT_NORMAL], GameWAD+':WEAPONS\'+UpperCase(WeapNames[a]));
107 g_Texture_CreateWAD(WeaponID[a][W_POS_NORMAL][W_ACT_FIRE], GameWAD+':WEAPONS\'+UpperCase(WeapNames[a])+'_FIRE');
108 g_Texture_CreateWAD(WeaponID[a][W_POS_UP][W_ACT_NORMAL], GameWAD+':WEAPONS\'+UpperCase(WeapNames[a])+'_UP');
109 g_Texture_CreateWAD(WeaponID[a][W_POS_UP][W_ACT_FIRE], GameWAD+':WEAPONS\'+UpperCase(WeapNames[a])+'_UP_FIRE');
110 g_Texture_CreateWAD(WeaponID[a][W_POS_DOWN][W_ACT_NORMAL], GameWAD+':WEAPONS\'+UpperCase(WeapNames[a])+'_DN');
111 g_Texture_CreateWAD(WeaponID[a][W_POS_DOWN][W_ACT_FIRE], GameWAD+':WEAPONS\'+UpperCase(WeapNames[a])+'_DN_FIRE');
112 end;
113 Models := nil;
114 if PlayerModelsArray <> nil then
115 begin
116 SetLength(Models, Length(PlayerModelsArray));
117 for i := 0 to High(PlayerModelsArray) do
118 begin
119 prefix := PlayerModelsArray[i].FileName + ':TEXTURES\';
120 for b := A_STAND to A_LAST do
121 begin
122 aname := PlayerModelsArray[i].Info.Name + '_RIGHTANIM' + IntToStr(b);
123 with PlayerModelsArray[i].Anim[TDirection.D_RIGHT, b] do
124 begin
125 if not (g_Frames_CreateWAD(@ID1, aname, prefix + Resource, 64, 64, Frames, Back) and
126 g_Frames_CreateWAD(@ID2, aname + '_MASK', prefix + Mask, 64, 64, Frames, Back)) then
127 begin
128 if b > A_LASTBASE then
129 begin
130 ExtAnimFromBaseAnim(PlayerModelsArray[i].Info.Name, b);
131 continue
132 end
133 end;
134 Models[i].Frames[TDirection.D_RIGHT, b].base := ID1;
135 Models[i].Frames[TDirection.D_RIGHT, b].mask := ID2;
136 end;
137 with PlayerModelsArray[i].Anim[TDirection.D_LEFT, b] do
138 begin
139 if (Resource <> '') and (Mask <> '') then
140 begin
141 aname := PlayerModelsArray[i].Info.Name + '_LEFTANIM' + IntToStr(b);
142 g_Frames_CreateWAD(@ID1, aname, prefix + Resource, 64, 64, Frames, Back);
143 g_Frames_CreateWAD(@ID2, aname + '_MASK', prefix + Mask, 64, 64, Frames, Back);
144 Models[i].Frames[TDirection.D_LEFT, b].base := ID1;
145 Models[i].Frames[TDirection.D_LEFT, b].mask := ID2;
146 end
147 end
148 end
149 end
150 end
151 end;
153 procedure r_PlayerModel_Free;
154 var i, a, b, c: Integer;
155 begin
156 e_DeleteTexture(RedFlagFrames);
157 e_DeleteTexture(BlueFlagFrames);
158 if PlayerModelsArray = nil then Exit;
159 for i := 0 to High(PlayerModelsArray) do
160 begin
161 with PlayerModelsArray[i] do
162 begin
163 for a := A_STAND to A_LAST do
164 begin
165 g_Frames_DeleteByName(Info.Name+'_LEFTANIM'+IntToStr(a));
166 g_Frames_DeleteByName(Info.Name+'_LEFTANIM'+IntToStr(a)+'_MASK');
167 g_Frames_DeleteByName(Info.Name+'_RIGHTANIM'+IntToStr(a));
168 g_Frames_DeleteByName(Info.Name+'_RIGHTANIM'+IntToStr(a)+'_MASK');
169 end;
170 if Gibs <> nil then
171 begin
172 for a := 0 to High(Gibs) do
173 begin
174 e_DeleteTexture(Gibs[a].ID);
175 e_DeleteTexture(Gibs[a].MaskID);
176 Gibs[a].ID := DWORD(-1);
177 Gibs[a].MaskID := DWORD(-1);
178 end
179 end
180 end
181 end;
182 for a := WP_FIRST + 1 to WP_LAST do
183 for b := W_POS_NORMAL to W_POS_DOWN do
184 for c := W_ACT_NORMAL to W_ACT_FIRE do
185 e_DeleteTexture(WeaponID[a][b][c])
186 end;
188 procedure r_PlayerModel_Update;
189 begin
190 FlagAnimState.Update
191 end;
193 procedure r_PlayerModel_Draw (pm: TPlayerModel; X, Y: Integer; Alpha: Byte = 0);
194 var
195 Mirror: TMirrorType;
196 pos, act: Byte;
197 fp, p: TDFPoint;
198 FramesID: DWORD;
199 fa: Integer;
200 begin
201 // Флаги:
202 if pm.Direction = TDirection.D_LEFT then
203 Mirror := TMirrorType.None
204 else
205 Mirror := TMirrorType.Horizontal;
207 FramesID := 0;
208 case pm.Flag of
209 FLAG_RED: FramesID := RedFlagFrames;
210 FLAG_BLUE: FramesID := BlueFlagFrames;
211 end;
212 if (FramesID <> 0) and (not (pm.CurrentAnimation in [A_DIE1, A_DIE2])) then
213 begin
214 fp := PlayerModelsArray[pm.id].FlagPoint;
215 fa := PlayerModelsArray[pm.id].FlagAngle;
216 p.X := IfThen(pm.Direction = TDirection.D_LEFT, FLAG_BASEPOINT.X, 64 - FLAG_BASEPOINT.X);
217 p.Y := FLAG_BASEPOINT.Y;
218 r_AnimationState_DrawEx(
219 FramesID,
220 FlagAnimState,
221 X + IfThen(pm.Direction = TDirection.D_LEFT, fp.X - 1, 2 * FLAG_BASEPOINT.X - fp.X + 1) - FLAG_BASEPOINT.X,
222 Y + fp.Y - FLAG_BASEPOINT.Y + 1,
223 Mirror,
224 p,
225 IfThen(pm.Direction = TDirection.D_RIGHT, fa, -fa)
226 );
227 end;
229 // Оружие:
230 if pm.Direction = TDirection.D_RIGHT then
231 Mirror := TMirrorType.None
232 else
233 Mirror := TMirrorType.Horizontal;
235 if PlayerModelsArray[pm.id].Info.HaveWeapon and (not (pm.CurrentAnimation in [A_DIE1, A_DIE2, A_PAIN])) and (pm.CurrentWeapon in [WP_FIRST + 1..WP_LAST]) then
236 begin
237 if pm.CurrentAnimation in [A_SEEUP, A_ATTACKUP] then
238 pos := W_POS_UP
239 else
240 if pm.CurrentAnimation in [A_SEEDOWN, A_ATTACKDOWN] then
241 pos := W_POS_DOWN
242 else
243 pos := W_POS_NORMAL;
245 if (pm.CurrentAnimation in [A_ATTACK, A_ATTACKUP, A_ATTACKDOWN]) or pm.Fire then
246 act := W_ACT_FIRE
247 else
248 act := W_ACT_NORMAL;
250 if Alpha < 201 then
251 e_Draw(
252 WeaponID[pm.CurrentWeapon][pos][act],
253 X + PlayerModelsArray[pm.id].WeaponPoints[pm.CurrentWeapon, pm.CurrentAnimation, pm.Direction, pm.AnimState.CurrentFrame].X,
254 Y + PlayerModelsArray[pm.id].WeaponPoints[pm.CurrentWeapon, pm.CurrentAnimation, pm.Direction, pm.AnimState.CurrentFrame].Y,
255 0,
256 True,
257 False,
258 Mirror
259 );
260 end;
262 // Модель:
263 if (pm.Direction = TDirection.D_LEFT) and (Models[pm.id].Frames[TDirection.D_LEFT, pm.CurrentAnimation].base <> 0) then
264 begin
265 pm.AnimState.Alpha := Alpha; // !!!
266 FramesID := Models[pm.id].Frames[TDirection.D_LEFT, pm.CurrentAnimation].base;
267 r_AnimationState_Draw(FramesID, pm.AnimState, X, Y, TMirrorType.None);
268 end
269 else
270 begin
271 pm.AnimState.Alpha := Alpha; // !!!
272 FramesID := Models[pm.id].Frames[TDirection.D_RIGHT, pm.CurrentAnimation].base;
273 r_AnimationState_Draw(FramesID, pm.AnimState, X, Y, Mirror);
274 end;
276 // Маска модели:
277 e_Colors := pm.Color;
279 if (pm.Direction = TDirection.D_LEFT) and (Models[pm.id].Frames[TDirection.D_LEFT, pm.CurrentAnimation].mask <> 0) then
280 begin
281 pm.AnimState.Alpha := Alpha; // !!!
282 FramesID := Models[pm.id].Frames[TDirection.D_LEFT, pm.CurrentAnimation].mask;
283 r_AnimationState_Draw(FramesID, pm.AnimState, X, Y, TMirrorType.None);
284 end
285 else
286 begin
287 pm.AnimState.Alpha := Alpha; // !!!
288 FramesID := Models[pm.id].Frames[TDirection.D_RIGHT, pm.CurrentAnimation].mask;
289 r_AnimationState_Draw(FramesID, pm.AnimState, X, Y, Mirror);
290 end;
292 e_Colors.R := 255;
293 e_Colors.G := 255;
294 e_Colors.B := 255;
295 end;
297 end.