1#include "ObjectCarTGE.hh"
3#include "game/field/ObjectCollisionCylinder.hh"
4#include "game/field/ObjectDirector.hh"
5#include "game/field/RailManager.hh"
6#include "game/field/obj/ObjectHighwayManager.hh"
8#include "game/kart/KartObject.hh"
10#include "game/system/RaceConfig.hh"
16 : ObjectCollidable(params), StateManager(this, STATE_ENTRIES), m_auxCollision(nullptr),
17 m_carName{}, m_mdlName{}, m_carType(CarType::Normal), m_dummyId(ObjectId::None),
18 m_scaledTangentDir(
EGG::Vector3f::zero), m_currSpeed(0.0f), m_up(
EGG::Vector3f::zero),
19 m_tangent(
EGG::Vector3f::zero) {
20 u32 carVariant =
static_cast<u32
>(params.setting(3));
21 m_highwayVel =
static_cast<f32
>(params.setting(2));
22 m_localVel =
static_cast<f32
>(params.setting(1));
24 s16 pathId = params.pathId();
38 RailManager::Instance()->rail(pathId)->checkSphereFull();
40 const auto *name = getName();
42 if (strcmp(name,
"car_body") == 0) {
43 snprintf(m_carName,
sizeof(m_carName),
"%s",
"K_car_body");
44 m_carType = CarType::Normal;
45 }
else if (strcmp(name,
"kart_truck") == 0) {
46 snprintf(m_carName,
sizeof(m_carName),
"%s",
"K_truck");
47 m_carType = CarType::Truck;
48 }
else if (strcmp(name,
"K_bomb_car") == 0) {
49 PANIC(
"Bomb cars are not implemented!");
52 const auto *resourceName = getResources();
56 if (strcmp(resourceName,
"K_truck") == 0) {
57 snprintf(m_mdlName,
sizeof(m_mdlName),
"%s_b",
"K_truck");
58 }
else if (strcmp(resourceName,
"K_car_body") == 0) {
59 snprintf(m_mdlName,
sizeof(m_mdlName),
"%s_b",
"K_car");
63 if (strcmp(resourceName,
"K_truck") == 0) {
64 snprintf(m_mdlName,
sizeof(m_mdlName),
"%s_o",
"K_truck");
65 }
else if (strcmp(resourceName,
"K_car_body") == 0) {
66 snprintf(m_mdlName,
sizeof(m_mdlName),
"%s_r",
"K_car");
70 if (strcmp(resourceName,
"K_truck") == 0) {
71 snprintf(m_mdlName,
sizeof(m_mdlName),
"%s_g",
"K_truck");
72 }
else if (strcmp(resourceName,
"K_car_body") == 0) {
73 snprintf(m_mdlName,
sizeof(m_mdlName),
"%s_y",
"K_car");
77 PANIC(
"Bomb cars are not implemented!");
84 m_dummyId = ObjectDirector::Instance()->flowTable().getIdFromName(
"car_body_dummy");
87 m_dummyId = ObjectDirector::Instance()->flowTable().getIdFromName(
"kart_truck_dummy");
90 PANIC(
"Bomb cars are not implemented!");
94 if (System::RaceConfig::Instance()->raceScenario().course == Course::Moonview_Highway) {
95 registerManagedObject();
100ObjectCarTGE::~ObjectCarTGE() {
101 delete m_auxCollision;
105void ObjectCarTGE::init() {
106 constexpr f32 HIT_ANGLE_TRUCK = 20.0f;
107 constexpr f32 HIT_ANGLE_NORMAL = 40.0f;
109 if (m_mapObj->pathId() == -1) {
113 u16 idx = m_mapObj->setting(0);
114 m_railInterpolator->init(0.0f, idx);
116 auto *rail = RailManager::Instance()->rail(m_mapObj->pathId());
117 u16 speedSetting = rail->points()[idx].setting[1];
118 if (speedSetting == 1) {
119 m_railInterpolator->setCurrVel(m_highwayVel);
120 }
else if (speedSetting == 0) {
121 m_railInterpolator->setCurrVel(m_localVel);
124 u16 curPointSpeedSetting = m_railInterpolator->curPoint().setting[1];
125 u16 nextPointSpeedSetting = m_railInterpolator->nextPoint().setting[1];
127 if (curPointSpeedSetting == 0 && nextPointSpeedSetting == 1) {
129 }
else if (curPointSpeedSetting == 1 && nextPointSpeedSetting == 0) {
134 m_pos = m_railInterpolator->curPos();
135 m_flags.setBit(eFlags::Position);
136 m_currSpeed = m_railInterpolator->speed();
137 m_scaledTangentDir = m_railInterpolator->curTangentDir() * m_currSpeed;
138 m_hitAngle = (m_carType == CarType::Truck) ? HIT_ANGLE_TRUCK : HIT_ANGLE_NORMAL;
142void ObjectCarTGE::calc() {
143 StateManager::calc();
145 if (m_railInterpolator->calc() == RailInterpolator::Status::SegmentEnd) {
146 u16 curPointSpeedSetting = m_railInterpolator->curPoint().setting[1];
147 u16 nextPointSpeedSetting = m_railInterpolator->nextPoint().setting[1];
149 if (curPointSpeedSetting == 0 && nextPointSpeedSetting == 1) {
151 }
else if (curPointSpeedSetting == 1 && nextPointSpeedSetting == 0) {
158 m_hasAuxCollision =
false;
162void ObjectCarTGE::createCollision() {
163 constexpr f32 TRUCK_RADIUS = 190.0f;
164 constexpr f32 TRUCK_HEIGHT = 500.0f;
165 constexpr f32 NORMAL_RADIUS = 150.0f;
166 constexpr f32 NORMAL_HEIGHT = 200.0f;
168 ASSERT(m_carType == CarType::Truck || m_carType == CarType::Normal);
170 bool isTruck = (m_carType == CarType::Truck);
172 ObjectCollidable::createCollision();
174 f32 radius = isTruck ? TRUCK_RADIUS : NORMAL_RADIUS;
175 f32 height = isTruck ? TRUCK_HEIGHT : NORMAL_HEIGHT;
177 m_auxCollision =
new ObjectCollisionCylinder(radius, height, collisionCenter());
181void ObjectCarTGE::calcCollisionTransform() {
182 auto *col = collision();
189 col->transform(m_transform, m_scale, m_scaledTangentDir);
192 SetRotTangentHorizontal(mat, m_transform.base(2), EGG::Vector3f::ey);
194 mat.
setBase(3, m_transform.base(3));
195 m_auxCollision->transform(mat, m_scale, m_scaledTangentDir);
199f32 ObjectCarTGE::getCollisionRadius()
const {
200 constexpr f32 NORMAL_RADIUS = 600.0f;
201 constexpr f32 TRUCK_RADIUS = 1100.0f;
203 ASSERT(m_carType == CarType::Truck || m_carType == CarType::Normal);
204 return (m_carType == CarType::Truck) ? TRUCK_RADIUS : NORMAL_RADIUS;
208Kart::Reaction ObjectCarTGE::onCollision(
Kart::KartObject *kartObj, Kart::Reaction reactionOnKart,
210 constexpr u32 SQUASH_INVULNERABILITY = 200;
212 if (!m_hasAuxCollision) {
214 hitDepthNorm.normalise2();
216 if (hitDepthNorm.y > 0.9f) {
217 return Kart::Reaction::UntrickableJumpPad;
221 if (m_highwayMgr && m_highwayMgr->squashTimer() < SQUASH_INVULNERABILITY) {
222 const auto &hitTable = ObjectDirector::Instance()->hitTableKart();
223 reactionOnKart = hitTable.reaction(hitTable.slot(
static_cast<ObjectId
>(m_dummyId)));
227 if (reactionOnKart != Kart::Reaction::None && reactionOnKart != Kart::Reaction::WallAllSpeed) {
235 posDelta.normalise2();
237 if (v2.
dot(posDelta) < EGG::Mathf::CosFIdx(0.7111111f * m_hitAngle) && !m_hasAuxCollision) {
238 reactionOnKart = Kart::Reaction::LaunchSpin;
244 return reactionOnKart;
248bool ObjectCarTGE::checkCollision(ObjectCollisionBase *lhs,
EGG::Vector3f &dist) {
249 dist = EGG::Vector3f::zero;
250 bool hasCol = lhs->check(*m_collision, dist);
253 hasCol = lhs->check(*m_auxCollision, dist);
254 m_hasAuxCollision = hasCol;
269 case CarType::Normal:
270 return CENTER_NORMAL;
272 return CENTER_DEFAULT;
276void ObjectCarTGE::enterStateStub() {}
278void ObjectCarTGE::calcStateStub() {}
284void ObjectCarTGE::calcState1() {
285 m_currSpeed += TOLL_BOOTH_ACCEL;
287 if (m_currSpeed > m_highwayVel) {
288 m_currSpeed = m_highwayVel;
292 m_railInterpolator->setCurrVel(m_currSpeed);
293 m_scaledTangentDir = m_railInterpolator->curTangentDir() * m_currSpeed;
300void ObjectCarTGE::calcState2() {
301 m_currSpeed -= TOLL_BOOTH_ACCEL;
303 if (m_currSpeed < m_localVel) {
304 m_currSpeed = m_localVel;
308 m_railInterpolator->setCurrVel(m_currSpeed);
309 m_scaledTangentDir = m_railInterpolator->curTangentDir() * m_currSpeed;
313void ObjectCarTGE::calcPos() {
314 constexpr f32 NORMAL_SPEED = 1500.0f;
315 constexpr f32 TRUCK_SPEED = 1600.0f;
317 f32 speed = (m_carType == CarType::Truck) ? TRUCK_SPEED : NORMAL_SPEED;
318 f32 t = speed * m_scale.z * 0.5f;
322 m_railInterpolator->evalCubicBezierOnPath(t, curDir, curTangentDir);
326 posDelta.normalise2();
327 m_tangent += 0.1f * (posDelta - m_tangent);
328 m_tangent.y = posDelta.y;
329 m_tangent.normalise2();
331 if (m_tangent.y > -0.05f) {
332 m_pos = curPos - m_tangent * t * 0.5f;
334 m_pos = (curPos - m_tangent * t * 0.5f) - EGG::Vector3f::ey * 5.0f;
337 m_flags.setBit(eFlags::Position);
338 m_up = OrthonormalBasis(m_tangent).base(1);
339 setMatrixTangentTo(m_up, m_tangent);
void setBase(size_t col, const Vector3f &base)
Sets one column of a matrix.
The highest level abstraction for a kart.
f32 dot(const Vector3f &rhs) const
The dot product between two vectors.