1
0
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:
Daniel Evans 2016-05-24 23:49:01 +01:00
parent 040f216407
commit b7ac33caec
4 changed files with 85 additions and 17 deletions

View File

@ -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);
};

View File

@ -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;

View File

@ -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();
}

View File

@ -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;
}