A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectDossun.cc
1#include "ObjectDossun.hh"
2
3#include "game/field/CollisionDirector.hh"
4#include "game/field/ObjectDirector.hh"
5
6#include "game/kart/KartObject.hh"
7
8namespace Kinoko::Field {
9
11ObjectDossun::ObjectDossun(const System::MapdataGeoObj &params)
12 : ObjectCollidable(params), m_touchingGround(false) {}
13
15ObjectDossun::~ObjectDossun() = default;
16
18void ObjectDossun::init() {
19 constexpr f32 BEFORE_FALL_VEL = 30.0f;
20
21 m_anmState = AnmState::Still;
22
23 initState();
24
25 if (m_railInterpolator) {
26 m_railInterpolator->init(0.0f, 0);
27 }
28
29 m_initialPosY = pos().y;
30 m_vel = 0.0f;
31
32 for (u32 i = 0; i < BEFORE_FALL_DURATION; ++i) {
33 setPos(EGG::Vector3f(pos().x, BEFORE_FALL_VEL + pos().y, pos().z));
34 }
35
36 bool hasCol = false;
37 auto *colDir = CollisionDirector::Instance();
38 CollisionInfo info;
39 u32 frameCount = 0;
40
41 do {
42 ++frameCount;
43 m_vel -= STOMP_ACCEL;
44 setPos(EGG::Vector3f(pos().x, m_vel + pos().y, pos().z));
45
46 info.reset();
47 EGG::Vector3f colPos = pos() + STOMP_POS_OFFSET;
48
49 hasCol = colDir->checkSphereFull(STOMP_RADIUS, colPos, EGG::Vector3f::inf, KCL_TYPE_FLOOR,
50 &info, nullptr, 0);
51 } while (!hasCol);
52
53 addPos(info.tangentOff);
54 m_vel = 0.0f;
55
56 f32 fallDuration = frameCount;
57
58 frameCount = 0;
59 f32 riseDuration;
60
61 while (true) {
62 f32 posY = RISING_VEL + pos().y;
63 ++frameCount;
64
65 if (posY >= m_initialPosY) {
66 setPos(EGG::Vector3f(pos().x, m_initialPosY, pos().z));
67 riseDuration = frameCount;
68 break;
69 } else {
70 setPos(EGG::Vector3f(pos().x, posY, pos().z));
71 }
72 }
73
74 m_fullDuration = fallDuration + GROUND_DURATION + riseDuration + BEFORE_FALL_DURATION;
75 m_touchingGround = false;
76}
77
79void ObjectDossun::calcCollisionTransform() {
80 constexpr f32 HEIGHT = 400.0f;
81
82 if (!m_collision) {
83 return;
84 }
85
86 calcTransform();
87
88 EGG::Matrix34f mat = transform();
89 mat[1, 3] += HEIGHT * scale().x;
90
91 collision()->transform(mat, scale());
92}
93
95Kart::Reaction ObjectDossun::onCollision(Kart::KartObject *kartObj, Kart::Reaction reactionOnKart,
96 Kart::Reaction /*reactionOnObj*/, EGG::Vector3f & /*hitDepth*/) {
97 constexpr f32 SQUISH_DISTANCE = 375.0f;
98
99 EGG::Vector3f xzDist = kartObj->pos() - pos();
100 xzDist.y = 0.0f;
101
102 if (xzDist.length() < SQUISH_DISTANCE * scale().x &&
103 (m_anmState == AnmState::Falling || m_touchingGround)) {
104 const auto &hitTable = ObjectDirector::Instance()->hitTableKart();
105 return hitTable.reaction(hitTable.slot(ObjectId::DossuncSoko));
106 }
107
108 return reactionOnKart;
109}
110
112void ObjectDossun::initState() {
113 m_stillTimer = static_cast<u32>(m_mapObj->setting(2));
114 if (m_stillTimer == 0) {
115 m_stillTimer = static_cast<u32>(m_mapObj->setting(3));
116 }
117
118 m_groundedTimer = 0;
119 m_beforeFallTimer = 0;
120 m_shakePhase = 0;
121}
122
124void ObjectDossun::calcStomp() {
125 switch (m_anmState) {
126 case AnmState::BeforeFall:
127 calcBeforeFall();
128 break;
129 case AnmState::Falling:
130 calcFalling();
131 break;
132 case AnmState::Grounded:
133 calcGrounded();
134 break;
135 case AnmState::Rising:
136 calcRising();
137 break;
138 default:
139 break;
140 }
141
142 if (m_cycleTimer-- == 0) {
143 startStill();
144 }
145}
146
148void ObjectDossun::calcBeforeFall() {
149 constexpr f32 BEFORE_FALL_VEL = 50.0f;
150
151 setPos(EGG::Vector3f(pos().x, BEFORE_FALL_VEL + pos().y, pos().z));
152
153 if (--m_beforeFallTimer == 0) {
154 m_anmState = AnmState::Falling;
155 }
156}
157
159void ObjectDossun::checkFloorCollision() {
160 CollisionInfo info;
161 EGG::Vector3f colPos = pos() + STOMP_POS_OFFSET;
162
163 if (!CollisionDirector::Instance()->checkSphereFull(STOMP_RADIUS, colPos, EGG::Vector3f::inf,
164 KCL_TYPE_FLOOR, &info, nullptr, 0)) {
165 return;
166 }
167
168 m_vel = 0.0f;
169 addPos(info.tangentOff);
170
171 startGrounded();
172 m_touchingGround = true;
173}
174
175} // namespace Kinoko::Field
#define KCL_TYPE_FLOOR
0x20E80FFF - Any KCL that the player or items can drive/land on.
Pertains to collision.