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