Some item ability stuff

- Two new item abilities that increase damage as sp/hp is lost
- Two new item abilities that reduce damage as sp/hp is lost
- Support for using sp/hp as a weapon's key skill to determine hit chance
This commit is contained in:
2015-10-12 14:11:27 -04:00
parent b61200f627
commit ba984279b0
8 changed files with 50 additions and 13 deletions

View File

@@ -12,10 +12,10 @@ Unused
Weak weapon Weak weapon
Cause fear Cause fear
Call special when attacking Call special when attacking
Does less damage as health lost
Does more damage as health lost
Does less damage as SP lost
Does more damage as SP lost

View File

@@ -702,11 +702,16 @@ static void apply_weapon_status(eStatus status, int how_much, int dmg, iLiving&
void pc_attack_weapon(short who_att,iLiving& target,short hit_adj,short dam_adj,cItem& weap,short primary,bool do_poison) { void pc_attack_weapon(short who_att,iLiving& target,short hit_adj,short dam_adj,cItem& weap,short primary,bool do_poison) {
short r1, r2; short r1, r2;
cPlayer& attacker = univ.party[who_att]; cPlayer& attacker = univ.party[who_att];
eSkill what_skill = weap.weap_type;
// safety valve // safety valve
if(what_skill == eSkill::INVALID) int skill;
what_skill = eSkill::EDGED_WEAPONS; if(weap.weap_type == eSkill::INVALID)
skill = univ.party[who_att].skill(eSkill::EDGED_WEAPONS);
else if(weap.weap_type == eSkill::MAX_HP)
skill = 20 * univ.party[who_att].cur_health / univ.party[who_att].m_health;
else if(weap.weap_type == eSkill::MAX_SP)
skill = 20 * univ.party[who_att].cur_sp / univ.party[who_att].max_sp;
else skill = univ.party[who_att].skill(weap.weap_type);
std::string create_line = attacker.name + " swings."; std::string create_line = attacker.name + " swings.";
add_string_to_buf(create_line); add_string_to_buf(create_line);
@@ -734,6 +739,14 @@ void pc_attack_weapon(short who_att,iLiving& target,short hit_adj,short dam_adj,
if(primary) r2 += 2; else r2 -= 1; if(primary) r2 += 2; else r2 -= 1;
if(weap.ability == eItemAbil::WEAK_WEAPON) if(weap.ability == eItemAbil::WEAK_WEAPON)
r2 = (r2 * (10 - weap.abil_data[0])) / 10; r2 = (r2 * (10 - weap.abil_data[0])) / 10;
if(weap.ability == eItemAbil::HP_DAMAGE)
r2 = std::max<short>(1, double(r2) * double(attacker.cur_health) / double(attacker.max_health));
if(weap.ability == eItemAbil::SP_DAMAGE)
r2 = std::max<short>(1, double(r2) * double(attacker.cur_sp) / double(attacker.max_sp));
if(weap.ability == eItemAbil::HP_DAMAGE_REVERSE)
r2 += double(weap.abil_data[0]) * (1.0 - double(attacker.cur_health) / double(attacker.max_health));
if(weap.ability == eItemAbil::SP_DAMAGE_REVERSE)
r2 += double(weap.abil_data[0]) * (1.0 - double(attacker.cur_sp) / double(attacker.max_sp));
if(cPlayer* pc_target = dynamic_cast<cPlayer*>(&target)) { if(cPlayer* pc_target = dynamic_cast<cPlayer*>(&target)) {
// PCs get some additional defensive perks // PCs get some additional defensive perks
@@ -755,7 +768,7 @@ void pc_attack_weapon(short who_att,iLiving& target,short hit_adj,short dam_adj,
do_explosion_anim(5,0); do_explosion_anim(5,0);
end_missile_anim(); end_missile_anim();
handle_marked_damage(); handle_marked_damage();
} else if(r1 <= hit_chance[univ.party[who_att].skill(what_skill)]) { } else if(r1 <= hit_chance[skill]) {
eDamageType dmg_tp = eDamageType::SPECIAL; eDamageType dmg_tp = eDamageType::SPECIAL;
short spec_dam = calc_spec_dam(weap.ability,weap.abil_data[0],weap.abil_data[1],target,dmg_tp); short spec_dam = calc_spec_dam(weap.ability,weap.abil_data[0],weap.abil_data[1],target,dmg_tp);
short bonus_dam = 0; short bonus_dam = 0;
@@ -1714,7 +1727,13 @@ void fire_missile(location target) {
cItem& missile = missile_firer.items[missile_inv_slot]; cItem& missile = missile_firer.items[missile_inv_slot];
cItem& ammo = missile_firer.items[ammo_inv_slot]; cItem& ammo = missile_firer.items[ammo_inv_slot];
skill = missile_firer.skill(missile.weap_type); if(missile.weap_type == eSkill::INVALID)
skill = missile_firer.skill(eSkill::ARCHERY);
else if(missile.weap_type == eSkill::MAX_HP)
skill = 20 * missile_firer.cur_health / missile_firer.m_health;
else if(missile.weap_type == eSkill::MAX_SP)
skill = 20 * missile_firer.cur_sp / missile_firer.max_sp;
else skill = missile_firer.skill(missile.weap_type);
range = (overall_mode == MODE_FIRING) ? 12 : 8; range = (overall_mode == MODE_FIRING) ? 12 : 8;
dam = ammo.item_level; dam = ammo.item_level;
dam_bonus = ammo.bonus + minmax(-8,8,missile_firer.status[eStatus::BLESS_CURSE]); dam_bonus = ammo.bonus + minmax(-8,8,missile_firer.status[eStatus::BLESS_CURSE]);
@@ -1795,6 +1814,14 @@ void fire_missile(location target) {
r2 = get_ran(1,1,dam) + dam_bonus; r2 = get_ran(1,1,dam) + dam_bonus;
if(ammo.ability == eItemAbil::WEAK_WEAPON) if(ammo.ability == eItemAbil::WEAK_WEAPON)
r2 = (r2 * (10 - ammo.abil_data[0])) / 10; r2 = (r2 * (10 - ammo.abil_data[0])) / 10;
if(ammo.ability == eItemAbil::HP_DAMAGE)
r2 = std::max<short>(1, double(r2) * double(missile_firer.cur_health) / double(missile_firer.max_health));
if(ammo.ability == eItemAbil::SP_DAMAGE)
r2 = std::max<short>(1, double(r2) * double(missile_firer.cur_sp) / double(missile_firer.max_sp));
if(ammo.ability == eItemAbil::HP_DAMAGE_REVERSE)
r2 += double(ammo.abil_data[0]) * (1.0 - double(missile_firer.cur_health) / double(missile_firer.max_health));
if(ammo.ability == eItemAbil::SP_DAMAGE_REVERSE)
r2 += double(ammo.abil_data[0]) * (1.0 - double(missile_firer.cur_sp) / double(missile_firer.max_sp));
std::string create_line = missile_firer.name + " fires."; std::string create_line = missile_firer.name + " fires.";
add_string_to_buf(create_line); add_string_to_buf(create_line);

View File

@@ -1180,6 +1180,7 @@ void use_item(short pc,short item) {
case eItemAbil::SMOKY_CRYSTAL: case eItemAbil::SOULSUCKER: case eItemAbil::SPEED: case eItemAbil::STATUS_PROTECTION: case eItemAbil::SMOKY_CRYSTAL: case eItemAbil::SOULSUCKER: case eItemAbil::SPEED: case eItemAbil::STATUS_PROTECTION:
case eItemAbil::STATUS_WEAPON: case eItemAbil::THIEVING: case eItemAbil::WEAK_WEAPON: case eItemAbil::WEAPON_CALL_SPECIAL: case eItemAbil::STATUS_WEAPON: case eItemAbil::THIEVING: case eItemAbil::WEAK_WEAPON: case eItemAbil::WEAPON_CALL_SPECIAL:
case eItemAbil::WORMGRASS: case eItemAbil::UNUSED: case eItemAbil::DROP_CALL_SPECIAL: case eItemAbil::WORMGRASS: case eItemAbil::UNUSED: case eItemAbil::DROP_CALL_SPECIAL:
case eItemAbil::HP_DAMAGE: case eItemAbil::HP_DAMAGE_REVERSE: case eItemAbil::SP_DAMAGE: case eItemAbil::SP_DAMAGE_REVERSE:
break; break;
} }
} }

View File

@@ -152,6 +152,7 @@ template<typename E> bool readEnum(std::istream& in, E& to, cEnumLookup& tbl, E
cEnumLookup skill_names = { cEnumLookup skill_names = {
"str", "dex", "int", "edged", "bashing", "pole", "thrown", "archery", "defense", "str", "dex", "int", "edged", "bashing", "pole", "thrown", "archery", "defense",
"mage", "priest", "mage-lore", "alchemy", "item-lore", "traps", "lockpick", "assassin", "poison", "luck", "mage", "priest", "mage-lore", "alchemy", "item-lore", "traps", "lockpick", "assassin", "poison", "luck",
"hp", "sp",
}; };
std::ostream& operator << (std::ostream& out, eSkill e) { std::ostream& operator << (std::ostream& out, eSkill e) {
@@ -203,9 +204,9 @@ std::istream& operator >> (std::istream& in, eItemUse& e){
cEnumLookup item_abils = { cEnumLookup item_abils = {
"none", "weap-dmg", "weap-slay", "weap-heal", "weap-explode", "weap-return", "weap-dist", "weap-seek", "weap-antimagic", "weap-status", "none", "weap-dmg", "weap-slay", "weap-heal", "weap-explode", "weap-return", "weap-dist", "weap-seek", "weap-antimagic", "weap-status",
"weap-soulsuck", "", "weap-weak", "weap-fear", "spec-weap", "", "", "", "", "", "weap-soulsuck", "", "weap-weak", "weap-fear", "spec-weap", "hp-dmg", "hp-dmg-rev", "sp-dmg", "sp-dmg-rev", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"prot-dmg", "prot-full", "prot-melee", "evade", "martyr", "encumber", "prot-status", "skill", "boost-stat", "boost-war", "prot-dmg", "prot-full", "magery", "evade", "martyr", "encumber", "prot-status", "skill", "boost-stat", "boost-war",
"boost-magic", "accuracy", "thief", "giant", "light", "heavy", "status", "spec-hit", "save-life", "prot-petrify", "boost-magic", "accuracy", "thief", "giant", "light", "heavy", "status", "spec-hit", "save-life", "prot-petrify",
"regen", "poison-aug", "radiant", "will", "freedom", "speed", "slow", "prot-race", "lockpick", "missile-drain", "regen", "poison-aug", "radiant", "will", "freedom", "speed", "slow", "prot-race", "lockpick", "missile-drain",
"spec-drop", "", "", "", "", "", "", "", "", "", "spec-drop", "", "", "", "", "", "", "", "", "",

View File

@@ -975,6 +975,10 @@ std::string cItem::getAbilName() const {
case eItemAbil::SOULSUCKER: sout << "Soulsucker"; break; case eItemAbil::SOULSUCKER: sout << "Soulsucker"; break;
case eItemAbil::DRAIN_MISSILES: sout << "Drain Missiles"; break; case eItemAbil::DRAIN_MISSILES: sout << "Drain Missiles"; break;
case eItemAbil::WEAK_WEAPON: sout << "Weak Weapon"; break; case eItemAbil::WEAK_WEAPON: sout << "Weak Weapon"; break;
case eItemAbil::HP_DAMAGE: sout << "Damage Linked to Health"; break;
case eItemAbil::HP_DAMAGE_REVERSE: sout << "Berserker's Weapon"; break;
case eItemAbil::SP_DAMAGE: sout << "Damage Linked to Spell Points"; break;
case eItemAbil::SP_DAMAGE_REVERSE: sout << "Wildmage's Weapon"; break;
case eItemAbil::CAUSES_FEAR: sout << "Causes Fear"; break; case eItemAbil::CAUSES_FEAR: sout << "Causes Fear"; break;
case eItemAbil::WEAPON_CALL_SPECIAL: sout << "Unusual Attack Effect"; break; case eItemAbil::WEAPON_CALL_SPECIAL: sout << "Unusual Attack Effect"; break;
case eItemAbil::FULL_PROTECTION: sout << "Full Protection"; break; case eItemAbil::FULL_PROTECTION: sout << "Full Protection"; break;

View File

@@ -394,6 +394,10 @@ enum class eItemAbil {
WEAK_WEAPON = 12, WEAK_WEAPON = 12,
CAUSES_FEAR = 13, CAUSES_FEAR = 13,
WEAPON_CALL_SPECIAL = 14, WEAPON_CALL_SPECIAL = 14,
HP_DAMAGE = 15,
HP_DAMAGE_REVERSE = 16,
SP_DAMAGE = 17,
SP_DAMAGE_REVERSE = 18,
// General abilities // General abilities
DAMAGE_PROTECTION = 30, DAMAGE_PROTECTION = 30,
FULL_PROTECTION = 31, FULL_PROTECTION = 31,

View File

@@ -1894,7 +1894,7 @@ static bool edit_item_abil_event_filter(cDialog& me, std::string hit, cItem& ite
showError("You can only give an ability of this sort to a weapon.","",&me); showError("You can only give an ability of this sort to a weapon.","",&me);
return true; return true;
} }
i = choose_text_res("item-abilities", 1, 14, int(item.ability), &me, "Choose Weapon Ability (inherent)"); i = choose_text_res("item-abilities", 1, 18, int(item.ability), &me, "Choose Weapon Ability (inherent)");
if(i < 0) return true; if(i < 0) return true;
eItemAbil abil = eItemAbil(i + 1); eItemAbil abil = eItemAbil(i + 1);
if(abil >= eItemAbil::RETURNING_MISSILE && abil <= eItemAbil::SEEKING_MISSILE) { if(abil >= eItemAbil::RETURNING_MISSILE && abil <= eItemAbil::SEEKING_MISSILE) {

View File

@@ -31,7 +31,7 @@ static void test_enum(T val, string sym, Rest... rest) {
} }
TEST_CASE("Enum text conversions") { TEST_CASE("Enum text conversions") {
test_enum(eSkill::STRENGTH, "str", eSkill::LUCK, "luck"); test_enum(eSkill::STRENGTH, "str", eSkill::LUCK, "luck", eSkill::MAX_SP, "sp");
test_enum(eItemType::NO_ITEM, "none", eItemType::QUEST, "quest"); test_enum(eItemType::NO_ITEM, "none", eItemType::QUEST, "quest");
test_enum(eItemUse::HARM_ALL, "harm-all", eItemUse::HELP_ALL, "help-all", eItemUse::HARM_ONE, "harm-one", eItemUse::HELP_ONE, "help-one"); test_enum(eItemUse::HARM_ALL, "harm-all", eItemUse::HELP_ALL, "help-all", eItemUse::HARM_ONE, "harm-one", eItemUse::HELP_ONE, "help-one");
test_enum(eItemAbil::NONE, "none", eItemAbil::SOULSUCKER, "weap-soulsuck", eItemAbil::WEAK_WEAPON, "weap-weak", eItemAbil::WEAPON_CALL_SPECIAL, "spec-weap", eItemAbil::DAMAGE_PROTECTION, "prot-dmg", eItemAbil::DRAIN_MISSILES, "missile-drain", eItemAbil::LOCKPICKS, "lockpick", eItemAbil::DROP_CALL_SPECIAL, "spec-drop", eItemAbil::POISON_WEAPON, "use-poison", eItemAbil::QUICKFIRE, "use-quickfire", eItemAbil::HOLLY, "holly", eItemAbil::RESURRECTION_BALM, "balm"); test_enum(eItemAbil::NONE, "none", eItemAbil::SOULSUCKER, "weap-soulsuck", eItemAbil::WEAK_WEAPON, "weap-weak", eItemAbil::WEAPON_CALL_SPECIAL, "spec-weap", eItemAbil::DAMAGE_PROTECTION, "prot-dmg", eItemAbil::DRAIN_MISSILES, "missile-drain", eItemAbil::LOCKPICKS, "lockpick", eItemAbil::DROP_CALL_SPECIAL, "spec-drop", eItemAbil::POISON_WEAPON, "use-poison", eItemAbil::QUICKFIRE, "use-quickfire", eItemAbil::HOLLY, "holly", eItemAbil::RESURRECTION_BALM, "balm");