Skip to content

Commit

Permalink
Added ability to grant bonuses to power levels via items
Browse files Browse the repository at this point in the history
Closes flareteam#1648

As an example, let's say we want to grant a +1 bonus to the Blood Strike
power, which has a power id of 7 at level 1:

    bonus_power_level=7,1

Bonuses don't have to start at the base level of the power. The
following will grant a +1 bonus to Blood Strike, but only if it is
already at least level 3 (i.e. power id 9):

    bonus_power_level=9,1

Item sets can also take advantage of this property. The only difference
is that there are three values, the first being the number of set items
for the bonus to activate. The following example grants a +2 bonus to
Blood Strike if 3 set items are equipped:

    bonus_power_level=3,7,2
  • Loading branch information
dorkster committed Aug 24, 2018
1 parent a61426c commit 3053f4d
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 35 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Engine features:
* 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.
* Added support for playing a sound effect and showing a message when player lacks required MP for power usage.
* Added ability to grant bonuses to power levels via items with the "bonus_power_level" property.

Engine fixes:

Expand Down
4 changes: 4 additions & 0 deletions docs/attribute-reference.html
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,8 @@ <h4>ItemManager: Items</h4>

<p><strong>bonus</strong> | <code>repeatable(predefined_string, int) : Stat name, Value</code> | Adds a bonus to the item by stat name, example bonus=hp, 50</p>

<p><strong>bonus_power_level</strong> | <code>repeatable(power_id, int) : Base power, Bonus levels</code> | Grants bonus levels to a given base power.</p>

<p><strong>soundfx</strong> | <code>filename</code> | Sound effect filename to play for the specific item.</p>

<p><strong>gfx</strong> | <code>filename</code> | Filename of an animation set to display when the item is equipped.</p>
Expand Down Expand Up @@ -1111,6 +1113,8 @@ <h4>ItemManager: Sets</h4>

<p><strong>bonus</strong> | <code>repeatable(int, string, int) : Required set item count, Stat name, Value</code> | Bonus to append to items in the set.</p>

<p><strong>bonus_power_level</strong> | <code>repeatable(int, power_id, int) : Required set item count, Base power, Bonus levels</code> | Grants bonus levels to a given base power.</p>

<hr />

<h4>Map</h4>
Expand Down
30 changes: 28 additions & 2 deletions src/ItemManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ FLARE. If not, see http:https://www.gnu.org/licenses/
#include "FontEngine.h"
#include "InputState.h"
#include "ItemManager.h"
#include "MenuManager.h"
#include "MenuPowers.h"
#include "MessageEngine.h"
#include "PowerManager.h"
#include "Settings.h"
#include "SharedGameResources.h"
#include "SharedResources.h"
Expand Down Expand Up @@ -267,6 +270,13 @@ void ItemManager::loadItems(const std::string& filename) {
parseBonus(bdata, infile);
items[id].bonus.push_back(bdata);
}
else if (infile.key == "bonus_power_level") {
// @ATTR bonus_power_level|repeatable(power_id, int) : Base power, Bonus levels|Grants bonus levels to a given base power.
BonusData bdata;
bdata.power_id = Parse::popFirstInt(infile.val);
bdata.value = Parse::popFirstInt(infile.val);
items[id].bonus.push_back(bdata);
}
else if (infile.key == "soundfx") {
// @ATTR soundfx|filename|Sound effect filename to play for the specific item.
items[id].sfx = infile.val;
Expand Down Expand Up @@ -565,11 +575,19 @@ void ItemManager::loadSets(const std::string& filename) {
item_sets[id].bonus.clear();
clear_bonus = false;
}
Set_bonus bonus;
SetBonusData bonus;
bonus.requirement = Parse::popFirstInt(infile.val);
parseBonus(bonus, infile);
item_sets[id].bonus.push_back(bonus);
}
else if (infile.key == "bonus_power_level") {
// @ATTR bonus_power_level|repeatable(int, power_id, int) : Required set item count, Base power, Bonus levels|Grants bonus levels to a given base power.
SetBonusData bonus;
bonus.requirement = Parse::popFirstInt(infile.val);
bonus.power_id = Parse::popFirstInt(infile.val);
bonus.value = Parse::popFirstInt(infile.val);
item_sets[id].bonus.push_back(bonus);
}
else {
infile.error("ItemManager: '%s' is not a valid key.", infile.key.c_str());
}
Expand Down Expand Up @@ -658,6 +676,14 @@ void ItemManager::getBonusString(std::stringstream& ss, BonusData* bdata) {
else if (bdata->base_index > -1 && static_cast<size_t>(bdata->base_index) < eset->primary_stats.list.size()) {
ss << " " << eset->primary_stats.list[bdata->base_index].name;
}
else if (powers && bdata->power_id > 0) {
ss << " " << powers->powers[bdata->power_id].name;
if (menu && menu->pow) {
std::string req_str = menu->pow->getItemBonusPowerReqString(bdata->power_id);
if (!req_str.empty())
ss << " (" << msg->get("Requires %s", req_str) << ")";
}
}
}

void ItemManager::playSound(int item, const Point& pos) {
Expand Down Expand Up @@ -873,7 +899,7 @@ TooltipData ItemManager::getTooltip(ItemStack stack, StatBlock *stats, int conte
while (bonus_counter < set.bonus.size()) {
ss.str("");

Set_bonus* bdata = &set.bonus[bonus_counter];
SetBonusData* bdata = &set.bonus[bonus_counter];

ss << msg->get("%d items:", bdata->requirement) << ' ';

Expand Down
10 changes: 6 additions & 4 deletions src/ItemManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class BonusData {
bool is_speed;
bool is_attack_speed;
int value;
int power_id; // for bonus_power_level
BonusData()
: stat_index(-1)
, damage_index_min(-1)
Expand All @@ -63,14 +64,15 @@ class BonusData {
, base_index(-1)
, is_speed(false)
, is_attack_speed(false)
, value(0) {
, value(0)
, power_id(0) {
}
};

class Set_bonus : public BonusData {
class SetBonusData : public BonusData {
public:
int requirement;
Set_bonus()
SetBonusData()
: BonusData()
, requirement(0) {
}
Expand Down Expand Up @@ -142,7 +144,7 @@ class ItemSet {
public:
std::string name; // item set name displayed on long and short tool tips
std::vector<int> items; // items, included into set
std::vector<Set_bonus> bonus;// vector with stats to increase/decrease
std::vector<SetBonusData> bonus;// vector with stats to increase/decrease
Color color;

ItemSet()
Expand Down
23 changes: 15 additions & 8 deletions src/MenuInventory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ FLARE. If not, see http:https://www.gnu.org/licenses/
#include "Menu.h"
#include "MenuActionBar.h"
#include "MenuInventory.h"
#include "MenuManager.h"
#include "MenuPowers.h"
#include "MessageEngine.h"
#include "PowerManager.h"
#include "Settings.h"
Expand Down Expand Up @@ -962,6 +964,9 @@ void MenuInventory::applyEquipment() {
// remove all effects and bonuses added by items
pc->stats.effects.clearItemEffects();

// reset power level bonuses
menu->pow->clearBonusLevels();

applyItemStats();
applyItemSetBonuses();

Expand Down Expand Up @@ -1034,7 +1039,6 @@ void MenuInventory::applyItemStats() {
if (pc->stats.effects.triggered_others)
powers->activateSinglePassive(&pc->stats, item.power);
}

}
}

Expand All @@ -1056,13 +1060,12 @@ void MenuInventory::applyItemSetBonuses() {
}
}
// apply item set bonuses
ItemSet temp_set;
for (unsigned k=0; k<set.size(); k++) {
temp_set = items->item_sets[set[k]];
unsigned bonus_counter = 0;
for (bonus_counter=0; bonus_counter<temp_set.bonus.size(); bonus_counter++) {
if (temp_set.bonus[bonus_counter].requirement > quantity[k]) continue;
applyBonus(&temp_set.bonus[bonus_counter]);
for (size_t i = 0; i < set.size(); ++i) {
ItemSet& temp_set = items->item_sets[set[i]];
for (size_t j = 0; j < temp_set.bonus.size(); ++j) {
if (temp_set.bonus[j].requirement > quantity[i])
continue;
applyBonus(&temp_set.bonus[j]);
}
}
}
Expand Down Expand Up @@ -1091,6 +1094,10 @@ void MenuInventory::applyBonus(const BonusData* bdata) {
else if (bdata->base_index > -1 && static_cast<size_t>(bdata->base_index) < eset->primary_stats.list.size()) {
ed.id = ed.type = eset->primary_stats.list[bdata->base_index].id;
}
else if (bdata->power_id > 0) {
menu->pow->addBonusLevels(bdata->power_id, bdata->value);
return; // don't add item effect
}

pc->stats.effects.addItemEffect(ed, 0, bdata->value);
}
Expand Down
Loading

0 comments on commit 3053f4d

Please sign in to comment.