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_MOVEMENTS_H
24 #define TWINE_SCENE_MOVEMENTS_H
25
26 #include "common/scummsys.h"
27 #include "twine/shared.h"
28
29 namespace TwinE {
30
31 class TwinEEngine;
32 class ActorStruct;
33 struct ActorMoveStruct;
34
35 class Movements {
36 private:
37 TwinEEngine *_engine;
38
39 struct ChangedCursorKeys {
40 uint8 forwardChange = 0;
41 uint8 backwardChange = 0;
42 uint8 leftChange = 0;
43 uint8 rightChange = 0;
44 uint8 forwardDown = 0;
45 uint8 backwardDown = 0;
46 uint8 leftDown = 0;
47 uint8 rightDown = 0;
48
49 void update(TwinEEngine *engine);
50
51 inline bool operator==(const ChangedCursorKeys &rhs) const {
52 return forwardChange == rhs.forwardChange && backwardChange == rhs.backwardChange && leftChange == rhs.leftChange && rightChange == rhs.rightChange;
53 }
54
55 inline operator bool() const {
56 return forwardChange && backwardChange && leftChange && rightChange;
57 }
58
59 inline bool operator!=(const ChangedCursorKeys &rhs) const {
60 return forwardChange != rhs.forwardChange || backwardChange != rhs.backwardChange || leftChange != rhs.leftChange || rightChange != rhs.rightChange;
61 }
62 };
63
64 // enter, space, ...
65 int16 _heroActionKey = 0;
66 int32 _previousLoopActionKey = 0;
67 // cursor keys
68 ChangedCursorKeys _changedCursorKeys;
69 ChangedCursorKeys _previousChangedCursorKeys;
70
71 /**
72 * The Actor is controlled by the player. This works well only for the Hero Actor in general.
73 * To use it for other Actors they would have to have necessary animations that would be also
74 * correctly indexed. The primary purpose for this mode is to re-enable player's control over
75 * the Hero after it has been disabled for some reasons.
76 */
77 void processManualAction(int actorIdx);
78 /**
79 * The Actor tries to move towards the target Actor. This only means that it will always face
80 * in its direction (as fast as the Rotation delay property allows). To make it really follow
81 * anything it must be assigned a moving Animation first, and the Actor will not stop by itself
82 * after reaching the target. To make a real following, the Actor's animation must be changed
83 * for example to standing animation when the Actor is near the target, and changed back to a
84 * moving animation when it's far from it. The Follow mode handles only the facing angle.
85 */
86 void processFollowAction(int actorIdx);
87 /**
88 * Makes the Actor walk and turn by random angles and at random moments. In original game it is
89 * only used for Nitro-Mecha-Penguins, but it can be used for any 3-D Actor that has standing
90 * and walking animation (with virtual indexes 0 and 1 respectively). This mode requires the
91 * Randomize interval (Info1) property to be less or equal to 117, otherwise the Actor will just
92 * walk without turning. Exact meaning of the property is not known.
93 */
94 void processRandomAction(int actorIdx);
95 /**
96 * The Actor's Track Script is run from the first command, and when it reaches END or STOP it
97 * starts over again.
98 */
99 void processTrackAction(int actorIdx);
100 /**
101 * This mode is used to make an Actor follow specified Actor's X and Z (horizontal) coordinates.
102 * This is mainly used for Sprite Actors to be always above other Sprite Actors (like platforms).
103 * Unlike the Follow mode, this mode sets the Actor's position. If the Actor is a Sprite Actor,
104 * its speed is not taken into consideration in this mode.
105 */
106 void processSameXZAction(int actorIdx);
107
108 /**
109 * @return A value of @c true means that the actor should e.g. start reading a sign or checking
110 * a locker for loot or secrets
111 */
112 bool processBehaviourExecution(int actorIdx);
113 bool processAttackExecution(int actorIdx);
114 void processManualMovementExecution(int actorIdx);
115 void processManualRotationExecution(int actorIdx);
116
117 bool _heroAction = false;
118
119 public:
120 Movements(TwinEEngine *engine);
121
122 void update();
123
124 /**
125 * Hero executes the current action of the trigger zone
126 */
127 bool shouldTriggerZoneAction() const;
128
129 bool _heroMoved = false;
130
131 /** Process actor coordinate */
132 IVec3 _processActor;
133
134 /** Previous process actor coordinate */
135 IVec3 _previousActor;
136
137 int32 _targetActorDistance = 0;
138
139 /**
140 * Get shadow position
141 * @param pos Shadow coordinates
142 */
143 void getShadowPosition(const IVec3 &pos);
144
145 /**
146 * Set actor safe angle
147 * @param startAngle start angle
148 * @param endAngle end angle
149 * @param stepAngle number of steps
150 * @param movePtr time pointer to update
151 */
152 void setActorAngleSafe(int16 startAngle, int16 endAngle, int16 stepAngle, ActorMoveStruct *movePtr);
153
154 /**
155 * Clear actors safe angle
156 * @param actorPtr actor pointer
157 */
158 void clearRealAngle(ActorStruct *actorPtr);
159
160 /**
161 * Set actor safe angle
162 * @param startAngle start angle
163 * @param endAngle end angle
164 * @param stepAngle number of steps
165 * @param movePtr time pointer to update
166 */
167 void setActorAngle(int16 startAngle, int16 endAngle, int16 stepAngle, ActorMoveStruct *movePtr);
168
169 /**
170 * Get actor angle
171 * @param x1 Actor 1 X
172 * @param z1 Actor 1 Z
173 * @param x2 Actor 2 X
174 * @param z2 Actor 2 Z
175 */
176 int32 getAngleAndSetTargetActorDistance(int32 x1, int32 z1, int32 x2, int32 z2);
177
getAngleAndSetTargetActorDistance(const IVec3 & v1,const IVec3 & v2)178 inline int32 getAngleAndSetTargetActorDistance(const IVec3& v1, const IVec3 &v2) {
179 return getAngleAndSetTargetActorDistance(v1.x, v1.z, v2.x, v2.z);
180 }
181
182 /**
183 * Rotate actor with a given angle
184 * @param x Actor current X coordinate
185 * @param z Actor current Z coordinate
186 * @param angle Actor angle to rotate
187 */
188 IVec3 rotateActor(int32 x, int32 z, int32 angle);
189
190 /**
191 * Move actor around the scene
192 * @param angleFrom Current actor angle
193 * @param angleTo Angle to rotate
194 * @param speed Rotate speed
195 * @param movePtr Pointer to process movements
196 */
197 void moveActor(int32 angleFrom, int32 angleTo, int32 speed, ActorMoveStruct *movePtr) const;
198
199 void processActorMovements(int32 actorIdx);
200 };
201
shouldTriggerZoneAction()202 inline bool Movements::shouldTriggerZoneAction() const {
203 return _heroAction;
204 }
205
206 } // namespace TwinE
207
208 #endif
209