feat: Implement contextual actions
Currently, only door unlocking is supported.
This commit is contained in:
parent
e51b219d7f
commit
fad3f9054e
7 changed files with 108 additions and 9 deletions
|
@ -25,6 +25,7 @@ enum class ActionType {
|
|||
MoveToPoint = 0,
|
||||
OpenDoor = 5,
|
||||
CloseDoor = 6,
|
||||
OpenLock = 13,
|
||||
Follow = 35,
|
||||
FollowLeader = 38,
|
||||
QueueEmpty = 65534,
|
||||
|
|
|
@ -80,6 +80,9 @@ void ActionExecutor::executeActions(Object &object, float dt) {
|
|||
case ActionType::OpenContainer:
|
||||
executeOpenContainer(static_cast<Creature &>(object), *dynamic_cast<ObjectAction *>(action), dt);
|
||||
break;
|
||||
case ActionType::OpenLock:
|
||||
executeOpenLock(static_cast<Creature &>(object), *dynamic_cast<ObjectAction *>(action), dt);
|
||||
break;
|
||||
default:
|
||||
warn("ActionExecutor: action not implemented: " + to_string(static_cast<int>(type)));
|
||||
action->isCompleted();
|
||||
|
@ -255,6 +258,24 @@ void ActionExecutor::executeOpenContainer(Creature &actor, ObjectAction &action,
|
|||
}
|
||||
}
|
||||
|
||||
void ActionExecutor::executeOpenLock(Creature &actor, ObjectAction &action, float dt) {
|
||||
Door *door = dynamic_cast<Door *>(action.object());
|
||||
if (door) {
|
||||
bool reached = navigateCreature(actor, door->position(), 1.0f, dt);
|
||||
if (reached) {
|
||||
door->setLocked(false);
|
||||
door->open(&actor);
|
||||
if (!door->blueprint().onOpen().empty()) {
|
||||
runScript(door->blueprint().onOpen(), door->id(), actor.id(), -1);
|
||||
}
|
||||
action.complete();
|
||||
}
|
||||
} else {
|
||||
warn("ActionExecutor: unsupported OpenLock object: " + to_string(action.object()->id()));
|
||||
action.complete();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
||||
|
|
|
@ -59,6 +59,7 @@ private:
|
|||
void executeOpenDoor(Object &actor, ObjectAction &action, float dt);
|
||||
void executeCloseDoor(Object &actor, ObjectAction &action, float dt);
|
||||
void executeOpenContainer(Creature &actor, ObjectAction &action, float dt);
|
||||
void executeOpenLock(Creature &actor, ObjectAction &action, float dt);
|
||||
|
||||
// END Actions
|
||||
};
|
||||
|
|
|
@ -148,6 +148,12 @@ void HUD::load() {
|
|||
hideControl("TB_STEALTH");
|
||||
}
|
||||
|
||||
bool HUD::handle(const SDL_Event &event) {
|
||||
if (_select.handle(event)) return true;
|
||||
|
||||
return GUI::handle(event);
|
||||
}
|
||||
|
||||
void HUD::update(float dt) {
|
||||
GUI::update(dt);
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
|
||||
void load() override;
|
||||
|
||||
bool handle(const SDL_Event &event) override;
|
||||
void update(float dt) override;
|
||||
void render() const override;
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace game {
|
|||
static const int kOffsetToReticle = 8;
|
||||
static const int kTitleBarWidth = 250;
|
||||
static const int kTitleBarPadding = 6;
|
||||
static const int kActionCount = 3;
|
||||
static const int kActionBarMargin = 3;
|
||||
static const int kActionBarPadding = 3;
|
||||
static const int kActionWidth = 35;
|
||||
|
@ -70,6 +71,52 @@ void SelectionOverlay::addTextureByAction(ContextualAction action, const string
|
|||
_textureByAction.insert(make_pair(action, Textures::instance().get(resRef, TextureType::GUI)));
|
||||
}
|
||||
|
||||
bool SelectionOverlay::handle(const SDL_Event &event) {
|
||||
switch (event.type) {
|
||||
case SDL_MOUSEMOTION:
|
||||
return handleMouseMotion(event.motion);
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
return handleMouseButtonDown(event.button);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SelectionOverlay::handleMouseMotion(const SDL_MouseMotionEvent &event) {
|
||||
_selectedActionIdx = -1;
|
||||
|
||||
if (!_hasSelected) return false;
|
||||
|
||||
for (int i = 0; i < kActionCount; ++i) {
|
||||
float x, y;
|
||||
getActionScreenCoords(i, x, y);
|
||||
if (event.x >= x && event.y >= y && event.x < x + kActionWidth && event.y < y + kActionHeight) {
|
||||
_selectedActionIdx = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SelectionOverlay::handleMouseButtonDown(const SDL_MouseButtonEvent &event) {
|
||||
if (event.clicks > 1 || _selectedActionIdx == -1) return false;
|
||||
|
||||
shared_ptr<Area> area(_game->module()->area());
|
||||
ObjectSelector &selector = area->objectSelector();
|
||||
shared_ptr<SpatialObject> object(area->find(selector.selectedObjectId()));
|
||||
|
||||
switch (_actions[_selectedActionIdx]) {
|
||||
case ContextualAction::Unlock: {
|
||||
ActionQueue &actions = _game->party().leader()->actionQueue();
|
||||
actions.add(make_unique<ObjectAction>(ActionType::OpenLock, object));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SelectionOverlay::update() {
|
||||
shared_ptr<Module> module(_game->module());
|
||||
shared_ptr<Area> area(module->area());
|
||||
|
@ -177,10 +224,10 @@ void SelectionOverlay::drawTitleBar() const {
|
|||
|
||||
void SelectionOverlay::drawActionBar() const {
|
||||
const GraphicsOptions &opts = _game->options().graphics;
|
||||
float frameY = opts.height * (1.0f - _selectedScreenCoords.y) - _reticleHeight / 2 - kActionHeight - kOffsetToReticle - kActionBarMargin;
|
||||
|
||||
for (int i = -1; i < 2; ++i) {
|
||||
float frameX = opts.width * _selectedScreenCoords.x + (static_cast<float>(i) - 0.5f) * kActionWidth + i * kActionBarMargin;
|
||||
for (int i = 0; i < kActionCount; ++i) {
|
||||
float frameX, frameY;
|
||||
getActionScreenCoords(i, frameX, frameY);
|
||||
|
||||
glm::mat4 transform(1.0f);
|
||||
transform = glm::translate(transform, glm::vec3(frameX, frameY, 0.0f));
|
||||
|
@ -191,19 +238,24 @@ void SelectionOverlay::drawActionBar() const {
|
|||
|
||||
Shaders::instance().activate(ShaderProgram::GUIGUI, locals);
|
||||
|
||||
_friendlyScroll->bind(0);
|
||||
shared_ptr<Texture> frameTexture;
|
||||
if (i == _selectedActionIdx) {
|
||||
frameTexture = _hilightedScroll;
|
||||
} else {
|
||||
frameTexture = _friendlyScroll;
|
||||
}
|
||||
frameTexture->bind(0);
|
||||
|
||||
Quad::getDefault().renderTriangles();
|
||||
|
||||
_friendlyScroll->unbind(0);
|
||||
frameTexture->unbind(0);
|
||||
|
||||
int actionIdx = i + 1;
|
||||
if (actionIdx < static_cast<int>(_actions.size())) {
|
||||
ContextualAction action = _actions[actionIdx];
|
||||
if (i < static_cast<int>(_actions.size())) {
|
||||
ContextualAction action = _actions[i];
|
||||
|
||||
shared_ptr<Texture> texture(_textureByAction.find(action)->second);
|
||||
if (texture) {
|
||||
float y = opts.height * (1.0f - _selectedScreenCoords.y) - (_reticleHeight + kActionHeight + kActionWidth) / 2 - kOffsetToReticle - kActionBarMargin;
|
||||
float y = opts.height * (1.0f - _selectedScreenCoords.y) - (_reticleHeight + kActionHeight + kActionWidth) / 2.0f - kOffsetToReticle - kActionBarMargin;
|
||||
|
||||
transform = glm::mat4(1.0f);
|
||||
transform = glm::translate(transform, glm::vec3(frameX, y, 0.0f));
|
||||
|
@ -224,6 +276,16 @@ void SelectionOverlay::drawActionBar() const {
|
|||
}
|
||||
}
|
||||
|
||||
bool SelectionOverlay::getActionScreenCoords(int index, float &x, float &y) const {
|
||||
if (!_hasSelected) return false;
|
||||
|
||||
const GraphicsOptions &opts = _game->options().graphics;
|
||||
x = opts.width * _selectedScreenCoords.x + (static_cast<float>(index - 1) - 0.5f) * kActionWidth + (index - 1) * kActionBarMargin;
|
||||
y = opts.height * (1.0f - _selectedScreenCoords.y) - _reticleHeight / 2 - kActionHeight - kOffsetToReticle - kActionBarMargin;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
|
||||
void load();
|
||||
|
||||
bool handle(const SDL_Event &event);
|
||||
void update();
|
||||
void render() const;
|
||||
|
||||
|
@ -63,12 +64,18 @@ private:
|
|||
glm::vec3 _selectedScreenCoords { 0.0f };
|
||||
std::string _selectedTitle;
|
||||
int _reticleHeight { 0 };
|
||||
int _selectedActionIdx { -1 };
|
||||
|
||||
void addTextureByAction(ContextualAction action, const std::string &resRef);
|
||||
|
||||
bool handleMouseMotion(const SDL_MouseMotionEvent &event);
|
||||
bool handleMouseButtonDown(const SDL_MouseButtonEvent &event);
|
||||
|
||||
void drawReticle(render::Texture &texture, const glm::vec3 &screenCoords) const;
|
||||
void drawTitleBar() const;
|
||||
void drawActionBar() const;
|
||||
|
||||
bool getActionScreenCoords(int index, float &x, float &y) const;
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
|
Loading…
Reference in a new issue