Skip to content

Commit

Permalink
Playing sound effect/show message when player lacks required MP for p…
Browse files Browse the repository at this point in the history
…ower

Closes flareteam#1666

This removes the implementation of fallback powers. Simply notifying the
player that they've run out of mana is a better solution to the core
problem.
  • Loading branch information
dorkster committed Aug 6, 2018
1 parent a03f110 commit 2738d42
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 44 deletions.
2 changes: 1 addition & 1 deletion RELEASE_NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Engine features:
* Display a list of completed quests in the Quests log.
* Item icons can now have an overlay image based on their quality.
* Added widget settings for modifying the appearance of the quantity text on item icons.
* Powers can now have a fallback power which will be cast instead if the player lacks the appropriate amount of HP/MP.
* Added support for playing a sound effect and showing a message when player lacks required MP for power usage.

Engine fixes:

Expand Down
4 changes: 2 additions & 2 deletions docs/attribute-reference.html
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ <h4>EngineSettings: Misc</h4>

<p><strong>keep_buyback_on_map_change</strong> | <code>bool</code> | If true, NPC buyback stocks will persist when the map changes. If false, save_buyback is disabled.</p>

<p><strong>sfx_unable_to_cast</strong> | <code>filename</code> | Sound to play when the player lacks the MP to cast a power.</p>

<hr />

<h4>EngineSettings: Resolution</h4>
Expand Down Expand Up @@ -1735,8 +1737,6 @@ <h4>PowerManager: Powers</h4>

<p><strong>power.requires_hpmp_state</strong> | <code>["hp", "mp"], ["percent", "not_percent", "ignore"], int : Stat, Current state, Percentage value</code> | Power can only be used when HP/MP matches the specified state</p>

<p><strong>power.fallback_power</strong> | <code>power_id</code> | If the hero tries to cast this power, but does not satisfy the requires_mp or requires_hp properties, this power will automatically be used instead.</p>

<p><strong>power.animation</strong> | <code>filename</code> | The filename of the power animation.</p>

<p><strong>power.soundfx</strong> | <code>filename</code> | Filename of a sound effect to play when the power is used.</p>
Expand Down
4 changes: 4 additions & 0 deletions src/EngineSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ void EngineSettings::Misc::load() {
camera_speed = 10.f;
save_buyback = true;
keep_buyback_on_map_change = true;
sfx_unable_to_cast = "";

FileParser infile;
// @CLASS EngineSettings: Misc|Description of engine/misc.txt
Expand Down Expand Up @@ -134,6 +135,9 @@ void EngineSettings::Misc::load() {
// @ATTR keep_buyback_on_map_change|bool|If true, NPC buyback stocks will persist when the map changes. If false, save_buyback is disabled.
else if (infile.key == "keep_buyback_on_map_change")
keep_buyback_on_map_change = Parse::toBool(infile.val);
// @ATTR sfx_unable_to_cast|filename|Sound to play when the player lacks the MP to cast a power.
else if (infile.key == "sfx_unable_to_cast")
sfx_unable_to_cast = infile.val;

else infile.error("EngineSettings: '%s' is not a valid key.", infile.key.c_str());
}
Expand Down
1 change: 1 addition & 0 deletions src/EngineSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class EngineSettings {
float camera_speed;
bool save_buyback;
bool keep_buyback_on_map_change;
std::string sfx_unable_to_cast;
};

class Resolutions {
Expand Down
60 changes: 26 additions & 34 deletions src/MenuActionBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ FLARE. If not, see https://www.gnu.org/licenses/
#include "Settings.h"
#include "SharedGameResources.h"
#include "SharedResources.h"
#include "SoundManager.h"
#include "StatBlock.h"
#include "TooltipManager.h"
#include "UtilsParsing.h"
Expand All @@ -54,6 +55,7 @@ MenuActionBar::MenuActionBar()
: sprite_emptyslot(NULL)
, sprite_disabled(NULL)
, sprite_attention(NULL)
, sfx_unable_to_cast(0)
, slots_count(0)
, drag_prev_slot(-1)
, updated(false)
Expand Down Expand Up @@ -164,11 +166,15 @@ MenuActionBar::MenuActionBar()
slot_enabled.resize(slots_count);
slot_activated.resize(slots_count);
slot_cooldown_size.resize(slots_count);
slot_fail_cooldown.resize(slots_count);

clear();

loadGraphics();

if (!eset->misc.sfx_unable_to_cast.empty())
sfx_unable_to_cast = snd->load(eset->misc.sfx_unable_to_cast, "MenuActionBar unable to cast");

align();

menu_act = this;
Expand Down Expand Up @@ -232,6 +238,7 @@ void MenuActionBar::clear() {
locked[i] = false;
slot_activated[i] = false;
slot_cooldown_size[i] = 0;
slot_fail_cooldown[i] = 0;
}

// clear menu notifications
Expand Down Expand Up @@ -332,6 +339,9 @@ void MenuActionBar::logic() {
else {
slot_cooldown_size[i] = (slot_enabled[i] ? 0 : eset->resolutions.icon_size);;
}

if (slot_fail_cooldown[i] > 0)
slot_fail_cooldown[i]--;
}

}
Expand Down Expand Up @@ -563,44 +573,24 @@ void MenuActionBar::checkAction(std::vector<ActionData> &action_queue) {

// a power slot was activated
if (action.power > 0 && static_cast<unsigned>(action.power) < powers->powers.size()) {
Power *power = &powers->powers[action.power];

if (pc->stats.mp < power->requires_mp || (!power->sacrifice && pc->stats.hp < power->requires_hp)) {
if (power->fallback_power > 0) {
action.power = power->fallback_power;
power = &powers->powers[action.power];

if (power->meta_power) {
int id = menu->inv->getPowerMod(action.power);
if (id > 0) {
action.power = id;
power = &powers->powers[action.power];
}
}
const Power& power = powers->powers[action.power];

for (size_t j = 0; j < action_queue.size(); ++j) {
if (action_queue[j].hotkey == i)
action_queue.erase(action_queue.begin()+j);
}
}
else {
continue;
}
}
else if (slot_enabled[i]) {
for (size_t j = 0; j < action_queue.size(); ++j) {
if (action_queue[j].hotkey == i && action_queue[j].power != action.power)
action_queue.erase(action_queue.begin()+j);
}
if (pc->stats.mp < power.requires_mp && slot_fail_cooldown[i] == 0) {
slot_fail_cooldown[i] = settings->max_frames_per_sec;
pc->logMsg(msg->get("Not enough MP."), Avatar::MSG_NORMAL);
snd->play(sfx_unable_to_cast, "ACT_NO_MP", snd->NO_POS, !snd->LOOP);
continue;
}
else {
else if (!slot_enabled[i]) {
continue;
}

slot_fail_cooldown[i] = pc->power_cast_duration[action.power];

action.instant_item = false;
if (power->new_state == Power::STATE_INSTANT) {
for (size_t j = 0; j < power->required_items.size(); ++j) {
if (power->required_items[j].id > 0 && !power->required_items[j].equipped) {
if (power.new_state == Power::STATE_INSTANT) {
for (size_t j = 0; j < power.required_items.size(); ++j) {
if (power.required_items[j].id > 0 && !power.required_items[j].equipped) {
action.instant_item = true;
break;
}
Expand All @@ -613,7 +603,7 @@ void MenuActionBar::checkAction(std::vector<ActionData> &action_queue) {
for (size_t j=0; j<action_queue.size(); j++) {
if (action_queue[j].hotkey == i) {
// this power is already in the action queue, update its target
action_queue[j].target = setTarget(have_aim, *power);
action_queue[j].target = setTarget(have_aim, power);
can_use_power = false;
break;
}
Expand All @@ -626,7 +616,7 @@ void MenuActionBar::checkAction(std::vector<ActionData> &action_queue) {
continue;

// set the target depending on how the power was triggered
action.target = setTarget(have_aim, *power);
action.target = setTarget(have_aim, power);

// add it to the queue
action_queue.push_back(action);
Expand Down Expand Up @@ -881,4 +871,6 @@ MenuActionBar::~MenuActionBar() {

for (unsigned int i=0; i<4; i++)
delete menus[i];

snd->unload(sfx_unable_to_cast);
}
4 changes: 4 additions & 0 deletions src/MenuActionBar.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class MenuActionBar : public Menu {

Point last_mouse;

std::vector<int> slot_fail_cooldown;

SoundID sfx_unable_to_cast;

public:
enum {
MENU_CHARACTER = 0,
Expand Down
5 changes: 0 additions & 5 deletions src/PowerManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ Power::Power()
, requires_max_mp(-1)
, requires_not_max_hp(-1)
, requires_not_max_mp(-1)
, fallback_power(0)
, animation_name("")
, sfx_index(-1)
, sfx_hit(0)
Expand Down Expand Up @@ -468,10 +467,6 @@ void PowerManager::loadPowers() {
infile.error("PowerManager: Please specify 'hp' or 'mp'.");
}
}
else if (infile.key == "fallback_power") {
// @ATTR power.fallback_power|power_id|If the hero tries to cast this power, but does not satisfy the requires_mp or requires_hp properties, this power will automatically be used instead.
powers[input_id].fallback_power = Parse::toInt(infile.val);
}
// animation info
else if (infile.key == "animation") {
// @ATTR power.animation|filename|The filename of the power animation.
Expand Down
1 change: 0 additions & 1 deletion src/PowerManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ class Power {
int requires_max_mp;
int requires_not_max_hp;
int requires_not_max_mp;
int fallback_power;

// animation info
std::string animation_name;
Expand Down
2 changes: 1 addition & 1 deletion src/Version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ FLARE. If not, see https://www.gnu.org/licenses/

#include <SDL.h>

Version VersionInfo::ENGINE(1, 6, 36);
Version VersionInfo::ENGINE(1, 6, 37);
Version VersionInfo::MIN(0, 0, 0);
Version VersionInfo::MAX(USHRT_MAX, USHRT_MAX, USHRT_MAX);

Expand Down

0 comments on commit 2738d42

Please sign in to comment.