From 311a3c070201871e7c877b094aeb4de5bc8190e4 Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Wed, 21 Jan 2015 14:04:40 -0500 Subject: [PATCH] Get the item abilities dialog working and updated for new stuff - Add additional treasure type for "unique" items - Main item dialog now shows the item ability's display name, and also has more space for the item's full name - (Game) No-ammo missiles (eg slings) are now counted as weapons by shops - (Dialog Engine) Fix LED groups being drawn when invisible --- rsrc/dialogs/edit-item-abils.xml | 41 ++-- rsrc/dialogs/edit-item.xml | 134 ++++++------ rsrc/strings/item-abilities.txt | 349 ++++++++++--------------------- src/boe.items.cpp | 21 +- src/classes/item.cpp | 310 +++++++++++++++++++++++++++ src/classes/item.h | 2 + src/classes/simpletypes.h | 15 +- src/classes/spell.cpp | 8 + src/classes/spell.hpp | 1 + src/dialogxml/button.cpp | 1 + src/scenedit/scen.core.cpp | 252 +++++++++++++++------- src/scenedit/scen.core.h | 2 +- src/scenedit/scen.keydlgs.cpp | 4 +- 13 files changed, 713 insertions(+), 427 deletions(-) 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 @@ - - - - + + + Item use properties - Help using PC - Harm using PC + Help single PC + Harm single PC Help whole party Harm whole party @@ -18,17 +15,20 @@ Magical Cursed Conceal ability + Shops won't buy Edit Item Abilities Item number: - Item special ability: - - - Ability strength: (Usually 0-10, see instructions) - Item use properties - Only used for item abilities which are used (like healing). + + + + + + + + Other properties: Item treasure class: (0 is lowest level of treasure, 4 is highest) - - - - - - - - - - - - - - - + + - Item type: - Item level: (0 - 50) - Awkwardness: (0-20) - Bonus: (0-10) - Protection: (-10 - 20) - Charges: (0-100) - Type flag: (0-1000) - Value: (0-10000) - Weight: (0-250) - Special class: (0-100) - Missile type: - - - - Weapon key skill: - - - + Item Unidentified Name: + Item Ability: + + Item picture: + + Item type: + Item level: (0 - 50) + Awkwardness: (0-20) + Bonus: (0-10) + Protection: (-10 - 20) + Charges: (0-100) + Type flag: (0-1000) + Value: (0-10000) + Weight: (0-250) + Special class: (0-100) + Missile type: + + + + Weapon key skill: + + + Enter properties for this item type. For a detailed description of the fields, see the documentation. Click Edit Abilities to edit item abilities. - + 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);