Skip to content

Commit

Permalink
Some item ability stuff
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
CelticMinstrel committed Oct 12, 2015
1 parent b61200f commit ba98427
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 13 deletions.
8 changes: 4 additions & 4 deletions rsrc/strings/item-abilities.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ Unused
Weak weapon
Cause fear
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



Expand Down
37 changes: 32 additions & 5 deletions src/boe.combat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
short r1, r2;
cPlayer& attacker = univ.party[who_att];
eSkill what_skill = weap.weap_type;

// safety valve
if(what_skill == eSkill::INVALID)
what_skill = eSkill::EDGED_WEAPONS;
int skill;
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.";
add_string_to_buf(create_line);
Expand Down Expand Up @@ -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(weap.ability == eItemAbil::WEAK_WEAPON)
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)) {
// PCs get some additional defensive perks
Expand All @@ -755,7 +768,7 @@ void pc_attack_weapon(short who_att,iLiving& target,short hit_adj,short dam_adj,
do_explosion_anim(5,0);
end_missile_anim();
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;
short spec_dam = calc_spec_dam(weap.ability,weap.abil_data[0],weap.abil_data[1],target,dmg_tp);
short bonus_dam = 0;
Expand Down Expand Up @@ -1714,7 +1727,13 @@ void fire_missile(location target) {
cItem& missile = missile_firer.items[missile_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;
dam = ammo.item_level;
dam_bonus = ammo.bonus + minmax(-8,8,missile_firer.status[eStatus::BLESS_CURSE]);
Expand Down Expand Up @@ -1795,6 +1814,14 @@ void fire_missile(location target) {
r2 = get_ran(1,1,dam) + dam_bonus;
if(ammo.ability == eItemAbil::WEAK_WEAPON)
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.";
add_string_to_buf(create_line);

Expand Down
1 change: 1 addition & 0 deletions src/boe.specials.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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::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::HP_DAMAGE: case eItemAbil::HP_DAMAGE_REVERSE: case eItemAbil::SP_DAMAGE: case eItemAbil::SP_DAMAGE_REVERSE:
break;
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/classes/estreams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ template<typename E> bool readEnum(std::istream& in, E& to, cEnumLookup& tbl, E
cEnumLookup skill_names = {
"str", "dex", "int", "edged", "bashing", "pole", "thrown", "archery", "defense",
"mage", "priest", "mage-lore", "alchemy", "item-lore", "traps", "lockpick", "assassin", "poison", "luck",
"hp", "sp",
};

std::ostream& operator << (std::ostream& out, eSkill e) {
Expand Down Expand Up @@ -203,9 +204,9 @@ std::istream& operator >> (std::istream& in, eItemUse& e){

cEnumLookup item_abils = {
"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",
"regen", "poison-aug", "radiant", "will", "freedom", "speed", "slow", "prot-race", "lockpick", "missile-drain",
"spec-drop", "", "", "", "", "", "", "", "", "",
Expand Down
4 changes: 4 additions & 0 deletions src/classes/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,10 @@ std::string cItem::getAbilName() const {
case eItemAbil::SOULSUCKER: sout << "Soulsucker"; break;
case eItemAbil::DRAIN_MISSILES: sout << "Drain Missiles"; 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::WEAPON_CALL_SPECIAL: sout << "Unusual Attack Effect"; break;
case eItemAbil::FULL_PROTECTION: sout << "Full Protection"; break;
Expand Down
4 changes: 4 additions & 0 deletions src/classes/simpletypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,10 @@ enum class eItemAbil {
WEAK_WEAPON = 12,
CAUSES_FEAR = 13,
WEAPON_CALL_SPECIAL = 14,
HP_DAMAGE = 15,
HP_DAMAGE_REVERSE = 16,
SP_DAMAGE = 17,
SP_DAMAGE_REVERSE = 18,
// General abilities
DAMAGE_PROTECTION = 30,
FULL_PROTECTION = 31,
Expand Down
2 changes: 1 addition & 1 deletion src/scenedit/scen.core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
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;
eItemAbil abil = eItemAbil(i + 1);
if(abil >= eItemAbil::RETURNING_MISSILE && abil <= eItemAbil::SEEKING_MISSILE) {
Expand Down
2 changes: 1 addition & 1 deletion test/enums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ static void test_enum(T val, string sym, Rest... rest) {
}

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(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");
Expand Down

0 comments on commit ba98427

Please sign in to comment.