Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
ChompChainSupport.inc.c
Go to the documentation of this file.
1#include "common.h"
2
3// ----------------------------------------------------------------
4// Requirements
5
6// actor part of the first link in the chain
7#ifndef CHOMP_CHAIN_FIRST_PART_IDX
8 #error CHOMP_CHAIN_FIRST_PART_IDX is not defined!
9#endif
10
11// actor part of the last link in the chain
12#ifndef CHOMP_CHAIN_LAST_PART_IDX
13 #error CHOMP_CHAIN_LAST_PART_IDX is not defined!
14#endif
15
16// actor var index which determines if chain sounds can play
17#ifndef CHOMP_CHAIN_AVAR_SOUNDS
18 #error CHOMP_CHAIN_AVAR_SOUNDS is not defined!
19#endif
20
21// ----------------------------------------------------------------
22// Options
23
24// define this TRUE to enable updating the z-pos of the chain
25// CHOMP_CHAIN_UPDATE_Z
26
27// ----------------------------------------------------------------
28
29#define NUM_CHAIN_LINKS (1 + CHOMP_CHAIN_LAST_PART_IDX - CHOMP_CHAIN_FIRST_PART_IDX)
30
31API_CALLABLE(N(ChompChainInit)) {
32 Actor* actor = get_actor(script->owner1.actorID);
33 ActorPart* actorPart;
34 ChompChain* chainParts;
35 s32 baseChainPart = CHOMP_CHAIN_FIRST_PART_IDX;
36 f32 x, y, z;
37 s32 i;
38
39 chainParts = heap_malloc(NUM_CHAIN_LINKS * sizeof(*chainParts));
40 actor->state.functionTempPtr[0] = chainParts;
41
42 x = actor->curPos.x + 12.0;
43 y = actor->curPos.y + 5.0;
44 z = actor->curPos.z;
45
46 for (i = 0; i < NUM_CHAIN_LINKS; i++, chainParts++) {
47 chainParts->outerLinkLen = 7.0f;
48 chainParts->linkLengthZ = 7.0f;
49 chainParts->innerLinkLen = 7.0f;
50 chainParts->curPos.x = x;
51 chainParts->curPos.y = y;
52 chainParts->curPos.z = z;
53 chainParts->settleAmt = 0;
54 chainParts->settleRate = 0.6f;
55 chainParts->gravAccel = 3.0f;
56 chainParts->velY = 0;
57 actorPart = get_actor_part(actor, baseChainPart + i);
58 actorPart->absolutePos.x = chainParts->curPos.x;
59 actorPart->absolutePos.y = chainParts->curPos.y;
60 actorPart->absolutePos.z = chainParts->curPos.z;
61 }
62 return ApiStatus_DONE2;
63}
64
65void N(ChompChainAddPolarPos)(ChompChain* script, f32 magnitude, f32 angleDeg) {
66 f32 angle = DEG_TO_RAD(angleDeg);
67 f32 dirX = sin_rad(angle);
68 f32 dirY = cos_rad(angle);
69
70 script->curPos.x += -magnitude * dirX;
71 script->curPos.y += magnitude * dirY;
72}
73
74void N(ChompChainGetPolarX)(f32* x, f32 magnitude, f32 angleDeg) {
75 f32 angle = DEG_TO_RAD(angleDeg);
76 f32 dirX = sin_rad(angle);
77 f32 dirY = cos_rad(angle);
78
79 *x = magnitude * dirY;
80}
81
82API_CALLABLE(N(ChompChainUpdate)) {
83 Bytecode* args = script->ptrReadPos;
84 f32 sp18;
85 Actor* actor;
86 ActorPart* part;
87 ChompChain* chain;
88 f32 dist;
89 f32 angle;
90 f32 prevX, prevY;
91 s32 baseChainPart;
92 s32 posZ;
93 s32 i;
94
95 actor = get_actor(script->owner1.actorID);
96 if (actor == NULL) {
97 return ApiStatus_BLOCK;
98 }
99
100 #if CHOMP_CHAIN_UPDATE_Z == TRUE
101 posZ = evt_get_variable(script, *args++);
102 #endif
103
104 baseChainPart = CHOMP_CHAIN_FIRST_PART_IDX;
105
106 // initialize prev positions to the rear of the actor's body
107 chain = actor->state.functionTempPtr[0];
108 if (actor->debuff == STATUS_KEY_SHRINK) {
109 prevX = actor->curPos.x + 6.0;
110 prevY = actor->curPos.y + 2.5;
111 } else {
112 prevX = actor->curPos.x + 12.0;
113 prevY = actor->curPos.y + 5.0;
114 }
115
116 // update each link in the chain
117 for (i = 0; i < NUM_CHAIN_LINKS; i++, chain++) {
118 if (actor->debuff == STATUS_KEY_SHRINK) {
119 chain->outerLinkLen = 3.5f;
120 chain->linkLengthZ = 3.5f;
121 chain->innerLinkLen = 3.5f;
122 } else {
123 chain->outerLinkLen = 7.0f;
124 chain->linkLengthZ = 7.0f;
125 chain->innerLinkLen = 7.0f;
126 }
127
128 // add gravity and clamp velocity at -2G
129 chain->velY -= chain->gravAccel;
130 if (chain->velY < 2.0f * -chain->gravAccel) {
131 chain->velY = 2.0f * -chain->gravAccel;
132 if (actor->state.varTable[CHOMP_CHAIN_AVAR_SOUNDS] && i == 0) {
134 }
135 }
136
137 // add velocity and clamp position to roughly the radius of the chain (assuming ground at y = 0)
138 chain->curPos.y += chain->velY;
139 if (actor->debuff == STATUS_KEY_SHRINK) {
140 if (chain->curPos.y < 2.5) {
141 chain->curPos.y = 2.5f;
142 chain->velY = 0.0f;
143 }
144 } else {
145 if (chain->curPos.y < 5.0) {
146 chain->curPos.y = 5.0f;
147 chain->velY = 0.0f;
148 }
149 }
150
151 // get distance from previous part of the chain
152 dist = dist2D(prevX, prevY, chain->curPos.x, chain->curPos.y);
153 angle = atan2(prevX, prevY, chain->curPos.x, chain->curPos.y);
154
155 if (dist >= chain->linkLengthZ) {
156 N(ChompChainGetPolarX)(&sp18, dist - chain->linkLengthZ, angle);
157 chain->velY += sp18 * 0.5;
158 }
159
160 if (dist >= chain->innerLinkLen) {
161 f32 moveLen;
162
163 if (dist >= chain->outerLinkLen) {
164 // clamp position to be outerLinkLen away from previous part
165 moveLen = dist;
166 moveLen = dist - chain->outerLinkLen;
167 } else {
168 chain->settleAmt += chain->settleRate;
169 moveLen = chain->settleAmt;
170 }
171 N(ChompChainAddPolarPos)(chain, moveLen, angle);
172 } else {
173 chain->settleAmt -= chain->settleRate * 0.2;
174 if (chain->settleAmt < 0.0) {
175 chain->settleAmt = 0.0f;
176 }
177 N(ChompChainAddPolarPos)(chain, chain->settleAmt, angle);
178 }
179 if (chain->settleAmt > 4.0) {
180 chain->settleAmt = 4.0f;
181 }
182
183 #if CHOMP_CHAIN_UPDATE_Z == TRUE
184 chain->curPos.z = posZ;
185 #endif
186
187 part = get_actor_part(actor, baseChainPart + i);
188 part->absolutePos.x = chain->curPos.x;
189 part->absolutePos.y = chain->curPos.y;
190 part->absolutePos.z = chain->curPos.z;
191
192 if (actor->debuff == STATUS_KEY_SHRINK) {
193 part->scale.x = 0.5f;
194 part->scale.y = 0.5f;
195 part->scale.z = 1.0f;
196 } else {
197 part->scale.x = 1.0f;
198 part->scale.y = 1.0f;
199 part->scale.z = 1.0f;
200 }
201 prevX = chain->curPos.x;
202 prevY = chain->curPos.y;
203 }
204
205 return ApiStatus_DONE2;
206}
void N ChompChainGetPolarX(f32 *x, f32 magnitude, f32 angleDeg)
void N ChompChainAddPolarPos(ChompChain *script, f32 magnitude, f32 angleDeg)
#define NUM_CHAIN_LINKS
ActorState state
Vec3f curPos
#define sfx_play_sound_at_position
#define atan2
@ STATUS_KEY_SHRINK
Definition enums.h:2206
@ SOUND_CHAIN_RATTLE
Definition enums.h:1397
@ SOUND_SPACE_DEFAULT
Definition enums.h:1737
#define ApiStatus_DONE2
Definition evt.h:118
s32 Bytecode
Definition evt.h:7
#define ApiStatus_BLOCK
Definition evt.h:116
s32 evt_get_variable(Evt *script, Bytecode var)
Definition evt.c:1690
f32 cos_rad(f32 x)
Definition 43F0.c:717
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:670
ActorPart * get_actor_part(Actor *actor, s32 partID)
Definition 190B20.c:1191
Actor * get_actor(s32 actorID)
Definition actor_api.c:155
f32 sin_rad(f32 x)
Definition 43F0.c:713
void * heap_malloc(s32 size)
Definition heap.c:34
#define DEG_TO_RAD(deg)
Definition macros.h:134
#define CHOMP_CHAIN_AVAR_SOUNDS
#define CHOMP_CHAIN_FIRST_PART_IDX