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