diff --git a/rsrc/dialogs/edit-item-abils.xml b/rsrc/dialogs/edit-item-abils.xml
index 8d17339a..33a729d8 100644
--- a/rsrc/dialogs/edit-item-abils.xml
+++ b/rsrc/dialogs/edit-item-abils.xml
@@ -2,15 +2,12 @@
diff --git a/rsrc/strings/item-abilities.txt b/rsrc/strings/item-abilities.txt
index 17f1603e..103adfa1 100644
--- a/rsrc/strings/item-abilities.txt
+++ b/rsrc/strings/item-abilities.txt
@@ -1,18 +1,17 @@
-No ability
-Flaming Weapon
-Demon Slayer
-Undead Slayer
-Lizard Slayer
-Giant Slayer
-Mage Slayer
-Priest Slayer
-Bug Slayer
-Acidic Weapon
-Soulsucker
-Drain Missiles
-Weak Weapon
-Causes Fear
-Poisoned Weapon
+Bonus damage of type
+Bonus damage against race
+Heal target
+Explodes
+Returning missile
+Farflight missile
+Seeking missile
+Drain magic from target
+Afflict status on target
+Drain life from target
+Unused
+Weak weapon
+Cause fear
+Call special when attacking
@@ -28,71 +27,36 @@ Poisoned Weapon
-Protection
-Full Protection
-Fire Protection
-Cold Protection
-Poison Protection
-Magic Protection
-Acid Protection
-Skill
-Strength
-Dexterity
-Intelligence
-Accuracy
-Thieving
-Giant Strength
-Lighter Object
-Heavier Object
-Occasional Bless
-Occasional Haste
-Life Saving
-Prot. From Petrify
+Protection from damage type
+Full protection
+Protection from melee damage
+Evasion
+Martyr's shield
+Awkward weapon
+Protection from status effect
+Boost attack skill
+Boost statistic
+Boost combat statistics
+Boost magic statistics
+Boost missile accuracy
+Boost thieving skills
+Giant strength
+Lighter object
+Heavier object
+Occasional status effect
+Call special when attacked
+Life saving
+Protect from petrification
Regenerate
-Poison Augment
-Disease Party
-Will
-Free Action
-Speed
-Slow Wearer
-Protection from Undead
-Protection from Demons
-Prot. from Humanoids
-Prot. from Reptiles
-Prot. from Giants
-Prot. from Disease
-
-
-
-
-
-
-
-Poison Weapon
-Curse/Bless User
-Cure/Cause Poison
-Speed/Slow User
-Add/Lose Invulnerability
-Add/Lose Magic Res.
-Add/Lose Web
-Cause/Cure Disease
-Add/Lose Sanctuary
-Cure/Cause Dumbfound
-Add/Lose Martyr's Shield
-Cure/Cause Sleep
-Cure/Cause Paralysis
-Cure/Cause Acid
-Bliss
-Add/Lose Experience
-Add/Lose Skill Pts.
-Add/Lose Health
-Add/Lose Spell Points
-Doom
-Light
-Stealth
-Firewalk
-Flying
-Major Healing
+Augment weapon poison
+Radiance
+Boost willpower
+Free action
+Boost speed
+Slow wearer
+Protect from race
+Lockpicks
+Drain missiles
@@ -103,37 +67,72 @@ Major Healing
-
-
-
-
-
-Flame
-Fireball
-Firestorm
-Kill
-Ice Bolt
-Slow
-Shockwave
-Dispel Undead
-Dispel Spirit
+Weapon poison
+Affect status effect
+Cast spell
+Bliss/Doom
+Affect experience
+Affect skill points
+Affect health
+Affect spell points
+Affect light level
+Affect party status
+Affect health and poison
+Call special when used
Summoning
-Mass Summoning
-Acid Spray
-Stinking Cloud
-Sleep Field
-Venom
-Shockstorm
-Paralysis
-Web Spell
-Strengthen Target
+Mass summoning
Quickfire
-Mass Charm
-Magic Map
-Dispel Barrier
-Make Ice Wall
-Charm Spell
-Antimagic Cloud
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -151,144 +150,14 @@ Antimagic Cloud
Holly/Toadstool
Comfrey Root
Glowing Nettle
-Crypt Shroom/Wormgr.
+Crypt Shroom/Wormgrass
Asptongue Mold
Ember Flowers
Graymold
Mandrake
Sapphire
Smoky Crystal
-Ressurection Balm
-Lockpicks
-
-
-
-
-
-
-
-
-Returning
-Lightning
-Exploding
-Acid
-Slay Undead
-Slay Demon
-Heal Target
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+Resurrection Balm
diff --git a/src/boe.items.cpp b/src/boe.items.cpp
index 4815ea24..2fbee29a 100644
--- a/src/boe.items.cpp
+++ b/src/boe.items.cpp
@@ -39,24 +39,9 @@ extern sf::RenderWindow mini_map;
extern sf::Texture pc_gworld;
extern cUniverse univ;
-const std::multiset equippable = {
- eItemType::ONE_HANDED, eItemType::TWO_HANDED, eItemType::BOW, eItemType::ARROW, eItemType::THROWN_MISSILE,
- eItemType::TOOL, eItemType::SHIELD, eItemType::ARMOR, eItemType::HELM, eItemType::GLOVES,
- eItemType::SHIELD_2, eItemType::BOOTS, eItemType::RING, eItemType::NECKLACE, eItemType::PANTS,
- eItemType::CROSSBOW, eItemType::BOLTS, eItemType::MISSILE_NO_AMMO,
- // And these are the ones that you can equip two of
- eItemType::ONE_HANDED, eItemType::RING,
-};
-const std::multiset num_hands_to_use = {
- eItemType::ONE_HANDED, eItemType::TWO_HANDED, eItemType::TWO_HANDED, eItemType::SHIELD, eItemType::SHIELD_2,
-};
-
-// For following, if an item of type n is equipped, no other items of type n can be equipped,
-// TODO: Should SHIELD and SHIELD_2 have an entry here?
-std::map excluding_types = {
- {eItemType::BOW, 2}, {eItemType::ARROW, 1}, {eItemType::THROWN_MISSILE, 1},
- {eItemType::CROSSBOW, 2}, {eItemType::BOLTS, 1}, {eItemType::MISSILE_NO_AMMO, 2}
-};
+extern const std::multiset equippable;
+extern const std::multiset num_hands_to_use;
+extern std::map excluding_types;
short selected,item_max = 0;
diff --git a/src/classes/item.cpp b/src/classes/item.cpp
index 4a3d1fd4..37b32e23 100644
--- a/src/classes/item.cpp
+++ b/src/classes/item.cpp
@@ -14,6 +14,27 @@
#include "classes.h"
#include "boe.consts.h" // TODO: If this is needed here, maybe it shouldn't be in the "boe" namespace
#include "oldstructs.h"
+#include "spell.hpp"
+
+extern const std::multiset equippable = {
+ eItemType::ONE_HANDED, eItemType::TWO_HANDED, eItemType::BOW, eItemType::ARROW, eItemType::THROWN_MISSILE,
+ eItemType::TOOL, eItemType::SHIELD, eItemType::ARMOR, eItemType::HELM, eItemType::GLOVES,
+ eItemType::SHIELD_2, eItemType::BOOTS, eItemType::RING, eItemType::NECKLACE, eItemType::PANTS,
+ eItemType::CROSSBOW, eItemType::BOLTS, eItemType::MISSILE_NO_AMMO,
+ // And these are the ones that you can equip two of
+ eItemType::ONE_HANDED, eItemType::RING,
+};
+
+extern const std::multiset num_hands_to_use = {
+ eItemType::ONE_HANDED, eItemType::TWO_HANDED, eItemType::TWO_HANDED, eItemType::SHIELD, eItemType::SHIELD_2,
+};
+
+// For following, if an item of type n is equipped, no other items of type n can be equipped,
+// TODO: Should SHIELD and SHIELD_2 have an entry here?
+std::map excluding_types = {
+ {eItemType::BOW, 2}, {eItemType::ARROW, 1}, {eItemType::THROWN_MISSILE, 1},
+ {eItemType::CROSSBOW, 2}, {eItemType::BOLTS, 1}, {eItemType::MISSILE_NO_AMMO, 2}
+};
unsigned char cItem::rec_treas_class() const {
short tmp = value;
@@ -911,6 +932,295 @@ void cItem::append(legacy::item_record_type& old){
}
}
+std::string cItem::getAbilName() {
+ bool harmful = magic_use_type % 2;
+ bool party = magic_use_type >= 2;
+ std::ostringstream sout;
+ switch(ability) {
+ case eItemAbil::NONE: sout << "No ability"; break;
+ case eItemAbil::HEALING_WEAPON: sout << "Heals target"; break;
+ case eItemAbil::RETURNING_MISSILE: sout << "Returning missile"; break;
+ case eItemAbil::DISTANCE_MISSILE: sout << "Farflight missile"; break;
+ case eItemAbil::SEEKING_MISSILE: sout << "Seeking missile"; break;
+ case eItemAbil::ANTIMAGIC_WEAPON: sout << "Manasucker"; break;
+ case eItemAbil::SOULSUCKER: sout << "Soulsucker"; break;
+ case eItemAbil::DRAIN_MISSILES: sout << "Drain Missiles"; break;
+ case eItemAbil::WEAK_WEAPON: sout << "Weak Weapon"; break;
+ case eItemAbil::CAUSES_FEAR: sout << "Causes Fear"; break;
+ case eItemAbil::WEAPON_CALL_SPECIAL: sout << "Unusual Attack Effect"; break;
+ case eItemAbil::FULL_PROTECTION: sout << "Full Protection"; break;
+ case eItemAbil::MELEE_PROTECTION: sout << "Melee Protection"; break;
+ case eItemAbil::EVASION: sout << "Evasion"; break;
+ case eItemAbil::MARTYRS_SHIELD: sout << "Martyr's Shield"; break;
+ case eItemAbil::ENCUMBERING: sout << "Awkward Weapon"; break;
+ case eItemAbil::SKILL: sout << "Skill"; break;
+ case eItemAbil::BOOST_WAR: sout << "Warrior's Mantle"; break;
+ case eItemAbil::BOOST_MAGIC: sout << "Mage's Mantle"; break;
+ case eItemAbil::ACCURACY: sout << "Accuracy"; break;
+ case eItemAbil::THIEVING: sout << "Thieving"; break;
+ case eItemAbil::GIANT_STRENGTH: sout << "Giant Strength"; break;
+ case eItemAbil::LIGHTER_OBJECT: sout << "Lighter Object"; break;
+ case eItemAbil::HEAVIER_OBJECT: sout << "Heavier Object"; break;
+ case eItemAbil::HIT_CALL_SPECIAL: sout << "Unusual Defense Effect"; break;
+ case eItemAbil::LIFE_SAVING: sout << "Life Saving"; break;
+ case eItemAbil::PROTECT_FROM_PETRIFY: sout << "Protect from Petrify"; break;
+ case eItemAbil::REGENERATE: sout << "Regenerate"; break;
+ case eItemAbil::POISON_AUGMENT: sout << "Poison Augment"; break;
+ case eItemAbil::RADIANT: sout << "Radiance"; break;
+ case eItemAbil::WILL: sout << "Will"; break;
+ case eItemAbil::FREE_ACTION: sout << "Free Action"; break;
+ case eItemAbil::SPEED: sout << "Speed"; break;
+ case eItemAbil::SLOW_WEARER: sout << "Slow Wearer"; break;
+ case eItemAbil::LOCKPICKS: sout << "Lockpicks"; break;
+ case eItemAbil::POISON_WEAPON: sout << "Poison Weapon"; break;
+ case eItemAbil::CALL_SPECIAL: sout << "Unusual Ability"; break;
+ case eItemAbil::QUICKFIRE: sout << "Quickfire"; break;
+ case eItemAbil::HOLLY: sout << "Holly/Toadstool"; break;
+ case eItemAbil::COMFREY: sout << "Comfrey Root"; break;
+ case eItemAbil::NETTLE: sout << "Glowing Nettle"; break;
+ case eItemAbil::WORMGRASS: sout << "Crypt Shroom/Wormgrass"; break;
+ case eItemAbil::ASPTONGUE: sout << "Asptongue Mold"; break;
+ case eItemAbil::EMBERF: sout << "Ember Flower"; break;
+ case eItemAbil::GRAYMOLD: sout << "Graymold"; break;
+ case eItemAbil::MANDRAKE: sout << "Mandrake Root"; break;
+ case eItemAbil::SAPPHIRE: sout << "Sapphire"; break;
+ case eItemAbil::SMOKY_CRYSTAL: sout << "Smoky Crystal"; break;
+ case eItemAbil::RESURRECTION_BALM: sout << "Resurrection Balm"; break;
+ case eItemAbil::DAMAGING_WEAPON:
+ switch(eDamageType(abil_data[1])) {
+ case eDamageType::FIRE: sout << "Flaming"; break;
+ case eDamageType::MAGIC: sout << "Shocking"; break;
+ case eDamageType::COLD: sout << "Frosty"; break;
+ case eDamageType::POISON: sout << "Slimy"; break;
+ case eDamageType::WEAPON: sout << "Enhanced"; break;
+ case eDamageType::UNDEAD: sout << "Necrotic"; break;
+ case eDamageType::DEMON: sout << "Unholy"; break;
+ case eDamageType::UNBLOCKABLE: sout << "Dark"; break;
+ case eDamageType::MARKED: break; // Invalid
+ }
+ sout << " Weapon";
+ break;
+ case eItemAbil::SLAYER_WEAPON:
+ switch(eRace(abil_data[1])) {
+ case eRace::UNKNOWN: break; // Invalid
+ case eRace::DEMON: sout << "Demon"; break;
+ case eRace::UNDEAD: sout << "Undead"; break;
+ case eRace::REPTILE: sout << "Lizard"; break;
+ case eRace::GIANT: sout << "Giant"; break;
+ case eRace::MAGE: sout << "Mage"; break;
+ case eRace::PRIEST: sout << "Priest"; break;
+ case eRace::BUG: sout << "Bug"; break;
+ case eRace::HUMAN: sout << "Human"; break;
+ case eRace::NEPHIL: sout << "Nephil"; break;
+ case eRace::SLITH: sout << "Slith"; break;
+ case eRace::VAHNATAI: sout << "Vahnatai"; break;
+ case eRace::HUMANOID: sout << "Humanoid"; break;
+ case eRace::BEAST: sout << "Beast"; break;
+ case eRace::IMPORTANT: sout << "VIP"; break; // TODO: This one should probably not exist
+ case eRace::SLIME: sout << "Slime"; break;
+ case eRace::STONE: sout << "Golem"; break;
+ case eRace::DRAGON: sout << "Dragon"; break;
+ case eRace::MAGICAL: sout << "Magical Beast"; break;
+ case eRace::PLANT: sout << "Plant"; break;
+ case eRace::BIRD: sout << "Bird"; break;
+ }
+ sout << " Slayer";
+ break;
+ case eItemAbil::EXPLODING_WEAPON:
+ sout << "Explodes ";
+ switch(eDamageType(abil_data[1])) {
+ case eDamageType::FIRE: sout << "in flames"; break;
+ case eDamageType::COLD: sout << "into frost"; break;
+ case eDamageType::MAGIC: sout << "in sparks"; break;
+ case eDamageType::POISON: sout << "into slime"; break;
+ case eDamageType::WEAPON: sout << "in shrapnel"; break;
+ case eDamageType::UNBLOCKABLE: sout << "in darkness"; break;
+ case eDamageType::UNDEAD: sout.str("Implodes"); break;
+ case eDamageType::DEMON: sout << "into corruption"; break;
+ case eDamageType::MARKED: break; // Invalid
+ }
+ break;
+ case eItemAbil::STATUS_WEAPON:
+ switch(eStatus(abil_data[1])) {
+ case eStatus::MAIN: break; // Invalid
+ case eStatus::POISONED_WEAPON:
+ case eStatus::INVULNERABLE:
+ case eStatus::MAGIC_RESISTANCE:
+ case eStatus::INVISIBLE:
+ break; // TODO: Not implemented?
+ case eStatus::ACID: sout << "Acidic"; break;
+ case eStatus::POISON: sout << "Poisoned"; break;
+ case eStatus::BLESS_CURSE: sout << "Cursing"; break;
+ case eStatus::HASTE_SLOW: sout << "Slowing"; break;
+ case eStatus::WEBS: sout << "Webbing"; break;
+ case eStatus::DISEASE: sout << "Infectious"; break;
+ case eStatus::DUMB: sout << "Dumbfounding"; break;
+ case eStatus::MARTYRS_SHIELD: sout << "Martyr Draining"; break;
+ case eStatus::ASLEEP: sout << "Soporific"; break;
+ case eStatus::PARALYZED: sout << "Paralytic"; break;
+ case eStatus::FORCECAGE: sout << "Entrapping"; break;
+ case eStatus::CHARM: sout << "Charming"; break;
+ }
+ sout << " Weapon";
+ break;
+ case eItemAbil::DAMAGE_PROTECTION:
+ switch(eDamageType(abil_data[1])) {
+ case eDamageType::WEAPON: break;
+ case eDamageType::FIRE: sout << "Fire"; break;
+ case eDamageType::COLD: sout << "Cold"; break;
+ case eDamageType::MAGIC: sout << "Magic"; break;
+ case eDamageType::DEMON: sout << "Demon"; break;
+ case eDamageType::UNDEAD: sout << "Undead"; break;
+ case eDamageType::POISON: sout << "Poison"; break;
+ case eDamageType::UNBLOCKABLE: sout << "Darkness"; break;
+ case eDamageType::MARKED: break; // Invalid
+ }
+ sout << " Protection";
+ break;
+ case eItemAbil::STATUS_PROTECTION:
+ sout << "Protect From ";
+ switch(eStatus(abil_data[1])) {
+ case eStatus::MAIN: break; // Invalid;
+ case eStatus::POISONED_WEAPON:
+ case eStatus::INVULNERABLE:
+ case eStatus::MARTYRS_SHIELD:
+ case eStatus::FORCECAGE:
+ case eStatus::CHARM:
+ case eStatus::INVISIBLE:
+ break; // TODO: Not implemented:
+ case eStatus::POISON: sout << "Poison"; break;
+ case eStatus::ACID: sout << "Acid"; break;
+ case eStatus::DISEASE: sout << "Disease"; break;
+ case eStatus::BLESS_CURSE: sout << "Curses"; break;
+ case eStatus::HASTE_SLOW: sout << "Slowing"; break;
+ case eStatus::MAGIC_RESISTANCE: sout << "Magic Vulnerability"; break;
+ case eStatus::WEBS: sout << "Webbing"; break;
+ case eStatus::DUMB: sout << "Dumbfounding"; break;
+ case eStatus::ASLEEP: sout << "Sleep"; break;
+ case eStatus::PARALYZED: sout << "Paralysis"; break;
+ }
+ break;
+ case eItemAbil::BOOST_STAT:
+ sout << get_str("skills", abil_data[1] * 2 + 1);
+ break;
+ case eItemAbil::OCCASIONAL_STATUS:
+ sout << "Occasional ";
+ switch(eStatus(abil_data[1])) {
+ case eStatus::MAIN: break; // Invalid;
+ case eStatus::FORCECAGE:
+ case eStatus::CHARM:
+ break; // TODO: Not implemented?
+ case eStatus::DISEASE: sout << (harmful ? "Disease" : "Cure Disease"); break;
+ case eStatus::HASTE_SLOW: sout << (harmful ? "Slow" : "Haste"); break;
+ case eStatus::BLESS_CURSE: sout << (harmful ? "Curse" : "Bless"); break;
+ case eStatus::POISON: sout << (harmful ? "Poison" : "Cure"); break;
+ case eStatus::WEBS: sout << (harmful ? "Webbing" : "Cleansing"); break;
+ case eStatus::DUMB: sout << (harmful ? "Dumbfounding" : "Enlightening"); break;
+ case eStatus::MARTYRS_SHIELD: sout << (harmful ? "Lose" : "Gain") << " Martyr's Shield"; break;
+ case eStatus::INVULNERABLE: sout << (harmful ? "Lose" : "Gain") << " Invulnerability"; break;
+ case eStatus::MAGIC_RESISTANCE: sout << "Magic " << (harmful ? "Vulnerability" : "Resistance"); break;
+ case eStatus::INVISIBLE: sout << (harmful ? "Lose" : "Gain") << " Sanctuary"; break;
+ case eStatus::POISONED_WEAPON: sout << (harmful ? "Lose" : "Gain") << " Weapon Poison"; break;
+ case eStatus::ASLEEP: sout << (harmful ? "Sleep" : "Hyperactivity"); break;
+ case eStatus::PARALYZED: sout << (harmful ? "Gain" : "Lose") << " Paralysis"; break;
+ case eStatus::ACID: sout << (harmful ? "Gain" : "Neutralize") << " Acid"; break;
+ }
+ sout << (party ? " Party" : " Wearer");
+ break;
+ case eItemAbil::PROTECT_FROM_SPECIES:
+ sout << "Protection from ";
+ switch(eRace(abil_data[1])) {
+ case eRace::UNKNOWN: break; // Invalid
+ case eRace::UNDEAD: sout << "Undead"; break;
+ case eRace::DEMON: sout << "Demons"; break;
+ case eRace::HUMANOID: sout << "Humanoids"; break;
+ case eRace::REPTILE: sout << "Reptiles"; break;
+ case eRace::GIANT: sout << "Giants"; break;
+ case eRace::HUMAN: sout << "Humans"; break;
+ case eRace::NEPHIL: sout << "Nephilim"; break;
+ case eRace::SLITH: sout << "Sliths"; break;
+ case eRace::VAHNATAI: sout << "Vahnatai"; break;
+ case eRace::BEAST: sout << "Beasts"; break;
+ case eRace::IMPORTANT: sout << "VIPs"; break;
+ case eRace::MAGE: sout << "Mages"; break;
+ case eRace::PRIEST: sout << "Priests"; break;
+ case eRace::SLIME: sout << "Slimes"; break;
+ case eRace::STONE: sout << "Golems"; break;
+ case eRace::BUG: sout << "Bugs"; break;
+ case eRace::DRAGON: sout << "Dragons"; break;
+ case eRace::MAGICAL: sout << "Magical Beasts"; break;
+ case eRace::PLANT: sout << "Plants"; break;
+ case eRace::BIRD: sout << "Birds"; break;
+ }
+ break;
+ case eItemAbil::AFFECT_STATUS:
+ switch(eStatus(abil_data[1])) {
+ case eStatus::MAIN: break; // Invalid;
+ case eStatus::FORCECAGE: break;
+ case eStatus::CHARM: break;
+ case eStatus::POISONED_WEAPON: sout << (harmful ? "Increase" : "Decrease") << " Weapon Poison"; break;
+ case eStatus::BLESS_CURSE: sout << (harmful ? "Curse" : "Bless"); break;
+ case eStatus::POISON: sout << (harmful ? "Cause" : "Cure") << " Poison"; break;
+ case eStatus::HASTE_SLOW: sout << (harmful ? "Slow" : "Haste"); break;
+ case eStatus::INVULNERABLE: sout << (harmful ? "Lose" : "Add") << " Invulnerability"; break;
+ case eStatus::MAGIC_RESISTANCE: sout << (harmful ? "Lose" : "Add") << " Magic Resistance"; break;
+ case eStatus::WEBS: sout << (harmful ? "Lose" : "Add") << "Webs"; break;
+ case eStatus::DISEASE: sout << (harmful ? "Cause" : "Cure") << " Disease"; break;
+ case eStatus::INVISIBLE: sout << (harmful ? "Lose" : "Add") << " Sanctuary"; break;
+ case eStatus::DUMB: sout << (harmful ? "Add" : "Lose") << " Dumbfounding"; break;
+ case eStatus::MARTYRS_SHIELD: sout << (harmful ? "Lose" : "Add") << " Martyr's Shield"; break;
+ case eStatus::ASLEEP: sout << (harmful ? "Cause" : "Cure") << " Sleep"; break;
+ case eStatus::PARALYZED: sout << (harmful ? "Cause" : "Cure") << " Paralysis"; break;
+ case eStatus::ACID: sout << (harmful ? "Cause" : "Cure") << " Acid"; break;
+ }
+ break;
+ case eItemAbil::CAST_SPELL:
+ sout << "Spell: " << (*cSpell::fromNum(abil_data[1])).name();
+ break;
+ case eItemAbil::BLISS_DOOM:
+ if(magic_use_type >= 2)
+ sout << "Party ";
+ sout << (harmful ? "Doom" : "Bliss");
+ break;
+ case eItemAbil::AFFECT_EXPERIENCE:
+ sout << (harmful ? "Drain" : "Gain") << " Experience";
+ break;
+ case eItemAbil::AFFECT_SKILL_POINTS:
+ sout << (harmful ? "Drain" : "Gain") << " Skill Points";
+ break;
+ case eItemAbil::AFFECT_HEALTH:
+ sout << (harmful ? "Drain Health" : "Heal");
+ break;
+ case eItemAbil::AFFECT_SPELL_POINTS:
+ sout << (harmful ? "Drain" : "Restore") << " Spell Points";
+ break;
+ case eItemAbil::LIGHT:
+ sout << (harmful ? "Drain" : "Increase") << " Light";
+ break;
+ case eItemAbil::AFFECT_PARTY_STATUS:
+ sout << (harmful ? "Lose " : "Gain ");
+ switch(ePartyStatus(abil_data[1])) {
+ case ePartyStatus::STEALTH: sout << "Stealth"; break;
+ case ePartyStatus::FLIGHT: sout << "Flight"; break;
+ case ePartyStatus::DETECT_LIFE: sout << "Life Detection"; break;
+ case ePartyStatus::FIREWALK: sout << "Firewalk"; break;
+ }
+ break;
+ case eItemAbil::HEALTH_POISON:
+ sout << "Major " << (harmful ? "Poison" : "Healing");
+ if(party) sout << " All";
+ break;
+ case eItemAbil::SUMMONING:
+ // TODO: Figure out a way to wedge the monster name in here.
+ sout << "Summons " << "monst-names";
+ break;
+ case eItemAbil::MASS_SUMMONING:
+ sout << "Mass summon " << "monst-names";
+ break;
+ }
+ return sout.str();
+}
+
void cItem::writeTo(std::ostream& file, std::string prefix) const {
file << prefix << "VARIETY " << variety << '\n';
file << prefix << "LEVEL " << item_level << '\n';
diff --git a/src/classes/item.h b/src/classes/item.h
index bede6636..f22c2a3d 100644
--- a/src/classes/item.h
+++ b/src/classes/item.h
@@ -53,6 +53,8 @@ public:
unsigned char rec_treas_class() const;
short item_weight() const;
+ std::string getAbilName();
+
cItem();
explicit cItem(long preset);
explicit cItem(eAlchemy recipe);
diff --git a/src/classes/simpletypes.h b/src/classes/simpletypes.h
index 52aaf4a9..db92daec 100644
--- a/src/classes/simpletypes.h
+++ b/src/classes/simpletypes.h
@@ -309,10 +309,8 @@ inline bool isArmourType(eItemType type) {
}
inline bool isWeaponType(eItemType type) {
- if(type == eItemType::CROSSBOW || type == eItemType::BOLTS)
- return true;
int code = (int) type;
- return code >= 1 && code <= 6 && code != 3;
+ return (code >= 1 && code <= 6 && code != 3) || (code >= 23 && code <= 25);
}
/* items[i].ability */
@@ -329,7 +327,7 @@ enum class eItemAbil {
ANTIMAGIC_WEAPON = 8,
STATUS_WEAPON = 9,
SOULSUCKER = 10,
- DRAIN_MISSILES = 11,
+ UNUSED = 11,
WEAK_WEAPON = 12,
CAUSES_FEAR = 13,
WEAPON_CALL_SPECIAL = 14,
@@ -362,8 +360,10 @@ enum class eItemAbil {
SPEED = 55,
SLOW_WEARER = 56,
PROTECT_FROM_SPECIES = 57,
+ LOCKPICKS = 58,
+ DRAIN_MISSILES = 59,
// Usable
- POISON_WEAPON = 70, //put poison on weapon
+ POISON_WEAPON = 70,
AFFECT_STATUS = 71,
CAST_SPELL = 72,
BLISS_DOOM = 73,
@@ -390,7 +390,6 @@ enum class eItemAbil {
SAPPHIRE = 158,
SMOKY_CRYSTAL = 159,
RESURRECTION_BALM = 160,
- LOCKPICKS = 161,
};
enum class eItemAbilCat {
@@ -535,7 +534,7 @@ enum class eSpecType {
DISPLAY_PICTURE = 24,
REST = 25,
WANDERING_WILL_FIGHT = 26,
- END_SCENARIO = 27,
+ END_SCENARIO = 27, // add "win/lose" option
SET_POINTER = 28,
SET_CAMP_FLAG = 29,
PRINT_NUMS = 30, // For debugging
@@ -666,7 +665,7 @@ enum class eSpecType {
OUT_MAKE_WANDER = 225,
UNUSED20 = 226,
OUT_PLACE_ENCOUNTER = 227,
- OUT_MOVE_PARTY = 228,
+ OUT_MOVE_PARTY = 228, // allow change sector
};
enum class eSpecCat {
diff --git a/src/classes/spell.cpp b/src/classes/spell.cpp
index 2ab0e67f..f1e3fa03 100644
--- a/src/classes/spell.cpp
+++ b/src/classes/spell.cpp
@@ -56,6 +56,7 @@ const cSpell& cSpell::finish() {
}
std::string cSpell::name() const {
+ if(num == eSpell::NONE) return "INVALID SPELL";
return get_str("magic-names", int(num) + 1);
}
@@ -77,6 +78,13 @@ eSpell cSpell::fromNum(eSkill type, int num) {
return eSpell::NONE;
}
+eSpell cSpell::fromNum(int num) {
+ eSpell check = eSpell(num);
+ if(dictionary.find(check) == dictionary.end())
+ return eSpell::NONE;
+ return check;
+}
+
// Mage Spells
cSpell M_LIGHT = cSpell(eSpell::LIGHT).asType(eSkill::MAGE_SPELLS).asLevel(1)
.withCost(1).when(WHEN_COMBAT).when(WHEN_TOWN).when(WHEN_OUTDOORS).finish();
diff --git a/src/classes/spell.hpp b/src/classes/spell.hpp
index ed9db5e6..ee8cbe7d 100644
--- a/src/classes/spell.hpp
+++ b/src/classes/spell.hpp
@@ -42,6 +42,7 @@ public:
std::string name() const;
bool is_priest() const;
static eSpell fromNum(eSkill type, int num);
+ static eSpell fromNum(int num);
};
// Need to declare this a second time in order for it to be in scope where it's needed
diff --git a/src/dialogxml/button.cpp b/src/dialogxml/button.cpp
index 56e9611d..a5d772f7 100644
--- a/src/dialogxml/button.cpp
+++ b/src/dialogxml/button.cpp
@@ -478,6 +478,7 @@ std::string cLedGroup::getPrevSelection(){
}
void cLedGroup::draw(){
+ if(!visible) return;
ledIter iter = choices.begin();
while(iter != choices.end()){
iter->second->draw();
diff --git a/src/scenedit/scen.core.cpp b/src/scenedit/scen.core.cpp
index 283de6ff..53f3c87f 100644
--- a/src/scenedit/scen.core.cpp
+++ b/src/scenedit/scen.core.cpp
@@ -34,6 +34,13 @@ extern cSpecial null_spec_node;
extern cSpeech null_talk_node;
extern location cur_out;
extern short start_volume, start_dir;
+extern const std::multiset equippable;
+
+const std::set items_no_strength = {
+ eItemAbil::NONE, eItemAbil::HEALING_WEAPON, eItemAbil::RETURNING_MISSILE, eItemAbil::SEEKING_MISSILE, eItemAbil::DRAIN_MISSILES,
+ eItemAbil::LIGHTER_OBJECT, eItemAbil::HEAVIER_OBJECT, eItemAbil::LIFE_SAVING, eItemAbil::POISON_AUGMENT,
+ eItemAbil::QUICKFIRE,
+};
static bool save_ter_info(cDialog& me, cTerrain& store_ter) {
@@ -879,6 +886,7 @@ static bool edit_monst_abil_detail(cDialog& me, std::string hit, cMonster& monst
std::map::iterator iter;
if(me[hit].getText() == "Add") {
int i = choose_text_res("monster-abilities", 1, 70, 0, &me, "Select an ability to add.");
+ if(i < 0) return true;
eMonstAbilTemplate tmpl = eMonstAbilTemplate(i);
int param = 0;
switch(tmpl) {
@@ -982,13 +990,14 @@ static bool edit_monst_abil_detail(cDialog& me, std::string hit, cMonster& monst
if(cat == eMonstAbilCat::MISSILE) first = 110, last = 117;
else if(cat == eMonstAbilCat::GENERAL) first = 120, last = 124;
else if(cat == eMonstAbilCat::SUMMON) first = 150, last = 152;
- abil_dlg["pick-subtype"].attachClickHandler([&,cat](cDialog& me,std::string,eKeyMod) -> bool {
+ abil_dlg["pick-subtype"].attachClickHandler([&,cat,first,last](cDialog& me,std::string,eKeyMod) -> bool {
save_monst_abil_detail(me, abil, abil_params);
int i = 0;
if(cat == eMonstAbilCat::MISSILE) i = int(abil_params.missile.type);
else if(cat == eMonstAbilCat::GENERAL) i = int(abil_params.gen.type);
else if(cat == eMonstAbilCat::SUMMON) i = int(abil_params.summon.type);
i = choose_text_res("monster-abilities", first, last, i + first, &me, "Select ability subtype:");
+ if(i < 0) return true;
if(cat == eMonstAbilCat::MISSILE) abil_params.missile.type = eMonstMissile(i);
else if(cat == eMonstAbilCat::GENERAL) abil_params.gen.type = eMonstGen(i);
else if(cat == eMonstAbilCat::SUMMON) abil_params.summon.type = eMonstSummon(i);
@@ -1250,6 +1259,7 @@ static void put_item_info_in_dlog(cDialog& me, cItem& store_item, short which_it
me["value"].setTextToNum(store_item.value);
me["weight"].setTextToNum(store_item.weight);
me["class"].setTextToNum(store_item.special_class);
+ me["abilname"].setText(store_item.getAbilName());
}
static void save_item_info(cDialog& me, cItem& store_item, short which_item) {
@@ -1359,6 +1369,7 @@ static bool edit_item_type_event_filter(cDialog& me, std::string item_hit, cItem
if(i < 0) return true;
store_item.missile = i;
} else if(item_hit == "abils") {
+ save_item_info(me, store_item, store_which_item);
if(store_item.variety == eItemType::NO_ITEM) {
giveError("You must give the item a type (weapon, armor, etc.) before you can choose its abilities.","",&me);
return true;
@@ -1367,7 +1378,7 @@ static bool edit_item_type_event_filter(cDialog& me, std::string item_hit, cItem
giveError("Gold, Food, and Special Items cannot be given special abilities.","",&me);
return true;
}
- temp_item = edit_item_abil(store_item,store_which_item);
+ temp_item = edit_item_abil(store_item,store_which_item,me);
if(temp_item.variety != eItemType::NO_ITEM)
store_item = temp_item;
}
@@ -1433,129 +1444,226 @@ static void put_item_abils_in_dlog(cDialog& me, cItem& store_item, short which_i
me["num"].setTextToNum(which_item);
me["name"].setText(store_item.full_name.c_str());
- me["variety"].setText(get_str("item-types", (int)store_item.variety));
- me["abilname"].setText(get_str("item-abilities", int(store_item.ability) + 1));
+ me["variety"].setText(get_str("item-types", int(store_item.variety) + 1));
+ if(store_item.ability == eItemAbil::NONE)
+ me["abilname"].setText("No ability");
+ else me["abilname"].setText(get_str("item-abilities", int(store_item.ability)));
dynamic_cast(me["use-type"]).setSelected("use" + std::to_string(store_item.magic_use_type));
dynamic_cast(me["treasure"]).setSelected("type" + std::to_string(store_item.treas_class));
- me["str"].setTextToNum(store_item.abil_data[0]);
+ me["str1"].setTextToNum(store_item.abil_data[0]);
+ me["str2"].setTextToNum(store_item.abil_data[1]);
+
+ if(store_item.ability == eItemAbil::CALL_SPECIAL || store_item.ability == eItemAbil::WEAPON_CALL_SPECIAL || store_item.ability == eItemAbil::HIT_CALL_SPECIAL) {
+ me["str1-choose"].show();
+ me["str1-title"].setText("Special to call");
+ } else {
+ me["str1-choose"].hide();
+ if(getItemAbilCategory(store_item.ability) == eItemAbilCat::REAGENT || items_no_strength.count(store_item.ability) > 0)
+ me["str1-title"].setText("Unused");
+ else me["str1-title"].setText("Ability strength");
+ }
+
+ me["str2-choose1"].show();
+ me["str2-choose1"].setText("Choose");
+ me["str2-choose2"].hide();
+ switch(store_item.ability) {
+ case eItemAbil::DAMAGING_WEAPON:
+ case eItemAbil::EXPLODING_WEAPON:
+ case eItemAbil::DAMAGE_PROTECTION:
+ me["str2-title"].setText("Type of damage");
+ break;
+ case eItemAbil::STATUS_WEAPON:
+ case eItemAbil::STATUS_PROTECTION:
+ case eItemAbil::OCCASIONAL_STATUS:
+ case eItemAbil::AFFECT_STATUS:
+ case eItemAbil::AFFECT_PARTY_STATUS:
+ me["str2-title"].setText("Which status effect");
+ break;
+ case eItemAbil::SLAYER_WEAPON:
+ case eItemAbil::PROTECT_FROM_SPECIES:
+ me["str2-title"].setText("Which species");
+ break;
+ case eItemAbil::BOOST_STAT:
+ me["str2-title"].setText("Which statistic");
+ break;
+ case eItemAbil::CAST_SPELL:
+ me["str2-title"].setText("Which spell");
+ me["str2-choose1"].setText("Mage");
+ me["str2-choose2"].show();
+ break;
+ case eItemAbil::SUMMONING:
+ case eItemAbil::MASS_SUMMONING:
+ me["str2-title"].setText("Which monster");
+ break;
+ default:
+ me["str2-title"].setText("Unused");
+ me["str2-choose1"].hide();
+ break;
+ }
+
+ if((store_item.ability >= eItemAbil::BLISS_DOOM && store_item.ability <= eItemAbil::HEALTH_POISON) || store_item.ability == eItemAbil::AFFECT_STATUS || store_item.ability == eItemAbil::OCCASIONAL_STATUS) {
+ me["use-title"].show();
+ me["use-type"].show();
+ } else {
+ me["use-title"].hide();
+ me["use-type"].hide();
+ }
dynamic_cast(me["always-id"]).setState(store_item.ident ? led_red : led_off);
dynamic_cast(me["magic"]).setState(store_item.magic ? led_red : led_off);
dynamic_cast(me["cursed"]).setState(store_item.cursed ? led_red : led_off);
dynamic_cast(me["conceal"]).setState(store_item.concealed ? led_red : led_off);
+ dynamic_cast(me["no-sell"]).setState(store_item.unsellable ? led_red : led_off);
}
-static bool save_item_abils(cDialog& me, cItem& store_item) {
+static void save_item_abils(cDialog& me, cItem& store_item) {
store_item.magic_use_type = boost::lexical_cast(dynamic_cast(me["use-type"]).getSelected().substr(3));
store_item.treas_class = boost::lexical_cast(dynamic_cast(me["treasure"]).getSelected().substr(4));
- store_item.abil_data[0] = me["str"].getTextAsNum();
+ store_item.abil_data[0] = me["str1"].getTextAsNum();
+ store_item.abil_data[1] = me["str2"].getTextAsNum();
store_item.property = store_item.enchanted = store_item.contained = false;
store_item.ident = dynamic_cast(me["always-id"]).getState() != led_off;
store_item.magic = dynamic_cast(me["magic"]).getState() != led_off;
- store_item.cursed = store_item.unsellable = dynamic_cast(me["cursed"]).getState() != led_off;
+ store_item.cursed = dynamic_cast(me["cursed"]).getState() != led_off;
+ store_item.unsellable = dynamic_cast(me["no-sell"]).getState() != led_off;
store_item.concealed = dynamic_cast(me["conceal"]).getState() != led_off;
- return true;
}
static bool edit_item_abil_event_filter(cDialog& me, std::string item_hit, cItem& store_item, short which_item) {
short i;
if(item_hit == "cancel") {
- store_item.ability = eItemAbil::NONE;
+ store_item.variety = eItemType::NO_ITEM;
me.toast(false);
return true;
} else if(item_hit == "okay") {
- if(save_item_abils(me, store_item)) {
- me.toast(true);
- return true;
+ save_item_abils(me, store_item);
+ me.toast(true);
+ } else if(item_hit == "str1-choose") {
+ save_item_abils(me, store_item);
+ short spec = me["str1"].getTextAsNum();
+ if(spec < 0 || spec > 255) {
+ spec = get_fresh_spec(0);
+ if(spec < 0) {
+ giveError("You can't create a new scenario special encounter because there are no more free special nodes.",
+ "To free a special node, set its type to No Special and set its Jump To special to -1.", &me);
+ return true;
+ }
}
+ if(edit_spec_enc(spec,0,&me)) {
+ store_item.abil_data[0] = spec;
+ me["str1"].setTextToNum(spec);
+ }
+ } else if(item_hit == "str2-choose1") {
+ save_item_abils(me, store_item);
+ i = store_item.abil_data[1];
+ switch(store_item.ability) {
+ case eItemAbil::DAMAGING_WEAPON:
+ case eItemAbil::EXPLODING_WEAPON:
+ case eItemAbil::DAMAGE_PROTECTION:
+ i = choose_damage_type(i, &me);
+ break;
+ case eItemAbil::STATUS_WEAPON:
+ case eItemAbil::STATUS_PROTECTION:
+ case eItemAbil::OCCASIONAL_STATUS:
+ case eItemAbil::AFFECT_STATUS:
+ case eItemAbil::AFFECT_PARTY_STATUS:
+ i = choose_status_effect(i, store_item.ability == eItemAbil::AFFECT_PARTY_STATUS, &me);
+ break;
+ case eItemAbil::SLAYER_WEAPON:
+ case eItemAbil::PROTECT_FROM_SPECIES:
+ i = choose_text(STRT_RACE, i, &me, "Which species?");
+ break;
+ case eItemAbil::BOOST_STAT:
+ i = choose_text(STRT_SKILL, i, &me, "Boost which skill?");
+ break;
+ case eItemAbil::CAST_SPELL:
+ i = choose_text_res("magic-names", 1, 73, i + 1, &me, "Which mage spell?");
+ if(i < 0) return true;
+ break;
+ case eItemAbil::SUMMONING:
+ case eItemAbil::MASS_SUMMONING:
+ i = choose_text(STRT_MONST, i, &me, "Summon which monster type?");
+ break;
+ default: return true;
+ }
+ store_item.abil_data[1] = i;
+ me["str2"].setTextToNum(i);
+ } else if(item_hit == "str2-choose2") {
+ save_item_abils(me, store_item);
+ i = 100 + choose_text_res("magic-names", 101, 166, store_item.abil_data[1] + 1, &me, "Which priest spell?");
+ if(i < 100) return true;
+ store_item.abil_data[1] = i;
+ me["str2"].setTextToNum(i);
+ } else if(item_hit == "clear") {
+ save_item_abils(me, store_item);
+ store_item.ability = eItemAbil::NONE;
+ put_item_abils_in_dlog(me, store_item, which_item);
} else if(item_hit == "weapon") {
- if(!save_item_abils(me, store_item)) return true;
- if(store_item.variety != eItemType::ONE_HANDED && store_item.variety != eItemType::TWO_HANDED) {
- giveError("You can only give an ability of this sort to a melee weapon.","",&me);
+ save_item_abils(me, store_item);
+ if(!isWeaponType(store_item.variety)) {
+ giveError("You can only give an ability of this sort to a weapon.","",&me);
return true;
}
- i = choose_text_res("item-abilities", 0, 14, int(store_item.ability), &me, "Choose Weapon Ability (inherent)");
- if(i >= 0) store_item.ability = eItemAbil(i);
- else store_item.ability = eItemAbil::NONE;
+ i = choose_text_res("item-abilities", 1, 14, int(store_item.ability), &me, "Choose Weapon Ability (inherent)");
+ if(i < 0) return true;
+ eItemAbil abil = eItemAbil(i + 1);
+ if(abil >= eItemAbil::RETURNING_MISSILE && abil <= eItemAbil::SEEKING_MISSILE) {
+ if(store_item.variety != eItemType::THROWN_MISSILE && store_item.variety != eItemType::ARROW &&
+ store_item.variety != eItemType::BOLTS && store_item.variety != eItemType::MISSILE_NO_AMMO) {
+ giveError("You can only give this ability to a missile.",&me);
+ return true;
+ }
+ }
+ store_item.ability = abil;
put_item_abils_in_dlog(me, store_item, which_item);
} else if(item_hit == "general") {
- if(!save_item_abils(me, store_item)) return true;
- if((store_item.variety == eItemType::ARROW) || (store_item.variety == eItemType::THROWN_MISSILE)|| (store_item.variety == eItemType::POTION) || (store_item.variety == eItemType::SCROLL) ||
- (store_item.variety == eItemType::WAND) || (store_item.variety == eItemType::TOOL) || (store_item.variety == eItemType::WEAPON_POISON) ||
- (store_item.variety == eItemType::NON_USE_OBJECT) || (store_item.variety == eItemType::BOLTS)){
- giveError("You can only give an ability of this sort to an non-missile item which can be equipped (like armor, or a ring).","",&me);
+ save_item_abils(me, store_item);
+ if(equippable.count(store_item.variety) == 0 || store_item.variety == eItemType::ARROW || store_item.variety == eItemType::THROWN_MISSILE || store_item.variety == eItemType::BOLTS){
+ giveError("You can only give an ability of this sort to an non-missile item which can be equipped (like armor, or a ring).",&me);
return true;
}
- i = choose_text_res("item-abilities", 30, 62, int(store_item.ability), &me, "Choose General Ability (inherent)");
- if(i >= 0) store_item.ability = eItemAbil(i + 30);
- else store_item.ability = eItemAbil::NONE;
+ i = choose_text_res("item-abilities", 30, 58, int(store_item.ability), &me, "Choose General Ability (inherent)");
+ if(i < 0) return true;
+ store_item.ability = eItemAbil(i + 30);
put_item_abils_in_dlog(me, store_item, which_item);
} else if(item_hit == "usable") {
- if(!save_item_abils(me, store_item)) return true;
+ save_item_abils(me, store_item);
if((store_item.variety == eItemType::ARROW) || (store_item.variety == eItemType::THROWN_MISSILE) || (store_item.variety == eItemType::BOLTS)){
- giveError("You can only give an ability of this sort to an item which isn't a missile.","",&me);
+ giveError("You can't give an ability of this sort to a missile.",&me);
return true;
}
- i = choose_text_res("item-abilities", 70, 94, int(store_item.ability), &me, "Choose Usable Ability (Not spell)");
- if(i >= 0) store_item.ability = eItemAbil(i + 70);
- else store_item.ability = eItemAbil::NONE;
- put_item_abils_in_dlog(me, store_item, which_item);
- } else if(item_hit == "spell") {
- if(!save_item_abils(me,store_item)) return true;
- if((store_item.variety == eItemType::ARROW) || (store_item.variety == eItemType::THROWN_MISSILE) || (store_item.variety == eItemType::BOLTS)){
- giveError("You can only give an ability of this sort to an item which isn't a missile.","",&me);
- return true;
- }
- i = choose_text_res("item-abilities", 110, 135, int(store_item.ability), &me, "Choose Usable Ability (Spell)");
- if(i >= 0) store_item.ability = eItemAbil(i + 110);
- else store_item.ability = eItemAbil::NONE;
+ i = choose_text_res("item-abilities", 70, 84, int(store_item.ability), &me, "Choose Usable Ability");
+ if(i < 0) return true;
+ store_item.ability = eItemAbil(i + 70);
put_item_abils_in_dlog(me, store_item, which_item);
} else if(item_hit == "reagent") {
- if(!save_item_abils(me, store_item)) return true;
- // TODO: Some of these should also be applicable to tools, as I recall?
+ save_item_abils(me, store_item);
if(store_item.variety != eItemType::NON_USE_OBJECT){
- giveError("You can only give an ability of this sort to an item of type Non-Use Object.","",&me);
+ giveError("You can only give an ability of this sort to an item of type Non-Use Object.",&me);
return true;
}
- i = choose_text_res("item-abilities", 150, 161, int(store_item.ability), &me, "Choose Reagent Ability");
- if(i >= 0) store_item.ability = eItemAbil(i + 150);
- else store_item.ability = eItemAbil::NONE;
+ i = choose_text_res("item-abilities", 150, 160, int(store_item.ability), &me, "Choose Reagent Ability");
+ if(i < 0) return true;
+ store_item.ability = eItemAbil(i + 150);
put_item_abils_in_dlog(me, store_item, which_item);
- } else if(item_hit == "missile") {
- if(!save_item_abils(me,store_item)) return true;
- if((store_item.variety == eItemType::ARROW) || (store_item.variety == eItemType::THROWN_MISSILE) || (store_item.variety == eItemType::BOLTS)){
- giveError("You can only give an ability of this sort to an item which isn't a missile.","",&me);
- return true;
- }
- i = choose_text_res("item-abilities", 170, 176, int(store_item.ability), &me, "Choose Missile Ability");
- if(i >= 0) store_item.ability = eItemAbil(i + 170);
- else store_item.ability = eItemAbil::NONE;
- put_item_abils_in_dlog(me, store_item, which_item);
- }
- using namespace std::placeholders;
- if(store_item.ability != eItemAbil::SUMMONING && store_item.ability != eItemAbil::MASS_SUMMONING) {
- me["str"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 10, "Ability Strength"));
- } else {
- me["str"].attachFocusHandler(std::bind(check_range_msg, _1,_2,_3, 0,255, "Ability Strength","the number of the monster to summon"));
}
return true;
}
-cItem edit_item_abil(cItem starting_record,short which_item) {
+cItem edit_item_abil(cItem starting_record,short which_item,cDialog& parent) {
using namespace std::placeholders;
cItem store_item = starting_record;
- cDialog item_dlg("edit-item-abils");
- if(store_item.ability != eItemAbil::SUMMONING && store_item.ability != eItemAbil::MASS_SUMMONING) {
- item_dlg["str"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 10, "Ability Strength"));
- } else {
- item_dlg["str"].attachFocusHandler(std::bind(check_range_msg,_1,_2,_3, 0,255, "Ability Strength","the number of the monster to summon"));
- }
- item_dlg.attachClickHandlers(std::bind(edit_item_abil_event_filter, _1, _2, std::ref(store_item), which_item), {"okay", "cancel", "weapon", "general", "usable", "missile", "reagent", "spell"});
+ cDialog item_dlg("edit-item-abils",&parent);
+ item_dlg.attachClickHandlers(std::bind(edit_item_abil_event_filter, _1, _2, std::ref(store_item), which_item), {
+ "okay", "cancel",
+ "clear", "weapon", "general", "usable", "reagent",
+ "str1-choose", "str2-choose1", "str2-choose2",
+ });
put_item_abils_in_dlog(item_dlg, store_item, which_item);
diff --git a/src/scenedit/scen.core.h b/src/scenedit/scen.core.h
index 66c1468c..bfa8d602 100644
--- a/src/scenedit/scen.core.h
+++ b/src/scenedit/scen.core.h
@@ -6,7 +6,7 @@ short edit_ter_type(ter_num_t which_ter);
short edit_monst_type(short which_monst);
cMonster edit_monst_abil(cMonster starting_record,short which_monst,cDialog& parent);
short edit_item_type(short which_item);
-cItem edit_item_abil(cItem starting_record,short parent_num);
+cItem edit_item_abil(cItem starting_record,short which_item,cDialog& parent);
void edit_spec_item(short which_item);
void edit_save_rects();
void edit_horses();
diff --git a/src/scenedit/scen.keydlgs.cpp b/src/scenedit/scen.keydlgs.cpp
index f876a86f..0d5fd33c 100644
--- a/src/scenedit/scen.keydlgs.cpp
+++ b/src/scenedit/scen.keydlgs.cpp
@@ -131,8 +131,8 @@ pic_num_t choose_graphic(short cur_choice,ePicType g_type,cDialog* parent) {
short choose_text_res(std::string res_list,short first_t,short last_t,unsigned short cur_choice,cDialog* parent,const char *title) {
location view_loc;
if((cur_choice < first_t) || (cur_choice > last_t))
- cur_choice = first_t;
- cur_choice -= first_t;
+ cur_choice = -1;
+ else cur_choice -= first_t;
StringRsrc strings = *ResMgr::get(res_list);
cStringChoice dlog(strings.begin() + first_t - 1, strings.begin() + last_t, title, parent);