diff --git a/rwengine/include/ai/CharacterController.hpp b/rwengine/include/ai/CharacterController.hpp index 99713b4b..e900c7dd 100644 --- a/rwengine/include/ai/CharacterController.hpp +++ b/rwengine/include/ai/CharacterController.hpp @@ -60,6 +60,8 @@ protected: bool running; + float vehicleIdle; + // Goal related variables Goal currentGoal; CharacterObject* leader; diff --git a/rwengine/include/objects/CharacterObject.hpp b/rwengine/include/objects/CharacterObject.hpp index 448d22b6..5c7d3bbd 100644 --- a/rwengine/include/objects/CharacterObject.hpp +++ b/rwengine/include/objects/CharacterObject.hpp @@ -37,11 +37,16 @@ struct AnimationGroup Animation* car_getin_lhs; Animation* car_getout_lhs; + Animation* car_open_rhs; + Animation* car_getin_rhs; + Animation* car_getout_rhs; + AnimationGroup() : idle(nullptr), walk(nullptr), walk_start(nullptr), run(nullptr), jump_start(nullptr), jump_glide(nullptr), jump_land(nullptr), car_sit(nullptr), car_sit_low(nullptr), car_open_lhs(nullptr), - car_getin_lhs(nullptr), car_getout_lhs(nullptr) + car_getin_lhs(nullptr), car_getout_lhs(nullptr), car_open_rhs(nullptr), + car_getin_rhs(nullptr), car_getout_rhs(nullptr) {} }; diff --git a/rwengine/include/objects/VehicleObject.hpp b/rwengine/include/objects/VehicleObject.hpp index 8dbc296a..d30558c1 100644 --- a/rwengine/include/objects/VehicleObject.hpp +++ b/rwengine/include/objects/VehicleObject.hpp @@ -38,7 +38,7 @@ public: ModelFrame* damaged; btRigidBody* body; btHingeConstraint* constraint; - bool holdAngle; + bool moveToAngle; float targetAngle; float openAngle; float closedAngle; diff --git a/rwengine/src/ai/CharacterController.cpp b/rwengine/src/ai/CharacterController.cpp index 52b38189..b96d7517 100644 --- a/rwengine/src/ai/CharacterController.cpp +++ b/rwengine/src/ai/CharacterController.cpp @@ -28,7 +28,7 @@ void CharacterController::setActivity(CharacterController::Activity* activity) CharacterController::CharacterController(CharacterObject* character) : character(character), _currentActivity(nullptr), _nextActivity(nullptr), running(false), -currentGoal(None), leader(nullptr) +vehicleIdle(0.f), currentGoal(None), leader(nullptr) { character->controller = this; } @@ -73,21 +73,26 @@ void CharacterController::update(float dt) /// @todo play _low variant if car has low flag. character->playAnimation(character->animations.car_sit, true); - // If character is idle in vehicle, close door. if( glm::length( d ) <= 0.1f ) { - auto entryDoor = character->getCurrentVehicle()->getSeatEntryDoor(character->getCurrentSeat()); + vehicleIdle += dt; + } + else + { + vehicleIdle = 0.f; + } + + if( vehicleIdle >= 1.f ) + { + // If character is idle in vehicle, try to close the door. + auto v = character->getCurrentVehicle(); + auto entryDoor = v->getSeatEntryDoor(character->getCurrentSeat()); if( entryDoor && entryDoor->constraint ) { character->getCurrentVehicle()->setPartTarget(entryDoor, true, entryDoor->closedAngle); } } - else - { - auto entryDoor = character->getCurrentVehicle()->getSeatEntryDoor(character->getCurrentSeat()); - entryDoor->holdAngle = false; - } } } else { @@ -247,12 +252,18 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr character->enterVehicle(vehicle, seat); return true; } + + auto entryDoor = vehicle->getSeatEntryDoor(seat); auto anm_open = character->animations.car_open_lhs; auto anm_enter = character->animations.car_getin_lhs; - auto entryDoor = vehicle->getSeatEntryDoor(seat); - + if( entryDoor->dummy->getDefaultTranslation().x > 0.f ) + { + anm_open = character->animations.car_open_rhs; + anm_enter = character->animations.car_getin_rhs; + } + if( entering ) { if( character->animator->getAnimation() == anm_open ) { if( character->animator->isCompleted() ) { @@ -317,8 +328,16 @@ bool Activities::ExitVehicle::update(CharacterObject *character, CharacterContro if( character->getCurrentVehicle() == nullptr ) return true; auto vehicle = character->getCurrentVehicle(); - auto anm_exit = character->animations.car_getout_lhs; + auto seat = character->getCurrentSeat(); + auto door = vehicle->getSeatEntryDoor(seat); + + auto anm_exit = character->animations.car_getout_lhs; + + if( door->dummy->getDefaultTranslation().x > 0.f ) + { + anm_exit = character->animations.car_getout_rhs; + } if( vehicle->vehicle->type == VehicleData::BOAT ) { auto ppos = character->getPosition(); @@ -339,8 +358,6 @@ bool Activities::ExitVehicle::update(CharacterObject *character, CharacterContro } else { character->playAnimation(anm_exit, false); - - auto door = vehicle->getSeatEntryDoor(character->getCurrentSeat()); if( door ) { vehicle->setPartTarget(door, true, door->openAngle); diff --git a/rwengine/src/objects/CharacterObject.cpp b/rwengine/src/objects/CharacterObject.cpp index 1ca0dfa4..88edc56f 100644 --- a/rwengine/src/objects/CharacterObject.cpp +++ b/rwengine/src/objects/CharacterObject.cpp @@ -42,6 +42,10 @@ CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos, const animations.car_open_lhs = engine->gameData.animations["car_open_lhs"]; animations.car_getin_lhs = engine->gameData.animations["car_getin_lhs"]; animations.car_getout_lhs = engine->gameData.animations["car_getout_lhs"]; + + animations.car_open_rhs = engine->gameData.animations["car_open_rhs"]; + animations.car_getin_rhs = engine->gameData.animations["car_getin_rhs"]; + animations.car_getout_rhs = engine->gameData.animations["car_getout_rhs"]; if(model) { skeleton = new Skeleton; diff --git a/rwengine/src/objects/VehicleObject.cpp b/rwengine/src/objects/VehicleObject.cpp index 48fa2ae8..af538270 100644 --- a/rwengine/src/objects/VehicleObject.cpp +++ b/rwengine/src/objects/VehicleObject.cpp @@ -307,20 +307,30 @@ void VehicleObject::tickPhysics(float dt) //next.translation = p2; skeleton->setData(it.second.dummy->getIndex(), { next, prev, true } ); - if( it.second.holdAngle ) + if( it.second.moveToAngle ) { - it.second.constraint->setMotorTarget(it.second.targetAngle, 0.1f); + auto angledelta = it.second.targetAngle - it.second.constraint->getHingeAngle(); + if( glm::abs(angledelta) <= 0.01f ) + { + it.second.constraint->enableAngularMotor(false, 1.f, 1.f); + dynamicParts[it.first].moveToAngle = false; + } + else + { + it.second.constraint->enableAngularMotor(true, glm::sign(angledelta) * 5.f, 1.f); + } } - it.second.constraint->enableMotor( it.second.holdAngle ); // If the part is moving quite fast and near the limit, lock it. /// @TODO not all parts rotate in the z axis. - if(it.second.body->getAngularVelocity().getZ() >= PART_CLOSE_VELOCITY) + float zspeed = it.second.body->getAngularVelocity().getZ(); + if(it.second.openAngle < 0.f) zspeed = -zspeed; + if(zspeed >= PART_CLOSE_VELOCITY) { auto d = it.second.constraint->getHingeAngle() - it.second.closedAngle; - if( std::abs(d) < 0.05f ) + if( glm::abs(d) < 0.05f ) { - it.second.holdAngle = false; + dynamicParts[it.first].moveToAngle = false; setPartLocked(&(it.second), true); } } @@ -525,20 +535,14 @@ void VehicleObject::setPartTarget(VehicleObject::Part* part, bool enable, float } part->targetAngle = target; - part->holdAngle = true; - - part->constraint->enableMotor(true); + part->moveToAngle = true; + part->body->activate(true); } else { part->targetAngle = target; - part->holdAngle = false; - - if( part->constraint ) - { - part->constraint->enableMotor(false); - } + part->moveToAngle = false; } } @@ -692,7 +696,7 @@ void VehicleObject::destroyObjectHinge(Part* part) part->constraint = nullptr; // Reset target. - part->holdAngle = false; + part->moveToAngle = false; } }