NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
d_base_actor.hpp
1#pragma once
2#include <types.h>
3#include <game/bases/d_base.hpp>
4#include <game/cLib/c_list.hpp>
5#include <game/framework/f_list_mg.hpp>
6#include <game/mLib/m_angle.hpp>
7#include <game/mLib/m_mtx.hpp>
8#include <game/mLib/m_vec.hpp>
9
10/**
11 * @brief The minimum required implementation for an actor base.
12 * @ingroup bases
13 * @details dBaseActor_c allows placing bases in either 2D or 3D space, by implementing the basic
14 * concepts of translation, scale, rotation and visibility. It also comes with a barebones physics
15 * engine and a few other properties. All actor bases (including sub-implementations) use
16 * @ref fProfile::fActorProfile_c "fActorProfile_c" for their profile, and their instances are
17 * added to a @ref ::m_actorManage "dedicated list" in addition to the default ones.
18 *
19 * The class is used directly when the only purpose of the base is displaying a 3D model.
20 * For more complex behaviour, it's recommended to use one of the available sub-implementations:
21 * - dActor_c, the minimum required implementation for a stage actor.
22 * - dWmActor_c, the minimum required implementation for a worldmap actor.
23 * - dMdActor_c, the minimum required implementation for a cutscene actor.
24 *
25 * ## Creating Actors
26 * Actor bases can be created by calling one of the two ::construct methods, which define two
27 * additional arguments to provide the starting position and rotation. A parent base can optionally
28 * be provided.
29 *
30 * @hint{If using a sub-implementation, using the provided method overloads is recommended.}
31 *
32 * ## Notable Operation Changes
33 * The following operation changes have been made:
34 * - The @p execute operation will not run if the game is undergoing a @ref dReset::Manage_c "reset procedure".
35 * - The @p finalUpdate step has been added to the @p execute operation. See below for more details.
36 *
37 * ### finalUpdate
38 * @p finalUpdate is an additional step that runs after every actor's main @p execute operation steps have
39 * been completed. It's only used in stages, and appears to have been introduced to address some model
40 * positioning issues by delaying the execution of the related code.
41 *
42 * @hint{If an actor's model is being unwantedly repositioned, moving its model updating code to this
43 * function may resolve the issue, particularly if the actor exhibits any of the following behaviours:
44 * - The actor can be carried (e.g. POW Block, Barrel);
45 * - The actor can be frozen and carried (e.g. Goomba, Spiny);
46 * - The actor is thrown by an actor that can be frozen and carried (e.g. Hammer, Boomerang).}
47 *
48 * It is currently unknown why this fix is necessary, but incorrect base execution order is a likely
49 * suspect.
50 *
51 * ## Positioning
52 * Actor positions are stored as @ref mVec3_c "3-dimensional floating point vectors". The @ref mPos
53 * "current position" can be modified manually, while the @ref mLastPos "previous position" and the
54 * @ref mPosDelta "position delta" are updated automatically after the @p execute operation.
55 *
56 * @hint{The game uses a
57 * @xlink{https://learn.microsoft.com/en-us/windows/uwp/graphics-concepts/coordinate-systems,
58 * right-handed coordinate system}, with the Y axis used as height and the Z axis used as depth.}
59 *
60 * ### Notes for Stage Actors
61 * - The position vector generally does not represent the center of the actor. To get the
62 * centered position, use the ::getCenterPos function.
63 * - In stages, the origin point is placed in the top left corner, therefore Y values must be negated.
64 * - Tiles have a length and height of @p 16.0 .
65 *
66 * ## Moving an Actor
67 * You can move an actor by calling the ::posMove function. A translation vector can optionally be
68 * provided, otherwise the actor will be moved by its @ref mSpeed "current speed".
69 *
70 * @hint{Many subclasses will call this function automatically. Make sure to research this to avoid
71 * unexpected behaviour!}
72 *
73 * ## Speed and Acceleration
74 * Each axis has a dedicated speed value, which can be used to move the actor by a certain distance in
75 * its direction. Acceleration can be applied linearly to the X/Y axes (and Z in a limited fashion) to
76 * increase/decrease the actor's speed in said direction. More complex acceleration curves can be
77 * utilized by modifying the acceleration value through other libraries.
78 *
79 * Speed on the X/Y axes can also be limited. However, the limits act as a target speed rather than a
80 * hard cap: should the current speed on a given axis exceed the corresponding limit, the actor will
81 * linearly decelerate until the limit is reached. Numerous functions are provided to update speed
82 * values, and their behaviour is summarised into the table below:
83 * <table>
84 * <thead>
85 * <tr>
86 * <th>Function</th>
87 * <th>Supports</th>
88 * <th colspan="2">Speed Value Source(s)</th>
89 * <th>Speed Value Destination(s)</th>
90 * <th>Acceleration(s) Applied</th>
91 * <th>Speed Limit(s) Checked</th>
92 * <th>Usage Notes</th>
93 * </tr>
94 * </thead>
95 * <tbody>
96 * <tr>
97 * <td>::calcSpeedF</td>
98 * <td>All Actors</td>
99 * <td>**F**</td>
100 * <td>::mSpeedF</td>
101 * <td>::mSpeedF</td>
102 * <td>::mAccelF</td>
103 * <td>::mMaxSpeedF</td>
104 * <td>
105 * - This function cannot be used on its own to update horizontal speed, as the result is not
106 * placed into the ::mSpeed vector.
107 * - It is unknown what "F" stands for. Guesses are either Facing or Forward.
108 * </td>
109 * </tr>
110 * <tr>
111 * <td rowspan="3">::calcSpeed</td>
112 * <td rowspan="3">3D Actors</td>
113 * <td>**X**</td>
114 * <td>::mSpeedF</td>
115 * <td>@ref mSpeed "mSpeed.x"</td>
116 * <td>*none*</td>
117 * <td>*none*</td>
118 * <td rowspan="3">
119 * - ::mSpeedF is applied into the direction the actor is facing.
120 * - Combine this with ::calcSpeedF to implement acceleration and limiting on the X/Z axes.
121 * </td>
122 * </tr>
123 * <tr>
124 * <td>**Y**</td>
125 * <td>@ref mSpeed "mSpeed.y"</td>
126 * <td>@ref mSpeed "mSpeed.y"</td>
127 * <td>::mAccelY</td>
128 * <td>::mMaxFallSpeed</td>
129 * </tr>
130 * <tr>
131 * <td>**Z**</td>
132 * <td>::mSpeedF</td>
133 * <td>@ref mSpeed "mSpeed.z"</td>
134 * <td>*none*</td>
135 * <td>*none*</td>
136 * </tr>
137 * <tr>
138 * <td>::calcSpeedX</td>
139 * <td>2D Actors</td>
140 * <td>**X**</td>
141 * <td>@ref mSpeed "mSpeed.x"</td>
142 * <td>@ref mSpeed "mSpeed.x"</td>
143 * <td>::mAccelF</td>
144 * <td>@ref mSpeedMax "mSpeedMax.x"</td>
145 * <td></td>
146 * </tr>
147 * <tr>
148 * <td>::calcSpeedY</td>
149 * <td>2D Actors</td>
150 * <td>**Y**</td>
151 * <td>@ref mSpeed "mSpeed.y"</td>
152 * <td>@ref mSpeed "mSpeed.y"</td>
153 * <td>::mAccelY</td>
154 * <td>@ref mSpeedMax "mSpeedMax.y"</td>
155 * <td>
156 * - This function is intended to be used with negative speed values, but will also work with
157 * positive ones.
158 * - Unlike all the other functions, this one treats the provided limit as a hard cap, so ensure it
159 * is used properly to prevent unintentional breakage.
160 * </td>
161 * </tr>
162 * <tr>
163 * <td>::calcFallSpeed</td>
164 * <td>2D Actors</td>
165 * <td>**Y**</td>
166 * <td>@ref mSpeed "mSpeed.y"</td>
167 * <td>@ref mSpeed "mSpeed.y"</td>
168 * <td>::mAccelY</td>
169 * <td>::mMaxFallSpeed</td>
170 * <td>In order for this function to work correctly, the acceleration value must be negated (so
171 * downwards acceleration is achieved with positive values and viceversa).</td>
172 * </tr>
173 * <tr>
174 * <td rowspan="2">::calcSpeedXY</td>
175 * <td rowspan="2">2D Actors</td>
176 * <td>**X**</td>
177 * <td>::mSpeedF</td>
178 * <td>@ref mSpeed "mSpeed.x"</td>
179 * <td>::mAccelF</td>
180 * <td>::mMaxSpeedF</td>
181 * <td rowspan="2">This function combines ::calcSpeedF (with the correct destination value) and
182 * ::calcFallSpeed, so make sure to read the notes for each of the two functions to ensure
183 * proper functionality.
184 * </td>
185 * </tr>
186 * <tr>
187 * <td>**Y**</td>
188 * <td>@ref mSpeed "mSpeed.y"</td>
189 * <td>@ref mSpeed "mSpeed.y"</td>
190 * <td>::mAccelY</td>
191 * <td>::mMaxFallSpeed</td>
192 * </tr>
193 * </tbody>
194 * </table>
195 *
196 * ## Scaling
197 * An actor base' scale can be controlled through the ::mScale vector. Depending on the base's
198 * implementation, the effects may only be visual or there may be no change at all.
199 *
200 * ## Rotation
201 * Actor rotations are stored as @ref mAng3_c "3-dimensional short vectors". There are two vectors:
202 * ::mAngle, which is used by 2D actors, and ::mAngle3D, which is used by 3D actors. A small number of
203 * bases ignore these conventions and employ the unused vector either as a backup or as a delta value.
204 *
205 * Just like for scaling, the effects of a rotation change also depend on the base's implementation.
206 *
207 * ## Visibility
208 * The actor's visibility can be controlled through the ::mVisible attribute. The actor won't be drawn
209 * if said property is set to @p false .
210 *
211 * ## Actor Properties
212 * ::mActorProperties is a bitfield storing various properties, which are later interpreted by inheriting
213 * classes. They are copied from the @ref fProfile::fActorProfile_c::mActorProperties
214 * "corresponding field" in @ref fProfile::fActorProfile_c "fActorProfile_c" when the base is
215 * constructed.
216 *
217 * ## Specialties
218 * ### Drawing Models Over 2D Layouts
219 * The ::draw2D function can replace the @p draw operation to allow 3D models to be drawn over the
220 * game's interface (the ::mVisible attribute in this case is ignored). This feature can only be
221 * used in the following scenes:
222 * - Main Menu (dScGameSetup_c)
223 * - Multiplayer Level Select (dScMulti_c)
224 * - Multiplayer Results (dScResult_c)
225 * - World 9 Unlock Cutscene (dScWorld9DeMo_c)
226 * - World Map (dScWMap_c)
227 *
228 * The world map scene also supports an additional function (::draw2D_lyt2), which is executed in a
229 * later draw pass.
230 *
231 * @hint{To use this feature in other scenes, simply call ::draw2DActorOnLyt1 (and optionally
232 * ::draw2DActorOnLyt2) from the scene's paint function (do so before the LinkScene call for the
233 * respective draw pass).}
234 *
235 * ### Profile Counting
236 * The number of actor bases using a given profile can be obtained by calling ::GetProfNameActorNum.
237 *
238 * ### Map Actor Types
239 * The ::GetActorType function offers basic type information about map actors. See ::ACTOR_KIND_e for
240 * details.
241 *
242 * ## Unused Content
243 * - The Z component of ::mSpeedMax is never used, despite being set to zero by various actors.
244 * - ::ACTOR_KIND_e type @ref ACTOR_KIND_e::ACTOR_UNK_6 "UNK_6" is not used anywhere, and presumably
245 * identifies a now-deleted actor.
246 *
247 * @todo Add missing links (especially the dGraph bit to avoid confusing terminology). Find the official
248 * name of LinkScene and link it.
249 */
250class dBaseActor_c : public dBase_c {
251public:
252
253 /// @brief An identifier that represents the actor's kind.
254 /// @details [This is only used in worldmaps].
256 ACTOR_MAP_GENERIC, ///< A generic map actor (dWmActor_c).
257 ACTOR_MAP_DEMO, ///< A map actor affected by cutscenes (dWmDemoActor_c).
258 ACTOR_MAP_OBJECT, ///< A map object (dWmObjActor_c).
259 ACTOR_MAP_ENEMY, ///< A map enemy (dWmEnemy_c).
260 ACTOR_MAP_PLAYER, ///< The worldmap player actor (dWmPlayer_c).
261 ACTOR_MAP_STOP, ///< @unused The unused map stop actor (daWmStop_c).
262 ACTOR_UNK_6, ///< @unused Not used anywhere.
263 ACTOR_MENU_PLAYER, ///< The menu player actor (da2DPlayer_c).
264 ACTOR_GENERIC, ///< A generic non-map actor.
265 };
266
267 dBaseActor_c(); ///< Constructs a new actor.
268
269protected:
270 virtual int preCreate();
271 virtual void postCreate(fBase_c::MAIN_STATE_e status);
272
273 virtual int preDelete();
274 virtual void postDelete(fBase_c::MAIN_STATE_e status);
275
276 virtual int preExecute();
277 virtual void postExecute(fBase_c::MAIN_STATE_e status);
278
279 virtual int preDraw();
280 virtual void postDraw(fBase_c::MAIN_STATE_e status);
281
282 virtual ~dBaseActor_c(); ///< Destroys the actor.
283
284 /// @brief Alternate drawing function used to draw 3D models in front of 2D graphics (first draw pass).
285 /// @details This feature is not used in stages. See [here](#drawing-models-over-2d-layouts)
286 /// for details.
287 virtual void draw2D();
288
289 /// @brief Alternate drawing function used to draw 3D models in front of 2D graphics (second draw pass).
290 /// @details This feature is not used in stages. See [here](#drawing-models-over-2d-layouts)
291 /// for details.
292 virtual void draw2D_lyt2();
293
294 virtual int GetActorType(); ///< Gets the actor kind. See ::ACTOR_KIND_e.
295
296 virtual void finalUpdate(); ///< Code to be executed after all actors' @p execute operation has run.
297
298public:
299 /// @brief Updates the actor's speed (3D actors). See [here](#speed-and-acceleration) for details.
300 void calcSpeed();
301
302 /// @brief Updates the actor's speed (2D actors). See [here](#speed-and-acceleration) for details.
303 void calcSpeedXY();
304
305 void calcSpeedX(); ///< Updates the actor's X speed. See [here](#speed-and-acceleration) for details.
306 void calcFallSpeed(); ///< Updates the actor's falling speed. See [here](#speed-and-acceleration) for details.
307 void calcSpeedY(); ///< Updates the actor's Y speed. See [here](#speed-and-acceleration) for details.
308 void calcSpeedF(); ///< Updates the actor's forward speed. See [here](#speed-and-acceleration) for details.
309
310 /// @brief Generates a partial transformation matrix for the actor and stores it in ::mMatrix.
311 /// @details The transformation matrix only contains the translation and the rotation on the Y axis.
312 void makeMtx();
313
314 mVec3_c getCenterPos() const; ///< Gets the actor's centered position.
315 void posMove(mVec3_c &delta); ///< Moves the actor by the given delta.
316 void posMove(); ///< Moves the actor by its @ref mSpeed "speed".
317
318 // [why is this not static?]
319 int GetProfNameActorNum(ProfileName profile); ///< Counts the instances of the given actor profile.
320
321 static void draw2DActorOnLyt1(); ///< Calls ::draw2D on every actor.
322 static void draw2DActorOnLyt2(); ///< Calls ::draw2D_lyt2 on every actor.
323
324 /**
325 * @brief Creates an actor without a parent.
326 *
327 * @details The actor is created as a child of the current scene actor, so that all actors can be
328 * deleted on a scene change, acting as a garbage collection mechanism.
329 * @param profName The actor's profile name.
330 * @param param The actor's parameters.
331 * @param position The actor's position.
332 * @param rotation The actor's rotation.
333 * @return A pointer to the instantiated actor, or @p nullptr .
334 */
335 static dBaseActor_c *construct(ProfileName profName, unsigned long param, const mVec3_c *position, const mAng3_c *rotation);
336
337 /**
338 * @brief Creates a child actor with the given parent.
339 *
340 * @param profName The actor's profile name.
341 * @param parent The actor's parent. Must not be @p nullptr .
342 * @param param The actor's parameters.
343 * @param position The actor's position.
344 * @param rotation The actor's rotation.
345 * @return A pointer to the instantiated actor, or @p nullptr .
346 */
347 static dBaseActor_c *construct(ProfileName profName, dBase_c *parent, unsigned long param, const mVec3_c *position, const mAng3_c *rotation);
348
349private:
350 /**
351 * @brief Sets temporary data to be used for the next actor's construction.
352 *
353 * @param position The actor's position.
354 * @param rotation The actor's rotation.
355 */
356 static void setTmpCtData(const mVec3_c *position, const mAng3_c *rotation);
357
358 fLiNdBa_c mLinkActor; ///< The node in ::m_actorManage.
359
360public:
361 mMtx_c mMatrix; ///< The actor's partial transformation matrix. See ::makeMtx for details.
362
363 mVec3_c mPos; ///< The actor's position.
364 mVec3_c mLastPos; ///< The actor's position in the previous frame.
365 mVec3_c mPosDelta; ///< The actor's position delta since the previous frame.
366
367 mVec3_c mCenterOffs; ///< The offset from the position to the center of the actor (defaults to 0).
368 mVec3_c mScale; ///< The actor's scale (defaults to 1).
369 mVec3_c mSpeed; ///< The actor's speed.
370 mVec3_c mSpeedMax; ///< The actor's maximum speed.
371
372 mAng3_c mAngle; ///< The actor's rotation (for 2D actors).
373 mAng3_c mAngle3D; ///< The actor's rotation (for 3D actors).
374
375 float mSpeedF; ///< The actor's horizontal speed.
376 float mMaxSpeedF; ///< The actor's maximum horizontal speed.
377 float mAccelY; ///< The actor's vertical acceleration.
378 float mMaxFallSpeed; ///< The actor's maximum fall speed.
379 float mAccelF; ///< The actor's horizontal acceleration.
380
381 u32 mActorProperties; ///< The actor's properties. See fProfile::fActorProfile_c::mActorProperties.
382 bool mVisible; ///< Whether the actor should be visible or not. Defaults to @p true .
383
384private:
385 static const mVec3_c *m_tmpCtPosP; ///< Temporary storage for the next constructed actor's position. See ::mPos.
386 static const mAng3_c *m_tmpCtAngleP; ///< Temporary storage for the next constructed actor's rotation. See ::mAngle.
387 static fLiMgBa_c m_actorManage; ///< A list of all actor bases.
388};
bool mVisible
Whether the actor should be visible or not. Defaults to true .
mAng3_c mAngle3D
The actor's rotation (for 3D actors).
void calcSpeedXY()
Updates the actor's speed (2D actors). See here for details.
int GetProfNameActorNum(ProfileName profile)
Counts the instances of the given actor profile.
mMtx_c mMatrix
The actor's partial transformation matrix. See makeMtx for details.
virtual int preDraw()
pre method for the draw operation.
mVec3_c mScale
The actor's scale (defaults to 1).
float mAccelF
The actor's horizontal acceleration.
mVec3_c mSpeed
The actor's speed.
mVec3_c mLastPos
The actor's position in the previous frame.
mVec3_c mPos
The actor's position.
virtual void draw2D_lyt2()
Alternate drawing function used to draw 3D models in front of 2D graphics (second draw pass).
mVec3_c mSpeedMax
The actor's maximum speed.
void makeMtx()
Generates a partial transformation matrix for the actor and stores it in mMatrix.
virtual void postExecute(fBase_c::MAIN_STATE_e status)
post method for the execute operation.
virtual void postDraw(fBase_c::MAIN_STATE_e status)
post method for the draw operation.
static const mVec3_c * m_tmpCtPosP
Temporary storage for the next constructed actor's position. See mPos.
virtual void finalUpdate()
Code to be executed after all actors' execute operation has run.
void calcSpeedX()
Updates the actor's X speed. See here for details.
mVec3_c mPosDelta
The actor's position delta since the previous frame.
mVec3_c mCenterOffs
The offset from the position to the center of the actor (defaults to 0).
void calcFallSpeed()
Updates the actor's falling speed. See here for details.
fLiNdBa_c mLinkActor
The node in m_actorManage.
static void setTmpCtData(const mVec3_c *position, const mAng3_c *rotation)
Sets temporary data to be used for the next actor's construction.
static dBaseActor_c * construct(ProfileName profName, unsigned long param, const mVec3_c *position, const mAng3_c *rotation)
Creates an actor without a parent.
virtual int preDelete()
pre method for the delete operation.
float mSpeedF
The actor's horizontal speed.
virtual void postDelete(fBase_c::MAIN_STATE_e status)
post method for the delete operation.
void posMove()
Moves the actor by its speed.
virtual void draw2D()
Alternate drawing function used to draw 3D models in front of 2D graphics (first draw pass).
virtual int GetActorType()
Gets the actor kind. See ACTOR_KIND_e.
float mMaxFallSpeed
The actor's maximum fall speed.
void calcSpeed()
Updates the actor's speed (3D actors). See here for details.
mVec3_c getCenterPos() const
Gets the actor's centered position.
static const mAng3_c * m_tmpCtAngleP
Temporary storage for the next constructed actor's rotation. See mAngle.
void calcSpeedF()
Updates the actor's forward speed. See here for details.
static fLiMgBa_c m_actorManage
A list of all actor bases.
mAng3_c mAngle
The actor's rotation (for 2D actors).
static void draw2DActorOnLyt2()
Calls draw2D_lyt2 on every actor.
virtual ~dBaseActor_c()
Destroys the actor.
virtual void postCreate(fBase_c::MAIN_STATE_e status)
post method for the create operation.
u32 mActorProperties
The actor's properties. See fProfile::fActorProfile_c::mActorProperties.
float mAccelY
The actor's vertical acceleration.
float mMaxSpeedF
The actor's maximum horizontal speed.
void calcSpeedY()
Updates the actor's Y speed. See here for details.
virtual int preExecute()
pre method for the execute operation.
virtual int preCreate()
pre method for the create operation.
static void draw2DActorOnLyt1()
Calls draw2D on every actor.
ACTOR_KIND_e
An identifier that represents the actor's kind.
@ ACTOR_MAP_STOP
[Unused]. The unused map stop actor (daWmStop_c).
@ ACTOR_MAP_ENEMY
A map enemy (dWmEnemy_c).
@ ACTOR_MAP_GENERIC
A generic map actor (dWmActor_c).
@ ACTOR_MAP_OBJECT
A map object (dWmObjActor_c).
@ ACTOR_MAP_DEMO
A map actor affected by cutscenes (dWmDemoActor_c).
@ ACTOR_UNK_6
[Unused]. Not used anywhere.
@ ACTOR_MAP_PLAYER
The worldmap player actor (dWmPlayer_c).
@ ACTOR_GENERIC
A generic non-map actor.
@ ACTOR_MENU_PLAYER
The menu player actor (da2DPlayer_c).
dBaseActor_c()
Constructs a new actor.
dBase_c()
Constructs a new base.
Definition d_base.cpp:12
MAIN_STATE_e
The possible operation results.
Definition f_base.hpp:137
A base list, made of fLiNdBa_c nodes.
Definition f_list_mg.hpp:13
A three-dimensional short angle vector.
Definition m_angle.hpp:60
A 3x4 matrix.
Definition m_mtx.hpp:9
A three-dimensional floating point vector.
Definition m_vec.hpp:100
u16 ProfileName
The name of a profile. Value is a fProfile::PROFILE_NAME_e.
Definition f_profile.hpp:32