1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #ifndef TWINE_SCENE_ACTOR_H
24 #define TWINE_SCENE_ACTOR_H
25
26 #include "common/scummsys.h"
27 #include "twine/parser/anim.h"
28 #include "twine/parser/entity.h"
29 #include "twine/shared.h"
30
31 namespace TwinE {
32
33 /** Total number of sprites allowed in the game */
34 #define NUM_SPRITES 425 // 200 for lba1
35
36 /** Total number of bodies allowed in the game */
37 #define NUM_BODIES 469 // 131 for lba1
38
39 /** Actors move structure */
40 struct ActorMoveStruct {
41 int16 from = 0;
42 int16 to = 0;
43 int16 numOfStep = 0;
44 int32 timeOfChange = 0;
45
46 /**
47 * Get actor real angle
48 * @param time engine time used for interpolation
49 */
50 int32 getRealAngle(int32 time);
51
52 /**
53 * Get actor step
54 * @param time engine time used for interpolation
55 */
56 int32 getRealValue(int32 time);
57 };
58
59 /** Actors animation timer structure */
60 struct AnimTimerDataStruct {
61 const KeyFrame *ptr = nullptr;
62 int32 time = 0;
63 };
64
65 /** Actors static flags structure */
66 struct StaticFlagsStruct {
67 uint32 bComputeCollisionWithObj : 1; // 0x000001
68 uint32 bComputeCollisionWithBricks : 1; // 0x000002
69 uint32 bIsZonable : 1; // 0x000004
70 uint32 bUsesClipping : 1; // 0x000008
71 uint32 bCanBePushed : 1; // 0x000010
72 uint32 bComputeLowCollision : 1; // 0x000020
73 uint32 bCanDrown : 1; // 0x000040
74 uint32 bComputeCollisionWithFloor : 1; // 0x000080
75 uint32 bUnk0100 : 1; // 0x000100
76 uint32 bIsHidden : 1; // 0x000200
77 uint32 bIsSpriteActor : 1; // 0x000400
78 uint32 bCanFall : 1; // 0x000800
79 uint32 bDoesntCastShadow : 1; // 0x001000
80 uint32 bIsBackgrounded : 1; // 0x002000
81 uint32 bIsCarrierActor : 1; // 0x004000
82 // take smaller value for bound, or if not set take average for bound
83 uint32 bUseMiniZv : 1; // 0x008000
84 uint32 bHasInvalidPosition : 1; // 0x010000
85 uint32 bNoElectricShock : 1; // 0x020000
86 uint32 bHasSpriteAnim3D : 1; // 0x040000
87 uint32 bNoPreClipping : 1; // 0x080000
88 uint32 bHasZBuffer : 1; // 0x100000
89 uint32 bHasZBufferInWater : 1; // 0x200000
90 };
91
92 /** Actors dynamic flags structure */
93 struct DynamicFlagsStruct {
94 uint16 bWaitHitFrame : 1; // 0x0001 wait for hit frame
95 uint16 bIsHitting : 1; // 0x0002 hit frame anim
96 uint16 bAnimEnded : 1; // 0x0004 anim ended in the current loop (will be looped in the next engine loop)
97 uint16 bAnimFrameReached : 1; // 0x0008 new frame anim reached
98 uint16 bIsVisible : 1; // 0x0010 actor has been drawn in this loop
99 uint16 bIsDead : 1; // 0x0020 is dead
100 uint16 bIsSpriteMoving : 1; // 0x0040 door is opening or closing (wait to reach the destination position)
101 uint16 bIsRotationByAnim : 1; // 0x0080 actor rotation is managed by its animaation not by the engine
102 uint16 bIsFalling : 1; // 0x0100 is falling on scene
103 uint16 bUnk0200 : 1; // 0x0200 unused
104 uint16 bUnk0400 : 1; // 0x0400 unused
105 uint16 bUnk0800 : 1; // 0x0800 unused
106 uint16 bUnk1000 : 1; // 0x1000 unused
107 uint16 bUnk2000 : 1; // 0x2000 unused
108 uint16 bUnk4000 : 1; // 0x4000 unused
109 uint16 bUnk8000 : 1; // 0x8000 unused
110 };
111
112 /**
113 * Bonus type flags - a bitfield value, of which the bits mean:
114 * bit 8: clover leaf,
115 * bit 7: small key,
116 * bit 6: magic,
117 * bit 5: life,
118 * bit 4: money,
119 * If more than one type of bonus is selected, the actual type of bonus
120 * will be chosen randomly each time player uses Action.
121 */
122 struct BonusParameter {
123 uint16 unk1 : 1;
124 uint16 unk2 : 1;
125 uint16 unk3 : 1;
126 uint16 unk4 : 1;
127 uint16 kashes : 1;
128 uint16 lifepoints : 1;
129 uint16 magicpoints : 1;
130 uint16 key : 1;
131 uint16 cloverleaf : 1;
132 uint16 unused : 7;
133 };
134
135 #define kActorMaxLife 50
136
137 /**
138 * Actors structure
139 *
140 * Such as characters, doors, moving plataforms, invisible actors, ...
141 */
142 class ActorStruct {
143 private:
144 ShapeType _brickShape = ShapeType::kNone; // field_3
145 bool _brickCausesDamage = false;
146
147 EntityData _entityData;
148 public:
149 StaticFlagsStruct _staticFlags;
150 DynamicFlagsStruct _dynamicFlags;
151
brickShape()152 inline ShapeType brickShape() const { return _brickShape; }
setBrickShape(ShapeType shapeType)153 inline void setBrickShape(ShapeType shapeType) {
154 _brickShape = shapeType;
155 _brickCausesDamage = false;
156 }
setBrickCausesDamage()157 inline void setBrickCausesDamage() { _brickCausesDamage = true; }
brickCausesDamage()158 inline bool brickCausesDamage() { return _brickCausesDamage; }
159 void loadModel(int32 modelIndex, bool lba1);
160
161 void addLife(int32 val);
162
163 void setLife(int32 val);
164
165 bool isAttackWeaponAnimationActive() const;
166 bool isAttackAnimationActive() const;
167 bool isJumpAnimationActive() const;
168
169 const IVec3 &pos() const;
170
171 int32 _entity = 0; // costumeIndex - index into bodyTable
172 BodyType _body = BodyType::btNormal;
173 AnimationTypes _anim = AnimationTypes::kAnimNone;
174 AnimationTypes _animExtra = AnimationTypes::kStanding;
175 AnimationTypes _animExtraPtr = AnimationTypes::kAnimNone;
176 int32 _sprite = 0;
177 EntityData *_entityDataPtr = nullptr;
178
179 int16 _actorIdx = 0; // own actor index
180 IVec3 _pos;
181 int32 _strengthOfHit = 0;
182 int32 _hitBy = 0;
183 BonusParameter _bonusParameter;
184 int32 _angle = 0; // facing angle of actor. Minumum is 0 (SW). Going counter clock wise
185 int32 _speed = 0;
186 ControlMode _controlMode = ControlMode::kNoMove;
187 int32 _delayInMillis = 0;
188 int32 _cropLeft = 0;
189 int32 _cropTop = 0;
190 int32 _cropRight = 0;
191 int32 _cropBottom = 0;
192 int32 _followedActor = 0; // same as info3
193 int32 _bonusAmount = 0;
194 int32 _talkColor = COLOR_BLACK;
195 int32 _armor = 0;
196 int32 _life = 0;
197
198 IVec3 _collisionPos;
199
200 int32 _positionInMoveScript = 0;
201 uint8 *_moveScript = nullptr;
202 int32 _moveScriptSize = 0;
203
204 int32 _positionInLifeScript = 0;
205 uint8 *_lifeScript = nullptr;
206 int32 _lifeScriptSize = 0;
207
208 int32 _labelIdx = 0; // script label index
209 int32 _currentLabelPtr = 0; // pointer to LABEL offset
210 int32 _pausedTrackPtr = 0;
211
212 /**
213 * colliding actor id
214 */
215 int32 _collision = 0;
216 /**
217 * actor id we are standing on
218 */
219 int32 _standOn = 0;
220 int32 _zone = 0;
221
222 int32 _lastRotationAngle = ANGLE_0;
223 IVec3 _lastPos;
224 int32 _previousAnimIdx = 0;
225 int32 _doorStatus = 0;
226 int32 _animPosition = 0;
227 AnimType _animType = AnimType::kAnimationTypeLoop;
228 int32 _spriteActorRotation = 0;
229 uint8 _brickSound = 0U;
230
231 BoundingBox _boudingBox;
232 ActorMoveStruct _move;
233 AnimTimerDataStruct _animTimerData;
234 };
235
pos()236 inline const IVec3 &ActorStruct::pos() const {
237 return _pos;
238 }
239
addLife(int32 val)240 inline void ActorStruct::addLife(int32 val) {
241 setLife(_life + val);
242 }
243
setLife(int32 val)244 inline void ActorStruct::setLife(int32 val) {
245 _life = val;
246 if (_life > kActorMaxLife) {
247 _life = kActorMaxLife;
248 }
249 }
250
251 class TwinEEngine;
252
253 class Actor {
254 private:
255 TwinEEngine *_engine;
256
257 /** Hero 3D entity for normal behaviour */
258 EntityData _heroEntityNORMAL;
259 /** Hero 3D entity for athletic behaviour */
260 EntityData _heroEntityATHLETIC;
261 /** Hero 3D entity for aggressive behaviour */
262 EntityData _heroEntityAGGRESSIVE;
263 /** Hero 3D entity for discrete behaviour */
264 EntityData _heroEntityDISCRETE;
265 /** Hero 3D entity for protopack behaviour */
266 EntityData _heroEntityPROTOPACK;
267
268 void initSpriteActor(int32 actorIdx);
269
270 /**
271 * Initialize 3D actor body
272 * @param bodyIdx 3D actor body index
273 * @param actorIdx 3D actor index
274 */
275 int32 initBody(BodyType bodyIdx, int32 actorIdx, ActorBoundingBox &actorBoundingBox);
276
277 void loadBehaviourEntity(ActorStruct *actor, EntityData &entityData, int16 &bodyAnimIndex, int32 index);
278
279 public:
280 Actor(TwinEEngine *engine);
281
282 ActorStruct *_processActorPtr = nullptr;
283
284 /** Actor shadow coordinate */
285 IVec3 _shadowCoord;
286
287 HeroBehaviourType _heroBehaviour = HeroBehaviourType::kNormal;
288 /** Hero auto aggressive mode */
289 bool _autoAggressive = true;
290 /** Previous Hero behaviour */
291 HeroBehaviourType _previousHeroBehaviour = HeroBehaviourType::kNormal;
292 /** Previous Hero angle */
293 int16 _previousHeroAngle = 0;
294
295 int16 _cropBottomScreen = 0;
296
297 /** Hero current anim for normal behaviour */
298 int16 _heroAnimIdxNORMAL = 0;
299 /** Hero current anim for athletic behaviour */
300 int16 _heroAnimIdxATHLETIC = 0;
301 /** Hero current anim for aggressive behaviour */
302 int16 _heroAnimIdxAGGRESSIVE = 0;
303 /** Hero current anim for discrete behaviour */
304 int16 _heroAnimIdxDISCRETE = 0;
305 /** Hero current anim for protopack behaviour */
306 int16 _heroAnimIdxPROTOPACK = 0;
307
308 /** Hero anim for behaviour menu */
309 int16 _heroAnimIdx[4];
310
311 /** Restart hero variables while opening new scenes */
312 void restartHeroScene();
313
314 /** Load hero 3D body and animations */
315 void loadHeroEntities();
316
317 TextId getTextIdForBehaviour() const;
318
319 /**
320 * Set hero behaviour
321 * @param behaviour behaviour value to set
322 */
323 void setBehaviour(HeroBehaviourType behaviour);
324
325 /**
326 * Initialize 3D actor
327 * @param bodyIdx 3D actor body index
328 * @param actorIdx 3D actor index
329 */
330 void initModelActor(BodyType bodyIdx, int16 actorIdx);
331
332 /**
333 * Initialize actors
334 * @param actorIdx actor index to init
335 */
336 void initActor(int16 actorIdx);
337
338 /**
339 * Reset actor
340 * @param actorIdx actor index to init
341 */
342 void resetActor(int16 actorIdx);
343
344 /**
345 * Process hit actor
346 * @param actorIdx actor hitting index
347 * @param actorIdxAttacked actor attacked index
348 * @param strengthOfHit actor hitting strength of hit
349 * @param angle angle of actor hitting
350 */
351 void hitActor(int32 actorIdx, int32 actorIdxAttacked, int32 strengthOfHit, int32 angle);
352
353 /** Process actor carrier */
354 void processActorCarrier(int32 actorIdx);
355
356 /** Process actor extra bonus */
357 void processActorExtraBonus(int32 actorIdx);
358 };
359
360 } // namespace TwinE
361
362 #endif
363