Clean up, fix, and tweak the spellcasting dialog

- Includes new status effect images for the forcecage and for hypothetical inverses of dumbfound and magic resistance, as well as icons for the whole-party statuses.
This commit is contained in:
2014-12-10 17:47:33 -05:00
parent 34be9a0233
commit 869ca7b2d7
8 changed files with 166 additions and 64 deletions

View File

@@ -1,4 +1,7 @@
#ifndef BOE_GLOBAL_H
#define BOE_GLOBAL_H
#include <vector>
#include <string>
#include <sstream>
@@ -61,3 +64,5 @@ public:
struct effect_pat_type {
unsigned char pattern[9][9];
};
#endif

View File

@@ -45,6 +45,7 @@ short spell_cost[2][62] = {
4,5,4,8,30,-1,8,6, 5,8,8,6,9,10,6,6, 7,6,8,7,12,10,12,20, 12,8,20,10,14,10,50,10},
{1,1,1,2,1,1,3,5,50,1, 2,2,2,2,3,5,8,6,4,2, 3,4,3,3,3,10,5,3,4,6,
5,5,5,15,6,5,5,8, 6,7,25,8,10,12,12,6, 8,7,8,8,14,17,8,7, 10,10,35,10,12,12,30,10}};
// TODO: Use magic-names.txt instead of these arrays
const char *mage_s_name[62] = {
"Light","Spark","Minor Haste","Strength","Scare",
"Flame Cloud","Identify","Scry Monster","Goo","True Sight",
@@ -2066,6 +2067,45 @@ static void draw_spell_info(cDialog& me, const short store_situation) {
}
}
// TODO: Use the map here to simplify drawing the graphics in draw_pc_effects()
static void put_target_status_graphics(cDialog& me, short for_pc) {
// First icon is displayed for positive values, second for negative, if -1 no negative icon.
// This omits two special cases - major poison, and normal speed; they are hard-coded.
static std::map<eStatus, std::pair<short, short>> statIcons = {
{eStatus::POISONED_WEAPON, {4,-1}}, {eStatus::BLESS_CURSE, {2,3}}, {eStatus::POISON, {0,-1}},
{eStatus::HASTE_SLOW, {6,8}}, {eStatus::INVULNERABLE, {5,-1}}, {eStatus::MAGIC_RESISTANCE, {9,19}},
{eStatus::WEBS, {10,-1}}, {eStatus::DISEASE, {11,-1}}, {eStatus::INVISIBLE, {12,-1}},
{eStatus::DUMB, {13,18}}, {eStatus::MARTYRS_SHIELD, {14,-1}}, {eStatus::ASLEEP, {15,-1}},
{eStatus::PARALYZED, {16,-1}}, {eStatus::ACID, {17,-1}}, {eStatus::FORCECAGE, {20,-1}},
};
bool isAlive = univ.party[for_pc].main_status == eMainStatus::ALIVE;
univ.party[for_pc].status[eStatus::HASTE_SLOW]; // This just makes sure it exists in the map, without changing its value if it does
std::string id = "pc" + std::to_string(for_pc + 1);
int slot = 0;
for(auto next : univ.party[for_pc].status) {
std::string id2 = id + "-stat" + std::to_string(slot + 1);
cPict& pic = dynamic_cast<cPict&>(me[id2]);
pic.setFormat(TXT_FRAME, false);
if(isAlive) {
short placedIcon = -1;
if(next.first == eStatus::POISON && next.second > 4) placedIcon = 1;
else if(next.second > 0) placedIcon = statIcons[next.first].first;
else if(next.second < 0) placedIcon = statIcons[next.first].second;
else if(next.first == eStatus::HASTE_SLOW) placedIcon = 7;
if(placedIcon >= 0) {
pic.show();
pic.setPict(placedIcon);
slot++;
} else pic.hide();
} else pic.hide();
}
while(slot < 15) {
std::string id2 = id + "-stat" + std::to_string(slot + 1);
me[id2].hide();
slot++;
}
}
static void draw_spell_pc_info(cDialog& me)
{
short i;
@@ -2082,6 +2122,7 @@ static void draw_spell_pc_info(cDialog& me)
me["hp" + n].setTextToNum(univ.party[i].cur_health);
me["sp" + n].setTextToNum(univ.party[i].cur_sp);
}
put_target_status_graphics(me, i);
}
}
}
@@ -2155,13 +2196,10 @@ static void put_spell_list(cDialog& me, const short store_situation) {
std::string id = "spell" + boost::lexical_cast<std::string>(i + 1);
if (store_situation == 0) {
if (i == 35)
sprintf((char *) add_text,"%s %c ?",mage_s_name[i],
(char) ((97 + i > 122) ? 65 + (i - 26) : 97 + i));
else sprintf((char *) add_text,"%s %c %d",mage_s_name[i],
(char) ((97 + i > 122) ? 65 + (i - 26) : 97 + i),spell_cost[0][i]);
sprintf((char *) add_text,"%s (?)",mage_s_name[i]);
else sprintf((char *) add_text,"%s (%d)",mage_s_name[i],spell_cost[0][i]);
}
else sprintf((char *) add_text,"%s %c %d",priest_s_name[i],
(char) ((97 + i > 122) ? 65 + (i - 26) : 97 + i),spell_cost[1][i]);
else sprintf((char *) add_text,"%s (%d)",priest_s_name[i],spell_cost[1][i]);
//for (j = 0; j < 30; i++)
// if (add_text[j] == '&')
// add_text[j] = (char) ((97 + i > 122) ? 65 + (i - 26) : 97 + i);
@@ -2190,20 +2228,6 @@ static void put_spell_list(cDialog& me, const short store_situation) {
}
}
static void put_pick_spell_graphics(cDialog& me, const short store_situation, short& last_darkened) {
short i;
put_spell_list(me, store_situation);
put_pc_caster_buttons(me);
put_pc_target_buttons(me, last_darkened);
put_spell_led_buttons(me, store_situation);
for (i = 0; i < 6; i++)
if(univ.party[i].main_status == eMainStatus::ALIVE)
draw_pc_effects(10 + i); // TODO: This line might mean that the "kludge" from the old code is already handled here; verify?
}
static bool pick_spell_caster(cDialog& me, std::string id, const short store_situation, short& last_darkened) {
short item_hit = id[id.length() - 1] - '1';
// TODO: This visibility check is probably not needed; wouldn't the dialog framework only trigger on visible elements?
@@ -2428,12 +2452,14 @@ short pick_spell(short pc_num,short type) // 70 - no spell OW spell num
}
// If a target is needed, keep the same target if that PC still targetable
if(store_spell_target < 6) {
if (((type == 0) && (mage_need_select[store_mage] > 0)) ||
((type == 1) && (priest_need_select[store_priest] > 0))) {
if(univ.party[store_spell_target].main_status != eMainStatus::ALIVE)
store_spell_target = 6;
}
else store_spell_target = 6;
}
// Set the spell page, based on starting spell
if (((type == 0) && (store_mage >= 38)) || ((type == 1) && (store_priest >= 38)))
@@ -2454,10 +2480,13 @@ short pick_spell(short pc_num,short type) // 70 - no spell OW spell num
dynamic_cast<cPict&>(castSpell["pic"]).setPict(14 + type,PIC_DLOG);
for(int i = 0; i < 38; i++) {
std::string id = "spell" + boost::lexical_cast<std::string>(i + 1);
cKey key;
if (i > 25)
castSpell[id].attachKey({false, static_cast<unsigned char>('a' + i - 26), mod_shift});
else castSpell[id].attachKey({false, static_cast<unsigned char>('a' + i), mod_none});
key = {false, static_cast<unsigned char>('a' + i - 26), mod_shift};
else key = {false, static_cast<unsigned char>('a' + i), mod_none};
cLed& led = dynamic_cast<cLed&>(castSpell[id]);
led.attachKey(key);
castSpell.addLabelFor(id, {i > 25 ? toupper(key.c) : key.c}, LABEL_LEFT, 8, true);
led.setState((pc_can_cast_spell(pc_casting,type, (on_which_spell_page == 0) ? i : spell_index[i]))
? led_red : led_green);
led.attachClickHandler(std::bind(pick_spell_select_led, _1, _2, _3, type, dark));

View File

@@ -103,9 +103,10 @@ enum class eStatus {
ASLEEP = 11,
PARALYZED = 12,
ACID = 13,
FORCECAGE = 14, // This is new and currently unused, since forcecages aren't even really implemented yet.
// This one is new
// It's not quite a real status effect since it doesn't expire
// We use 15 because 14 was technically a "reserved/unused" status, though I don't think it was ever used for anything
// We use 15 because 14 was technically a "reserved/unused" status, though it was never used for anything
CHARM = 15,
};

View File

@@ -158,10 +158,12 @@ bool mod_contains(eKeyMod mods, eKeyMod mod) {
void cControl::show(){
visible = true;
if(labelCtrl) labelCtrl->show();
}
void cControl::hide(){
visible = false;
if(labelCtrl) labelCtrl->hide();
}
bool cControl::isVisible(){
@@ -170,6 +172,10 @@ bool cControl::isVisible(){
else return false;
}
void cControl::setLabelCtrl(cControl* label) {
labelCtrl = label;
}
cKey cControl::getAttachedKey() {
return key;
}

View File

@@ -200,6 +200,10 @@ public:
/// should be hilited in some way while pressed and is cancelled by releasing the mouse
/// button outside the control's bounds.
virtual bool handleClick(location where);
/// Specifies that another control acts as a label for this one.
/// The practical effect of this is that hiding or showing this control automatically hides or shows the label as well.
/// @param label A pointer to the control that acts as a label.
void setLabelCtrl(cControl* label);
/// Create a new control attached to an arbitrary window, rather than a dialog.
/// @param t The type of the control.
/// @param p The parent window.
@@ -217,6 +221,8 @@ protected:
/// The parent dialog of the control.
/// May be null, if the control was created via cControl(eControlType,sf::RenderWindow&).
cDialog* parent;
/// This control's labelling control.
cControl* labelCtrl = NULL;
/// The parent window of the control.
/// This is for use in implementing draw().
sf::RenderWindow* inWindow;

View File

@@ -1217,6 +1217,7 @@ bool cDialog::addLabelFor(std::string key, std::string label, eLabelPos where, s
if(bg == BG_DARK && dynamic_cast<cButton*>(&ctrl) != NULL)
labelCtrl->setColour(defTextClr);
else labelCtrl->setColour(ctrl.getColour());
ctrl.setLabelCtrl(labelCtrl);
return add(labelCtrl, labelRect, key);
}

View File

@@ -11,6 +11,9 @@
<button name='caster4' type='regular' def-key='4' top='153' left='10'>4</button>
<button name='caster5' type='regular' def-key='5' top='177' left='10'>5</button>
<button name='caster6' type='regular' def-key='6' top='201' left='10'>6</button>
<!--
TODO: Use the <key/> element here.
-->
<button name='target1' type='small' def-key='1' key-mod='shift' top='82' left='235'>!</button>
<button name='target2' type='small' def-key='2' key-mod='shift' top='106' left='235'>@</button>
<button name='target3' type='small' def-key='3' key-mod='shift' top='130' left='235'>#</button>
@@ -38,47 +41,44 @@
<text name='sp5' top='181' left='304' width='32' height='16'/>
<text name='sp6' top='205' left='304' width='32' height='16'/>
<text name='feedback' framed='true' top='400' left='30' width='186' height='16'>Pick spell to cast.</text>
<!--
TODO: Add width attributes to these LEDs
-->
<led name='spell1' state='off' top='247' left='114'/>
<led name='spell2' state='off' top='261' left='114'/>
<led name='spell3' state='off' top='275' left='114'/>
<led name='spell4' state='off' top='289' left='114'/>
<led name='spell5' state='off' top='303' left='114'/>
<led name='spell6' state='off' top='317' left='114'/>
<led name='spell7' state='off' top='331' left='114'/>
<led name='spell8' state='off' top='345' left='114'/>
<led name='spell9' state='off' top='359' left='114'/>
<led name='spell10' state='off' top='373' left='114'/>
<led name='spell11' state='off' top='247' left='247'/>
<led name='spell12' state='off' top='261' left='247'/>
<led name='spell13' state='off' top='275' left='247'/>
<led name='spell14' state='off' top='289' left='247'/>
<led name='spell15' state='off' top='303' left='247'/>
<led name='spell16' state='off' top='317' left='247'/>
<led name='spell17' state='off' top='331' left='247'/>
<led name='spell18' state='off' top='345' left='247'/>
<led name='spell19' state='off' top='359' left='247'/>
<led name='spell20' state='off' top='373' left='247'/>
<led name='spell21' state='off' top='247' left='379'/>
<led name='spell22' state='off' top='261' left='379'/>
<led name='spell23' state='off' top='275' left='379'/>
<led name='spell24' state='off' top='289' left='379'/>
<led name='spell25' state='off' top='303' left='379'/>
<led name='spell26' state='off' top='317' left='379'/>
<led name='spell27' state='off' top='331' left='379'/>
<led name='spell28' state='off' top='345' left='379'/>
<led name='spell29' state='off' top='359' left='379'/>
<led name='spell30' state='off' top='373' left='379'/>
<led name='spell31' state='off' top='247' left='508'/>
<led name='spell32' state='off' top='261' left='508'/>
<led name='spell33' state='off' top='275' left='508'/>
<led name='spell34' state='off' top='289' left='508'/>
<led name='spell35' state='off' top='303' left='508'/>
<led name='spell36' state='off' top='317' left='508'/>
<led name='spell37' state='off' top='331' left='508'/>
<led name='spell38' state='off' top='345' left='508'/>
<led name='spell1' state='off' top='247' left='14' width='100'/>
<led name='spell2' state='off' top='261' left='14' width='100'/>
<led name='spell3' state='off' top='275' left='14' width='100'/>
<led name='spell4' state='off' top='289' left='14' width='100'/>
<led name='spell5' state='off' top='303' left='14' width='100'/>
<led name='spell6' state='off' top='317' left='14' width='100'/>
<led name='spell7' state='off' top='331' left='14' width='100'/>
<led name='spell8' state='off' top='345' left='14' width='100'/>
<led name='spell9' state='off' top='359' left='14' width='100'/>
<led name='spell10' state='off' top='373' left='14' width='100'/>
<led name='spell11' state='off' top='247' left='147' width='100'/>
<led name='spell12' state='off' top='261' left='147' width='100'/>
<led name='spell13' state='off' top='275' left='147' width='100'/>
<led name='spell14' state='off' top='289' left='147' width='100'/>
<led name='spell15' state='off' top='303' left='147' width='100'/>
<led name='spell16' state='off' top='317' left='147' width='100'/>
<led name='spell17' state='off' top='331' left='147' width='100'/>
<led name='spell18' state='off' top='345' left='147' width='100'/>
<led name='spell19' state='off' top='359' left='147' width='100'/>
<led name='spell20' state='off' top='373' left='147' width='100'/>
<led name='spell21' state='off' top='247' left='279' width='100'/>
<led name='spell22' state='off' top='261' left='279' width='100'/>
<led name='spell23' state='off' top='275' left='279' width='100'/>
<led name='spell24' state='off' top='289' left='279' width='100'/>
<led name='spell25' state='off' top='303' left='279' width='100'/>
<led name='spell26' state='off' top='317' left='279' width='100'/>
<led name='spell27' state='off' top='331' left='279' width='100'/>
<led name='spell28' state='off' top='345' left='279' width='100'/>
<led name='spell29' state='off' top='359' left='279' width='100'/>
<led name='spell30' state='off' top='373' left='279' width='100'/>
<led name='spell31' state='off' top='247' left='408' width='100'/>
<led name='spell32' state='off' top='261' left='408' width='100'/>
<led name='spell33' state='off' top='275' left='408' width='100'/>
<led name='spell34' state='off' top='289' left='408' width='100'/>
<led name='spell35' state='off' top='303' left='408' width='100'/>
<led name='spell36' state='off' top='317' left='408' width='100'/>
<led name='spell37' state='off' top='331' left='408' width='100'/>
<led name='spell38' state='off' top='345' left='408' width='100'/>
<button name='other' type='large' def-key='space' top='394' left='281'>Other Spells</button>
<text size='large' top='60' left='9' width='75' height='16'>Caster:</text>
<text size='large' top='60' left='209' width='223' height='16'>Target: HP: SP: Status:</text>
@@ -98,4 +98,58 @@
<text name='col2' top='227' left='132' width='100' height='16'/>
<text name='col3' top='227' left='266' width='100' height='16'/>
<text name='col4' top='227' left='396' width='100' height='16'/>
<!-- Whee... time for the status effects! Fifteen per PC! -->
<pict name='pc1-stat1' type='status' num='0' top='84' left='334'/> <pict name='pc1-stat2' type='status' num='0' top='84' left='347'/>
<pict name='pc1-stat3' type='status' num='0' top='84' left='360'/> <pict name='pc1-stat4' type='status' num='0' top='84' left='373'/>
<pict name='pc1-stat5' type='status' num='0' top='84' left='386'/> <pict name='pc1-stat6' type='status' num='0' top='84' left='399'/>
<pict name='pc1-stat7' type='status' num='0' top='84' left='412'/> <pict name='pc1-stat8' type='status' num='0' top='84' left='425'/>
<pict name='pc1-stat9' type='status' num='0' top='84' left='438'/> <pict name='pc1-stat10' type='status' num='0' top='84' left='451'/>
<pict name='pc1-stat11' type='status' num='0' top='84' left='464'/><pict name='pc1-stat12' type='status' num='0' top='84' left='477'/>
<pict name='pc1-stat13' type='status' num='0' top='84' left='490'/><pict name='pc1-stat14' type='status' num='0' top='84' left='503'/>
<pict name='pc1-stat15' type='status' num='0' top='84' left='516'/>
<pict name='pc2-stat1' type='status' num='0' top='109' left='334'/> <pict name='pc2-stat2' type='status' num='0' top='109' left='347'/>
<pict name='pc2-stat3' type='status' num='0' top='109' left='360'/> <pict name='pc2-stat4' type='status' num='0' top='109' left='373'/>
<pict name='pc2-stat5' type='status' num='0' top='109' left='386'/> <pict name='pc2-stat6' type='status' num='0' top='109' left='399'/>
<pict name='pc2-stat7' type='status' num='0' top='109' left='412'/> <pict name='pc2-stat8' type='status' num='0' top='109' left='425'/>
<pict name='pc2-stat9' type='status' num='0' top='109' left='438'/> <pict name='pc2-stat10' type='status' num='0' top='109' left='451'/>
<pict name='pc2-stat11' type='status' num='0' top='109' left='464'/><pict name='pc2-stat12' type='status' num='0' top='109' left='477'/>
<pict name='pc2-stat13' type='status' num='0' top='109' left='490'/><pict name='pc2-stat14' type='status' num='0' top='109' left='503'/>
<pict name='pc2-stat15' type='status' num='0' top='109' left='516'/>
<pict name='pc3-stat1' type='status' num='0' top='134' left='334'/> <pict name='pc3-stat2' type='status' num='0' top='134' left='347'/>
<pict name='pc3-stat3' type='status' num='0' top='134' left='360'/> <pict name='pc3-stat4' type='status' num='0' top='134' left='373'/>
<pict name='pc3-stat5' type='status' num='0' top='134' left='386'/> <pict name='pc3-stat6' type='status' num='0' top='134' left='399'/>
<pict name='pc3-stat7' type='status' num='0' top='134' left='412'/> <pict name='pc3-stat8' type='status' num='0' top='134' left='425'/>
<pict name='pc3-stat9' type='status' num='0' top='134' left='438'/> <pict name='pc3-stat10' type='status' num='0' top='134' left='451'/>
<pict name='pc3-stat11' type='status' num='0' top='134' left='464'/><pict name='pc3-stat12' type='status' num='0' top='134' left='477'/>
<pict name='pc3-stat13' type='status' num='0' top='134' left='490'/><pict name='pc3-stat14' type='status' num='0' top='134' left='503'/>
<pict name='pc3-stat15' type='status' num='0' top='134' left='516'/>
<pict name='pc4-stat1' type='status' num='0' top='159' left='334'/> <pict name='pc4-stat2' type='status' num='0' top='159' left='347'/>
<pict name='pc4-stat3' type='status' num='0' top='159' left='360'/> <pict name='pc4-stat4' type='status' num='0' top='159' left='373'/>
<pict name='pc4-stat5' type='status' num='0' top='159' left='386'/> <pict name='pc4-stat6' type='status' num='0' top='159' left='399'/>
<pict name='pc4-stat7' type='status' num='0' top='159' left='412'/> <pict name='pc4-stat8' type='status' num='0' top='159' left='425'/>
<pict name='pc4-stat9' type='status' num='0' top='159' left='438'/> <pict name='pc4-stat10' type='status' num='0' top='159' left='451'/>
<pict name='pc4-stat11' type='status' num='0' top='159' left='464'/><pict name='pc4-stat12' type='status' num='0' top='159' left='477'/>
<pict name='pc4-stat13' type='status' num='0' top='159' left='490'/><pict name='pc4-stat14' type='status' num='0' top='159' left='503'/>
<pict name='pc4-stat15' type='status' num='0' top='159' left='516'/>
<pict name='pc5-stat1' type='status' num='0' top='184' left='334'/> <pict name='pc5-stat2' type='status' num='0' top='184' left='347'/>
<pict name='pc5-stat3' type='status' num='0' top='184' left='360'/> <pict name='pc5-stat4' type='status' num='0' top='184' left='373'/>
<pict name='pc5-stat5' type='status' num='0' top='184' left='386'/> <pict name='pc5-stat6' type='status' num='0' top='184' left='399'/>
<pict name='pc5-stat7' type='status' num='0' top='184' left='412'/> <pict name='pc5-stat8' type='status' num='0' top='184' left='425'/>
<pict name='pc5-stat9' type='status' num='0' top='184' left='438'/> <pict name='pc5-stat10' type='status' num='0' top='184' left='451'/>
<pict name='pc5-stat11' type='status' num='0' top='184' left='464'/><pict name='pc5-stat12' type='status' num='0' top='184' left='477'/>
<pict name='pc5-stat13' type='status' num='0' top='184' left='490'/><pict name='pc5-stat14' type='status' num='0' top='184' left='503'/>
<pict name='pc5-stat15' type='status' num='0' top='184' left='516'/>
<pict name='pc6-stat1' type='status' num='0' top='209' left='334'/> <pict name='pc6-stat2' type='status' num='0' top='209' left='347'/>
<pict name='pc6-stat3' type='status' num='0' top='209' left='360'/> <pict name='pc6-stat4' type='status' num='0' top='209' left='373'/>
<pict name='pc6-stat5' type='status' num='0' top='209' left='386'/> <pict name='pc6-stat6' type='status' num='0' top='209' left='399'/>
<pict name='pc6-stat7' type='status' num='0' top='209' left='412'/> <pict name='pc6-stat8' type='status' num='0' top='209' left='425'/>
<pict name='pc6-stat9' type='status' num='0' top='209' left='438'/> <pict name='pc6-stat10' type='status' num='0' top='209' left='451'/>
<pict name='pc6-stat11' type='status' num='0' top='209' left='464'/><pict name='pc6-stat12' type='status' num='0' top='209' left='477'/>
<pict name='pc6-stat13' type='status' num='0' top='209' left='490'/><pict name='pc6-stat14' type='status' num='0' top='209' left='503'/>
<pict name='pc6-stat15' type='status' num='0' top='209' left='516'/>
</dialog>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB