1#include <game/bases/d_cc.hpp>
2#include <game/bases/d_s_stage.hpp>
3#include <game/bases/d_bg.hpp>
41 for (
unsigned int i = 0; i < ARRAY_SIZE(
mCollOffsetX); i++) {
103 const static hitCheck checks[3] = {
108 _hitCheck[0][0] = checks[dScStage_c::m_loopType];
144 float _unused = (1.0f / 256.f);
200 if ((catInteract1 & catMask2) && (catInteract2 & catMask1)) {
211 && (attCatMask2 & attInteract1) == 0
216 && (attCatMask1 & attInteract2) == 0
230 if (attInteract1 & attCatMask2) {
233 if (attCatMask1 & attInteract2) {
234 c1->
mAttSent |= attInteract2 & attCatMask1;
239 if (attInteract1 & attCatMask2) {
240 c2->
mAttSent |= attInteract1 & attCatMask2;
242 if (attCatMask1 & attInteract2) {
260 for (
dCc_c *c1 =
mEntryN; c1 !=
nullptr; c1 = c1->mpNext) {
261 for (
dCc_c *c2 = c1->mpNext; c2 !=
nullptr; c2 = c2->mpNext) {
272 float xDist = pos1.x - pos2.x;
274 float yDist = pos1.y - pos2.y;
277 if (std::fabs(xDist) < collSizeX && std::fabs(yDist) < collSizeY) {
290 float offsetX = (collSizeX - std::fabs(xDist)) / 2;
295 float offsetY = (collSizeY - std::fabs(yDist)) / 2;
330 p1.
incX(dBg_c::m_bg_p->mLoopOffset);
332 p2.
incX(dBg_c::m_bg_p->mLoopOffset);
349 float collSizeRadius = (collSizeX + collSizeY) / 2;
352 if (distVec.
length() <= collSizeRadius) {
354 float dist = collSizeRadius - distVec.
length();
355 s16 ang =
cM::atan2s(distVec.y, std::fabs(distVec.x));
358 float offsetX = dist * nw4r::math::CosIdx(ang);
359 float offsetY = -dist * nw4r::math::SinIdx(ang);
384#define DIR2SCALE(dir) (1.0f - dir * 2.0f)
387 dCc_c *boxCc, *circleCc;
404 float closerEdgeX[] = {
408 float closerEdgeY[] = {
413 if (closerEdgeY[ABOVE] < circlePos.y && circlePos.y < closerEdgeY[BELOW]) {
415 float colliderXDist = DIR2SCALE(boxSideX) * (circlePos.x - closerEdgeX[boxSideX]);
416 if (colliderXDist < circleRadius) {
419 float circleOffsetX = DIR2SCALE(boxSideX) * (circleRadius - colliderXDist) / 2;
432 if (closerEdgeX[RIGHT] < circlePos.x && circlePos.x < closerEdgeX[LEFT]) {
434 float smthA = DIR2SCALE(boxSideY) * (circlePos.y - closerEdgeY[boxSideY]);
435 if (smthA < circleRadius) {
439 float circleOffsetY = DIR2SCALE(boxSideY) * (circleRadius - smthA) / 2;
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;
474enum LINE_CHECK_RESULT_e {
482inline float ratioX(
mVec2_c diff,
float v) {
483 return v * diff.y / diff.x;
486inline float ratioY(
mVec2_c diff,
float v) {
487 return v * diff.x / diff.y;
490int dCc_c::_lineCheckUD(
mVec2_c p1,
mVec2_c p2,
float x,
float y) {
491 if (p1.x > x || p2.x < x) {
495 float scaled = ratioX(p2 - p1, x - p1.x);
496 if (scaled + p1.y < y) {
516 if (std::fabs(trpCenter.x - boxCenter.x) >= collSizeX) {
530 if (trpCorner1.y < boxBottom && trpCorner3.y < boxBottom) {
533 if (trpCorner2.y > boxTop && trpCorner4.y > boxTop) {
537 if (!(boxLeft <= trpCorner1.x) || !(trpCorner3.x <= boxRight)) {
538 if (_lineCheckUD(trpCorner1, trpCorner3, boxLeft, boxBottom) != THREE
539 && _lineCheckUD(trpCorner1, trpCorner3, boxRight, boxBottom) != THREE) {
543 if (_lineCheckUD(trpCorner2, trpCorner4, boxLeft, boxTop) != TWO
544 && _lineCheckUD(trpCorner2, trpCorner4, boxRight, boxTop) != TWO) {
562int dCc_c::_lineCheckLR(
mVec2_c p1,
mVec2_c p2,
float x,
float y) {
563 if (p1.y < y || p2.y > y) {
567 float scaled = ratioY(p1 - p2, y - p2.y);
568 if (scaled + p2.x < x) {
588 if (std::fabs(p1.y - p2.y) >= heightSum) {
602 if (trpCorner1.x > boxRight && trpCorner3.x > boxRight) {
605 if (trpCorner2.x < boxLeft && trpCorner4.x < boxLeft) {
609 if (!(boxBottom <= trpCorner3.y) || !(trpCorner1.y <= boxTop)) {
610 if (_lineCheckLR(trpCorner1, trpCorner3, boxRight, boxTop) != ZERO
611 && _lineCheckLR(trpCorner1, trpCorner3, boxRight, boxBottom) != ZERO) {
615 if (_lineCheckLR(trpCorner2, trpCorner4, boxLeft, boxTop) != ONE
616 && _lineCheckLR(trpCorner2, trpCorner4, boxLeft, boxBottom) != ONE) {
float length() const
Gets the length of the vector.
The minimum required implementation for an actor base.
Collider ("Collision Check") class - handles collisions between actors.
mVec2_c getCenterVec()
Gets the center of the collider as a vector.
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.
dBaseActor_c * mFriendActor
A second actor that this collider will not collide with.
bool mIsLinked
Whether this collider has been placed in the collider list.
u8 mFlag
Flags for this collider. See CC_FLAG_e .
static bool checkCollision(dCc_c *c1, dCc_c *c2, int active)
Checks for collisions between two colliders.
u8 mNonCollideMask
The non-collide mask for this collider.
static bool _hitCheckDaikeiUD_R(dCc_c *ccBox, dCc_c *ccTrp)
Check a rectangular collider against a trapezoid-shaped collider for collisions.
void registerCc(dBaseActor_c *actor, CcData_s *collInfo)
Registers an owner actor to this collider and sets the collider data.
float getUnderPos()
Gets the Y position of the bottom of the collider.
static bool _hitCheckLoop(dCc_c *c1, dCc_c *c2)
Check two rectangular colliders against each other for collisions with stage looping.
float getTopPos()
Gets the Y position of the top of the collider.
static dCc_c * mEntryN
The first collider in the list.
u16 isHitAtDmg(u16 mask) const
Gets the result of an attack hit check.
dCc_c * mpPrev
The previous collider in the list.
void clear()
Clear the data related to previous collisions.
float getCenterPosY()
Gets the Y position of the center of the collider.
float mCollOffsetY[8]
The Y offset for a collision.
void entry()
Places this collider in the collider list.
u16 mCollidedWith
The categories of the previously collided with colliders.
u8 mShape
The shape of the collider. See CC_SHAPE_e .
u16 mAttSent
The attack types sent by this collider in the previous collisions.
u16 isHit(u16 mask) const
Gets the result of a hit check.
static hitCheck _hitCheck[4][4]
The hit check function for each combination of collider shapes.
static InitializedUnkClass msInitializedUnkClass
u16 mAttReceived
The attack types received by this collider in the previous collisions.
u8 mLayer
The layer this collider is on.
@ CC_SHAPE_BOX
Rectangular collider.
@ CC_SHAPE_CIRCLE
Circular / elliptical collider.
CcData_s mCcData
The collision data of this collider.
float getCenterPosX()
Gets the X position of the center of the collider.
static bool _hitCheckCircle(dCc_c *c1, dCc_c *c2)
Check two circle colliders against each other for collisions.
float getLeftPos()
Gets the X position of the left side of the collider.
@ CC_DATA_NO_OFFSET
Don't set the collision offset if a collision occurs.
mVec2_c mCollPos
The position where the last collision occurred.
float getRightPos()
Gets the X position of the right side of the collider.
static bool _hitCheckDaikeiLR_R(dCc_c *ccBox, dCc_c *ccTrp)
Check a rectangular collider against a trapezoid-shaped collider for collisions.
virtual ~dCc_c()
Destroys the collider.
static void execute()
Check all colliders against each other for collisions.
static char msIsInitialized
void release()
Removes this collider from the collider list.
dBaseActor_c * mpOwner
The actor this collider belongs to.
float mCollOffsetX[8]
The X offset for a collision.
static bool _hitCheckDaikeiLR(dCc_c *ccTrp, dCc_c *ccBox)
Check a trapezoid-shaped collider against a rectangular collider for collisions.
@ CC_DISABLE
Disables all collisions with this collider.
static bool _hitCheckBoxCircle(dCc_c *c1, dCc_c *c2)
Check a rectangular and a circle collider against each other for collisions.
static void reset()
Clears the collider list.
dCc_c * mpNext
The next collider in the list.
dCc_c()
Constructs a new collider.
static dCc_c * mEntryB
The last collider in the list.
static bool _hitCheckNormal(dCc_c *c1, dCc_c *c2)
Check two rectangular colliders against each other for collisions without stage looping.
static bool _hitCheckDaikeiUD(dCc_c *ccTrp, dCc_c *ccBox)
Check a trapezoid-shaped collider against a rectangular collider for collisions.
bool isInside(dCc_c *other)
Checks if this collider is inside another collider.
A two-dimensional floating point vector.
void incX(float x)
Increments the X coordinate.
s16 atan2s(float sin, float cos)
Converts a sine and a cosine to an angle in units.
A structure that contains information about a collider.
void(* mCallback)(dCc_c *, dCc_c *)
The callback to execute when a collision occurs.
float mHeight
The height of the collider.
u32 mAttackCategoryInteract
Which attack categories this collider should be able to receive.
u8 mAttackCategory
The attack category of this collider. See CC_ATTACK_e .
u32 mCategoryInteract
Which categories this collider should be able to collide with.
float mWidth
The width of the collider.
u16 mFlag
Flags for this collider. See CC_DATA_FLAG_e .
u8 mCategory
The category of this collider. See CC_CATEGORY_e .