Gather all enchantment info into a single place

This also resolves several TODO notes about duplicate code and makes cPresetItem::ability an eEnchant
This commit is contained in:
2024-08-28 23:41:36 -04:00
committed by Celtic Minstrel
parent 71a9d11cd0
commit 6965b822dc
22 changed files with 216 additions and 83 deletions

View File

@@ -389,6 +389,7 @@
<ClCompile Include="..\..\..\src\gfx\tiling.cpp" />
<ClCompile Include="..\..\..\src\alchemy.cpp" />
<ClCompile Include="..\..\..\src\damage.cpp" />
<ClCompile Include="..\..\..\src\enchant.cpp" />
<ClCompile Include="..\..\..\src\location.cpp" />
<ClCompile Include="..\..\..\src\mathutil.cpp" />
<ClCompile Include="..\..\..\src\oldstructs.cpp" />

View File

@@ -718,6 +718,7 @@
</ClCompile>
<ClCompile Include="..\..\..\src\alchemy.cpp" />
<ClCompile Include="..\..\..\src\damage.cpp" />
<ClCompile Include="..\..\..\src\enchant.cpp" />
<ClCompile Include="..\..\..\src\location.cpp" />
<ClCompile Include="..\..\..\src\mathutil.cpp" />
<ClCompile Include="..\..\..\src\oldstructs.cpp" />
@@ -955,6 +956,7 @@
</ClInclude>
<ClInclude Include="..\..\..\src\alchemy.hpp" />
<ClInclude Include="..\..\..\src\damage.hpp" />
<ClInclude Include="..\..\..\src\enchant.hpp" />
<ClInclude Include="..\..\..\src\fields.hpp" />
<ClInclude Include="..\..\..\src\global.hpp" />
<ClInclude Include="..\..\..\src\location.hpp" />

View File

@@ -106,6 +106,8 @@
9153C7A01A994A1700D7F8A7 /* SFML.framework in Copy Libraries and Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E218F87F3700E3EA15 /* SFML.framework */; };
915473BF2C7E11B900EB1C94 /* damage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 915473BE2C7E11B900EB1C94 /* damage.cpp */; };
915473C62C7FCDBB00EB1C94 /* alchemy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 915473C52C7FCDBB00EB1C94 /* alchemy.cpp */; };
915473CE2C800AB000EB1C94 /* enchant.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 915473CC2C800AB000EB1C94 /* enchant.hpp */; };
915473CF2C800AB000EB1C94 /* enchant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 915473CD2C800AB000EB1C94 /* enchant.cpp */; };
915AF9E81BBF8B5C008AEF49 /* scrollpane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 919B13A81BBE2B54009905A4 /* scrollpane.cpp */; };
9176FEC71D550EFE006EF694 /* out_legacy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9176FEC01D550EFC006EF694 /* out_legacy.cpp */; };
9176FEC81D550EFE006EF694 /* scen_legacy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9176FEC11D550EFC006EF694 /* scen_legacy.cpp */; };
@@ -694,6 +696,8 @@
915325181A2E37EE000A9A1C /* special_parse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = special_parse.cpp; sourceTree = "<group>"; };
915473BE2C7E11B900EB1C94 /* damage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = damage.cpp; sourceTree = "<group>"; };
915473C52C7FCDBB00EB1C94 /* alchemy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = alchemy.cpp; sourceTree = "<group>"; };
915473CC2C800AB000EB1C94 /* enchant.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = enchant.hpp; sourceTree = "<group>"; };
915473CD2C800AB000EB1C94 /* enchant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = enchant.cpp; sourceTree = "<group>"; };
91574CC323CB97C5004766F8 /* enum_map.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = enum_map.hpp; sourceTree = "<group>"; };
91597A6C1A3BED2D00BE7BF9 /* spell.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = spell.hpp; sourceTree = "<group>"; };
91597A6E1A3BEDC700BE7BF9 /* spell.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = spell.cpp; sourceTree = "<group>"; };
@@ -1335,6 +1339,7 @@
children = (
915473C52C7FCDBB00EB1C94 /* alchemy.cpp */,
915473BE2C7E11B900EB1C94 /* damage.cpp */,
915473CD2C800AB000EB1C94 /* enchant.cpp */,
91279BE10F9D0F73007B0D52 /* location.cpp */,
91B3F11E0F97801F00BF5B67 /* mathutil.cpp */,
915325161A2E1DA8000A9A1C /* oldstructs.cpp */,
@@ -1345,6 +1350,7 @@
91B0D5D01E34428E002BE4DA /* view_dialogs.cpp */,
9185BD9B1EA02B8F0027C346 /* alchemy.hpp */,
9185BD961EA0234A0027C346 /* damage.hpp */,
915473CC2C800AB000EB1C94 /* enchant.hpp */,
9185BD991EA027B80027C346 /* fields.hpp */,
9185BDA01EA02FF80027C346 /* global.hpp */,
91279BE00F9D0F73007B0D52 /* location.hpp */,
@@ -1664,6 +1670,7 @@
9149924E25913E3F00B5BE97 /* led.hpp in Headers */,
9143044B2970EDC1003A3967 /* keymods.hpp in Headers */,
9149925025913E3F00B5BE97 /* ledgroup.hpp in Headers */,
915473CE2C800AB000EB1C94 /* enchant.hpp in Headers */,
91499254259140FF00B5BE97 /* keycodes.hpp in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -2078,6 +2085,7 @@
919CC27E1B37743B00273FDA /* undo.cpp in Sources */,
919CC27F1B37744000273FDA /* winutil.mac.mm in Sources */,
D384F6A32C1B9D4000A806C3 /* replay.cpp in Sources */,
915473CF2C800AB000EB1C94 /* enchant.cpp in Sources */,
915AF9E81BBF8B5C008AEF49 /* scrollpane.cpp in Sources */,
91E128E71BC1E6DD00C8BE1D /* basicbtns.cpp in Sources */,
91E128ED1BC2076B00C8BE1D /* 3choice.cpp in Sources */,

View File

@@ -17,6 +17,17 @@
<xs:enumeration value="hostile-b"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="enchantment">
<xs:restriction base="xs:token">
<xs:enumeration value="+1"/>
<xs:enumeration value="+2"/>
<xs:enumeration value="+3"/>
<xs:enumeration value="+5"/>
<xs:enumeration value="shoot-flame"/>
<xs:enumeration value="flaming"/>
<xs:enumeration value="blessed"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="town">
<xs:complexType>
@@ -129,7 +140,7 @@
<xs:complexType>
<xs:all>
<xs:element name="type" type="xs:integer"/>
<xs:element name="mod" type="xs:integer" minOccurs="0"/>
<xs:element name="mod" type="enchantment" minOccurs="0"/>
<xs:element name="charges" type="xs:integer" minOccurs="0"/>
<xs:element name="always" type="bool" minOccurs="0"/>
<xs:element name="property" type="bool" minOccurs="0"/>
@@ -211,4 +222,4 @@
<xs:field xpath='@id'/>
</xs:unique>
</xs:element>
</xs:schema>
</xs:schema>

76
src/enchant.cpp Normal file
View File

@@ -0,0 +1,76 @@
//
// enchant.cpp
// BoE
//
// Created by Celtic Minstrel on 2023-08-28.
//
//
#include "enchant.hpp"
#include "mathutil.hpp"
std::map<eEnchant, cEnchant> cEnchant::dictionary;
cEnchant::cEnchant(eEnchant id, std::string suf) : id(id), suffix(suf) {}
cEnchant& cEnchant::withCost(short cost) {
aug_cost = cost;
return *this;
}
cEnchant& cEnchant::withBonus(int bonus) {
add_bonus = bonus;
return *this;
}
cEnchant& cEnchant::withAbility(eItemAbil abil, unsigned int stren) {
add_ability = abil;
abil_strength = stren;
return *this;
}
cEnchant& cEnchant::withAbility(eItemAbil abil, unsigned int stren, eSpell spell) {
withAbility(abil, stren);
abil_data.spell = spell;
return *this;
}
cEnchant& cEnchant::withAbility(eItemAbil abil, unsigned int stren, eDamageType dmg) {
withAbility(abil, stren);
abil_data.damage = dmg;
return *this;
}
cEnchant& cEnchant::withAbility(eItemAbil abil, unsigned int stren, eStatus status) {
withAbility(abil, stren);
abil_data.status = status;
return *this;
}
cEnchant& cEnchant::withCharges(int c) {
charges = c;
return *this;
}
const cEnchant& cEnchant::finish() {
dictionary.emplace(id, *this);
return *this;
}
int cEnchant::adjust_value(int initial_value) const {
return max(aug_cost * 100, initial_value * (5 + aug_cost));
}
const cEnchant& operator* (eEnchant ench) {
static cEnchant none{eEnchant::NONE, ""};
if(ench == eEnchant::NONE) return none;
return cEnchant::dictionary.at(ench);
}
cEnchant E_PLUS_ONE = cEnchant(eEnchant::PLUS_ONE, "+1").withCost(4).withBonus(1).finish();
cEnchant E_PLUS_TWO = cEnchant(eEnchant::PLUS_TWO, "+2").withCost(7).withBonus(2).finish();
cEnchant E_PLUS_THREE = cEnchant(eEnchant::PLUS_THREE, "+3").withCost(10).withBonus(3).finish();
cEnchant E_SHOOT_FLAME = cEnchant(eEnchant::SHOOT_FLAME, "F").withCost(8).withAbility(eItemAbil::CAST_SPELL, 5, eSpell::FLAME).withCharges(8).finish();
cEnchant E_FLAMING = cEnchant(eEnchant::FLAMING, "F!").withCost(15).withAbility(eItemAbil::DAMAGING_WEAPON, 5, eDamageType::FIRE).finish();
cEnchant E_PLUS_FIVE = cEnchant(eEnchant::PLUS_FIVE, "+5").withCost(15).withBonus(5).finish();
cEnchant E_BLESSED = cEnchant(eEnchant::BLESSED, "B").withCost(10).withBonus(1).withAbility(eItemAbil::AFFECT_STATUS, 5, eStatus::BLESS_CURSE);

61
src/enchant.hpp Normal file
View File

@@ -0,0 +1,61 @@
//
// enchant.hpp
// BoE
//
// Created by Celtic Minstrel on 2023-08-28.
//
//
#ifndef BoE_ENCHANT_HPP
#define BoE_ENCHANT_HPP
#include <iosfwd>
#include <map>
#include <string>
#include "damage.hpp"
#include "scenario/item_abilities.hpp"
#include "spell.hpp"
enum class eEnchant {
NONE = -1,
PLUS_ONE,
PLUS_TWO,
PLUS_THREE,
SHOOT_FLAME,
FLAMING,
PLUS_FIVE,
BLESSED,
};
class cEnchant {
static std::map<eEnchant, cEnchant> dictionary;
friend const cEnchant& operator* (eEnchant ench);
public:
static const int MAX = int(eEnchant::BLESSED);
cEnchant(eEnchant id, std::string suf);
cEnchant& withCost(short cost);
cEnchant& withBonus(int bonus);
cEnchant& withAbility(eItemAbil abil, unsigned int stren);
cEnchant& withAbility(eItemAbil abil, unsigned int stren, eSpell spell);
cEnchant& withAbility(eItemAbil abil, unsigned int stren, eDamageType dmg);
cEnchant& withAbility(eItemAbil abil, unsigned int stren, eStatus status);
cEnchant& withCharges(int charges);
const cEnchant& finish();
eEnchant id;
std::string suffix;
short aug_cost;
int add_bonus = 0;
eItemAbil add_ability = eItemAbil::NONE;
unsigned int abil_strength = 0;
uItemAbilData abil_data;
int charges = 0;
int adjust_value(int initial_value) const;
};
// Need to declare this a second time in order for it to be in scope where it's needed
const cEnchant& operator* (eEnchant ench);
std::ostream& operator<< (std::ostream& out, eEnchant ench);
std::istream& operator>> (std::istream& in, eEnchant& ench);
#endif

View File

@@ -743,3 +743,18 @@ std::istream& operator>> (std::istream& in, eCreatureStatus& status) {
in.setstate(std::ios::failbit);
return in;
}
// MARK: eEnchant
cEnumLookup enchant_strs = {"+1", "+2", "+3", "shoot-flame", "flaming", "+5", "blessed"};
std::ostream& operator<< (std::ostream& out, eEnchant ench) {
writeEnum(out, ench, enchant_strs, "+1");
return out;
}
std::istream& operator>> (std::istream& in, eEnchant& ench) {
if(!readEnum(in, ench, enchant_strs, eEnchant::NONE))
in.setstate(std::ios::failbit);
return in;
}

View File

@@ -979,7 +979,7 @@ void handle_item_shop_action(short item_hit) {
play_sound(51);
ASB("Your item is now enchanted.");
eEnchant ench = eEnchant(shop_identify_cost);
target.enchant_weapon(ench,store_selling_values[i]);
target.enchant_weapon(ench);
}
break;
case MODE_INVEN: case MODE_SHOP:

View File

@@ -3246,10 +3246,7 @@ void affect_spec(const runtime_state& ctx) {
if(spec.ex1a >= 0 && spec.ex1a < univ.scenario.scen_items.size()) {
cItem to_give = univ.scenario.scen_items[spec.ex1a];
if(spec.ex1b >= 0 && spec.ex1b <= 6) {
// TODO: This array and accompanying calculation is now duplicated here, in start_town_mode(), and in place_buy_button()
const short aug_cost[10] = {4,7,10,8, 15,15,10, 0,0,0};
int val = max(aug_cost[spec.ex1b] * 100, to_give.value * (5 + aug_cost[spec.ex1b]));
to_give.enchant_weapon(eEnchant(spec.ex1b), val);
to_give.enchant_weapon(eEnchant(spec.ex1b));
}
if(to_give.charges > 0 && spec.ex1c >= 0)
to_give.charges = spec.ex1c;

View File

@@ -370,8 +370,6 @@ void place_buy_button(short position,short pc_num,short item_num) {
rectangle dest_rect,source_rect;
rectangle button_sources[3] = {{24,0,36,30},{36,0,48,30},{48,0,60,30}};
short val_to_place;
// TODO: This is now duplicated here and in start_town_mode()
short aug_cost[10] = {4,7,10,8, 15,15,10, 0,0,0};
const cPlayer& pc = univ.party[pc_num];
const cItem& item = pc.items[item_num];
@@ -416,7 +414,7 @@ void place_buy_button(short position,short pc_num,short item_num) {
if((item.variety == eItemType::ONE_HANDED || item.variety == eItemType::TWO_HANDED) && item.ident && item.ability == eItemAbil::NONE && !item.magic) {
item_area_button_active[position][ITEMBTN_SPEC] = true;
source_rect = button_sources[2];
val_to_place = max(aug_cost[shop_identify_cost] * 100, item.value * (5 + aug_cost[shop_identify_cost]));
val_to_place = (*eEnchant(shop_identify_cost)).adjust_value(item.value);
}
break;
case MODE_INVEN: case MODE_SHOP:

View File

@@ -386,18 +386,12 @@ void start_town_mode(short which_town, short entry_dir) {
}
// Not use the items data flags, starting with forcing an ability
if(preset.ability >= 0) {
if(preset.ability != eEnchant::NONE) {
// TODO: What other ways might there be to use this?
switch(item.variety) {
case eItemType::ONE_HANDED:
case eItemType::TWO_HANDED: {
if(preset.ability > int(eEnchant::BLESSED))
break;
// TODO: This array and accompanying calculation is now duplicated here and in place_buy_button()
const short aug_cost[10] = {4,7,10,8, 15,15,10, 0,0,0};
int ench = preset.ability;
int val = max(aug_cost[ench] * 100, item.value * (5 + aug_cost[ench]));
item.enchant_weapon(eEnchant(ench), val);
item.enchant_weapon(preset.ability);
break;
}
default: break; // Silence compiler warning

View File

@@ -348,57 +348,25 @@ cItem::cItem(eAlchemy recipe) : cItem(ITEM_POTION) {
magic_use_type = info.magic_use_type;
}
void cItem::enchant_weapon(eEnchant enchant_type,short new_val) {
void cItem::enchant_weapon(eEnchant enchant_type) {
if(magic || ability != eItemAbil::NONE)
return;
if(variety != eItemType::ONE_HANDED && variety != eItemType::TWO_HANDED)
return;
magic = true;
enchanted = true;
std::string store_name = full_name;
switch(enchant_type) {
case eEnchant::PLUS_ONE:
store_name += " (+1)";
bonus++;
value = new_val;
break;
case eEnchant::PLUS_TWO:
store_name += " (+2)";
bonus += 2;
value = new_val;
break;
case eEnchant::PLUS_THREE:
store_name += " (+3)";
bonus += 3;
value = new_val;
break;
case eEnchant::SHOOT_FLAME:
store_name += " (F)";
ability = eItemAbil::CAST_SPELL;
abil_strength = 5;
abil_data.spell = eSpell::FLAME;
charges = 8;
break;
case eEnchant::FLAMING:
store_name += " (F!)";
value = new_val;
ability = eItemAbil::DAMAGING_WEAPON;
abil_strength = 5;
abil_data.damage = eDamageType::FIRE;
break;
case eEnchant::PLUS_FIVE:
store_name += " (+5)";
value = new_val;
bonus += 5;
break;
case eEnchant::BLESSED:
store_name += " (B)";
bonus++;
ability = eItemAbil::AFFECT_STATUS;
abil_strength = 5;
abil_data.status = eStatus::BLESS_CURSE;
charges = 8;
break;
const cEnchant& info = *enchant_type;
std::string store_name = full_name + " (";
store_name += info.suffix + ")";
bonus += info.add_bonus;
value = info.adjust_value(value);
if(info.add_ability != eItemAbil::NONE) {
ability = info.add_ability;
abil_strength = info.abil_strength;
abil_data = info.abil_data;
}
if(info.charges > 0) {
charges = info.charges;
}
if(value > 15000)
value = 15000;

View File

@@ -17,6 +17,7 @@
#include "item_variety.hpp"
#include "skills_traits.hpp"
#include "alchemy.hpp"
#include "enchant.hpp"
namespace legacy { struct item_record_type; };
@@ -69,7 +70,7 @@ public:
std::string interesting_string() const;
std::string getAbilName() const;
void enchant_weapon(eEnchant enchant_type, short new_val);
void enchant_weapon(eEnchant enchant_type);
bool abil_harms() const;
bool abil_group() const;
bool can_use() const;

View File

@@ -59,8 +59,6 @@ const item_variety_t& operator*(eItemType type);
enum class eItemUse {HELP_ONE, HARM_ONE, HELP_ALL, HARM_ALL};
enum class eEnchant {PLUS_ONE, PLUS_TWO, PLUS_THREE, SHOOT_FLAME, FLAMING, PLUS_FIVE, BLESSED};
std::ostream& operator << (std::ostream& out, eItemUse e);
std::istream& operator >> (std::istream& in, eItemUse& e);
std::ostream& operator << (std::ostream& out, eItemType e);

View File

@@ -226,7 +226,7 @@ short cTown::light_obscurity(short x,short y) const {
cTown::cItem::cItem() {
loc = {80,80};
code = -1;
ability = -1;
ability = eEnchant::NONE;
charges = 0;
always_there = false;
property = false;

View File

@@ -55,7 +55,8 @@ public:
class cItem { // formerly preset_item_type
public:
location loc;
short code,ability;
short code;
eEnchant ability;
int charges = -1;
bool always_there = false, property = false, contained = false;

View File

@@ -767,7 +767,7 @@ void writeTownToXml(ticpp::Printer&& data, cTown& town) {
data.PushElement("type", town.preset_items[i].code);
if(town.preset_items[i].charges > 0)
data.PushElement("charges", town.preset_items[i].charges);
if(town.preset_items[i].ability >= 0)
if(town.preset_items[i].ability != eEnchant::NONE)
data.PushElement("mod", town.preset_items[i].ability);
if(town.preset_items[i].always_there)
data.PushElement("always", true);

View File

@@ -231,8 +231,8 @@ cTownperson edit_placed_monst_adv(cTownperson initial, short which, cDialog& par
static bool put_placed_item_in_dlog(cDialog& me, const cTown::cItem& item, const short which) {
std::ostringstream loc;
cItem base = scenario.scen_items[item.code];
if(item.ability >= 0 && item.ability <= int(eEnchant::BLESSED) && (base.variety == eItemType::ONE_HANDED || base.variety == eItemType::TWO_HANDED)) {
base.enchant_weapon(eEnchant(item.ability), 0);
if(item.ability != eEnchant::NONE && (base.variety == eItemType::ONE_HANDED || base.variety == eItemType::TWO_HANDED)) {
base.enchant_weapon(item.ability);
}
me["num"].setTextToNum(which);
@@ -240,7 +240,7 @@ static bool put_placed_item_in_dlog(cDialog& me, const cTown::cItem& item, const
me["loc"].setText(loc.str());
me["name"].setText(base.full_name);
me["charges"].setTextToNum(item.charges);
me["abil"].setTextToNum(item.ability);
me["abil"].setTextToNum(int(item.ability));
if(item.always_there)
dynamic_cast<cLed&>(me["always"]).setState(led_red);
if(item.property)
@@ -258,7 +258,7 @@ static bool put_placed_item_in_dlog(cDialog& me, const cTown::cItem& item, const
if(base.variety == eItemType::GOLD || base.variety == eItemType::FOOD) {
me["charges-lbl"].setText("Amount:");
} else if(base.charges == 0 && item.ability != 3) {
} else if(base.charges == 0 && (*item.ability).charges == 0) {
me["charges-lbl"].hide();
me["charges"].hide();
} else {
@@ -294,7 +294,8 @@ static bool get_placed_item_in_dlog(cDialog& me, cTown::cItem& item, const short
item.always_there = dynamic_cast<cLed&>(me["always"]).getState() != led_off;
item.property = dynamic_cast<cLed&>(me["owned"]).getState() != led_off;
item.contained = dynamic_cast<cLed&>(me["contained"]).getState() != led_off;
item.ability = me["abil"].getTextAsNum();
int ench = me["abil"].getTextAsNum();
if(ench >= 0 && ench <= cEnchant::MAX) item.ability = eEnchant(ench);
town->preset_items[which] = item;
return true;
@@ -312,13 +313,13 @@ static bool edit_placed_item_type(cDialog& me, cTown::cItem& item, const short w
static bool edit_placed_item_abil(cDialog& me, std::string item_hit, cTown::cItem& item, const short which) {
item.charges = me["charges"].getTextAsNum();
cItem& base = scenario.scen_items[item.code];
short i = item.ability;
short i = short(item.ability);
if(item_hit == "abil") { // User entered a number directly
i = me["abil"].getTextAsNum();
} else if(base.variety == eItemType::ONE_HANDED || base.variety == eItemType::TWO_HANDED) {
i = choose_text(STRT_ENCHANT, item.ability, &me, "Which enchantment?");
i = choose_text(STRT_ENCHANT, i, &me, "Which enchantment?");
}
if(i >= -1) item.ability = i;
if(i >= -1 && i <= cEnchant::MAX) item.ability = eEnchant(i);
put_placed_item_in_dlog(me, item, which);
return true;
}
@@ -961,7 +962,7 @@ static bool check_talk_xtra(cDialog& me, std::stack<node_ref_t>& talk_edit_stack
"Cost adjustment must be from 0 (cheapest) to 6 (most expensive).",
"Which shop must refer to an existing shop (0 - {max}).",
"Quest must be an existing quest (0 - {max}).",
"Enchantment type must be from 0 to 6. See the documentation for a list of possible abilities.",
"Enchantment type must be from 0 to {max}. See the documentation for a list of possible abilities.",
// 10
"The first boat/horse must be in the legal range (0 - {max}).",
"The special item must be in the legal range (0 - {max}).",
@@ -1026,7 +1027,7 @@ static bool check_talk_xtra(cDialog& me, std::stack<node_ref_t>& talk_edit_stack
break;
case eTalkNode::ENCHANT:
if(which == 0) {
lo = 0; hi = 6;
lo = 0; hi = cEnchant::MAX;
msg = 9;
}
break;

View File

@@ -9,6 +9,7 @@ tools = Split("""
replay.cpp
../alchemy.cpp
../damage.cpp
../enchant.cpp
../location.cpp
../mathutil.cpp
../porting.cpp

View File

@@ -86,7 +86,7 @@ TEST_CASE("Converting legacy town data") {
CHECK(town.preset_items[0].loc == loc(7,8));
CHECK(town.preset_items[0].code == 3);
CHECK(town.preset_items[0].charges == 9);
CHECK(town.preset_items[0].ability == -1);
CHECK(town.preset_items[0].ability == eEnchant::NONE);
CHECK(town.preset_items[0].always_there);
CHECK(town.preset_items[0].property);
CHECK(town.preset_items[0].contained);

View File

@@ -169,7 +169,7 @@ TEST_CASE("Loading a town definition") {
CHECK(town->spec_strs[7] == "Here is a town string.");
REQUIRE(town->preset_items.size() >= 3);
CHECK(town->preset_items[2].code == 120);
CHECK(town->preset_items[2].ability == 2);
CHECK(town->preset_items[2].ability == eEnchant::PLUS_THREE);
CHECK(town->preset_items[2].charges == 17);
CHECK(town->preset_items[2].always_there);
CHECK(town->preset_items[2].property);

View File

@@ -108,7 +108,7 @@ TEST_CASE("Saving a town") {
SECTION("With a preset item") {
town->preset_items.emplace_back();
town->preset_items.back().code = 52;
town->preset_items.back().ability = 9;
town->preset_items.back().ability = eEnchant::BLESSED;
town->preset_items.back().charges = 102;
town->preset_items.back().always_there = true;
town->preset_items.back().property = true;
@@ -116,7 +116,7 @@ TEST_CASE("Saving a town") {
in_and_out("item", town, scen);
REQUIRE(town->preset_items.size() >= 1);
CHECK(town->preset_items[0].code == 52);
CHECK(town->preset_items[0].ability == 9);
CHECK(town->preset_items[0].ability == eEnchant::BLESSED);
CHECK(town->preset_items[0].charges == 102);
CHECK(town->preset_items[0].always_there);
CHECK(town->preset_items[0].property);