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:
@@ -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
|
||||
|
||||
|
||||
|
||||
|
@@ -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);
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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]);
|
||||
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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) {
|
||||
@@ -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", "", "", "", "", "", "", "", "", "",
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
@@ -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) {
|
||||
|
@@ -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");
|
||||
|
Reference in New Issue
Block a user