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