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"
15ObjectCarTGE::ObjectCarTGE(
const System::MapdataGeoObj ¶ms)
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 EGG::egg_delete(m_auxCollision);
105void ObjectCarTGE::init() {
106 constexpr f32 HIT_ANGLE_TRUCK = 20.0f;
107 constexpr f32 HIT_ANGLE_NORMAL = 40.0f;
110 if (m_mapObj->pathId() == -1) {
114 u16 idx = m_mapObj->setting(0);
115 m_railInterpolator->init(0.0f, idx);
117 auto *rail = RailManager::Instance()->rail(m_mapObj->pathId());
118 u16 speedSetting = rail->points()[idx].setting[1];
119 if (speedSetting == 1) {
120 m_railInterpolator->setCurrVel(m_highwayVel);
121 }
else if (speedSetting == 0) {
122 m_railInterpolator->setCurrVel(m_localVel);
125 u16 curPointSpeedSetting = m_railInterpolator->curPoint().setting[1];
126 u16 nextPointSpeedSetting = m_railInterpolator->nextPoint().setting[1];
128 if (curPointSpeedSetting == 0 && nextPointSpeedSetting == 1) {
130 }
else if (curPointSpeedSetting == 1 && nextPointSpeedSetting == 0) {
135 setPos(m_railInterpolator->curPos());
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 = EGG::egg_new<ObjectCollisionCylinder>(radius, height, collisionCenter());
181void ObjectCarTGE::calcCollisionTransform() {
182 auto *col = collision();
189 col->transform(transform(), scale(), m_scaledTangentDir);
192 SetRotTangentHorizontal(mat, transform().base(2), EGG::Vector3f::ey);
194 mat.setBase(3, transform().base(3));
195 m_auxCollision->transform(mat, 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,
209 Kart::Reaction , EGG::Vector3f &hitDepth) {
210 constexpr u32 SQUASH_INVULNERABILITY = 200;
212 if (!m_hasAuxCollision) {
213 EGG::Vector3f hitDepthNorm = hitDepth;
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) {
230 EGG::Vector3f v2 = transform().base(2);
233 EGG::Vector3f posDelta = kartObj->pos() - pos();
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;
261const EGG::Vector3f &ObjectCarTGE::collisionCenter()
const {
262 static constexpr EGG::Vector3f CENTER_TRUCK = EGG::Vector3f(0.0f, 300.0f, 0.0f);
263 static constexpr EGG::Vector3f CENTER_NORMAL = EGG::Vector3f(0.0f, 100.0f, 0.0f);
264 static constexpr EGG::Vector3f CENTER_DEFAULT = EGG::Vector3f(0.0f, 0.0f, 0.0f);
269 case CarType::Normal:
270 return CENTER_NORMAL;
272 return CENTER_DEFAULT;
276void ObjectCarTGE::enterStateStub() {}
278void ObjectCarTGE::calcStateStub() {}
285 m_currSpeed += TOLL_BOOTH_ACCEL;
292 m_railInterpolator->setCurrVel(m_currSpeed);
293 m_scaledTangentDir = m_railInterpolator->curTangentDir() * m_currSpeed;
301 m_currSpeed -= TOLL_BOOTH_ACCEL;
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 * 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 setPos(curPos - m_tangent * t * 0.5f);
334 setPos(curPos - m_tangent * t * 0.5f - EGG::Vector3f::ey * 5.0f);
337 m_up = OrthonormalBasis(m_tangent).base(1);
338 setMatrixTangentTo(m_up, m_tangent);
f32 m_localVel
Speed while off the highway.
f32 m_highwayVel
Speed while on the highway.
void calcState1()
The state when cars are speeding up.
void calcState2()
The state when cars are slowing down.
Base class that represents different "states" for an object.