Update the edit item dialog for new things (missiles, arbitrary key weapon skills)

- Also, missile weapons now use the key skill as well
- Fix guessing of missile types - using the item level didn't work out since the levels weren't what the original code expected, so now it just goes by the name
This commit is contained in:
2015-01-19 15:49:46 -05:00
parent 5450ae1caf
commit bbe8e766ca
4 changed files with 144 additions and 88 deletions

View File

@@ -26,8 +26,8 @@
-->
<group name='variety'>
<led name='none' state='off' top='89' left='106' width='90'>No Item</led>
<led name='weap1' state='off' top='104' left='106' width='90'>1-Handed weapon</led>
<led name='weap2' state='off' top='119' left='106' width='90'>2-Handed weapon</led>
<led name='weap1' state='off' top='104' left='106' width='90'>1-Hand weapon</led>
<led name='weap2' state='off' top='119' left='106' width='90'>2-Hand weapon</led>
<led name='gold' state='off' top='134' left='106' width='90'>Gold</led>
<led name='bow' state='off' top='149' left='106' width='90'>Bow</led>
<led name='arrow' state='off' top='164' left='106' width='90'>Arrows</led>
@@ -44,7 +44,7 @@
<!--
TODO: Why are there two shields?
-->
<led name='shield2' state='off' top='119' left='336' width='90'>Shield</led>
<led name='shield2' state='off' top='119' left='336' width='90'>Shield 2</led>
<led name='boots' state='off' top='134' left='336' width='90'>Boots</led>
<led name='ring' state='off' top='149' left='336' width='90'>Ring</led>
<led name='necklace' state='off' top='164' left='336' width='90'>Necklace</led>
@@ -57,14 +57,6 @@
<led name='unused1' state='off' top='164' left='448' width='90'>Unused</led>
<led name='unused2' state='off' top='179' left='448' width='80'>Unused</led>
</group>
<!--
NOTE: These LEDs have been shifted 80 pixels left to account for the labels swapping sides
-->
<group name='melee-type'>
<led name='edge' state='off' top='233' left='442' width='80'>Edged</led>
<led name='bash' state='off' top='248' left='442' width='80'>Bashing</led>
<led name='pole' state='off' top='263' left='442' width='80'>Pole</led>
</group>
<pict name="pic" type='dlog' num='16' top='8' left='11'/>
<text size='large' top='6' left='50' width='158' height='16'>Edit an Item Type</text>
<text top='8' left='222' width='111' height='14'>Item number:</text>
@@ -83,7 +75,13 @@
<text top='224' left='220' width='141' height='13'>Value: (0-10000)</text>
<text top='248' left='220' width='141' height='13'>Weight: (0-250)</text>
<text top='272' left='220' width='141' height='13'>Special class: (0-100)</text>
<text top='200' left='425' width='161' height='28'>Weapon type: (ignored if not a weapon)</text>
<text name='missile-title' top='200' left='440' width='140' height='16'>Missile type:</text>
<field name='missile' top='223' left='463' width='50' height='16'/>
<pict name='missile-pic' type='missile' num='3' top='223' left='440'/>
<button name='choosemiss' type='regular' top='220' left='521'>Choose</button>
<text name='skill-title' top='250' left='440' width='140' height='16'>Weapon key skill:</text>
<field name='weap-type' top='271' left='440' width='73' height='16'/>
<button name='choosetp' type='regular' top='268' left='521'>Choose</button>
<text top='293' left='221' width='363' height='40'>
Enter properties for this item type.
For a detailed description of the fields, see the documentation.

View File

@@ -1475,17 +1475,18 @@ void load_missile() {
}
void fire_missile(location target) {
short r1, r2, skill, dam, dam_bonus, hit_bonus, range, targ_monst, spec_dam = 0,poison_amt = 0;
short r1, r2, skill, dam, dam_bonus, hit_bonus = 0, range, targ_monst, spec_dam = 0,poison_amt = 0;
short skill_item;
cCreature *cur_monst;
bool exploding = false;
missile_firer = current_pc;
skill = overall_mode == MODE_FIRING ? univ.party[missile_firer].skills[eSkill::ARCHERY] : univ.party[missile_firer].skills[eSkill::THROWN_MISSILES];
skill = univ.party[missile_firer].skills[univ.party[missile_firer].items[missile_inv_slot].weap_type];
range = (overall_mode == MODE_FIRING) ? 12 : 8;
dam = univ.party[missile_firer].items[ammo_inv_slot].item_level;
dam_bonus = univ.party[missile_firer].items[ammo_inv_slot].bonus + minmax(-8,8,univ.party[missile_firer].status[eStatus::BLESS_CURSE]);
hit_bonus = (overall_mode == MODE_FIRING) ? univ.party[missile_firer].items[missile_inv_slot].bonus : 0;
if(overall_mode == MODE_FIRING)
hit_bonus = univ.party[missile_firer].items[missile_inv_slot].bonus;
hit_bonus += stat_adj(missile_firer,eSkill::DEXTERITY) - can_see_light(univ.party[missile_firer].combat_pos,target,sight_obscurity)
+ minmax(-8,8,univ.party[missile_firer].status[eStatus::BLESS_CURSE]);
if((skill_item = univ.party[missile_firer].has_abil_equip(eItemAbil::ACCURACY)) < 24) {

View File

@@ -247,9 +247,13 @@ void cItem::append(legacy::item_record_type& old){
bonus = old.bonus;
protection = old.protection;
charges = old.charges;
if(old.type >= 3 && old.type <= 5)
weap_type = eSkill(old.type);
if(old.type >= 1 && old.type <= 3)
weap_type = eSkill(old.type + 2);
else weap_type = eSkill::INVALID;
if(variety == eItemType::BOW || variety == eItemType::CROSSBOW || variety == eItemType::MISSILE_NO_AMMO)
weap_type = eSkill::ARCHERY;
else if(variety == eItemType::THROWN_MISSILE)
weap_type = eSkill::THROWN_MISSILES;
magic_use_type = old.magic_use_type;
graphic_num = old.graphic_num;
if(graphic_num >= 150) // custom item graphic
@@ -742,42 +746,28 @@ void cItem::append(legacy::item_record_type& old){
case eItemType::BOLTS:
missile = magic ? 4 : 3;
break;
case eItemType::THROWN_MISSILE:
// This is tricky... basically, all we can really do is guess.
// We'll base our guess on the item's level, since the preset items have standard levels
switch(item_level) {
case 7: // Throwing knives
missile = 10;
break;
case 4: // Darts
missile = 1;
break;
case 8: // Javelins
missile = 5;
break;
case 9: // Razordisks
missile = 7;
break;
default:
auto npos = std::string::npos;
// Okay, that failed. Try examining the item's name.
// We'll use the unidentified name since it's more likely to contain the appropriate generic words
if(name.find("Knife") != npos) missile = 10;
else if(name.find("Knives") != npos) missile = 10;
else if(name.find("Spear") != npos) missile = 5;
else if(name.find("Javelin") != npos) missile = 5;
else if(name.find("Razordisk") != npos) missile = 7;
else if(name.find("Star") != npos) missile = 7;
else if(name.find("Dart") != npos) missile = 1;
else if(name.find("Rock") != npos) missile = 12;
// Okay, give up. Fall back to darts since we have no idea what's correct.
else missile = 1;
break;
}
case eItemType::MISSILE_NO_AMMO:
// Just assume it's a sling and use the rock missile.
missile = 12;
break;
case eItemType::THROWN_MISSILE:
// This is tricky... basically, all we can really do is guess.
// And the only way to guess is by examining the item's name
// We'll use the unidentified name since it's more likely to contain the appropriate generic words
auto npos = std::string::npos;
// Okay, that failed. Try examining the item's name.
if(name.find("Knife") != npos) missile = 10;
// Unidentified name limit was quite short, so the S might've been cut off
else if(name.find("Knive") != npos) missile = 10;
else if(name.find("Spear") != npos) missile = 5;
else if(name.find("Javelin") != npos) missile = 5;
else if(name.find("Razordisk") != npos) missile = 7;
else if(name.find("Star") != npos) missile = 7;
else if(name.find("Dart") != npos) missile = 1;
else if(name.find("Rock") != npos) missile = 12;
// Okay, give up. Fall back to darts since we have no idea what's correct.
else missile = 1;
break;
}
}

View File

@@ -1113,6 +1113,8 @@ static void put_item_info_in_dlog(cDialog& me, cItem& store_item, short which_it
else dynamic_cast<cPict&>(me["pic"]).setPict(store_item.graphic_num, PIC_ITEM);
me["picnum"].setTextToNum(store_item.graphic_num);
bool missile = false, weapon = false;
cLedGroup& variety = dynamic_cast<cLedGroup&>(me["variety"]);
switch(store_item.variety) {
case eItemType::NO_ITEM:
@@ -1120,21 +1122,27 @@ static void put_item_info_in_dlog(cDialog& me, cItem& store_item, short which_it
break;
case eItemType::ONE_HANDED:
variety.setSelected("weap1");
weapon = true;
break;
case eItemType::TWO_HANDED:
variety.setSelected("weap2");
weapon = true;
break;
case eItemType::GOLD:
variety.setSelected("gold");
break;
case eItemType::BOW:
variety.setSelected("bow");
weapon = true;
break;
case eItemType::ARROW:
variety.setSelected("arrow");
missile = true;
break;
case eItemType::THROWN_MISSILE:
variety.setSelected("thrown");
missile = true;
weapon = true;
break;
case eItemType::POTION:
variety.setSelected("potion");
@@ -1186,12 +1194,16 @@ static void put_item_info_in_dlog(cDialog& me, cItem& store_item, short which_it
break;
case eItemType::CROSSBOW:
variety.setSelected("xbow");
weapon = true;
break;
case eItemType::BOLTS:
variety.setSelected("bolt");
missile = true;
break;
case eItemType::MISSILE_NO_AMMO:
variety.setSelected("missile");
missile = true;
weapon = true;
break;
case eItemType::UNUSED1:
variety.setSelected("unused1");
@@ -1201,18 +1213,31 @@ static void put_item_info_in_dlog(cDialog& me, cItem& store_item, short which_it
break;
}
cLedGroup& weapType = dynamic_cast<cLedGroup&>(me["melee-type"]);
switch(store_item.weap_type) {
case eSkill::INVALID:
case eSkill::EDGED_WEAPONS:
weapType.setSelected("edge");
break;
case eSkill::BASHING_WEAPONS:
weapType.setSelected("bash");
break;
case eSkill::POLE_WEAPONS:
weapType.setSelected("pole");
break;
if(missile) {
me["missile"].show();
me["missile-pic"].show();
me["missile-pic"].show();
me["choosemiss"].show();
me["missile"].setTextToNum(store_item.missile);
dynamic_cast<cPict&>(me["missile-pic"]).setPict(store_item.missile);
} else {
me["missile"].hide();
me["missile-title"].hide();
me["missile-pic"].hide();
me["choosemiss"].hide();
me["missile"].setText("0");
}
if(weapon) {
me["skill-title"].show();
me["weap-type"].show();
me["choosetp"].show();
me["weap-type"].setTextToNum(int(store_item.weap_type));
} else {
me["skill-title"].hide();
me["weap-type"].hide();
me["choosetp"].hide();
me["weap-type"].setText("0");
}
me["level"].setTextToNum(store_item.item_level);
@@ -1226,7 +1251,7 @@ static void put_item_info_in_dlog(cDialog& me, cItem& store_item, short which_it
me["class"].setTextToNum(store_item.special_class);
}
static bool save_item_info(cDialog& me, cItem& store_item, short which_item) {
static void save_item_info(cDialog& me, cItem& store_item, short which_item) {
store_item.full_name = me["full"].getText();
store_item.name = me["short"].getText();
store_item.graphic_num = me["picnum"].getTextAsNum();
@@ -1260,13 +1285,8 @@ static bool save_item_info(cDialog& me, cItem& store_item, short which_item) {
else if(variety == "missile") store_item.variety = eItemType::MISSILE_NO_AMMO;
else if(variety == "unused1") store_item.variety = eItemType::UNUSED1;
else if(variety == "unused2") store_item.variety = eItemType::UNUSED2;
store_item.weap_type = eSkill::INVALID;
if(store_item.variety == eItemType::ONE_HANDED || store_item.variety == eItemType::TWO_HANDED) {
std::string weapType = dynamic_cast<cLedGroup&>(me["melee-type"]).getSelected();
if(weapType == "edge") store_item.weap_type = eSkill::EDGED_WEAPONS;
else if(weapType == "bash") store_item.weap_type = eSkill::BASHING_WEAPONS;
else if(weapType == "pole") store_item.weap_type = eSkill::POLE_WEAPONS;
}
store_item.weap_type = eSkill(me["weap-type"].getTextAsNum());
store_item.missile = me["missile"].getTextAsNum();
store_item.item_level = me["level"].getTextAsNum();
if((store_item.variety == eItemType::GOLD || store_item.variety == eItemType::FOOD) && store_item.item_level == 0)
@@ -1281,48 +1301,62 @@ static bool save_item_info(cDialog& me, cItem& store_item, short which_item) {
store_item.weight = me["weight"].getTextAsNum();
store_item.special_class = me["class"].getTextAsNum();
if((store_item.type_flag > 0) && (store_item.charges == 0)) {
giveError("If the Type Flag is greater than 0, the Charges must also be greater than 0.","",&me);
return false;
}
if(store_item.variety == eItemType::UNUSED1 || store_item.variety == eItemType::UNUSED2) {
giveError("The Unused item varieties are reserved for later expansions, and can't be used now.","",&me);
return false;
}
int was_charges = store_item.charges;
if(store_item.type_flag > 0 && store_item.charges == 0)
store_item.charges = 1;
eItemAbilCat cat = getItemAbilCategory(store_item.ability);
if((cat == eItemAbilCat::SPELL || cat == eItemAbilCat::NONSPELL || cat == eItemAbilCat::REAGENT) && (store_item.charges == 0)) {
giveError("An item with the special ability selected must have at least 1 charge.","",&me);
return false;
}
scenario.scen_items[which_item] = store_item;
return true;
if((cat == eItemAbilCat::SPELL || cat == eItemAbilCat::NONSPELL || cat == eItemAbilCat::REAGENT) && store_item.charges == 0)
store_item.charges = 1;
if(was_charges != store_item.charges)
giveError("Due to either the selected special ability or the presence of a type flag, this item's charges have been set to 1.", &me);
}
static bool edit_item_type_event_filter(cDialog& me, std::string item_hit, cItem& store_item, short& store_which_item) {
short i;
cItem temp_item;
std::string variety = dynamic_cast<cLedGroup&>(me["variety"]).getSelected();
bool valid = true;
if(variety.substr(0,6) == "unused") valid = false;
if(!valid && item_hit != "cancel" && item_hit.substr(0,6) != "choose") {
giveError("The Unused item varieties are reserved for later expansions, and can't be used now.","",&me);
return true;
}
if(item_hit == "cancel") {
me.toast(false);
} else if(item_hit == "okay") {
if(save_item_info(me, store_item, store_which_item)) me.toast(true);
save_item_info(me, store_item, store_which_item);
if(!me.toast(true)) return true;
scenario.scen_items[store_which_item] = store_item;
} else if(item_hit == "prev") {
if(!save_item_info(me, store_item, store_which_item)) return true;
save_item_info(me, store_item, store_which_item);
scenario.scen_items[store_which_item] = store_item;
store_which_item--;
if(store_which_item < 0) store_which_item = 399;
store_item = scenario.scen_items[store_which_item];
put_item_info_in_dlog(me, store_item, store_which_item);
} else if(item_hit == "next") {
if(!save_item_info(me, store_item, store_which_item)) return true;
save_item_info(me, store_item, store_which_item);
scenario.scen_items[store_which_item] = store_item;
store_which_item++;
if(store_which_item > 399) store_which_item = 0;
store_item = scenario.scen_items[store_which_item];
put_item_info_in_dlog(me, store_item, store_which_item);
} else if(item_hit == "choosepic") {
if(!save_item_info(me, store_item, store_which_item)) return true;
save_item_info(me, store_item, store_which_item);
i = pick_picture(PIC_ITEM, me, "picnum", "pic");
if(i < 0) return true;
store_item.graphic_num = i;
} else if(item_hit == "choosetp") {
save_item_info(me, store_item, store_which_item);
i = choose_text(STRT_SKILL, int(store_item.weap_type), &me, "Select the weapon's key skill:");
store_item.weap_type = eSkill(i);
me["weap-type"].setTextToNum(i);
} else if(item_hit == "choosemiss") {
save_item_info(me, store_item, store_which_item);
i = pick_picture(PIC_MISSILE, me, "missile", "missile-pic");
if(i < 0) return true;
store_item.missile = i;
} else if(item_hit == "abils") {
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);
@@ -1339,6 +1373,38 @@ static bool edit_item_type_event_filter(cDialog& me, std::string item_hit, cItem
return true;
}
static bool change_item_variety(cDialog& me, std::string group, const cItem& item) {
std::string hit = dynamic_cast<cLedGroup&>(me[group]).getSelected();
if(hit == "arrow" || hit == "thrown" || hit == "bolt" || hit == "missile") {
me["missile"].show();
me["missile-pic"].show();
me["missile-pic"].show();
me["choosemiss"].show();
me["missile"].setTextToNum(item.missile);
dynamic_cast<cPict&>(me["missile-pic"]).setPict(item.missile);
} else {
me["missile"].hide();
me["missile-title"].hide();
me["missile-pic"].hide();
me["choosemiss"].hide();
me["missile"].setText("0");
}
if(hit.substr(0,4) == "weap" || hit == "bow" || hit == "xbow" || hit == "missile" || hit == "thrown") {
me["skill-title"].show();
me["weap-type"].show();
me["choosetp"].show();
me["weap-type"].setTextToNum(int(item.weap_type));
} else {
me["skill-title"].hide();
me["weap-type"].hide();
me["choosetp"].hide();
me["weap-type"].setText("0");
}
return true;
}
short edit_item_type(short which_item) {
using namespace std::placeholders;
cItem store_item = scenario.scen_items[which_item];
@@ -1353,7 +1419,8 @@ short edit_item_type(short which_item) {
item_dlg["value"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 10000, "Value"));
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.attachClickHandlers(std::bind(edit_item_type_event_filter, _1, _2, std::ref(store_item), std::ref(which_item)), {"okay", "cancel", "prev", "next", "abils", "choosepic"});
item_dlg["variety"].attachFocusHandler(std::bind(change_item_variety, _1, _2, std::ref(store_item)));
item_dlg.attachClickHandlers(std::bind(edit_item_type_event_filter, _1, _2, std::ref(store_item), std::ref(which_item)), {"okay", "cancel", "prev", "next", "abils", "choosepic", "choosetp", "choosemiss"});
put_item_info_in_dlog(item_dlg, store_item, which_item);