Compare commits

..

3 Commits

Author SHA1 Message Date
tovjemam
05c8e66668 Make npcs not die inside when stuck but use reverse strategy again 2026-05-08 21:01:53 +02:00
tovjemam
5fa315fbcf Add vehicle rolling 2026-05-08 21:01:04 +02:00
tovjemam
db7fabe015 Add avia to vehicle list 2026-05-08 19:48:08 +02:00
5 changed files with 86 additions and 4 deletions

View File

@ -15,6 +15,7 @@ void game::NpcCharacter::VehicleChanged()
path_.clear(); path_.clear();
gas_ = false; gas_ = false;
stuck_counter_ = 0; stuck_counter_ = 0;
vehicle_state_ = NVT_NORMAL;
speed_limit_ = 0.0f; speed_limit_ = 0.0f;
if (GetVehicle() && IsDriver()) if (GetVehicle() && IsDriver())
@ -87,6 +88,22 @@ void game::NpcCharacter::VehicleThink()
if (!IsDriver() || !GetVehicle() || !roads_) if (!IsDriver() || !GetVehicle() || !roads_)
return; return;
if (vehicle_state_ == NVT_REVERSING)
{
if (reversing_frames_ > 0)
{
--reversing_frames_;
}
else
{
vehicle_state_ = NVT_NORMAL;
stuck_counter_ = 0;
vehicle_->SetInput(game::VIN_BACKWARD, false);
}
return;
}
const auto& vehicle_trans = GetVehicle()->GetRootTransform(); const auto& vehicle_trans = GetVehicle()->GetRootTransform();
const glm::vec3& pos = vehicle_trans.position; const glm::vec3& pos = vehicle_trans.position;
@ -203,8 +220,14 @@ void game::NpcCharacter::VehicleThink()
// BotThink(s); // BotThink(s);
//}); //});
GetVehicle()->SetInputs(0); // stop vehicle_->SetSteering(true, -angle); // try turn away while reversing
is_driver_ = false; // TODO: fix vehicle_->SetInputs(0); // stop
vehicle_->SetInput(game::VIN_BACKWARD, true);
vehicle_state_ = NVT_REVERSING;
reversing_frames_ = 50; // reverse for 50 frames
// GetVehicle()->SetInputs(0); // stop
// is_driver_ = false; // TODO: fix
return; return;
} }
} }

View File

@ -8,6 +8,12 @@ namespace game
class OpenWorld; class OpenWorld;
enum NpcVehicleThinkState
{
NVT_NORMAL,
NVT_REVERSING,
};
class NpcCharacter : public ControllableCharacter class NpcCharacter : public ControllableCharacter
{ {
public: public:
@ -32,11 +38,13 @@ private:
private: private:
// driver // driver
NpcVehicleThinkState vehicle_state_ = NVT_NORMAL;
const assets::MapGraph* roads_; const assets::MapGraph* roads_;
glm::vec3 seg_start_; glm::vec3 seg_start_;
std::deque<size_t> path_; std::deque<size_t> path_;
bool gas_ = false; bool gas_ = false;
size_t stuck_counter_ = 0; size_t stuck_counter_ = 0;
size_t reversing_frames_ = 0;
glm::vec3 last_pos_ = glm::vec3(0.0f); glm::vec3 last_pos_ = glm::vec3(0.0f);
float speed_limit_ = 0.0f; float speed_limit_ = 0.0f;
}; };

View File

@ -18,7 +18,7 @@ namespace game
static const char* GetRandomCarModel() static const char* GetRandomCarModel()
{ {
const char* vehicles[] = {"pickup_hd", "passat", "twingo", "polskifiat", "cow_static", "pig_static"}; const char* vehicles[] = {"pickup_hd", "passat", "twingo", "polskifiat", "cow_static", "pig_static", "avia"};
return vehicles[rand() % (sizeof(vehicles) / sizeof(vehicles[0]))]; return vehicles[rand() % (sizeof(vehicles) / sizeof(vehicles[0]))];
} }

View File

@ -272,12 +272,54 @@ void game::Vehicle::ProcessInput()
} }
} }
if (glm::abs(engineForce) > 0) if (glm::abs(engineForce) > 0)
flags_ |= VF_ACCELERATING; flags_ |= VF_ACCELERATING;
if (glm::abs(breakingForce) > 0) if (glm::abs(breakingForce) > 0)
flags_ |= VF_BREAKING; flags_ |= VF_BREAKING;
const bool can_roll = wheels_on_ground_ <= (wheels_.size() / 2);
if (can_roll)
++can_roll_frames_;
else
can_roll_frames_ = 0;
const bool roll_left = in_left || (steering_analog_ && target_steering_ < -0.1f);
const bool roll_right = in_right || (steering_analog_ && target_steering_ > 0.1f);
// check if airborne and apply roll if right/left pressed
if (can_roll_frames_ >= 50 && (roll_left || roll_right))
{
btVector3 ang_vel = physics_->GetBtBody().getAngularVelocity();
const float max_vel = 5.0f;
btTransform trans = physics_->GetBtBody().getWorldTransform();
btQuaternion quat = trans.getRotation();
glm::quat rot_quat(quat.getW(), quat.getX(), quat.getY(), quat.getZ());
glm::vec3 local_up_world = rot_quat * glm::vec3(0.0f, 0.0f, 1.0f);
float roll_factor = glm::clamp(1.0f - local_up_world.z, 0.0f, 1.0f);
glm::vec3 local_roll(0.0f, 0.5f * roll_factor, 0.0f);
glm::vec3 local_ang_vel = glm::inverse(rot_quat) * glm::vec3(ang_vel.x(), ang_vel.y(), ang_vel.z());
if (glm::abs(local_ang_vel.y) < max_vel)
{
glm::vec3 world_roll = rot_quat * local_roll;
glm::vec3 new_ang_vel = glm::vec3(ang_vel.x(), ang_vel.y(), ang_vel.z());
if (roll_left)
new_ang_vel -= world_roll;
if (roll_right)
new_ang_vel += world_roll;
ang_vel = btVector3(new_ang_vel.x, new_ang_vel.y, new_ang_vel.z);
}
physics_->GetBtBody().setAngularVelocity(ang_vel);
}
} }
void game::Vehicle::UpdateCrash() void game::Vehicle::UpdateCrash()
@ -324,12 +366,17 @@ void game::Vehicle::UpdateWheels()
{ {
auto& vehicle = physics_->GetBtVehicle(); auto& vehicle = physics_->GetBtVehicle();
wheels_on_ground_ = 0;
for (size_t i = 0; i < wheels_.size(); ++i) for (size_t i = 0; i < wheels_.size(); ++i)
{ {
auto& bt_wheel = vehicle.getWheelInfo(i); auto& bt_wheel = vehicle.getWheelInfo(i);
wheels_[i].speed = -(bt_wheel.m_rotation - wheels_[i].rotation) * 25.0f; wheels_[i].speed = -(bt_wheel.m_rotation - wheels_[i].rotation) * 25.0f;
wheels_[i].rotation = bt_wheel.m_rotation; wheels_[i].rotation = bt_wheel.m_rotation;
wheels_[i].z_offset = tuning_ctx_.wheels[i].z_offset - bt_wheel.m_raycastInfo.m_suspensionLength; wheels_[i].z_offset = tuning_ctx_.wheels[i].z_offset - bt_wheel.m_raycastInfo.m_suspensionLength;
if (bt_wheel.m_raycastInfo.m_isInContact)
++wheels_on_ground_;
} }
} }

View File

@ -131,6 +131,10 @@ private:
size_t no_crash_frames_ = 0; size_t no_crash_frames_ = 0;
std::unique_ptr<DeformGrid> deformgrid_; std::unique_ptr<DeformGrid> deformgrid_;
size_t wheels_on_ground_ = 0;
size_t can_roll_frames_ = 0;
}; };
} // namespace game } // namespace game