diff --git a/code/midtown/mmai/aiGoalFollowWayPts.cpp b/code/midtown/mmai/aiGoalFollowWayPts.cpp index 55f7345a..6406ada4 100644 --- a/code/midtown/mmai/aiGoalFollowWayPts.cpp +++ b/code/midtown/mmai/aiGoalFollowWayPts.cpp @@ -25,6 +25,8 @@ define_dummy_symbol(mmai_aiGoalFollowWayPts); #include "aiData.h" #include "aiMap.h" +#include "aiPath.h" +#include "aiVehicleOpponent.h" b32 aiGoalFollowWayPts::Context() { @@ -55,3 +57,127 @@ b32 aiGoalFollowWayPts::Context() return false; } } + +i32 aiGoalFollowWayPts::GetWayPtId(i16 index) +{ + if (index < 0 || index > NumWayPts) + { + Warningf("Check Point Index: %d, is outside of the array bounds.", index); + Warningf("Requested by: Opp %d.", Vehicle->OppId); + return WayPtIds[NumWayPts]; + } + + return WayPtIds[index]; +} + +void aiGoalFollowWayPts::Update() +{ + ++UpdateCount; + + if ((Car->Sim.ICS.Constraints & (ICS_CONSTRAIN_TX | ICS_CONSTRAIN_TZ)) != 0) + { + if (Car->Sim.FrontLeft.OnGround) + { + Car->Sim.Steering = 0.0f; + Car->Sim.Brakes = 0.0f; + Car->Sim.Engine.Throttle = 1.0f; + } + + return; + } + + Stuck.Update(); + + if (Car->Sim.Stuck.State == CAR_STUCK) + { + PlanRoute(); + *BackingUp = true; + Car->Sim.ICS.LinearMomentum = {0.0f, 0.0f, 0.0f}; + Car->Sim.ICS.AngularMomentum = {0.0f, 0.0f, 0.0f}; + UpdateCount = 0; + } + else if (Stuck.State == CAR_STUCK) + { + Car->Sim.Steering = 0.5f; + Car->Sim.Brakes = 0.0f; + Car->Sim.Engine.Throttle = 1.0f; + Car->Sim.Stuck.State = CAR_NOT_STUCK; + } + else + { + i16 road_segment_id; + + if (WayPtIdx <= 1 || WayPtIdx >= NumWayPts - 1) + { + road_segment_id = -1; + } + else + { + i16 prev_wp_index = WayPtIdx - 1; + + i32 prev_wp_id = GetWayPtId(prev_wp_index); + i32 cur_wp_id = GetWayPtId(WayPtIdx); + + road_segment_id = DetRdSegBetweenInts(AIMAP.Intersection(prev_wp_id), AIMAP.Intersection(cur_wp_id))->Id; + } + + LastMapCompType = road_segment_id; + + i16 out_index = 0; + f32 dist_to_side = 1.0f; + + CurMapCompIdx = static_cast( + AIMAP.DetermineOppMapComponent(Car->Sim.ICS.Matrix, Rail, &CurMapCompType, &CurRdVertIdx, &Rail->RoadDist, + &DistToSide, &out_index, &TargetPtOffset, Car->Sim.Speed, LastMapCompType, road_segment_id)); + + PlanRoute(); + + if (Rail->NextLink) + { + Rail->NextLink->StopDestinationSources(1); + } + + if (Vehicle->IsSemi || !DetectCollision(reinterpret_cast(&dist_to_side))) + { + aiVehicleOpponent* opp = DetectOpponentCollision(); + + if (opp) + { + AvoidOpponentCollision(opp); + } + else + { + SolveTargetPoint(); + } + } + else + { + AvoidCollision(reinterpret_cast(&dist_to_side)); + } + + Vector3 target_dir = TargetPt - Car->Sim.ICS.Matrix.m3; + + f32 angle = std::atan2(target_dir ^ Car->Sim.ICS.Matrix.m0, target_dir ^ -Car->Sim.ICS.Matrix.m2); + + Steering = std::clamp(angle, -1.0f, 1.0f); + + if (Car->Model.Flags & INST_FLAG_COLLIDED_PLAYER) + { + *Car->Sim.Realism = 1.0f; + } + else + { + *Car->Sim.Realism = 0.0f; + + if (angle < 0.1f && angle > -0.1f) + { + Car->Sim.ICS.AngularMomentum *= 0.1f; + } + } + + Car->Sim.Steering = Steering; + Car->Sim.Brakes = Brakes; + Car->Sim.Engine.Throttle = Throttle; + LastMapCompType = CurMapCompType; + } +} diff --git a/code/midtown/mmai/aiGoalFollowWayPts.h b/code/midtown/mmai/aiGoalFollowWayPts.h index 4730a7a6..e3c118f6 100644 --- a/code/midtown/mmai/aiGoalFollowWayPts.h +++ b/code/midtown/mmai/aiGoalFollowWayPts.h @@ -96,7 +96,7 @@ class aiGoalFollowWayPts final : public aiGoal ARTS_IMPORT void Reset() override; // ?Update@aiGoalFollowWayPts@@UAEXXZ - ARTS_IMPORT void Update() override; + ARTS_EXPORT void Update() override; // ?DeclareFields@aiGoalFollowWayPts@@SAXXZ ARTS_IMPORT static void DeclareFields(); @@ -106,7 +106,7 @@ class aiGoalFollowWayPts final : public aiGoal ARTS_IMPORT void AddToBlockedRange(f32 arg1, f32 arg2, f32 arg3); // ?AvoidCollision@aiGoalFollowWayPts@@AAEXH@Z - ARTS_IMPORT void AvoidCollision(i32 arg1); + ARTS_IMPORT void AvoidCollision(i32 dist_to_side); // ?AvoidOpponentCollision@aiGoalFollowWayPts@@AAEXPAVaiVehicleOpponent@@@Z ARTS_IMPORT void AvoidOpponentCollision(aiVehicleOpponent* arg1); @@ -135,6 +135,9 @@ class aiGoalFollowWayPts final : public aiGoal // ?SolveTargetPoint@aiGoalFollowWayPts@@AAEXXZ ARTS_IMPORT void SolveTargetPoint(); + i32 GetWayPtId(i16 index); + +public: aiVehicleOpponent* Vehicle; aiRailSet* Rail; mmCar* Car; diff --git a/code/midtown/mmai/aiStuck.h b/code/midtown/mmai/aiStuck.h index 957865c4..1c80fe2d 100644 --- a/code/midtown/mmai/aiStuck.h +++ b/code/midtown/mmai/aiStuck.h @@ -35,6 +35,7 @@ */ #include "arts7/node.h" +#include "vector7/vector3.h" class mmCarSim; @@ -69,7 +70,18 @@ class aiStuck final : public asNode // ?Update@aiStuck@@UAEXXZ ARTS_IMPORT void Update() override; - u8 gap20[0x38]; + i32 State; + i32 Impacted; + i32 field_28; + Vector3 field_2C; + i32 TimeThresh; + i32 PosThresh; + i32 MoveThresh; + i32 PosThreshSqr; + i32 MoveThreshSqr; + i32 RotAmount; + i32* ICS; + mmCarSim* CarSim; }; check_size(aiStuck, 0x58); diff --git a/code/midtown/mmai/aiVehicle.h b/code/midtown/mmai/aiVehicle.h index 1b67e2fa..e7cf111e 100644 --- a/code/midtown/mmai/aiVehicle.h +++ b/code/midtown/mmai/aiVehicle.h @@ -29,6 +29,8 @@ 0x61BC40 | const aiVehicle::`vftable' | ??_7aiVehicle@@6B@ */ +#include "data7/list.h" + class aiVehicle { public: @@ -51,7 +53,9 @@ class aiVehicle // ?Init@aiVehicle@@QAEXH@Z ARTS_IMPORT void Init(i32 arg1); - u8 gap4[0x10]; + List Goals; + i16 OppId; + i16 UpdateGroup; }; check_size(aiVehicle, 0x14); diff --git a/code/midtown/mmcar/stuck.h b/code/midtown/mmcar/stuck.h index bf01d2f4..96bb361c 100644 --- a/code/midtown/mmcar/stuck.h +++ b/code/midtown/mmcar/stuck.h @@ -41,6 +41,10 @@ class mmCarSim; class asInertialCS; +#define CAR_NOT_STUCK 0 +#define CAR_MAYBE_STUCK 1 +#define CAR_STUCK 2 + class mmStuck final : public asNode { public: diff --git a/code/midtown/mmcity/inst.h b/code/midtown/mmcity/inst.h index 54b0ad89..8eefcd4b 100644 --- a/code/midtown/mmcity/inst.h +++ b/code/midtown/mmcity/inst.h @@ -354,7 +354,7 @@ class mmInstance : public Base #define INST_FLAG_TERRAIN 0x800 #define INST_FLAG_1000 0x1000 // mmBangerInstance::Draw - Increment lod #define INST_FLAG_2000 0x2000 // Important shadows -#define INST_FLAG_4000 0x4000 // Collided with Player? +#define INST_FLAG_COLLIDED_PLAYER 0x4000 // INST_FLAG_* u16 Flags {INST_FLAG_ACTIVE};