mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-22 02:12:45 +01:00
Improve activities: canSkip(), let player cancel vehicle enter.
Closes #32
This commit is contained in:
parent
040f216407
commit
b7ac33caec
@ -26,6 +26,12 @@ public:
|
||||
|
||||
virtual std::string name() const = 0;
|
||||
|
||||
/**
|
||||
* @brief canSkip
|
||||
* @return true if the activity can be skipped.
|
||||
*/
|
||||
virtual bool canSkip(CharacterObject*, CharacterController*) const { return false; }
|
||||
|
||||
virtual bool update(CharacterObject* character, CharacterController* controller) = 0;
|
||||
};
|
||||
|
||||
@ -74,12 +80,12 @@ public:
|
||||
|
||||
virtual ~CharacterController() { }
|
||||
|
||||
Activity* getCurrentActivity() { return _currentActivity; }
|
||||
Activity* getCurrentActivity() const { return _currentActivity; }
|
||||
|
||||
Activity* getNextActivity() { return _nextActivity; }
|
||||
Activity* getNextActivity() const { return _nextActivity; }
|
||||
|
||||
/**
|
||||
* @brief skipActivity Cancel the current activity, immediatley.
|
||||
* @brief skipActivity Cancel the current activity immediatley, if possible.
|
||||
*/
|
||||
void skipActivity();
|
||||
|
||||
@ -89,6 +95,13 @@ public:
|
||||
* @param position
|
||||
*/
|
||||
void setNextActivity( Activity* activity );
|
||||
|
||||
/**
|
||||
* @brief IsCurrentActivity
|
||||
* @param activity Name of activity to check for
|
||||
* @return if the given activity is the current activity
|
||||
*/
|
||||
bool isCurrentActivity(const std::string& activity) const;
|
||||
|
||||
/**
|
||||
* @brief update Updates the controller.
|
||||
@ -117,7 +130,8 @@ public:
|
||||
};
|
||||
|
||||
#define DECL_ACTIVITY( activity_name ) \
|
||||
std::string name() const { return #activity_name; }
|
||||
static constexpr auto ActivityName = #activity_name; \
|
||||
std::string name() const { return ActivityName; }
|
||||
|
||||
// TODO: Refactor this with an ugly macro to reduce code dup.
|
||||
class WeaponItem;
|
||||
@ -138,6 +152,8 @@ namespace Activities {
|
||||
: target( target ), sprint(_sprint) {}
|
||||
|
||||
bool update(CharacterObject* character, CharacterController* controller);
|
||||
|
||||
bool canSkip(CharacterObject *, CharacterController *) const { return true; }
|
||||
};
|
||||
|
||||
struct Jump : public CharacterController::Activity
|
||||
@ -166,6 +182,8 @@ namespace Activities {
|
||||
EnterVehicle( VehicleObject* vehicle, int seat = 0 )
|
||||
: vehicle( vehicle ), seat( seat ), entering(false) {}
|
||||
|
||||
bool canSkip(CharacterObject* character, CharacterController*) const override;
|
||||
|
||||
bool update(CharacterObject *character, CharacterController *controller);
|
||||
};
|
||||
|
||||
|
@ -7,6 +7,18 @@
|
||||
#include <items/WeaponItem.hpp>
|
||||
#include <rw/defines.hpp>
|
||||
|
||||
CharacterController::CharacterController(CharacterObject* character)
|
||||
: character(character)
|
||||
, _currentActivity(nullptr)
|
||||
, _nextActivity(nullptr)
|
||||
, vehicleIdle(0.f)
|
||||
, currentGoal(None)
|
||||
, leader(nullptr)
|
||||
, targetNode(nullptr)
|
||||
{
|
||||
character->controller = this;
|
||||
}
|
||||
|
||||
bool CharacterController::updateActivity()
|
||||
{
|
||||
if( _currentActivity ) {
|
||||
@ -22,21 +34,13 @@ void CharacterController::setActivity(CharacterController::Activity* activity)
|
||||
_currentActivity = activity;
|
||||
}
|
||||
|
||||
CharacterController::CharacterController(CharacterObject* character)
|
||||
: character(character)
|
||||
, _currentActivity(nullptr)
|
||||
, _nextActivity(nullptr)
|
||||
, vehicleIdle(0.f)
|
||||
, currentGoal(None)
|
||||
, leader(nullptr)
|
||||
, targetNode(nullptr)
|
||||
{
|
||||
character->controller = this;
|
||||
}
|
||||
|
||||
void CharacterController::skipActivity()
|
||||
{
|
||||
setActivity(nullptr);
|
||||
// Some activities can't be cancelled, such as the final phase of entering a vehicle
|
||||
// or jumping.
|
||||
if (getCurrentActivity() != nullptr &&
|
||||
getCurrentActivity()->canSkip(character, this))
|
||||
setActivity(nullptr);
|
||||
}
|
||||
|
||||
void CharacterController::setNextActivity(CharacterController::Activity* activity)
|
||||
@ -51,6 +55,12 @@ void CharacterController::setNextActivity(CharacterController::Activity* activit
|
||||
}
|
||||
}
|
||||
|
||||
bool CharacterController::isCurrentActivity(const std::string& activity) const
|
||||
{
|
||||
if (getCurrentActivity() == nullptr) return false;
|
||||
return getCurrentActivity()->name() == activity;
|
||||
}
|
||||
|
||||
void CharacterController::update(float dt)
|
||||
{
|
||||
if( character->getCurrentVehicle() ) {
|
||||
@ -170,6 +180,12 @@ bool Activities::Jump::update(CharacterObject* character, CharacterController* c
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Activities::EnterVehicle::canSkip(CharacterObject *character, CharacterController *) const
|
||||
{
|
||||
// If we're already inside the vehicle, it can't helped.
|
||||
return character->getCurrentVehicle() == nullptr;
|
||||
}
|
||||
|
||||
bool Activities::EnterVehicle::update(CharacterObject *character, CharacterController *controller)
|
||||
{
|
||||
constexpr float kSprintToEnterDistance = 5.f;
|
||||
|
@ -396,6 +396,13 @@ void IngameState::handlePlayerInput(const sf::Event& event)
|
||||
if( player->getCharacter()->getCurrentVehicle()) {
|
||||
player->exitVehicle();
|
||||
}
|
||||
else
|
||||
if (player->isCurrentActivity(
|
||||
Activities::EnterVehicle::ActivityName))
|
||||
{
|
||||
// Give up entering a vehicle if we're alreadying doing so
|
||||
player->skipActivity();
|
||||
}
|
||||
else {
|
||||
player->enterNearestVehicle();
|
||||
}
|
||||
|
@ -83,6 +83,33 @@ BOOST_AUTO_TEST_CASE(test_activities)
|
||||
|
||||
BOOST_CHECK_EQUAL( vehicle, character->getCurrentVehicle() );
|
||||
|
||||
controller->setNextActivity( new Activities::ExitVehicle( ) );
|
||||
|
||||
for(float t = 0.f; t < 9.0f; t+=(1.f/60.f)) {
|
||||
character->tick(1.f/60.f);
|
||||
Global::get().e->dynamicsWorld->stepSimulation(1.f/60.f);
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL( nullptr, character->getCurrentVehicle() );
|
||||
|
||||
character->setPosition(glm::vec3(5.f, 0.f, 0.f));
|
||||
controller->setNextActivity( new Activities::EnterVehicle( vehicle, 0 ) );
|
||||
|
||||
for(float t = 0.f; t < 0.5f; t+=(1.f/60.f)) {
|
||||
character->tick(1.f/60.f);
|
||||
Global::get().e->dynamicsWorld->stepSimulation(1.f/60.f);
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL( nullptr, character->getCurrentVehicle() );
|
||||
controller->skipActivity();
|
||||
|
||||
for(float t = 0.f; t < 5.0f; t+=(1.f/60.f)) {
|
||||
character->tick(1.f/60.f);
|
||||
Global::get().e->dynamicsWorld->stepSimulation(1.f/60.f);
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL( nullptr, character->getCurrentVehicle() );
|
||||
|
||||
Global::get().e->destroyObject(character);
|
||||
delete controller;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user