NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
d_cc.cpp
1#include <game/bases/d_cc.hpp>
2#include <game/bases/d_actor.hpp>
3#include <game/bases/d_s_stage.hpp>
4#include <game/bases/d_bg.hpp>
5#include <game/sLib/s_GlobalData.hpp>
6#include <nw4r/math.h>
8
11
12template <>
14 0,
15 0xa000a0, 0xa00000a0,
16 true, true
17};
18
19// Note that for trapezoid checking, the second collider is always treated as a rectangular collider.
20dCc_c::hitCheck dCc_c::_hitCheck[4][4] = {
25};
26
28 mpNext = nullptr;
29 mpPrev = nullptr;
30 mIsLinked = false;
31 mpFriendActor = nullptr;
32 mAmiLine = true;
33 mLayer = LAYER_1;
34 clear();
35}
36
38 release();
39}
40
42 mCollidedWith = 0;
43 mAttSent = 0;
44 mAttReceived = 0;
45 mInfo &= ~CC_NO_HIT; // Enable the collider
46 for (unsigned int i = 0; i < ARRAY_SIZE(mCollOffsetX); i++) {
47 mCollOffsetX[i] = 0.0f;
48 mCollOffsetY[i] = 0.0f;
49 }
50}
51
53 if (mIsLinked) {
54 return;
55 }
56
58 mEntryN = this;
59 if (mpNext == nullptr) {
61 mEntryB = this;
62 } else {
63 mpPrev = mpNext->mpPrev;
64 mpNext->mpPrev = this;
65 }
66
67 mIsLinked = true;
68}
69
71 if (!mIsLinked) {
72 return;
73 }
74
75 if (mpNext != nullptr) {
76 mpNext->mpPrev = mpPrev;
77 } else {
79 }
80 if (mpPrev != nullptr) {
81 mpPrev->mpNext = mpNext;
82 } else {
84 }
85
86 mpNext = nullptr;
87 mpPrev = nullptr;
88 mIsLinked = false;
89}
90
91void dCc_c::set(dActor_c *actor, sCcDatNewF *collInfo) {
92 mpOwner = actor;
93 mCcData.set(*collInfo);
94 mInfo = 0;
95}
96
97void dCc_c::set(dActor_c *actor, sCcDatNewF *collInfo, u8 amiLine) {
98 set(actor, collInfo);
99 mAmiLine = amiLine;
100}
101
103 // Clear collision checker list
104 mEntryN = nullptr;
105 mEntryB = nullptr;
106
107 // Set the default hit check to the correct type
108 const static hitCheck hitCheckFuncTbl[3] = {
112 };
113 _hitCheck[0][0] = hitCheckFuncTbl[dScStage_c::m_loopType];
114}
115
116u16 dCc_c::isHit(u16 mask) const {
117 return mCollidedWith & mask;
118}
119
120u16 dCc_c::isHitAtDmg(u16 mask) const {
121 return mAttReceived & mask;
122}
123
125 return mCcData.mBase.mOffset.y + mpOwner->mPos.y + mCcData.mBase.mSize.y;
126}
127
129 return mCcData.mBase.mOffset.y + mpOwner->mPos.y - mCcData.mBase.mSize.y;
130}
131
133 return mCcData.mBase.mOffset.y + mpOwner->mPos.y;
134}
135
137 return mCcData.mBase.mOffset.x + mpOwner->mPos.x + mCcData.mBase.mSize.x;
138}
139
141 return mCcData.mBase.mOffset.x + mpOwner->mPos.x - mCcData.mBase.mSize.x;
142}
143
145 return mCcData.mBase.mOffset.x + mpOwner->mPos.x;
146}
147
148bool dCc_c::isInside(dCc_c *other) {
149 float _unused = (1.0f / 256.f); // [Needed to match order in .sdata2]
150 if (mShape == CC_SHAPE_CIRCLE) {
151 float dist = (getCenterVec() - other->getCenterVec()).length();
152 // [Seems like someone just gave up on writing this part.
153 // Every circle is always inside any other collider]
154 return true;
155 }
156 float xDist = getCenterPosX() - other->getCenterPosX();
157 if (std::fabs(xDist) > std::fabs(mCcData.mBase.mSize.x - other->mCcData.mBase.mSize.x)) {
158 return false;
159 }
160
161 float yDist = getCenterPosY() - other->getCenterPosY();
162 if (std::fabs(yDist) > std::fabs(mCcData.mBase.mSize.y - other->mCcData.mBase.mSize.y)) {
163 return false;
164 }
165 return true;
166}
167
168bool dCc_c::checkCollision(dCc_c *c1, dCc_c *c2, int active) {
169 if (c2 == c1) {
170 // No self-collisions
171 return false;
172 }
173 if (c2->mpOwner == c1->mpOwner) {
174 // No collisions between two colliders that belong to the same actor
175 return false;
176 }
177 if (c2->mpOwner == c1->mpFriendActor || c1->mpOwner == c2->mpFriendActor) {
178 // No collisions between friend actors
179 return false;
180 }
181 if ((c1->mInfo & CC_NO_HIT) || (c2->mInfo & CC_NO_HIT)) {
182 // Disabled colliders don't collide
183 return false;
184 }
185 if ((c1->mAmiLine & c2->mAmiLine) == 0) {
186 // If any bit is set in both non-collide masks, the colliders don't collide
187 return false;
188 }
189 if (c1->mLayer != c2->mLayer) {
190 // Colliders only collide if they are on the same layer
191 return false;
192 }
193
194 sCcDatNewF collInfo1 = c1->mCcData;
195 u32 catInteract1 = collInfo1.mVsKind;
196 u32 catMask1 = 1 << collInfo1.mKind;
197
198 sCcDatNewF collInfo2 = c2->mCcData;
199 u32 catInteract2 = collInfo2.mVsKind;
200 u32 catMask2 = 1 << collInfo2.mKind;
201
202 // First, check the category interaction.
203 // A collision only occurs if the two colliders' categories
204 // are set in the other's category interact masks.
205 if ((catInteract1 & catMask2) && (catInteract2 & catMask1)) {
206
207 u32 attInteract1 = collInfo1.mVsDamage;
208 u32 attCatMask1 = 1 << collInfo1.mAttack;
209 u32 attInteract2 = collInfo2.mVsDamage;
210 u32 attCatMask2 = 1 << collInfo2.mAttack;
211
212 if ((
213 // Collider 1 can collide with an attacker and collider 2 is of type attacker,
214 (catInteract1 & catMask2 & BIT_FLAG(CC_KIND_PLAYER_ATTACK))
215 // but the attack masks don't match
216 && (attCatMask2 & attInteract1) == 0
217 ) || ( // or
218 // Collider 2 can collide with an attacker and collider 1 is of type attacker,
219 (catInteract2 & catMask1 & BIT_FLAG(CC_KIND_PLAYER_ATTACK))
220 // but the attack masks don't match
221 && (attCatMask1 & attInteract2) == 0
222 )) {
223 return false;
224 }
225
226 // Check for collision
227 if (_hitCheck[c2->mShape][c1->mShape](c1, c2)) {
228 if (!active) {
229 return true;
230 }
231
232 // Set result flags
233 if (!(collInfo2.mStatus & CC_STATUS_NO_PASS_INFO)) {
234 c1->mCollidedWith |= catMask2;
235 if (attInteract1 & attCatMask2) {
236 c1->mAttReceived |= attInteract1 & attCatMask2;
237 }
238 if (attCatMask1 & attInteract2) {
239 c1->mAttSent |= attInteract2 & attCatMask1;
240 }
241 }
242 if (!(collInfo1.mStatus & CC_STATUS_NO_PASS_INFO)) {
243 c2->mCollidedWith |= catMask1;
244 if (attInteract1 & attCatMask2) {
245 c2->mAttSent |= attInteract1 & attCatMask2;
246 }
247 if (attCatMask1 & attInteract2) {
248 c2->mAttReceived |= attInteract2 & attCatMask1;
249 }
250 }
251
252 // Execute callback if needed
253 if (!(collInfo2.mStatus & CC_STATUS_NO_PASS_INFO) && collInfo1.mCallback != nullptr) {
254 collInfo1.mCallback(c1, c2);
255 }
256 if (!(collInfo1.mStatus & CC_STATUS_NO_PASS_INFO) && collInfo2.mCallback != nullptr) {
257 collInfo2.mCallback(c2, c1);
258 }
259 }
260 }
261 return c1->mCollidedWith != 0;
262}
263
265 for (dCc_c *c1 = mEntryN; c1 != nullptr; c1 = c1->mpNext) {
266 for (dCc_c *c2 = c1->mpNext; c2 != nullptr; c2 = c2->mpNext) {
267 checkCollision(c1, c2, 1);
268 }
269 }
270}
271
273 sCcDatNewF &ci1 = c1->mCcData;
274 sCcDatNewF &ci2 = c2->mCcData;
275
276 // Compute the distance between the two colliders and the maximum distances for a collision
277 float xDist = pos1.x - pos2.x;
278 float collSizeX = ci1.mBase.mSize.x + ci2.mBase.mSize.x;
279 float yDist = pos1.y - pos2.y;
280 float collSizeY = ci1.mBase.mSize.y + ci2.mBase.mSize.y;
281
282 if (std::fabs(xDist) < collSizeX && std::fabs(yDist) < collSizeY) {
283 c1->mCollPos = pos1;
284 c2->mCollPos = pos2;
285
286 // [Need to research what this check is for]
287 if ((ci1.mStatus & CC_STATUS_NO_REVISION || ci2.mStatus & CC_STATUS_NO_REVISION)
288 && ci1.mKind != CC_KIND_GOAL_POLE && ci2.mKind != CC_KIND_GOAL_POLE) {
289 return true;
290 }
291
292 // The offset is half the amount of overlap since we distribute the
293 // shifting between the two colliders
294
295 float offsetX = (collSizeX - std::fabs(xDist)) / 2;
296 if (xDist < 0.0f) {
297 offsetX = -offsetX;
298 }
299
300 float offsetY = (collSizeY - std::fabs(yDist)) / 2;
301 if (yDist < 0.0f) {
302 offsetY = -offsetY;
303 }
304
305 c1->mCollOffsetX[ci2.mKind] = offsetX;
306 c1->mCollOffsetY[ci2.mKind] = offsetY;
307
308 c2->mCollOffsetX[ci1.mKind] = -offsetX;
309 c2->mCollOffsetY[ci1.mKind] = -offsetY;
310 return true;
311 }
312 return false;
313}
314
316 mVec2_c v1 = c1->getCenterVec();
317 mVec2_c v2 = c2->getCenterVec();
318 return _hitCheckSquare(c1, c2, v1, v2);
319}
320
322 // For a looping stage, we check for overlap twice:
323 // - Once with the original positions (after accounting for the loop offset) and
324 // - Once with one of the colliders shifted by the loop offset.
325 // This second check is done for the case where
326 // the colliders are on opposite sides of the loop.
327
328 mVec2_c p1(dScStage_c::getLoopPosX(c1->getCenterPosX()), c1->getCenterPosY());
329 mVec2_c p2(dScStage_c::getLoopPosX(c2->getCenterPosX()), c2->getCenterPosY());
330 if (_hitCheckSquare(c1, c2, p1, p2)) {
331 return true;
332 }
333
334 if (p1.x < p2.x) {
335 p1.incX(dBg_c::m_bg_p->mLoopOffset);
336 } else {
337 p2.incX(dBg_c::m_bg_p->mLoopOffset);
338 }
339 if (_hitCheckSquare(c1, c2, p1, p2)) {
340 return true;
341 }
342 return false;
343}
344
346 mVec2_c p1 = c1->getCenterVec();
347 mVec2_c p2 = c2->getCenterVec();
348
349 // [Not sure why we are looking at the height here...
350 // It seems they maybe wanted the circles to also support ellipses?
351 // Either way, the collision calculations treat it as a circle.]
352 float collSizeX = c1->mCcData.mBase.mSize.x + c2->mCcData.mBase.mSize.x;
353 float collSizeY = c1->mCcData.mBase.mSize.y + c2->mCcData.mBase.mSize.y;
354 float collSizeRadius = (collSizeX + collSizeY) / 2;
355
356 mVec2_c distVec = p2 - p1;
357 if (distVec.length() <= collSizeRadius) {
358 // Push the circles apart in the direction of the collision
359 float dist = collSizeRadius - distVec.length();
360 mAng ang = cM::atan2s(distVec.y, std::fabs(distVec.x));
361 // [This calculation is incorrect. It should be dist / 2 * ...
362 // so that the shifting is distributed between the two colliders]
363 float offsetX = dist * ang.cos();
364 float offsetY = -dist * ang.sin();
365
366 c1->mCollOffsetX[c2->mCcData.mKind] = offsetX;
367 c1->mCollOffsetY[c2->mCcData.mKind] = offsetY;
368 c1->mCollPos.x = p1.x;
369 c1->mCollPos.y = p1.y;
370
371 c2->mCollOffsetX[c1->mCcData.mKind] = -offsetX;
372 c2->mCollOffsetY[c1->mCcData.mKind] = -offsetY;
373 c2->mCollPos.x = p2.x;
374 c2->mCollPos.y = p2.y;
375
376 return true;
377 }
378
379 return false;
380}
381
382enum dir_e {
383 LEFT = 0,
384 BELOW = 0,
385 RIGHT = 1,
386 ABOVE = 1,
387};
388
389#define DIR2SCALE(dir) (1.0f - dir * 2.0f)
390
392 dCc_c *boxCc, *circleCc;
393
394 if (c1->mShape == CC_SHAPE_BOX) {
395 boxCc = c1;
396 circleCc = c2;
397 } else {
398 boxCc = c2;
399 circleCc = c1;
400 }
401
402 mVec2_c circlePos = circleCc->getCenterVec();
403 mVec2_c boxPos = boxCc->getCenterVec();
404
405 float circleRadius = circleCc->mCcData.mBase.mSize.x;
406 dir_e boxSideX = (boxCc->getCenterPosX() < circleCc->getCenterPosX()) ? LEFT : RIGHT;
407 dir_e boxSideY = (boxCc->getCenterPosY() < circleCc->getCenterPosY()) ? BELOW : ABOVE;
408
409 float closerEdgeX[] = {
410 boxCc->getCenterPosX() + boxCc->mCcData.mBase.mSize.x, // Left edge, if box is on the left
411 boxCc->getCenterPosX() - boxCc->mCcData.mBase.mSize.x // Right edge, if box is on the right
412 };
413 float closerEdgeY[] = {
414 boxCc->getCenterPosY() + boxCc->mCcData.mBase.mSize.y, // Top edge, if box is below
415 boxCc->getCenterPosY() - boxCc->mCcData.mBase.mSize.y // Bottom edge, if box is above
416 };
417
418 if (closerEdgeY[ABOVE] < circlePos.y && circlePos.y < closerEdgeY[BELOW]) {
419 // The circle midpoint is fully within the Y bounds of the box
420 float colliderXDist = DIR2SCALE(boxSideX) * (circlePos.x - closerEdgeX[boxSideX]);
421 if (colliderXDist < circleRadius) {
422 // Move the circle and box apart just in the X direction
423
424 float circleOffsetX = DIR2SCALE(boxSideX) * (circleRadius - colliderXDist) / 2;
425 circleCc->mCollOffsetX[circleCc->mCcData.mKind] = circleOffsetX;
426 circleCc->mCollOffsetY[circleCc->mCcData.mKind] = 0.0f;
427 circleCc->mCollPos = circlePos;
428
429 float boxOffsetX = -circleCc->mCollOffsetX[circleCc->mCcData.mKind];
430 boxCc->mCollOffsetX[circleCc->mCcData.mKind] = boxOffsetX;
431 boxCc->mCollOffsetY[circleCc->mCcData.mKind] = 0.0f;
432 boxCc->mCollPos = boxPos;
433
434 return true;
435 }
436 }
437 if (closerEdgeX[RIGHT] < circlePos.x && circlePos.x < closerEdgeX[LEFT]) {
438 // The circle midpoint is fully within the X bounds of the box
439 float smthA = DIR2SCALE(boxSideY) * (circlePos.y - closerEdgeY[boxSideY]);
440 if (smthA < circleRadius) {
441 // Move the circle and box apart just in the Y direction
442
443 circleCc->mCollOffsetX[circleCc->mCcData.mKind] = 0.0f;
444 float circleOffsetY = DIR2SCALE(boxSideY) * (circleRadius - smthA) / 2;
445 circleCc->mCollOffsetY[circleCc->mCcData.mKind] = circleOffsetY;
446 circleCc->mCollPos = circlePos;
447
448 boxCc->mCollOffsetX[circleCc->mCcData.mKind] = 0.0f;
449 float boxOffsetY = -circleCc->mCollOffsetY[circleCc->mCcData.mKind];
450 boxCc->mCollOffsetY[circleCc->mCcData.mKind] = boxOffsetY;
451 boxCc->mCollPos = boxPos;
452
453 return true;
454 }
455 }
456
457 // The circle is overlapping with just a corner of the box
458 // Calculate the distance between the center of the circle and the closest corner
459 mVec2_c closerCorner(closerEdgeX[boxSideX], closerEdgeY[boxSideY]);
460 mVec2_c distVec = circlePos - closerCorner;
461 float distance = distVec.normalise();
462 if (distance < circleRadius) {
463 float offsetBy = (circleRadius - distance) / 2;
464 // [This should have been done the same way as in _hitCheckCircle - this way, we shift by too much.]
465 circleCc->mCollOffsetX[circleCc->mCcData.mKind] = distVec.x * offsetBy;
466 circleCc->mCollOffsetY[circleCc->mCcData.mKind] = distVec.y * offsetBy;
467 circleCc->mCollPos = circlePos;
468
469 boxCc->mCollOffsetX[boxCc->mCcData.mKind] = -circleCc->mCollOffsetX[circleCc->mCcData.mKind];
470 boxCc->mCollOffsetY[boxCc->mCcData.mKind] = -circleCc->mCollOffsetY[circleCc->mCcData.mKind];
471 boxCc->mCollPos = boxPos;
472
473 return true;
474 }
475
476 return false;
477}
478
479enum LINE_CHECK_RESULT_e {
480 INV = -1,
481 ZERO = 0,
482 ONE = 1,
483 TWO = 2,
484 THREE = 3
485};
486
487inline float ratioX(mVec2_c diff, float v) {
488 return v * diff.y / diff.x;
489}
490
491inline float ratioY(mVec2_c diff, float v) {
492 return v * diff.x / diff.y;
493}
494
495int dCc_c::_lineCheckUD(mVec2_c p1, mVec2_c p2, float x, float y) {
496 if (p1.x > x || p2.x < x) {
497 return INV;
498 }
499
500 float scaled = ratioX(p2 - p1, x - p1.x);
501 if (scaled + p1.y < y) {
502 return TWO;
503 }
504
505 return THREE;
506}
507
509 return _hitCheckDaikeiUD(ccTrp, ccBox);
510}
511
512bool dCc_c::_hitCheckDaikeiUD(dCc_c *ccTrp, dCc_c * ccBox) {
513 mVec2_c trpCenter = ccTrp->getCenterVec();
514 mVec2_c boxCenter = ccBox->getCenterVec();
515
516 // The left and right sides of the trapezoid are parallel,
517 // so the width of this shape is the same everywhere.
518
519 float collSizeX = ccTrp->mCcData.mBase.mSize.x + ccBox->mCcData.mBase.mSize.x;
520
521 if (std::fabs(trpCenter.x - boxCenter.x) >= collSizeX) {
522 return false;
523 }
524
525 float boxLeft = ccBox->getLeftPos();
526 float boxRight = ccBox->getRightPos();
527 float boxTop = ccBox->getTopPos();
528 float boxBottom = ccBox->getUnderPos();
529
530 mVec2_c trpCorner1(ccTrp->getLeftPos(), ccTrp->getTrpOffset(0) + trpCenter.y);
531 mVec2_c trpCorner2(ccTrp->getLeftPos(), ccTrp->getTrpOffset(1) + trpCenter.y);
532 mVec2_c trpCorner3(ccTrp->getRightPos(), ccTrp->getTrpOffset(2) + trpCenter.y);
533 mVec2_c trpCorner4(ccTrp->getRightPos(), ccTrp->getTrpOffset(3) + trpCenter.y);
534
535 if (trpCorner1.y < boxBottom && trpCorner3.y < boxBottom) {
536 return false;
537 }
538 if (trpCorner2.y > boxTop && trpCorner4.y > boxTop) {
539 return false;
540 }
541
542 if (!(boxLeft <= trpCorner1.x) || !(trpCorner3.x <= boxRight)) {
543 if (_lineCheckUD(trpCorner1, trpCorner3, boxLeft, boxBottom) != THREE
544 && _lineCheckUD(trpCorner1, trpCorner3, boxRight, boxBottom) != THREE) {
545 return false;
546 }
547
548 if (_lineCheckUD(trpCorner2, trpCorner4, boxLeft, boxTop) != TWO
549 && _lineCheckUD(trpCorner2, trpCorner4, boxRight, boxTop) != TWO) {
550 return false;
551 }
552 }
553
554 // No shifting of the colliders is done here.
555
556 ccTrp->mCollOffsetX[ccBox->mCcData.mKind] = 0;
557 ccTrp->mCollOffsetY[ccBox->mCcData.mKind] = 0;
558 ccTrp->mCollPos.set(ccTrp->getCenterPosX(), ccTrp->getCenterPosY());
559
560 ccBox->mCollOffsetX[ccTrp->mCcData.mKind] = 0;
561 ccBox->mCollOffsetY[ccTrp->mCcData.mKind] = 0;
562 ccBox->mCollPos.set(ccBox->getCenterPosX(), ccBox->getCenterPosY());
563
564 return true;
565}
566
567int dCc_c::_lineCheckLR(mVec2_c p1, mVec2_c p2, float x, float y) {
568 if (p1.y < y || p2.y > y) {
569 return INV;
570 }
571
572 float scaled = ratioY(p1 - p2, y - p2.y);
573 if (scaled + p2.x < x) {
574 return ZERO;
575 }
576
577 return ONE;
578}
579
581 return _hitCheckDaikeiLR(ccTrp, ccBox);
582}
583
585 mVec2_c p1 = mVec2_c(ccTrp->getCenterPosX(), ccTrp->getCenterPosY());
586 mVec2_c p2 = mVec2_c(ccBox->getCenterPosX(), ccBox->getCenterPosY());
587
588 // The top and bottom sides of the trapezoid are parallel,
589 // so the height of this shape is the same everywhere.
590
591 float heightSum = ccTrp->mCcData.mBase.mSize.y + ccBox->mCcData.mBase.mSize.y;
592
593 if (std::fabs(p1.y - p2.y) >= heightSum) {
594 return false;
595 }
596
597 float boxLeft = ccBox->getLeftPos();
598 float boxRight = ccBox->getRightPos();
599 float boxTop = ccBox->getTopPos();
600 float boxBottom = ccBox->getUnderPos();
601
602 mVec2_c trpCorner1(ccTrp->getTrpOffset(0) + p1.x, ccTrp->getTopPos());
603 mVec2_c trpCorner2(ccTrp->getTrpOffset(1) + p1.x, ccTrp->getTopPos());
604 mVec2_c trpCorner3(ccTrp->getTrpOffset(2) + p1.x, ccTrp->getUnderPos());
605 mVec2_c trpCorner4(ccTrp->getTrpOffset(3) + p1.x, ccTrp->getUnderPos());
606
607 if (trpCorner1.x > boxRight && trpCorner3.x > boxRight) {
608 return false;
609 }
610 if (trpCorner2.x < boxLeft && trpCorner4.x < boxLeft) {
611 return false;
612 }
613
614 if (!(boxBottom <= trpCorner3.y) || !(trpCorner1.y <= boxTop)) {
615 if (_lineCheckLR(trpCorner1, trpCorner3, boxRight, boxTop) != ZERO
616 && _lineCheckLR(trpCorner1, trpCorner3, boxRight, boxBottom) != ZERO) {
617 return false;
618 }
619
620 if (_lineCheckLR(trpCorner2, trpCorner4, boxLeft, boxTop) != ONE
621 && _lineCheckLR(trpCorner2, trpCorner4, boxLeft, boxBottom) != ONE) {
622 return false;
623 }
624 }
625
626 // No shifting of the colliders is done here.
627
628 ccTrp->mCollOffsetX[ccBox->mCcData.mKind] = 0;
629 ccTrp->mCollOffsetY[ccBox->mCcData.mKind] = 0;
630 ccTrp->mCollPos.set(ccTrp->getCenterPosX(), ccTrp->getCenterPosY());
631
632 ccBox->mCollOffsetX[ccTrp->mCcData.mKind] = 0;
633 ccBox->mCollOffsetY[ccTrp->mCcData.mKind] = 0;
634 ccBox->mCollPos.set(ccBox->getCenterPosX(), ccBox->getCenterPosY());
635
636 return true;
637}
The minimum required implementation for a stage actor.
Definition d_actor.hpp:15
Collider ("Collision Check") class - handles collisions between actors.
Definition d_cc.hpp:133
void set(dActor_c *actor, sCcDatNewF *collInfo)
Registers an owner actor to this collider and sets the collider data.
Definition d_cc.cpp:91
mVec2_c getCenterVec()
Gets the center of the collider as a vector.
Definition d_cc.hpp:203
static bool _hitCheckSquare(dCc_c *c1, dCc_c *c2, mVec2_c pos1, mVec2_c pos2)
A hit check function for rectangular colliders. Used in _hitCheckNormal and _hitCheckLoop.
Definition d_cc.cpp:272
bool mIsLinked
Whether this collider has been placed in the collider list.
Definition d_cc.hpp:340
static bool checkCollision(dCc_c *c1, dCc_c *c2, int active)
Checks for collisions between two colliders.
Definition d_cc.cpp:168
static bool _hitCheckDaikeiUD_R(dCc_c *ccBox, dCc_c *ccTrp)
Check a rectangular collider against a trapezoid-shaped collider for collisions.
Definition d_cc.cpp:508
dActor_c * mpOwner
The actor this collider belongs to.
Definition d_cc.hpp:278
float getUnderPos()
Gets the Y position of the bottom of the collider.
Definition d_cc.cpp:128
static bool _hitCheckLoop(dCc_c *c1, dCc_c *c2)
Check two rectangular colliders against each other for collisions with stage looping.
Definition d_cc.cpp:321
float getTopPos()
Gets the Y position of the top of the collider.
Definition d_cc.cpp:124
static dCc_c * mEntryN
The first collider in the list.
Definition d_cc.hpp:353
u16 isHitAtDmg(u16 mask) const
Gets the result of an attack hit check.
Definition d_cc.cpp:120
u8 mInfo
Info flags for this collider. See CC_INFO_e.
Definition d_cc.hpp:337
dCc_c * mpPrev
The previous collider in the list.
Definition d_cc.hpp:284
void clear()
Clear the data related to previous collisions.
Definition d_cc.cpp:41
float getCenterPosY()
Gets the Y position of the center of the collider.
Definition d_cc.cpp:132
void entry()
Places this collider in the collider list.
Definition d_cc.cpp:52
u16 mCollidedWith
The categories of the previously collided with colliders.
Definition d_cc.hpp:316
float mCollOffsetY[CC_KIND_COUNT]
The Y offset for a collision.
Definition d_cc.hpp:312
u8 mShape
The shape of the collider. See CC_SHAPE_e .
Definition d_cc.hpp:320
u16 mAttSent
The attack types sent by this collider in the previous collisions.
Definition d_cc.hpp:317
u16 isHit(u16 mask) const
Gets the result of a hit check.
Definition d_cc.cpp:116
static hitCheck _hitCheck[4][4]
The hit check function for each combination of collider shapes.
Definition d_cc.hpp:20
u16 mAttReceived
The attack types received by this collider in the previous collisions.
Definition d_cc.hpp:318
u8 mLayer
The layer this collider is on.
Definition d_cc.hpp:335
float getCenterPosX()
Gets the X position of the center of the collider.
Definition d_cc.cpp:144
static bool _hitCheckCircle(dCc_c *c1, dCc_c *c2)
Check two circle colliders against each other for collisions.
Definition d_cc.cpp:345
float getLeftPos()
Gets the X position of the left side of the collider.
Definition d_cc.cpp:140
mVec2_c mCollPos
The position where the last collision occurred.
Definition d_cc.hpp:314
float mCollOffsetX[CC_KIND_COUNT]
The X offset for a collision.
Definition d_cc.hpp:305
float getRightPos()
Gets the X position of the right side of the collider.
Definition d_cc.cpp:136
static bool _hitCheckDaikeiLR_R(dCc_c *ccBox, dCc_c *ccTrp)
Check a rectangular collider against a trapezoid-shaped collider for collisions.
Definition d_cc.cpp:580
virtual ~dCc_c()
Destroys the collider.
Definition d_cc.cpp:37
static void execute()
Check all colliders against each other for collisions.
Definition d_cc.cpp:264
void release()
Removes this collider from the collider list.
Definition d_cc.cpp:70
sCcDatNewF mCcData
The collision data of this collider.
Definition d_cc.hpp:288
static bool _hitCheckDaikeiLR(dCc_c *ccTrp, dCc_c *ccBox)
Check a trapezoid-shaped collider against a rectangular collider for collisions.
Definition d_cc.cpp:584
u8 mAmiLine
The non-collide mask for this collider.
Definition d_cc.hpp:328
static bool _hitCheckBoxCircle(dCc_c *c1, dCc_c *c2)
Check a rectangular and a circle collider against each other for collisions.
Definition d_cc.cpp:391
static void reset()
Clears the collider list.
Definition d_cc.cpp:102
dCc_c * mpNext
The next collider in the list.
Definition d_cc.hpp:283
dCc_c()
Constructs a new collider.
Definition d_cc.cpp:27
static dCc_c * mEntryB
The last collider in the list.
Definition d_cc.hpp:354
static bool _hitCheckNormal(dCc_c *c1, dCc_c *c2)
Check two rectangular colliders against each other for collisions without stage looping.
Definition d_cc.cpp:315
static bool _hitCheckDaikeiUD(dCc_c *ccTrp, dCc_c *ccBox)
Check a trapezoid-shaped collider against a rectangular collider for collisions.
Definition d_cc.cpp:512
dActor_c * mpFriendActor
A second actor that this collider will not collide with.
Definition d_cc.hpp:279
bool isInside(dCc_c *other)
Checks if this collider is inside another collider.
Definition d_cc.cpp:148
A two-dimensional floating point vector.
Definition m_vec.hpp:26
void incX(float x)
Increments the X coordinate.
Definition m_vec.hpp:51
static const T::GlobalData_t mData
s16 atan2s(float sin, float cos)
Converts a sine and a cosine to an angle in units.
Definition c_math.cpp:167
A one-dimensional short angle vector.
Definition m_angle.hpp:12
float cos() const
Computes the cosine of the angle.
Definition m_angle.hpp:58
float sin() const
Computes the sine of the angle.
Definition m_angle.hpp:55
A structure that contains information about a collider.
Definition d_cc.hpp:98
void(* mCallback)(dCc_c *self, dCc_c *target)
The callback to execute when a collision occurs.
Definition d_cc.hpp:114
u8 mKind
The type of this collider. See CC_KIND_e.
Definition d_cc.hpp:101
u8 mAttack
The attack type of this collider. See CC_ATTACK_e.
Definition d_cc.hpp:102
sCcDatNew mBase
Base collider data.
Definition d_cc.hpp:99
u16 mStatus
Status flags for this collider. See CC_STATUS_FLAG_e.
Definition d_cc.hpp:112
u32 mVsKind
Which attack types this collider should be able to receive. This is a bitfield with the bits enumerat...
Definition d_cc.hpp:106