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