From 8e43ce4347cfbd73b8219e89aec273df62eb5803 Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Sun, 22 Jan 2017 11:02:26 -0500 Subject: [PATCH] Add preview button to item/monster edit dialogs This shows the monster or item info dialog as it would appear in-game --- rsrc/dialogs/edit-item.xml | 1 + rsrc/dialogs/edit-monster.xml | 1 + src/BoE.xcodeproj/project.pbxproj | 8 ++ src/boe.infodlg.cpp | 184 +--------------------------- src/classes/creatlist.cpp | 2 +- src/scenedit/scen.core.cpp | 28 ++++- src/tools/view_dialogs.cpp | 197 ++++++++++++++++++++++++++++++ src/tools/view_dialogs.hpp | 16 +++ 8 files changed, 256 insertions(+), 181 deletions(-) create mode 100644 src/tools/view_dialogs.cpp create mode 100644 src/tools/view_dialogs.hpp diff --git a/rsrc/dialogs/edit-item.xml b/rsrc/dialogs/edit-item.xml index 533f5e0f..91ec9329 100644 --- a/rsrc/dialogs/edit-item.xml +++ b/rsrc/dialogs/edit-item.xml @@ -90,4 +90,5 @@ + diff --git a/rsrc/dialogs/edit-monster.xml b/rsrc/dialogs/edit-monster.xml index 22af490b..cfa58ae1 100644 --- a/rsrc/dialogs/edit-monster.xml +++ b/rsrc/dialogs/edit-monster.xml @@ -79,4 +79,5 @@ Attack 1: Attack 2: Attack 3: + diff --git a/src/BoE.xcodeproj/project.pbxproj b/src/BoE.xcodeproj/project.pbxproj index 63c5e19a..68d27a12 100755 --- a/src/BoE.xcodeproj/project.pbxproj +++ b/src/BoE.xcodeproj/project.pbxproj @@ -213,6 +213,8 @@ 91ACCE941900346C00FAEF8B /* sfml-graphics.framework in Copy Libraries and Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8DE18F87F3700E3EA15 /* sfml-graphics.framework */; }; 91ACCE961900346C00FAEF8B /* sfml-system.framework in Copy Libraries and Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E018F87F3700E3EA15 /* sfml-system.framework */; }; 91ACCE971900346C00FAEF8B /* sfml-window.framework in Copy Libraries and Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E118F87F3700E3EA15 /* sfml-window.framework */; }; + 91B0D5D11E3442FE002BE4DA /* view_dialogs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B0D5D01E34428E002BE4DA /* view_dialogs.cpp */; }; + 91B0D5D21E344300002BE4DA /* view_dialogs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B0D5D01E34428E002BE4DA /* view_dialogs.cpp */; }; 91B3EF1F0F969C9C00BF5B67 /* BoECharEd.icns in Resources */ = {isa = PBXBuildFile; fileRef = 91B3EF110F969BD300BF5B67 /* BoECharEd.icns */; }; 91B3EF470F969F1700BF5B67 /* BoEScenEd.icns in Resources */ = {isa = PBXBuildFile; fileRef = 91B3EEDB0F969BA700BF5B67 /* BoEScenEd.icns */; }; 91B3EF480F969F2300BF5B67 /* pc.main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B3EF050F969BD300BF5B67 /* pc.main.cpp */; }; @@ -669,6 +671,8 @@ 91B0D5CD1E3408AB002BE4DA /* stealth */ = {isa = PBXFileReference; lastKnownFileType = folder; path = stealth; sourceTree = ""; }; 91B0D5CE1E3408AB002BE4DA /* valleydy */ = {isa = PBXFileReference; lastKnownFileType = folder; path = valleydy; sourceTree = ""; }; 91B0D5CF1E3408AB002BE4DA /* zakhazi */ = {isa = PBXFileReference; lastKnownFileType = folder; path = zakhazi; sourceTree = ""; }; + 91B0D5D01E34428E002BE4DA /* view_dialogs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = view_dialogs.cpp; sourceTree = ""; }; + 91B0D5D31E3446CF002BE4DA /* view_dialogs.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = view_dialogs.hpp; sourceTree = ""; }; 91B3E8A50F938FFE00BF5B67 /* boe.consts.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = boe.consts.hpp; sourceTree = ""; }; 91B3EED90F969BA700BF5B67 /* BoEScenEd-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "BoEScenEd-Info.plist"; path = "scenedit/BoEScenEd-Info.plist"; sourceTree = SOURCE_ROOT; }; 91B3EEDB0F969BA700BF5B67 /* BoEScenEd.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = BoEScenEd.icns; path = icons/mac/BoEScenEd.icns; sourceTree = ""; }; @@ -1092,6 +1096,7 @@ 915325181A2E37EE000A9A1C /* specials_parse.cpp */, 91BFA3D81902AD78001686E4 /* tarball.cpp */, 912283C80FD0E16C00B21642 /* undo.cpp */, + 91B0D5D01E34428E002BE4DA /* view_dialogs.cpp */, 919145FF18E63B70005CF3A4 /* winutil.mac.mm */, ); name = src; @@ -1113,6 +1118,7 @@ 91BFA3D91902ADD5001686E4 /* tarball.hpp */, 917B573F100B956C0096C978 /* undo.hpp */, 9179A4621A47D4E200FEF872 /* vector2d.hpp */, + 91B0D5D31E3446CF002BE4DA /* view_dialogs.hpp */, 919145FE18E63B41005CF3A4 /* winutil.hpp */, ); name = headers; @@ -1764,6 +1770,7 @@ 912DFE8F18E2872400B00D75 /* boe.menus.mac.mm in Sources */, 919145FC18E3AB1B005CF3A4 /* boe.appleevents.mm in Sources */, 915325171A2E1DF0000A9A1C /* oldstructs.cpp in Sources */, + 91B0D5D11E3442FE002BE4DA /* view_dialogs.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1866,6 +1873,7 @@ 91B3F1850F97894A00BF5B67 /* scen.graphics.cpp in Sources */, 914CA45819074E0100B6ADD1 /* scen.menus.mac.mm in Sources */, 91034D211B225E4A008F01C1 /* scen.appleevents.mm in Sources */, + 91B0D5D21E344300002BE4DA /* view_dialogs.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/boe.infodlg.cpp b/src/boe.infodlg.cpp index 69366c6d..2fadf3d1 100644 --- a/src/boe.infodlg.cpp +++ b/src/boe.infodlg.cpp @@ -26,6 +26,7 @@ #include #include "prefs.hpp" #include "spell.hpp" +#include "view_dialogs.hpp" short mage_spell_pos = 0,priest_spell_pos = 0,skill_pos = 0; @@ -181,104 +182,6 @@ void display_skills(eSkill force_skill,cDialog* parent) { skillDlog.run(); } -static void put_item_info(cDialog& me,const cItem& s_i) { - std::string desc_str; - - cPict& pic = dynamic_cast(me["pic"]); - pic.setPict(s_i.graphic_num, PIC_ITEM); - - // id? magic? - cLed& id = dynamic_cast(me["id"]); - if(s_i.ident) - id.setState(led_red); - else id.setState(led_off); - cLed& magic = dynamic_cast(me["magic"]); - if(s_i.magic && s_i.ident) - magic.setState(led_red); - else magic.setState(led_off); - me["type"].setText(get_str("item-types-display", int(s_i.variety) + 1)); - - // Clear fields - me["val"].setText(""); - me["dmg"].setText(""); - me["bonus"].setText(""); - me["def"].setText(""); - me["enc"].setText(""); - me["use"].setText(""); - me["lvl"].setText(""); - me["abil"].setText(""); - - if(!s_i.ident) { - me["name"].setText(s_i.name); - return; - } - - me["name"].setText(s_i.full_name); - me["weight"].setTextToNum(s_i.item_weight()); - me["desc"].setText(s_i.desc.substr(0,s_i.desc.find("|||"))); - - // TODO: This calculation (value for an item with charges) should be in a member function of cItem - me["val"].setTextToNum((s_i.charges > 0) ? s_i.value * s_i.charges : s_i.value); - - if(s_i.ability != eItemAbil::NONE) { - if(s_i.concealed) { - me["abil"].setText("???"); - } else { - std::string abil = s_i.getAbilName(); - if(s_i.ability == eItemAbil::SUMMONING || s_i.ability == eItemAbil::MASS_SUMMONING) - abil.replace(abil.find("%s"), 2, univ.scenario.scen_monsters[s_i.abil_data[1]].m_name); - me["abil"].setText(abil); - } - } - if(s_i.charges > 0) - me["use"].setTextToNum(s_i.charges); - if(s_i.protection > 0) - me["def"].setTextToNum(s_i.protection); - - std::string store_text; - switch(s_i.variety) { - case eItemType::ONE_HANDED: - case eItemType::TWO_HANDED: - case eItemType::BOW: - case eItemType::CROSSBOW: - case eItemType::THROWN_MISSILE: - case eItemType::MISSILE_NO_AMMO: - if(s_i.ability == eItemAbil::NONE) - me["abil"].setText("Key skill: " + get_str("skills", int(s_i.weap_type) * 2 + 1)); - case eItemType::ARROW: - case eItemType::BOLTS: - me["dmg"].setTextToNum(s_i.item_level); - me["bonus"].setTextToNum(s_i.bonus); - break; - case eItemType::POTION: - case eItemType::RING: - case eItemType::SCROLL: // TODO: Does this make sense for a scroll, though? - case eItemType::TOOL: // and what about for a tool? - case eItemType::WAND: // and a wand? Maybe showing ability strength would be better... - case eItemType::NECKLACE: // TODO: This doesn't seem right for a necklace... - me["lvl"].setTextToNum(s_i.item_level); - break; - case eItemType::SHIELD: - case eItemType::ARMOR: - case eItemType::HELM: - case eItemType::GLOVES: - case eItemType::SHIELD_2: - case eItemType::BOOTS: // TODO: Should this also check eItemType::PANTS? - // TODO: Why is bonus and protection combined into "bonus"? Why not use the "defense" field? - me["bonus"].setTextToNum(s_i.bonus + s_i.protection); - me["def"].setTextToNum(s_i.item_level); - me["enc"].setTextToNum(s_i.awkward); - break; - case eItemType::WEAPON_POISON: - me["lvl"].setTextToNum(s_i.item_level); - break; - default: - // no item, gold, food, non-use, unused 1 and 2: do nothing - break; - } - -} - static bool display_pc_item_event_filter(cDialog& me, std::string item_hit, cItem& store_i, short& item, const short pc_num) { if(item_hit == "done") { @@ -288,13 +191,13 @@ static bool display_pc_item_event_filter(cDialog& me, std::string item_hit, cIte item = (item == 0) ? 23 : item - 1; } while(univ.party[pc_num].items[item].variety == eItemType::NO_ITEM); store_i = univ.party[pc_num].items[item]; - put_item_info(me,store_i); + put_item_info(me,store_i,univ.scenario); } else if(item_hit == "right") { do { item = (item == 23) ? 0 : item + 1; } while(univ.party[pc_num].items[item].variety == eItemType::NO_ITEM); store_i = univ.party[pc_num].items[item]; - put_item_info(me,store_i); + put_item_info(me,store_i,univ.scenario); } return true; } @@ -316,86 +219,11 @@ void display_pc_item(short pc_num,short item,cItem si,cDialog* parent) { itemInfo["right"].hide(); } - put_item_info(itemInfo,si); + put_item_info(itemInfo,si,univ.scenario); itemInfo.run(); } - -static void put_monst_info(cDialog& me, const cCreature& store_m) { - std::string store_text; - std::string str; - short i; - - cPict& pic = dynamic_cast(me["pic"]); - if(store_m.invisible) - pic.setPict(400,PIC_MONST);// TODO: should probably be PICT_BLANK? - else if(store_m.picture_num < 1000) - pic.setPict(store_m.picture_num,PIC_MONST); - else { - ePicType type_g = PIC_CUSTOM_MONST; - short size_g = store_m.picture_num / 1000; - switch(size_g){ - case 2: - type_g += PIC_WIDE; - break; - case 3: - type_g += PIC_TALL; - break; - case 4: - type_g += PIC_WIDE; - type_g += PIC_TALL; - break; - } - pic.setPict(store_m.picture_num % 1000, type_g); - } - - store_text = get_m_name(store_m.number); - me["name"].setText(store_text); - - i = 1; - for(auto& abil : store_m.abil) { - if(i > 4) break; // TODO: Support showing more than just the first four abilities - if(!abil.second.active) continue; - std::string id = "abil" + std::to_string(i); - std::string name = abil.second.to_string(abil.first); - if(abil.first == eMonstAbil::SUMMON && abil.second.summon.type == eMonstSummon::TYPE) - name.replace(name.find("%s"), 2, univ.scenario.scen_monsters[abil.second.summon.what].m_name); - me[id].setText(name); - i++; - } - - for(short i = 0; i < store_m.a.size(); i++) { - if(store_m.a[i].dice > 0) { - if(store_m.a[i].sides == 0) continue; - std::ostringstream sout(std::ios_base::ate); - sout << store_m.a[i]; - store_text = sout.str(); - sout.str("attack"); - sout << i + 1; - me[sout.str()].setText(store_text); - } - } - me["lvl"].setTextToNum(store_m.level); - me["hp"].setTextToNum(store_m.health); - me["sp"].setTextToNum(store_m.mp); - me["def"].setTextToNum(store_m.armor); - me["skill"].setTextToNum(store_m.skill); - me["morale"].setTextToNum(store_m.morale); - me["ap"].setTextToNum(store_m.speed); - me["mage"].setTextToNum(store_m.mu); - me["priest"].setTextToNum(store_m.cl); - // Immunities - me["magic-res"].setText(std::to_string(100 - store_m.resist.at(eDamageType::MAGIC)) + '%'); - me["fire-res"].setText(std::to_string(100 - store_m.resist.at(eDamageType::FIRE)) + '%'); - me["cold-res"].setText(std::to_string(100 - store_m.resist.at(eDamageType::COLD)) + '%'); - me["poison-res"].setText(std::to_string(100 - store_m.resist.at(eDamageType::POISON)) + '%'); - dynamic_cast(me["mindless"]).setState(store_m.mindless ? led_red : led_off); - dynamic_cast(me["invuln"]).setState(store_m.invuln ? led_red : led_off); - dynamic_cast(me["guard"]).setState(store_m.guard ? led_red : led_off); -} - - static bool display_monst_event_filter(cDialog& me, std::string item_hit, cCreature& store_m) { // This is a bit hacky; keep a cPopulation here to handle the full roster; it's treated like a rotating buffer. static cPopulation roster; @@ -422,7 +250,7 @@ static bool display_monst_event_filter(cDialog& me, std::string item_hit, cCreat roster.assign(position % 60, cCreature(on_monst_menu[position]), monst, univ.party.easy_mode, univ.difficulty_adjust()); store_m = roster[position % 60]; } - put_monst_info(me, store_m); + put_monst_info(me, store_m, univ.scenario); return true; } @@ -452,7 +280,7 @@ void display_monst(short array_pos,cCreature *which_m,short mode) { monstInfo["left"].hide(); monstInfo["right"].hide(); } - put_monst_info(monstInfo, store_m); + put_monst_info(monstInfo, store_m, univ.scenario); monstInfo.run(); } diff --git a/src/classes/creatlist.cpp b/src/classes/creatlist.cpp index a83b8c18..585ccc85 100644 --- a/src/classes/creatlist.cpp +++ b/src/classes/creatlist.cpp @@ -56,7 +56,7 @@ void cPopulation::assign(size_t n, const cTownperson& other, const cMonster& bas dudes[n].max_mp = dudes[n].mp = 12 * dudes[n].level; else dudes[n].max_mp = dudes[n].mp = 0; dudes[n].m_morale = 10 * dudes[n].level; - if(dudes[n].level >= 20) + if(dudes[n].level > 20) dudes[n].m_morale += 10 * (dudes[n].level - 20); dudes[n].morale = dudes[n].m_morale; dudes[n].direction = DIR_HERE; diff --git a/src/scenedit/scen.core.cpp b/src/scenedit/scen.core.cpp index 8301024d..bff11509 100644 --- a/src/scenedit/scen.core.cpp +++ b/src/scenedit/scen.core.cpp @@ -30,6 +30,7 @@ #include "spell.hpp" #include "mathutil.hpp" #include "winutil.hpp" +#include "view_dialogs.hpp" extern short cen_x, cen_y,cur_town; extern bool mouse_button_held; @@ -817,6 +818,14 @@ static bool edit_monst_type_event_filter(cDialog& me,std::string hit,cMonster& m monst.a[2].type = eMonstMelee(i); put_monst_info_in_dlog(me,monst,which); } + } else if(hit == "preview") { + cDialog monstInfo("monster-info", &me); + monstInfo["left"].hide(); + monstInfo["right"].hide(); + monstInfo.attachClickHandlers([](cDialog&,std::string,eKeyMod){return false;}, {"guard","mindless","invuln"}); + monstInfo["done"].attachClickHandler(std::bind(&cDialog::toast, &monstInfo, true)); + put_monst_info(monstInfo, monst, scenario); + monstInfo.run(); } return true; } @@ -853,7 +862,7 @@ bool edit_monst_type(short which) { monst_dlg["priest"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 7, "priest spells")); monst_dlg["treas"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 4, "treasure")); monst_dlg.attachFocusHandlers(check_monst_dice,{"dice1","dice2","dice3","sides1","sides2","sides3"}); - monst_dlg.attachClickHandlers(std::bind(edit_monst_type_event_filter,_1,_2,std::ref(monst),std::ref(which)),{"okay","abils","picktype","picktype1","picktype2","picktype3"}); + monst_dlg.attachClickHandlers(std::bind(edit_monst_type_event_filter,_1,_2,std::ref(monst),std::ref(which)),{"okay","abils","picktype","picktype1","picktype2","picktype3","preview"}); if(scenario.scen_monsters.size() == 1){ monst_dlg["left"].hide(); @@ -1665,6 +1674,21 @@ static bool edit_item_type_event_filter(cDialog& me, std::string hit, cItem& ite if(temp_item.variety != eItemType::NO_ITEM) item = temp_item; put_item_info_in_dlog(me, item, which); + } else if(hit == "preview") { + cItem temp_item = item; + temp_item.ident = true; + cDialog itemInfo("item-info", &me); + itemInfo["left"].hide(); + itemInfo["right"].hide(); + itemInfo["done"].attachClickHandler(std::bind(&cDialog::toast, &itemInfo, false)); + itemInfo["magic"].attachClickHandler([](cDialog&, std::string, eKeyMod){return false;}); + itemInfo["id"].attachClickHandler([&temp_item](cDialog& me, std::string, eKeyMod){ + temp_item.ident = !temp_item.ident; + put_item_info(me, temp_item, scenario); + return true; + }); + put_item_info(itemInfo, temp_item, scenario); + itemInfo.run(); } return true; } @@ -1718,7 +1742,7 @@ bool edit_item_type(short which) { item_dlg["weight"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 250, "Weight")); item_dlg["class"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 100, "Special Class")); item_dlg["variety"].attachFocusHandler(std::bind(change_item_variety, _1, _2, std::ref(item))); - item_dlg.attachClickHandlers(std::bind(edit_item_type_event_filter, _1, _2, std::ref(item), std::ref(which)), {"okay", "cancel", "abils", "choosepic", "choosetp", "choosemiss", "desc"}); + item_dlg.attachClickHandlers(std::bind(edit_item_type_event_filter, _1, _2, std::ref(item), std::ref(which)), {"okay", "cancel", "abils", "choosepic", "choosetp", "choosemiss", "desc", "preview"}); if(scenario.scen_items.size() == 1) { item_dlg["prev"].hide(); diff --git a/src/tools/view_dialogs.cpp b/src/tools/view_dialogs.cpp new file mode 100644 index 00000000..b9ae95a0 --- /dev/null +++ b/src/tools/view_dialogs.cpp @@ -0,0 +1,197 @@ +// +// view_dialogs.cpp +// BoE +// +// Created by Celtic Minstrel on 17-01-21. +// +// + +#include "view_dialogs.hpp" + +#include "dialog.hpp" +#include "pict.hpp" +#include "button.hpp" + +#include "item.hpp" +#include "creature.hpp" +#include "scenario.hpp" + +void put_item_info(cDialog& me, const cItem& s_i, const cScenario& scen) { + std::string desc_str; + + cPict& pic = dynamic_cast(me["pic"]); + pic.setPict(s_i.graphic_num, PIC_ITEM); + + // id? magic? + cLed& id = dynamic_cast(me["id"]); + if(s_i.ident) + id.setState(led_red); + else id.setState(led_off); + cLed& magic = dynamic_cast(me["magic"]); + if(s_i.magic && s_i.ident) + magic.setState(led_red); + else magic.setState(led_off); + me["type"].setText(get_str("item-types-display", int(s_i.variety) + 1)); + + // Clear fields + me["val"].setText(""); + me["dmg"].setText(""); + me["bonus"].setText(""); + me["def"].setText(""); + me["enc"].setText(""); + me["use"].setText(""); + me["lvl"].setText(""); + me["abil"].setText(""); + + if(!s_i.ident) { + me["name"].setText(s_i.name); + return; + } + + me["name"].setText(s_i.full_name); + me["weight"].setTextToNum(s_i.item_weight()); + me["desc"].setText(s_i.desc.substr(0,s_i.desc.find("|||"))); + + // TODO: This calculation (value for an item with charges) should be in a member function of cItem + me["val"].setTextToNum((s_i.charges > 0) ? s_i.value * s_i.charges : s_i.value); + + if(s_i.ability != eItemAbil::NONE) { + if(s_i.concealed) { + me["abil"].setText("???"); + } else { + std::string abil = s_i.getAbilName(); + if(s_i.ability == eItemAbil::SUMMONING || s_i.ability == eItemAbil::MASS_SUMMONING) + abil.replace(abil.find("%s"), 2, scen.scen_monsters[s_i.abil_data[1]].m_name); + me["abil"].setText(abil); + } + } + if(s_i.charges > 0) + me["use"].setTextToNum(s_i.charges); + if(s_i.protection > 0) + me["def"].setTextToNum(s_i.protection); + + std::string store_text; + switch(s_i.variety) { + case eItemType::ONE_HANDED: + case eItemType::TWO_HANDED: + case eItemType::BOW: + case eItemType::CROSSBOW: + case eItemType::THROWN_MISSILE: + case eItemType::MISSILE_NO_AMMO: + if(s_i.ability == eItemAbil::NONE) + me["abil"].setText("Key skill: " + get_str("skills", int(s_i.weap_type) * 2 + 1)); + case eItemType::ARROW: + case eItemType::BOLTS: + me["dmg"].setTextToNum(s_i.item_level); + me["bonus"].setTextToNum(s_i.bonus); + break; + case eItemType::POTION: + case eItemType::RING: + case eItemType::SCROLL: // TODO: Does this make sense for a scroll, though? + case eItemType::TOOL: // and what about for a tool? + case eItemType::WAND: // and a wand? Maybe showing ability strength would be better... + case eItemType::NECKLACE: // TODO: This doesn't seem right for a necklace... + me["lvl"].setTextToNum(s_i.item_level); + break; + case eItemType::SHIELD: + case eItemType::ARMOR: + case eItemType::HELM: + case eItemType::GLOVES: + case eItemType::SHIELD_2: + case eItemType::BOOTS: // TODO: Should this also check eItemType::PANTS? + // TODO: Why is bonus and protection combined into "bonus"? Why not use the "defense" field? + me["bonus"].setTextToNum(s_i.bonus + s_i.protection); + me["def"].setTextToNum(s_i.item_level); + me["enc"].setTextToNum(s_i.awkward); + break; + case eItemType::WEAPON_POISON: + me["lvl"].setTextToNum(s_i.item_level); + break; + default: + // no item, gold, food, non-use, unused 1 and 2: do nothing + break; + } + +} + +void put_monst_info(cDialog& me, const cMonster& store_m, const cScenario& scen) { + std::string store_text; + std::string str; + short i; + + cPict& pic = dynamic_cast(me["pic"]); + if(store_m.invisible) + pic.setPict(400,PIC_MONST);// TODO: should probably be PICT_BLANK? + else if(store_m.picture_num < 1000) + pic.setPict(store_m.picture_num,PIC_MONST); + else { + ePicType type_g = PIC_CUSTOM_MONST; + short size_g = store_m.picture_num / 1000; + switch(size_g){ + case 2: + type_g += PIC_WIDE; + break; + case 3: + type_g += PIC_TALL; + break; + case 4: + type_g += PIC_WIDE; + type_g += PIC_TALL; + break; + } + pic.setPict(store_m.picture_num % 1000, type_g); + } + + me["name"].setText(store_m.m_name); + + i = 1; + for(auto& abil : store_m.abil) { + if(i > 4) break; // TODO: Support showing more than just the first four abilities + if(!abil.second.active) continue; + std::string id = "abil" + std::to_string(i); + std::string name = abil.second.to_string(abil.first); + if(abil.first == eMonstAbil::SUMMON && abil.second.summon.type == eMonstSummon::TYPE) + name.replace(name.find("%s"), 2, scen.scen_monsters[abil.second.summon.what].m_name); + me[id].setText(name); + i++; + } + + for(short i = 0; i < store_m.a.size(); i++) { + if(store_m.a[i].dice > 0) { + if(store_m.a[i].sides == 0) continue; + std::ostringstream sout(std::ios_base::ate); + sout << store_m.a[i]; + store_text = sout.str(); + sout.str("attack"); + sout << i + 1; + me[sout.str()].setText(store_text); + } + } + me["lvl"].setTextToNum(store_m.level); + me["hp"].setTextToNum(store_m.m_health); + me["sp"].setTextToNum((store_m.mu + store_m.cl) ? store_m.level * 12 : 0); + me["def"].setTextToNum(store_m.armor); + me["skill"].setTextToNum(store_m.skill); + int morale = 10 * store_m.level; + if(store_m.level > 20) + morale += 10 * (store_m.level - 20); + me["morale"].setTextToNum(morale); + me["ap"].setTextToNum(store_m.speed); + me["mage"].setTextToNum(store_m.mu); + me["priest"].setTextToNum(store_m.cl); + // Immunities + me["magic-res"].setText(std::to_string(100 - store_m.resist.at(eDamageType::MAGIC)) + '%'); + me["fire-res"].setText(std::to_string(100 - store_m.resist.at(eDamageType::FIRE)) + '%'); + me["cold-res"].setText(std::to_string(100 - store_m.resist.at(eDamageType::COLD)) + '%'); + me["poison-res"].setText(std::to_string(100 - store_m.resist.at(eDamageType::POISON)) + '%'); + dynamic_cast(me["mindless"]).setState(store_m.mindless ? led_red : led_off); + dynamic_cast(me["invuln"]).setState(store_m.invuln ? led_red : led_off); + dynamic_cast(me["guard"]).setState(store_m.guard ? led_red : led_off); +} + +void put_monst_info(cDialog& me, const cCreature& store_m, const cScenario& scen) { + put_monst_info(me, static_cast(store_m), scen); + me["hp"].setTextToNum(store_m.health); + me["sp"].setTextToNum(store_m.mp); + me["morale"].setTextToNum(store_m.morale); +} diff --git a/src/tools/view_dialogs.hpp b/src/tools/view_dialogs.hpp new file mode 100644 index 00000000..4c01be71 --- /dev/null +++ b/src/tools/view_dialogs.hpp @@ -0,0 +1,16 @@ +// +// view_dialogs.hpp +// BoE +// +// Created by Celtic Minstrel on 17-01-21. +// +// + +#ifndef BOE_VIEW_DIALOGS_HPP +#define BOE_VIEW_DIALOGS_HPP + +void put_item_info(class cDialog& me, const class cItem& s_i, const class cScenario& scen); +void put_monst_info(class cDialog& me, const class cMonster& store_m, const class cScenario& scen); +void put_monst_info(class cDialog& me, const class cCreature& store_m, const class cScenario& scen); + +#endif