diff --git a/data/json/techniques.json b/data/json/techniques.json index f6acb1d85e2f5..e9baee7b8afa8 100644 --- a/data/json/techniques.json +++ b/data/json/techniques.json @@ -38,7 +38,8 @@ "name": "disarm", "melee_allowed": true, "disarms": true, - "description": "Unwield target's weapon" + "description": "Unwield target's weapon", + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -56,7 +57,8 @@ "crit_tec": true, "messages": [ "You swing through %s and everyone nearby", " swings through %s and everyone nearby" ], "aoe": "spin", - "description": "Attack adjacent enemies, crit only, min 4 melee" + "description": "Attack adjacent enemies, crit only, min 4 melee", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -68,7 +70,8 @@ "weighting": 2, "messages": [ "You swing in a wide arc through %s", " swings in a wide arc through %s" ], "aoe": "wide", - "description": "Attack in a wide arc, crit only, min 3 melee" + "description": "Attack in a wide arc, crit only, min 3 melee", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -79,7 +82,8 @@ "crit_tec": true, "messages": [ "You pierce straight through %s", " pierces through %s" ], "aoe": "impale", - "description": "Attack target and another one behind it, crit only, min 4 melee" + "description": "Attack target and another one behind it, crit only, min 4 melee", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -90,7 +94,8 @@ "stun_dur": 1, "knockback_dist": 1, "messages": [ "You send %s reeling", " sends %s reeling" ], - "description": "Stun 1 turn, knockback 1 tile, crit only" + "description": "Stun 1 turn, knockback 1 tile, crit only", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -104,7 +109,8 @@ { "stat": "damage", "type": "stab", "scale": 0.66 } ], "messages": [ "You quickly strike %s", " quickly strikes %s" ], - "description": "50% moves, 66% damage" + "description": "50% moves, 66% damage", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -118,7 +124,8 @@ "Snicker-snack! You slice through %s like hot knife slices through butter.", "Snicker-snack! slices through %s like hot knife slices through butter." ], - "description": "Cut damage multiply by 99, crit only" + "description": "Cut damage multiply by 99, crit only", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -127,7 +134,8 @@ "melee_allowed": true, "stun_dur": 2, "messages": [ "You wrap up %s", " wraps up %s" ], - "description": "Stun 2 turns" + "description": "Stun 2 turns", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -136,7 +144,8 @@ "melee_allowed": true, "down_dur": 2, "messages": [ "You sweep %s", " sweeps %s" ], - "description": "Down 2 turns" + "description": "Down 2 turns", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -146,7 +155,8 @@ "crit_tec": true, "messages": [ "You precisely hit %s", " precisely hits %s" ], "stun_dur": 2, - "description": "Stun 2 turns, crit only" + "description": "Stun 2 turns, crit only", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -155,7 +165,8 @@ "melee_allowed": true, "disarms": true, "messages": [ "You disarm %s using your whip", " disarms %s using their whip" ], - "description": "Unwield target's weapon" + "description": "Unwield target's weapon", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -182,7 +193,8 @@ "melee_allowed": true, "crit_tec": true, "messages": [ "You jab deftly at %s", " jabs deftly at %s" ], - "stun_dur": 2 + "stun_dur": 2, + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -197,7 +209,8 @@ "crit_ok": true, "down_dur": 1, "knockback_dist": 1, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.7 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.7 } ], + "attack_vectors": [ "THROW" ] }, { "type": "technique", @@ -211,7 +224,8 @@ "crit_ok": true, "down_dur": 1, "knockback_dist": 1, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.7 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.7 } ], + "attack_vectors": [ "THROW" ] }, { "type": "technique", @@ -227,7 +241,8 @@ "disarms": true, "down_dur": 1, "knockback_dist": 1, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.7 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.7 } ], + "attack_vectors": [ "THROW" ] }, { "type": "technique", @@ -243,7 +258,8 @@ "disarms": true, "down_dur": 1, "knockback_dist": 1, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.7 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.7 } ], + "attack_vectors": [ "THROW" ] }, { "type": "technique", @@ -267,7 +283,8 @@ "messages": [ "You thrust at the %s", " thrusts at %s" ], "skill_requirements": [ { "name": "melee", "level": 1 } ], "melee_allowed": true, - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.2 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.2 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -282,7 +299,8 @@ "block_counter": true, "crit_ok": true, "down_dur": 1, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -297,7 +315,8 @@ "block_counter": true, "crit_ok": true, "stun_dur": 1, - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.4 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.4 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -309,7 +328,8 @@ "required_buffs_all": [ "buff_bojutsu_onmove" ], "weighting": 2, "crit_ok": true, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.75 }, { "stat": "damage", "type": "bash", "scale": 1.5 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.75 }, { "stat": "damage", "type": "bash", "scale": 1.5 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -330,7 +350,8 @@ "skill_requirements": [ { "name": "melee", "level": 5 } ], "melee_allowed": true, "crit_ok": true, - "disarms": true + "disarms": true, + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -346,7 +367,8 @@ { "stat": "damage", "type": "cut", "scale": 1.1 }, { "stat": "damage", "type": "stab", "scale": 1.1 }, { "stat": "movecost", "scale": 1.2 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -361,7 +383,8 @@ { "stat": "damage", "type": "bash", "scale": 0.66 }, { "stat": "damage", "type": "cut", "scale": 0.66 }, { "stat": "damage", "type": "stab", "scale": 0.66 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -369,7 +392,8 @@ "name": "Cross", "messages": [ "You throw a heavy cross at %s", " throws a cross at %s" ], "unarmed_allowed": true, - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.2 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.2 } ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -385,7 +409,8 @@ "knockback_spread": 1, "stun_dur": 1, "down_dur": 1, - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.5 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.5 } ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -399,7 +424,8 @@ { "stat": "damage", "type": "bash", "scale": 0.66 }, { "stat": "damage", "type": "cut", "scale": 0.66 }, { "stat": "damage", "type": "stab", "scale": 0.66 } - ] + ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -410,7 +436,8 @@ "unarmed_allowed": true, "crit_tec": true, "stun_dur": 1, - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.4 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.4 } ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -459,7 +486,8 @@ "messages": [ "You knock %s's weapon away", " knock %s's weapon away" ], "skill_requirements": [ { "name": "melee", "level": 6 } ], "melee_allowed": true, - "disarms": true + "disarms": true, + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -468,7 +496,8 @@ "messages": [ "You knock %s's weapon away", " knock %s's weapon away" ], "skill_requirements": [ { "name": "unarmed", "level": 6 } ], "unarmed_allowed": true, - "disarms": true + "disarms": true, + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -479,7 +508,8 @@ "unarmed_allowed": true, "crit_tec": true, "knockback_dist": 1, - "stun_dur": 1 + "stun_dur": 1, + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -488,7 +518,8 @@ "messages": [ "You trip %s", " trip %s" ], "skill_requirements": [ { "name": "unarmed", "level": 5 } ], "unarmed_allowed": true, - "down_dur": 1 + "down_dur": 1, + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -510,7 +541,8 @@ { "stat": "damage", "type": "bash", "scale": 1.2 }, { "stat": "damage", "type": "cut", "scale": 1.2 }, { "stat": "damage", "type": "stab", "scale": 1.2 } - ] + ], + "attack_vectors": [ "FOOT" ] }, { "type": "technique", @@ -524,7 +556,8 @@ { "stat": "damage", "type": "bash", "scale": 1.4 }, { "stat": "damage", "type": "cut", "scale": 1.4 }, { "stat": "damage", "type": "stab", "scale": 1.4 } - ] + ], + "attack_vectors": [ "FOOT" ] }, { "type": "technique", @@ -541,7 +574,8 @@ { "stat": "damage", "type": "bash", "scale": 1.2 }, { "stat": "damage", "type": "cut", "scale": 1.2 }, { "stat": "damage", "type": "stab", "scale": 1.2 } - ] + ], + "attack_vectors": [ "FOOT" ] }, { "type": "technique", @@ -559,7 +593,8 @@ { "stat": "damage", "type": "bash", "scale": 1.4 }, { "stat": "damage", "type": "cut", "scale": 1.4 }, { "stat": "damage", "type": "stab", "scale": 1.4 } - ] + ], + "attack_vectors": [ "FOOT" ] }, { "type": "technique", @@ -584,7 +619,8 @@ { "stat": "damage", "type": "bash", "scale": 1.25 }, { "stat": "damage", "type": "cut", "scale": 1.25 }, { "stat": "damage", "type": "stab", "scale": 1.25 } - ] + ], + "attack_vectors": [ "FOOT" ] }, { "type": "technique", @@ -613,7 +649,8 @@ { "stat": "damage", "type": "bash", "scale": 1.5 }, { "stat": "damage", "type": "cut", "scale": 1.5 }, { "stat": "damage", "type": "stab", "scale": 1.5 } - ] + ], + "attack_vectors": [ "WRIST" ] }, { "type": "technique", @@ -621,7 +658,8 @@ "name": "Dragon Claw", "unarmed_allowed": true, "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.2 } ], - "messages": [ "You lash out at %s with a Dragon Claw", " lashes out at %s with a Dragon Claw" ] + "messages": [ "You lash out at %s with a Dragon Claw", " lashes out at %s with a Dragon Claw" ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -636,7 +674,8 @@ { "stat": "damage", "type": "bash", "scale": 1.4 }, { "stat": "damage", "type": "cut", "scale": 1.4 }, { "stat": "damage", "type": "stab", "scale": 1.4 } - ] + ], + "attack_vectors": [ "FOOT" ] }, { "type": "technique", @@ -652,7 +691,8 @@ { "stat": "damage", "type": "bash", "scale": 1.5 }, { "stat": "damage", "type": "cut", "scale": 1.5 }, { "stat": "damage", "type": "stab", "scale": 1.5 } - ] + ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -661,7 +701,8 @@ "messages": [ "You round strike %s", " round strikes %s" ], "skill_requirements": [ { "name": "melee", "level": 4 } ], "melee_allowed": true, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.6 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.6 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -670,7 +711,8 @@ "messages": [ "You fan strike %s", " fan strikes %s" ], "skill_requirements": [ { "name": "melee", "level": 2 } ], "melee_allowed": true, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.75 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.75 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -678,7 +720,8 @@ "name": "Snap Strike", "messages": [ "You snap out at %s", " snaps quickly at %s" ], "melee_allowed": true, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -694,7 +737,8 @@ { "stat": "damage", "type": "bash", "scale": 1.5 }, { "stat": "damage", "type": "cut", "scale": 1.5 }, { "stat": "damage", "type": "stab", "scale": 1.5 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -705,7 +749,8 @@ "melee_allowed": true, "crit_tec": true, "stun_dur": 1, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -715,7 +760,8 @@ "skill_requirements": [ { "name": "melee", "level": 4 } ], "melee_allowed": true, "crit_tec": true, - "down_dur": 1 + "down_dur": 1, + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -735,7 +781,8 @@ "skill_requirements": [ { "name": "melee", "level": 2 } ], "melee_allowed": true, "crit_ok": true, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -751,7 +798,8 @@ { "stat": "damage", "type": "bash", "scale": 1.25 }, { "stat": "damage", "type": "cut", "scale": 1.25 }, { "stat": "damage", "type": "stab", "scale": 1.25 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -767,7 +815,8 @@ { "stat": "damage", "type": "bash", "scale": 1.25 }, { "stat": "damage", "type": "cut", "scale": 1.25 }, { "stat": "damage", "type": "stab", "scale": 1.25 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -785,7 +834,8 @@ { "stat": "damage", "type": "bash", "scale": 1.2 }, { "stat": "damage", "type": "cut", "scale": 1.2 }, { "stat": "damage", "type": "stab", "scale": 1.2 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -803,7 +853,8 @@ { "stat": "damage", "type": "bash", "scale": 0.5 }, { "stat": "damage", "type": "cut", "scale": 0.5 }, { "stat": "damage", "type": "stab", "scale": 0.5 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -817,7 +868,8 @@ { "stat": "damage", "type": "bash", "scale": 1.1 }, { "stat": "damage", "type": "cut", "scale": 1.1 }, { "stat": "damage", "type": "stab", "scale": 1.1 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -855,7 +907,8 @@ { "stat": "damage", "type": "bash", "scale": 0.5 }, { "stat": "damage", "type": "cut", "scale": 0.5 }, { "stat": "damage", "type": "stab", "scale": 0.5 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -871,7 +924,8 @@ { "stat": "damage", "type": "bash", "scale": 1.5 }, { "stat": "damage", "type": "cut", "scale": 1.5 }, { "stat": "damage", "type": "stab", "scale": 1.5 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -883,7 +937,8 @@ "unarmed_weapons_allowed": false, "crit_ok": true, "down_dur": 1, - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.25 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.25 } ], + "attack_vectors": [ "THROW" ] }, { "type": "technique", @@ -896,7 +951,8 @@ "unarmed_weapons_allowed": false, "disarms": true, "down_dur": 1, - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.25 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.25 } ], + "attack_vectors": [ "THROW" ] }, { "type": "technique", @@ -911,7 +967,8 @@ "side_switch": true, "down_dur": 1, "stun_dur": 1, - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.5 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.5 } ], + "attack_vectors": [ "THROW" ] }, { "type": "technique", @@ -940,7 +997,8 @@ { "stat": "damage", "type": "bash", "scale": 1.4 }, { "stat": "damage", "type": "cut", "scale": 1.4 }, { "stat": "damage", "type": "stab", "scale": 1.4 } - ] + ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -954,7 +1012,8 @@ { "stat": "damage", "type": "bash", "scale": 0.66 }, { "stat": "damage", "type": "cut", "scale": 0.66 }, { "stat": "damage", "type": "stab", "scale": 0.66 } - ] + ], + "attack_vectors": [ "HAND_BACK" ] }, { "type": "technique", @@ -962,11 +1021,13 @@ "name": "Roundhouse Kick", "messages": [ "You roundhouse kick %s", " roundhouse kicks %s" ], "unarmed_allowed": true, + "melee_allowed": true, "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.2 }, { "stat": "damage", "type": "cut", "scale": 1.2 }, { "stat": "damage", "type": "stab", "scale": 1.2 } - ] + ], + "attack_vectors": [ "FOOT" ] }, { "type": "technique", @@ -975,7 +1036,8 @@ "messages": [ "You strike %s with your staff", " strikes %s with your staff" ], "skill_requirements": [ { "name": "melee", "level": 3 } ], "melee_allowed": true, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.9 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.9 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -990,7 +1052,8 @@ { "stat": "damage", "type": "bash", "scale": 1.1 }, { "stat": "damage", "type": "cut", "scale": 1.1 }, { "stat": "damage", "type": "stab", "scale": 1.1 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1005,7 +1068,8 @@ { "stat": "damage", "type": "bash", "scale": 0.66 }, { "stat": "damage", "type": "cut", "scale": 0.66 }, { "stat": "damage", "type": "stab", "scale": 0.66 } - ] + ], + "attack_vectors": [ "WEAPON", "HAND" ] }, { "type": "technique", @@ -1016,7 +1080,9 @@ "melee_allowed": true, "unarmed_allowed": true, "crit_tec": true, - "stun_dur": 1 + "stun_dur": 1, + "attack_vectors": [ "WEAPON" ], + "attack_vectors_random": [ "HAND", "FINGERS", "FOOT", "ELBOW", "KNEE", "LOWER_LEG", "HEAD" ] }, { "type": "technique", @@ -1027,7 +1093,8 @@ "melee_allowed": true, "unarmed_allowed": true, "crit_ok": true, - "down_dur": 1 + "down_dur": 1, + "attack_vectors": [ "THROW" ] }, { "type": "technique", @@ -1043,7 +1110,8 @@ "human_target": true, "stun_dur": 1, "flat_bonuses": [ { "stat": "arpen", "type": "bash", "scaling-stat": "str", "scale": 1.0 } ], - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 2.0 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 2.0 } ], + "attack_vectors": [ "GRAPPLE" ] }, { "type": "technique", @@ -1075,7 +1143,8 @@ "unarmed_allowed": true, "crit_tec": true, "stun_dur": 1, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.5 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.5 } ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1088,16 +1157,18 @@ { "stat": "damage", "type": "bash", "scale": 0.66 }, { "stat": "damage", "type": "cut", "scale": 0.66 }, { "stat": "damage", "type": "stab", "scale": 0.66 } - ] + ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", "id": "tec_leopard_claw", - "name": "Leopard Swipe", + "name": "Leopard Claw", "messages": [ "You savagely claw at %s", " savagely claws at %s" ], "unarmed_allowed": true, "crit_tec": true, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 }, { "stat": "damage", "type": "bash", "scale": 1.3 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 }, { "stat": "damage", "type": "bash", "scale": 1.3 } ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1108,7 +1179,8 @@ "required_buffs_all": [ "buff_leopard_oncrit" ], "crit_tec": true, "down_dur": 1, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 }, { "stat": "damage", "type": "bash", "scale": 2.0 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 }, { "stat": "damage", "type": "bash", "scale": 2.0 } ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1124,7 +1196,8 @@ { "stat": "damage", "type": "stab", "scale": 0.33 } ], "crit_tec": true, - "down_dur": 2 + "down_dur": 2, + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1140,7 +1213,8 @@ { "stat": "arpen", "type": "cut", "scaling-stat": "str", "scale": 1.5 }, { "stat": "arpen", "type": "stab", "scaling-stat": "str", "scale": 1.5 } ], - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 0 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 0 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1163,7 +1237,8 @@ "skill_requirements": [ { "name": "unarmed", "level": 1 } ], "unarmed_allowed": true, "crit_tec": true, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.5 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.5 } ], + "attack_vectors": [ "ELBOW" ] }, { "type": "technique", @@ -1176,7 +1251,8 @@ { "stat": "damage", "type": "bash", "scale": 1.3 }, { "stat": "damage", "type": "cut", "scale": 1.3 }, { "stat": "damage", "type": "stab", "scale": 1.3 } - ] + ], + "attack_vectors_random": [ "LOWER_LEG", "FOOT" ] }, { "type": "technique", @@ -1187,7 +1263,8 @@ "unarmed_allowed": true, "crit_tec": true, "stun_dur": 1, - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.4 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.4 } ], + "attack_vectors": [ "KNEE" ] }, { "type": "technique", @@ -1208,7 +1285,9 @@ "skill_requirements": [ { "name": "melee", "level": 2 } ], "unarmed_allowed": true, "melee_allowed": true, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ], + "attack_vectors": [ "WEAPON" ], + "attack_vectors_random": [ "HAND", "ELBOW", "LOWER_LEG", "FOOT" ] }, { "type": "technique", @@ -1220,7 +1299,9 @@ "melee_allowed": true, "required_buffs_all": [ "buff_ninjutsu_onattack" ], "crit_tec": true, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ], + "attack_vectors": [ "WEAPON" ], + "attack_vectors_random": [ "HAND", "ELBOW", "LOWER_LEG", "FOOT" ] }, { "type": "technique", @@ -1236,7 +1317,8 @@ { "stat": "damage", "type": "bash", "scale": 1.3 }, { "stat": "damage", "type": "cut", "scale": 1.3 }, { "stat": "damage", "type": "stab", "scale": 1.3 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1249,7 +1331,8 @@ "crit_tec": true, "down_dur": 2, "stun_dur": 2, - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 2.0 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 2.0 } ], + "attack_vectors": [ "THROW" ] }, { "type": "technique", @@ -1262,7 +1345,8 @@ { "stat": "movecost", "scale": 1.75 }, { "stat": "damage", "type": "bash", "scale": 2.0 }, { "stat": "damage", "type": "cut", "scale": 2.0 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1271,7 +1355,8 @@ "messages": [ "Your strike knocks %s off balance", "'s strike knocks %s off balance" ], "skill_requirements": [ { "name": "melee", "level": 3 } ], "melee_allowed": true, - "down_dur": 1 + "down_dur": 1, + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1286,7 +1371,8 @@ { "stat": "damage", "type": "bash", "scale": 1.5 }, { "stat": "damage", "type": "cut", "scale": 1.5 }, { "stat": "damage", "type": "stab", "scale": 1.5 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1302,7 +1388,8 @@ { "stat": "movecost", "scale": 0.5 }, { "stat": "damage", "type": "bash", "scale": 1.5 }, { "stat": "damage", "type": "cut", "scale": 1.5 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1325,7 +1412,8 @@ { "stat": "damage", "type": "bash", "scale": 1.2 }, { "stat": "damage", "type": "cut", "scale": 1.2 }, { "stat": "damage", "type": "stab", "scale": 1.2 } - ] + ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1335,7 +1423,8 @@ "skill_requirements": [ { "name": "unarmed", "level": 2 } ], "unarmed_allowed": true, "crit_tec": true, - "stun_dur": 2 + "stun_dur": 2, + "attack_vectors": [ "FOOT" ] }, { "type": "technique", @@ -1356,7 +1445,8 @@ "unarmed_allowed": true, "stunned_target": true, "weighting": 3, - "mult_bonuses": [ { "stat": "movecost", "scale": 0.5 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.5 } ], + "attack_vectors": [ "KNEE" ] }, { "type": "technique", @@ -1371,7 +1461,8 @@ "disarms": true, "stun_dur": 1, "flat_bonuses": [ { "stat": "arpen", "type": "bash", "scaling-stat": "str", "scale": 1.0 } ], - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.25 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.25 } ], + "attack_vectors": [ "GRAPPLE" ] }, { "type": "technique", @@ -1386,7 +1477,8 @@ "knockback_dist": 2, "knockback_spread": 2, "stunned_target": true, - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 2.0 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 2.0 } ], + "attack_vectors": [ "THROW" ] }, { "type": "technique", @@ -1396,7 +1488,8 @@ "skill_requirements": [ { "name": "melee", "level": 2 } ], "melee_allowed": true, "crit_tec": true, - "down_dur": 2 + "down_dur": 2, + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1412,7 +1505,8 @@ { "stat": "damage", "type": "bash", "scale": 1.33 }, { "stat": "damage", "type": "cut", "scale": 1.33 }, { "stat": "damage", "type": "stab", "scale": 1.33 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1422,7 +1516,8 @@ "skill_requirements": [ { "name": "melee", "level": 4 } ], "melee_allowed": true, "crit_tec": true, - "stun_dur": 2 + "stun_dur": 2, + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1438,7 +1533,8 @@ { "stat": "damage", "type": "bash", "scale": 1.33 }, { "stat": "damage", "type": "cut", "scale": 1.33 }, { "stat": "damage", "type": "stab", "scale": 1.33 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1452,7 +1548,8 @@ { "stat": "arpen", "type": "cut", "scaling-stat": "per", "scale": 0.5 }, { "stat": "arpen", "type": "stab", "scaling-stat": "per", "scale": 0.5 } ], - "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ] + "mult_bonuses": [ { "stat": "movecost", "scale": 0.8 } ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1489,7 +1586,8 @@ { "stat": "arpen", "type": "cut", "scaling-stat": "per", "scale": 1.0 }, { "stat": "arpen", "type": "stab", "scaling-stat": "per", "scale": 1.0 } ], - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.5 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.5 } ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1503,7 +1601,8 @@ { "stat": "damage", "type": "bash", "scale": 0.5 }, { "stat": "damage", "type": "cut", "scale": 0.5 }, { "stat": "damage", "type": "stab", "scale": 0.5 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1517,7 +1616,8 @@ { "stat": "damage", "type": "bash", "scale": 0.5 }, { "stat": "damage", "type": "cut", "scale": 0.5 }, { "stat": "damage", "type": "stab", "scale": 0.5 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -1538,7 +1638,8 @@ "unarmed_allowed": true, "weighting": 2, "take_weapon": true, - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 0.5 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 0.5 } ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1558,7 +1659,8 @@ { "stat": "damage", "type": "bash", "scale": 1.5 }, { "stat": "damage", "type": "cut", "scale": 1.5 }, { "stat": "damage", "type": "stab", "scale": 1.5 } - ] + ], + "attack_vectors": [ "FOOT" ] }, { "type": "technique", @@ -1566,7 +1668,8 @@ "name": "Side Kick", "unarmed_allowed": true, "messages": [ "You turn slightly and side-kick %s", " turns slightly and side-kicks %s" ], - "knockback_dist": 1 + "knockback_dist": 1, + "attack_vectors": [ "FOOT" ] }, { "type": "technique", @@ -1576,7 +1679,8 @@ "skill_requirements": [ { "name": "unarmed", "level": 2 } ], "unarmed_allowed": true, "crit_ok": true, - "down_dur": 1 + "down_dur": 1, + "attack_vectors_random": [ "FOOT", "LOWER_LEG" ] }, { "type": "technique", @@ -1588,7 +1692,8 @@ { "stat": "damage", "type": "bash", "scale": 1.2 }, { "stat": "damage", "type": "cut", "scale": 1.2 }, { "stat": "damage", "type": "stab", "scale": 1.2 } - ] + ], + "attack_vectors": [ "FOOT" ] }, { "type": "technique", @@ -1607,7 +1712,8 @@ "messages": [ "You gently disarm %s", " gently disarms %s" ], "skill_requirements": [ { "name": "unarmed", "level": 3 } ], "unarmed_allowed": true, - "disarms": true + "disarms": true, + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1622,7 +1728,8 @@ { "stat": "damage", "type": "bash", "scale": 1.5 }, { "stat": "damage", "type": "cut", "scale": 1.5 }, { "stat": "damage", "type": "stab", "scale": 1.5 } - ] + ], + "attack_vectors": [ "PALM" ] }, { "type": "technique", @@ -1639,7 +1746,8 @@ { "stat": "damage", "type": "bash", "scale": 1.2 }, { "stat": "damage", "type": "cut", "scale": 1.2 }, { "stat": "damage", "type": "stab", "scale": 1.2 } - ] + ], + "attack_vectors": [ "THROW" ] }, { "type": "technique", @@ -1656,7 +1764,8 @@ { "stat": "damage", "type": "bash", "scale": 2.0 }, { "stat": "damage", "type": "cut", "scale": 2.0 }, { "stat": "damage", "type": "stab", "scale": 2.0 } - ] + ], + "attack_vectors": [ "PALM" ] }, { "type": "technique", @@ -1678,7 +1787,8 @@ "skill_requirements": [ { "name": "unarmed", "level": 1 } ], "unarmed_allowed": true, "down_dur": 1, - "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.25 } ] + "mult_bonuses": [ { "stat": "damage", "type": "bash", "scale": 1.25 } ], + "attack_vectors": [ "THROW" ] }, { "type": "technique", @@ -1697,7 +1807,8 @@ { "stat": "damage", "type": "bash", "scale": 1.25 }, { "stat": "damage", "type": "cut", "scale": 1.25 }, { "stat": "damage", "type": "stab", "scale": 1.25 } - ] + ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1712,12 +1823,13 @@ { "stat": "damage", "type": "bash", "scale": 1.25 }, { "stat": "damage", "type": "cut", "scale": 1.25 }, { "stat": "damage", "type": "stab", "scale": 1.25 } - ] + ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", "id": "tec_tiger_wide", - "name": "Tiger Ramage", + "name": "Tiger Rampage", "messages": [ "You slash wildly at %s and those nearby", " slashes wildly at %s and those nearby" ], "skill_requirements": [ { "name": "unarmed", "level": 5 } ], "unarmed_allowed": true, @@ -1728,7 +1840,8 @@ { "stat": "damage", "type": "bash", "scale": 1.25 }, { "stat": "damage", "type": "cut", "scale": 1.25 }, { "stat": "damage", "type": "stab", "scale": 1.25 } - ] + ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1740,7 +1853,8 @@ { "stat": "damage", "type": "bash", "scale": 1.1 }, { "stat": "damage", "type": "cut", "scale": 1.1 }, { "stat": "damage", "type": "stab", "scale": 1.1 } - ] + ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1757,7 +1871,8 @@ { "stat": "damage", "type": "bash", "scale": 1.1 }, { "stat": "damage", "type": "cut", "scale": 1.1 }, { "stat": "damage", "type": "stab", "scale": 1.1 } - ] + ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1772,7 +1887,8 @@ { "stat": "damage", "type": "bash", "scale": 1.2 }, { "stat": "damage", "type": "cut", "scale": 1.2 }, { "stat": "damage", "type": "stab", "scale": 1.2 } - ] + ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1791,7 +1907,8 @@ { "stat": "damage", "type": "bash", "scale": 1.2 }, { "stat": "damage", "type": "cut", "scale": 1.2 }, { "stat": "damage", "type": "stab", "scale": 1.2 } - ] + ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1824,7 +1941,8 @@ { "stat": "damage", "type": "bash", "scale": 1.2 }, { "stat": "damage", "type": "cut", "scale": 1.2 }, { "stat": "damage", "type": "stab", "scale": 1.2 } - ] + ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1851,7 +1969,8 @@ { "stat": "damage", "type": "bash", "scale": 1.3 }, { "stat": "damage", "type": "cut", "scale": 1.3 }, { "stat": "damage", "type": "stab", "scale": 1.3 } - ] + ], + "attack_vectors_random": [ "HAND", "FOOT" ] }, { "type": "technique", @@ -1865,7 +1984,8 @@ { "stat": "damage", "type": "bash", "scaling-stat": "str", "scale": 0.1 } ], "flat_bonuses": [ { "stat": "movecost", "scale": 100 }, { "stat": "movecost", "scaling-stat": "str", "scale": 10 } ], - "messages": [ "You slowly strike %s", " slowly strikes %s" ] + "messages": [ "You slowly strike %s", " slowly strikes %s" ], + "attack_vectors": [ "HAND" ] }, { "type": "technique", @@ -1885,6 +2005,7 @@ { "stat": "arpen", "type": "bash", "scaling-stat": "per", "scale": 1 } ], "crit_tec": true, - "messages": [ "You phase-strike %s", " phase-strikes %s" ] + "messages": [ "You phase-strike %s", " phase-strikes %s" ], + "attack_vectors": [ "WEAPON", "HAND" ] } ] diff --git a/data/mods/MMA/techniques.json b/data/mods/MMA/techniques.json index 761dcd525cda5..7b9e80d941b21 100644 --- a/data/mods/MMA/techniques.json +++ b/data/mods/MMA/techniques.json @@ -5,7 +5,8 @@ "name": "Burning Blade", "messages": [ "You unleash a fiery attack against %s", " unleash a fiery attack against %s" ], "melee_allowed": true, - "flat_bonuses": [ { "stat": "damage", "type": "heat", "scale": 3.0 } ] + "flat_bonuses": [ { "stat": "damage", "type": "heat", "scale": 3.0 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -15,7 +16,8 @@ "skill_requirements": [ { "name": "melee", "level": 1 } ], "melee_allowed": true, "crit_tec": true, - "flat_bonuses": [ { "stat": "damage", "type": "heat", "scale": 7.0 } ] + "flat_bonuses": [ { "stat": "damage", "type": "heat", "scale": 7.0 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -26,7 +28,8 @@ "melee_allowed": true, "crit_ok": true, "aoe": "impale", - "flat_bonuses": [ { "stat": "damage", "type": "heat", "scale": 7.0 } ] + "flat_bonuses": [ { "stat": "damage", "type": "heat", "scale": 7.0 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -40,7 +43,8 @@ "melee_allowed": true, "crit_tec": true, "aoe": "spin", - "flat_bonuses": [ { "stat": "damage", "type": "heat", "scale": 10.0 } ] + "flat_bonuses": [ { "stat": "damage", "type": "heat", "scale": 10.0 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -49,7 +53,8 @@ "messages": [ "You carve an arc through %s and those nearby", " carve an arc through %s and those nearby" ], "skill_requirements": [ { "name": "melee", "level": 2 } ], "melee_allowed": true, - "aoe": "wide" + "aoe": "wide", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -58,7 +63,8 @@ "messages": [ "You spot %s's weakpoint and strike", " spot %s's weakpoint and strike" ], "skill_requirements": [ { "name": "melee", "level": 1 } ], "melee_allowed": true, - "flat_bonuses": [ { "stat": "damage", "type": "stab", "scaling-stat": "int", "scale": 0.5 } ] + "flat_bonuses": [ { "stat": "damage", "type": "stab", "scaling-stat": "int", "scale": 0.5 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -68,7 +74,8 @@ "skill_requirements": [ { "name": "melee", "level": 4 } ], "melee_allowed": true, "crit_tec": true, - "flat_bonuses": [ { "stat": "damage", "type": "stab", "scaling-stat": "int", "scale": 1.0 } ] + "flat_bonuses": [ { "stat": "damage", "type": "stab", "scaling-stat": "int", "scale": 1.0 } ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -82,7 +89,8 @@ "melee_allowed": true, "required_buffs_all": [ "mma_buff_hylian_onpause" ], "crit_ok": true, - "aoe": "spin" + "aoe": "spin", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -96,7 +104,8 @@ "melee_allowed": true, "required_buffs_all": [ "mma_buff_hylian_onpause" ], "crit_ok": true, - "aoe": "wide" + "aoe": "wide", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -104,7 +113,8 @@ "name": "Disarming Strike", "messages": [ "You skillfully disarm %s", " skillfully disarms %s" ], "unarmed_allowed": true, - "disarms": true + "disarms": true, + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -114,7 +124,8 @@ "skill_requirements": [ { "name": "melee", "level": 1 } ], "melee_allowed": true, "defensive": true, - "miss_recovery": true + "miss_recovery": true, + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -129,7 +140,8 @@ { "stat": "damage", "type": "bash", "scale": 1.25 }, { "stat": "damage", "type": "cut", "scale": 1.25 }, { "stat": "damage", "type": "stab", "scale": 1.25 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -144,7 +156,8 @@ { "stat": "damage", "type": "bash", "scale": 1.4 }, { "stat": "damage", "type": "cut", "scale": 1.4 }, { "stat": "damage", "type": "stab", "scale": 1.4 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -156,7 +169,8 @@ ], "skill_requirements": [ { "name": "melee", "level": 3 } ], "melee_allowed": true, - "aoe": "wide" + "aoe": "wide", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -171,7 +185,8 @@ { "stat": "damage", "type": "bash", "scale": 1.25 }, { "stat": "damage", "type": "cut", "scale": 1.25 }, { "stat": "damage", "type": "stab", "scale": 1.25 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -185,7 +200,8 @@ { "stat": "damage", "type": "bash", "scale": 1.2 }, { "stat": "damage", "type": "cut", "scale": 1.2 }, { "stat": "damage", "type": "stab", "scale": 1.2 } - ] + ], + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -208,7 +224,8 @@ { "stat": "damage", "type": "bash", "scale": 1.5 }, { "stat": "damage", "type": "cut", "scale": 1.5 }, { "stat": "damage", "type": "stab", "scale": 1.5 } - ] + ], + "attack_vectors": [ "WEAPON", "HAND" ] }, { "type": "technique", @@ -224,7 +241,8 @@ { "stat": "damage", "type": "bash", "scale": 0.66 }, { "stat": "damage", "type": "cut", "scale": 0.66 }, { "stat": "damage", "type": "stab", "scale": 0.66 } - ] + ], + "attack_vectors": [ "WEAPON", "HAND" ] }, { "type": "technique", @@ -238,7 +256,8 @@ { "stat": "damage", "type": "bash", "scale": 2.0 }, { "stat": "damage", "type": "cut", "scale": 2.0 }, { "stat": "damage", "type": "stab", "scale": 2.0 } - ] + ], + "attack_vectors": [ "FOOT" ] }, { "type": "technique", @@ -252,7 +271,8 @@ { "stat": "arpen", "type": "bash", "scaling-stat": "str", "scale": 1.5 }, { "stat": "arpen", "type": "cut", "scaling-stat": "str", "scale": 1.5 }, { "stat": "arpen", "type": "stab", "scaling-stat": "str", "scale": 1.5 } - ] + ], + "attack_vectors": [ "ARM" ] }, { "type": "technique", @@ -262,7 +282,8 @@ "skill_requirements": [ { "name": "unarmed", "level": 3 } ], "unarmed_allowed": true, "crit_ok": true, - "flat_bonuses": [ { "stat": "hit", "scale": 5.0 } ] + "flat_bonuses": [ { "stat": "hit", "scale": 5.0 } ], + "attack_vectors_random": [ "HAND", "FOOT", "HEAD", "TORSO", "HEAD" ] }, { "type": "technique", @@ -272,7 +293,8 @@ "skill_requirements": [ { "name": "unarmed", "level": 3 } ], "unarmed_allowed": true, "crit_ok": true, - "down_dur": 1 + "down_dur": 1, + "attack_vectors_random": [ "FOOT", "LOWER_LEG" ] }, { "type": "technique", @@ -283,7 +305,8 @@ "melee_allowed": true, "unarmed_allowed": true, "crit_tec": true, - "stun_dur": 1 + "stun_dur": 1, + "attack_vectors": [ "WEAPON", "HAND" ] }, { "type": "technique", @@ -300,7 +323,8 @@ { "stat": "damage", "type": "bash", "scale": 1.33 }, { "stat": "damage", "type": "cut", "scale": 1.33 }, { "stat": "damage", "type": "stab", "scale": 1.33 } - ] + ], + "attack_vectors": [ "THOW" ] }, { "type": "technique", @@ -320,7 +344,8 @@ { "stat": "damage", "type": "bash", "scale": 1.5 }, { "stat": "damage", "type": "cut", "scale": 1.5 }, { "stat": "damage", "type": "stab", "scale": 1.5 } - ] + ], + "attack_vectors": [ "THROW" ] }, { "type": "technique", @@ -330,7 +355,8 @@ "skill_requirements": [ { "name": "melee", "level": 2 } ], "melee_allowed": true, "crit_ok": true, - "disarms": true + "disarms": true, + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -340,7 +366,8 @@ "skill_requirements": [ { "name": "melee", "level": 5 } ], "melee_allowed": true, "crit_ok": true, - "aoe": "wide" + "aoe": "wide", + "attack_vectors": [ "WEAPON" ] }, { "type": "technique", @@ -357,7 +384,8 @@ { "stat": "arpen", "type": "bash", "scaling-stat": "str", "scale": 0.5 }, { "stat": "arpen", "type": "cut", "scaling-stat": "str", "scale": 0.5 }, { "stat": "arpen", "type": "stab", "scaling-stat": "str", "scale": 0.5 } - ] + ], + "attack_vectors": [ "WEAPON", "HAND" ] }, { "type": "technique", @@ -368,7 +396,8 @@ "melee_allowed": true, "unarmed_allowed": true, "crit_tec": true, - "stun_dur": 1 + "stun_dur": 1, + "attack_vectors": [ "WEAPON", "HAND" ] }, { "type": "technique", @@ -385,7 +414,8 @@ { "stat": "damage", "type": "bash", "scale": 1.3 }, { "stat": "damage", "type": "cut", "scale": 1.3 }, { "stat": "damage", "type": "stab", "scale": 1.3 } - ] + ], + "attack_vectors": [ "WEAPON", "HAND" ] }, { "type": "technique", diff --git a/src/character.h b/src/character.h index b15e60a85bf76..a9ee8aad509f1 100644 --- a/src/character.h +++ b/src/character.h @@ -966,18 +966,23 @@ class Character : public Creature, public visitable // If average == true, adds expected values of random rolls instead of rolling. /** Adds all 3 types of physical damage to instance */ void roll_all_damage( bool crit, damage_instance &di, bool average, const item &weap, + std::string attack_vector, const Creature *target, const bodypart_id &bp ) const; /** Adds player's total bash damage to the damage instance */ void roll_bash_damage( bool crit, damage_instance &di, bool average, const item &weap, + std::string attack_vector, float crit_mod ) const; /** Adds player's total cut damage to the damage instance */ void roll_cut_damage( bool crit, damage_instance &di, bool average, const item &weap, + std::string attack_vector, float crit_mod ) const; /** Adds player's total stab damage to the damage instance */ void roll_stab_damage( bool crit, damage_instance &di, bool average, const item &weap, + std::string attack_vector, float crit_mod ) const; /** Adds player's total non-bash, non-cut, non-stab damage to the damage instance */ void roll_other_damage( bool crit, damage_instance &di, bool average, const item &weap, + std::string attack_vector, float crit_mod ) const; /** Returns true if the player should be dead */ diff --git a/src/character_martial_arts.h b/src/character_martial_arts.h index 62079c12835cf..52db277f7bb6a 100644 --- a/src/character_martial_arts.h +++ b/src/character_martial_arts.h @@ -78,6 +78,11 @@ class character_martial_arts /** Fires all kill-triggered martial arts events */ void ma_onkill_effects( Character &owner ); + /** Returns an attack vector that the player can use */ + std::string get_valid_attack_vector( const Character &user, + std::vector attack_vectors ) const; + /** Returns true if the player is able to use the given attack vector */ + bool can_use_attack_vector( const Character &user, std::string av ) const; /** Returns true if the player has the leg block technique available */ bool can_leg_block( const Character &owner ) const; /** Returns true if the player has the arm block technique available */ diff --git a/src/item.cpp b/src/item.cpp index 14e780fa5b52c..e895694f51ea2 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -1843,7 +1843,7 @@ double item::effective_dps( const Character &guy, Creature &mon ) const Creature *temp_mon = &mon; double subtotal_damage = 0; damage_instance base_damage; - guy.roll_all_damage( crit, base_damage, true, *this, &mon, bp ); + guy.roll_all_damage( crit, base_damage, true, *this, "WEAPON", &mon, bp ); damage_instance dealt_damage = base_damage; // TODO: Modify DPS calculation to consider weakpoints. resistances r = resistances( *static_cast( temp_mon ) ); @@ -1868,7 +1868,7 @@ double item::effective_dps( const Character &guy, Creature &mon ) const if( has_technique( RAPID ) ) { Creature *temp_rs_mon = &mon; damage_instance rs_base_damage; - guy.roll_all_damage( crit, rs_base_damage, true, *this, &mon, bp ); + guy.roll_all_damage( crit, rs_base_damage, true, *this, "WEAPON", &mon, bp ); damage_instance dealt_rs_damage = rs_base_damage; for( damage_unit &dmg_unit : dealt_rs_damage.damage_units ) { dmg_unit.damage_multiplier *= 0.66; @@ -4768,9 +4768,9 @@ void item::melee_combat_info( std::vector &info, const iteminfo_query ( dmg_bash || dmg_cut || dmg_stab || type->m_to_hit > 0 ) ) || debug_mode ) { bodypart_id bp = bodypart_id( "torso" ); damage_instance non_crit; - player_character.roll_all_damage( false, non_crit, true, *this, nullptr, bp ); + player_character.roll_all_damage( false, non_crit, true, *this, "WEAPON", nullptr, bp ); damage_instance crit; - player_character.roll_all_damage( true, crit, true, *this, nullptr, bp ); + player_character.roll_all_damage( true, crit, true, *this, "WEAPON", nullptr, bp ); int attack_cost = player_character.attack_speed( *this ); insert_separation_line( info ); if( parts->test( iteminfo_parts::DESCRIPTION_MELEEDMG ) ) { diff --git a/src/martialarts.cpp b/src/martialarts.cpp index 122d72615c724..c7eb2be199837 100644 --- a/src/martialarts.cpp +++ b/src/martialarts.cpp @@ -263,6 +263,9 @@ void ma_technique::load( const JsonObject &jo, const std::string &src ) optional( jo, was_loaded, "flags", flags, auto_flags_reader<> {} ); optional( jo, was_loaded, "tech_effects", tech_effects, tech_effect_reader{} ); + optional( jo, was_loaded, "attack_vectors", attack_vectors, {} ); + optional( jo, was_loaded, "attack_vectors_random", attack_vectors_random, {} ); + reqs.load( jo, src ); bonuses.load( jo ); } @@ -1236,6 +1239,40 @@ ma_technique character_martial_arts::get_miss_recovery( const Character &owner ) return get_valid_technique( owner, &ma_technique::miss_recovery ); } + +std::string character_martial_arts::get_valid_attack_vector( const Character &user, + std::vector attack_vectors ) const +{ + for( auto av : attack_vectors ) { + if( can_use_attack_vector( user, av ) ) { + return av; + } + } + + return "NONE"; +} + +bool character_martial_arts::can_use_attack_vector( const Character &user, std::string av ) const +{ + martialart ma = style_selected.obj(); + bool valid_weapon = ma.weapon_valid( user.get_wielded_item() ); + int arm_r_hp = user.get_part_hp_cur( bodypart_id( "arm_r" ) ); + int arm_l_hp = user.get_part_hp_cur( bodypart_id( "arm_l" ) ); + int leg_r_hp = user.get_part_hp_cur( bodypart_id( "leg_r" ) ); + int leg_l_hp = user.get_part_hp_cur( bodypart_id( "leg_l" ) ); + bool healthy_arm = arm_r_hp > 0 || arm_l_hp > 0; + bool healthy_arms = arm_r_hp > 0 && arm_l_hp > 0; + bool healthy_legs = leg_r_hp > 0 && leg_l_hp > 0; + bool always_ok = av == "HEAD" || av == "TORSO"; + bool weapon_ok = av == "WEAPON" && valid_weapon && healthy_arm; + bool arm_ok = ( av == "HAND" || av == "FINGER" || av == "WRIST" || av == "ARM" || av == "ELBOW" || + av == "HAND_BACK" || av == "PALM" || av == "SHOULDER" ) && healthy_arm; + bool arms_ok = ( av == "GRAPPLE" || av == "THROW" ) && healthy_arms; + bool legs_ok = ( av == "FOOT" || av == "LOWER_LEG" || av == "KNEE" || av == "HIP" ) && healthy_legs; + + return always_ok || weapon_ok || arm_ok || arms_ok || legs_ok; +} + bool character_martial_arts::can_leg_block( const Character &owner ) const { const martialart &ma = style_selected.obj(); diff --git a/src/martialarts.h b/src/martialarts.h index 964472906f6ab..6997257468a11 100644 --- a/src/martialarts.h +++ b/src/martialarts.h @@ -155,6 +155,10 @@ class ma_technique ma_requirements reqs; + // What way is the technique delivered to the target? + std::vector attack_vectors; // by priority + std::vector attack_vectors_random; // randomly + int repeat_min = 1; // Number of times the technique is repeated on a successful proc int repeat_max = 1; diff --git a/src/melee.cpp b/src/melee.cpp index ecc8eecfb1dbc..669e92cadcdf0 100644 --- a/src/melee.cpp +++ b/src/melee.cpp @@ -417,16 +417,16 @@ std::string Character::get_miss_reason() } void Character::roll_all_damage( bool crit, damage_instance &di, bool average, - const item &weap, const Creature *target, const bodypart_id &bp ) const + const item &weap, std::string attack_vector, const Creature *target, const bodypart_id &bp ) const { float crit_mod = 1.f; if( target != nullptr ) { crit_mod = target->get_crit_factor( bp ); } - roll_bash_damage( crit, di, average, weap, crit_mod ); - roll_cut_damage( crit, di, average, weap, crit_mod ); - roll_stab_damage( crit, di, average, weap, crit_mod ); - roll_other_damage( crit, di, average, weap, crit_mod ); + roll_bash_damage( crit, di, average, weap, attack_vector, crit_mod ); + roll_cut_damage( crit, di, average, weap, attack_vector, crit_mod ); + roll_stab_damage( crit, di, average, weap, attack_vector, crit_mod ); + roll_other_damage( crit, di, average, weap, attack_vector, crit_mod ); } static void melee_train( Character &you, int lo, int hi, const item &weap ) @@ -582,25 +582,7 @@ bool Character::melee_attack_abstract( Creature &t, bool allow_special, item *cur_weapon = allow_unarmed ? &used_weapon() : &weapon; - // If no weapon is selected, use highest layer of gloves instead. - bool unarmed_flag_set = false; - if( cur_weapon->is_null() ) { - for( item &worn_item : worn ) { - // Uses enum layer_level to make distinction for top layer. - if( ( worn_item.covers( bodypart_id( "hand_l" ) ) && - worn_item.covers( bodypart_id( "hand_r" ) ) ) ) { - if( cur_weapon->is_null() || ( worn_item.get_layer() >= cur_weapon->get_layer() ) ) { - cur_weapon = &worn_item; - cur_weapon->set_flag( flag_UNARMED_WEAPON ); - unarmed_flag_set = true; - } - - } - } - } - - int move_cost = attack_speed( cur_weapon->has_flag( flag_UNARMED_WEAPON ) ? - null_item_reference() : *cur_weapon ); + int move_cost = attack_speed( *cur_weapon ); if( cur_weapon->attack_time() > move_cost * 20 ) { add_msg( m_bad, _( "This weapon is too unwieldy to attack with!" ) ); @@ -703,8 +685,6 @@ bool Character::melee_attack_abstract( Creature &t, bool allow_special, // select target body part const bodypart_id &target_bp = t.select_body_part( -1, -1, can_attack_high(), hit_spread ); - damage_instance d; - roll_all_damage( critical_hit, d, false, *cur_weapon, &t, target_bp ); const bool has_force_technique = !force_technique.str().empty(); @@ -718,9 +698,83 @@ bool Character::melee_attack_abstract( Creature &t, bool allow_special, technique_id = tec_none; } - // if you have two broken arms you aren't doing any martial arts - // and your hits are not going to hurt very much - if( get_working_arm_count() < 1 ) { + std::string attack_vector; + + // Failsafe for tec_none + if( technique_id == tec_none ) { + attack_vector = "HANDS"; + } else { + attack_vector = martial_arts_data->get_valid_attack_vector( *this, + technique_id.obj().attack_vectors ); + + if( attack_vector == "NONE" ) { + std::vector shuffled_attack_vectors = technique_id.obj().attack_vectors_random; + std::shuffle( shuffled_attack_vectors.begin(), shuffled_attack_vectors.end(), rng_get_engine() ); + attack_vector = martial_arts_data->get_valid_attack_vector( *this, shuffled_attack_vectors ); + } + } + + // If no weapon is selected, use highest layer of gloves instead. + if( attack_vector != "WEAPON" ) { + for( item &worn_item : worn ) { + bool covers = false; + + if( attack_vector == "HAND" || attack_vector == "GRAPPLE" || attack_vector == "THROW" ) { + covers = worn_item.covers( bodypart_id( "hand_l" ) ) && + worn_item.covers( bodypart_id( "hand_r" ) ); + } else if( attack_vector == "ARM" ) { + covers = worn_item.covers( bodypart_id( "arm_l" ) ) && + worn_item.covers( bodypart_id( "arm_r" ) ); + } else if( attack_vector == "ELBOW" ) { + covers = worn_item.covers( sub_bodypart_id( "arm_elbow_l" ) ) && + worn_item.covers( sub_bodypart_id( "arm_elbow_r" ) ); + } else if( attack_vector == "FINGERS" ) { + covers = worn_item.covers( sub_bodypart_id( "hand_fingers_l" ) ) && + worn_item.covers( sub_bodypart_id( "hand_fingers_r" ) ); + } else if( attack_vector == "WRIST" ) { + covers = worn_item.covers( sub_bodypart_id( "hand_wrist_l" ) ) && + worn_item.covers( sub_bodypart_id( "hand_wrist_r" ) ); + } else if( attack_vector == "PALM" ) { + covers = worn_item.covers( sub_bodypart_id( "hand_palm_l" ) ) && + worn_item.covers( sub_bodypart_id( "hand_palm_r" ) ); + } else if( attack_vector == "HAND_BACK" ) { + covers = worn_item.covers( sub_bodypart_id( "hand_back_l" ) ) && + worn_item.covers( sub_bodypart_id( "hand_back_r" ) ); + } else if( attack_vector == "SHOULDER" ) { + covers = worn_item.covers( sub_bodypart_id( "arm_shoulder_l" ) ) && + worn_item.covers( sub_bodypart_id( "arm_shoulder_r" ) ); + } else if( attack_vector == "FOOT" ) { + covers = worn_item.covers( bodypart_id( "foot_l" ) ) && + worn_item.covers( bodypart_id( "foot_r" ) ); + } else if( attack_vector == "LOWER_LEG" ) { + covers = worn_item.covers( sub_bodypart_id( "leg_lower_l" ) ) && + worn_item.covers( sub_bodypart_id( "leg_lower_r" ) ); + } else if( attack_vector == "KNEE" ) { + covers = worn_item.covers( sub_bodypart_id( "leg_knee_l" ) ) && + worn_item.covers( sub_bodypart_id( "leg_knee_r" ) ); + } else if( attack_vector == "HIP" ) { + covers = worn_item.covers( sub_bodypart_id( "leg_hip_l" ) ) && + worn_item.covers( sub_bodypart_id( "leg_hip_r" ) ); + } else if( attack_vector == "HEAD" ) { + covers = worn_item.covers( bodypart_id( "head" ) ); + } else if( attack_vector == "TORSO" ) { + covers = worn_item.covers( bodypart_id( "torso" ) ); + } + + // Uses enum layer_level to make distinction for top layer. + if( covers ) { + if( cur_weapon->is_null() || ( worn_item.get_layer() >= cur_weapon->get_layer() ) ) { + cur_weapon = &worn_item; + } + } + } + } + + damage_instance d; + roll_all_damage( critical_hit, d, false, *cur_weapon, attack_vector, &t, target_bp ); + + // your hits are not going to hurt very much if you can't use martial arts due to broken limbs + if( attack_vector == "HANDS" && get_working_arm_count() < 1 ) { technique_id = tec_none; d.mult_damage( 0.1 ); add_msg_if_player( m_bad, _( "You arms are too damaged or encumbered to fight effectively!" ) ); @@ -867,10 +921,6 @@ bool Character::melee_attack_abstract( Creature &t, bool allow_special, } } - if( unarmed_flag_set ) { - cur_weapon->unset_flag( flag_UNARMED_WEAPON ); - } - if( !t.is_hallucination() ) { handle_melee_wear( *cur_weapon ); } @@ -1170,12 +1220,12 @@ float Character::bonus_damage( bool random ) const } void Character::roll_bash_damage( bool crit, damage_instance &di, bool average, - const item &weap, float crit_mod ) const + const item &weap, std::string attack_vector, float crit_mod ) const { float bash_dam = 0.0f; + bool unarmed = attack_vector == "WEAPON"; int arpen = 0; - const bool unarmed = weap.is_unarmed_weapon(); int skill = get_skill_level( unarmed ? skill_unarmed : skill_bashing ); int melee_bonus = get_skill_level( skill_melee ); if( has_active_bionic( bio_cqb ) ) { @@ -1211,13 +1261,44 @@ void Character::roll_bash_damage( bool crit, damage_instance &di, bool average, if( unarmed ) { - const bool left_empty = !natural_attack_restricted_on( bodypart_id( "hand_l" ) ); - const bool right_empty = !natural_attack_restricted_on( bodypart_id( "hand_r" ) ) && - weap.is_null(); - if( left_empty || right_empty ) { - // TODO: Deprecate when either unarmed attacks define a bodypart or - // all mainline mutations are moved over to the limb system - float per_hand = 0.0f; + bool bp_unrestricted; + + if( attack_vector == "ARM" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "arm_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "arm_r" ) ) ); + } else if( attack_vector == "ELBOW" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "arm_elbow_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "arm_elbow_r" ) ) ); + } else if( attack_vector == "WRIST" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "hand_wrist_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "hand_wrist_r" ) ) ); + } else if( attack_vector == "SHOULDER" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "arm_shoulder_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "arm_shoulder_r" ) ) ); + } else if( attack_vector == "FOOT" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "foot_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "foot_r" ) ) ); + } else if( attack_vector == "LOWER_LEG" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "leg_lower_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "leg_lower_r" ) ) ); + } else if( attack_vector == "KNEE" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "leg_knee_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "leg_knee_r" ) ) ); + } else if( attack_vector == "HIP" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "leg_hip_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "leg_hip_r" ) ) ); + } else if( attack_vector == "HEAD" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "head" ) ); + } else if( attack_vector == "TORSO" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "torso" ) ); + } else { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "hand_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "hand_r" ) ) && weap.is_null() ); + } + + if( bp_unrestricted ) { + float extra_damage = 0.0f; + for( const trait_id &mut : get_mutations() ) { if( mut->flags.count( json_flag_NEED_ACTIVE_TO_MELEE ) > 0 && !has_active_mutation( mut ) ) { continue; @@ -1227,16 +1308,12 @@ void Character::roll_bash_damage( bool crit, damage_instance &di, bool average, if( mut->flags.count( json_flag_UNARMED_BONUS ) > 0 && bash_bonus > 0 ) { unarmed_bonus += std::min( get_skill_level( skill_unarmed ) / 2, 4 ); } - per_hand += bash_bonus + unarmed_bonus; + extra_damage += bash_bonus + unarmed_bonus; const std::pair rand_bash = mut->rand_bash_bonus; - per_hand += average ? ( rand_bash.first + rand_bash.second ) / 2.0f : rng( rand_bash.first, - rand_bash.second ); - } - bash_dam += per_hand; // First hand - if( left_empty && right_empty ) { - // Second hand - bash_dam += per_hand; + extra_damage += average ? ( rand_bash.first + rand_bash.second ) / 2.0f : rng( rand_bash.first, + rand_bash.second ); } + bash_dam += extra_damage; } float dam = 0.0f; float ap = 0.0f; @@ -1304,13 +1381,13 @@ void Character::roll_bash_damage( bool crit, damage_instance &di, bool average, } void Character::roll_cut_damage( bool crit, damage_instance &di, bool average, - const item &weap, float crit_mod ) const + const item &weap, std::string attack_vector, float crit_mod ) const { float cut_dam = mabuff_damage_bonus( damage_type::CUT ) + weap.damage_melee( damage_type::CUT ); float cut_mul = 1.0f; + bool unarmed = attack_vector == "WEAPON"; int arpen = 0; - const bool unarmed = weap.is_unarmed_weapon(); int skill = get_skill_level( unarmed ? skill_unarmed : skill_cutting ); if( has_active_bionic( bio_cqb ) ) { @@ -1318,16 +1395,43 @@ void Character::roll_cut_damage( bool crit, damage_instance &di, bool average, } if( unarmed ) { - // TODO: 1-handed weapons that aren't unarmed attacks - const bool left_empty = !natural_attack_restricted_on( bodypart_id( "hand_l" ) ); - const bool right_empty = !natural_attack_restricted_on( bodypart_id( "hand_r" ) ) && - weap.is_null(); - if( left_empty || right_empty ) { - float per_hand = 0.0f; - if( has_bionic( bio_razors ) ) { - per_hand += 2; - } + bool bp_unrestricted; + + if( attack_vector == "ARM" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "arm_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "arm_r" ) ) ); + } else if( attack_vector == "ELBOW" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "arm_elbow_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "arm_elbow_r" ) ) ); + } else if( attack_vector == "WRIST" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "hand_wrist_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "hand_wrist_r" ) ) ); + } else if( attack_vector == "SHOULDER" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "arm_shoulder_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "arm_shoulder_r" ) ) ); + } else if( attack_vector == "FOOT" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "foot_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "foot_r" ) ) ); + } else if( attack_vector == "LOWER_LEG" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "leg_lower_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "leg_lower_r" ) ) ); + } else if( attack_vector == "KNEE" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "leg_knee_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "leg_knee_r" ) ) ); + } else if( attack_vector == "HIP" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "leg_hip_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "leg_hip_r" ) ) ); + } else if( attack_vector == "HEAD" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "head" ) ); + } else if( attack_vector == "TORSO" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "torso" ) ); + } else { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "hand_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "hand_r" ) ) && weap.is_null() ); + } + if( bp_unrestricted ) { + float extra_damage = 0.0f; for( const trait_id &mut : get_mutations() ) { if( mut->flags.count( json_flag_NEED_ACTIVE_TO_MELEE ) > 0 && !has_active_mutation( mut ) ) { continue; @@ -1337,19 +1441,14 @@ void Character::roll_cut_damage( bool crit, damage_instance &di, bool average, if( mut->flags.count( json_flag_UNARMED_BONUS ) > 0 && cut_bonus > 0 ) { unarmed_bonus += std::min( get_skill_level( skill_unarmed ) / 2, 4 ); } - per_hand += cut_bonus + unarmed_bonus; + extra_damage += cut_bonus + unarmed_bonus; const std::pair rand_cut = mut->rand_cut_bonus; - per_hand += average ? ( rand_cut.first + rand_cut.second ) / 2.0f : rng( rand_cut.first, - rand_cut.second ); - } - // TODO: add acidproof check back to slime hands (probably move it elsewhere) - - cut_dam += per_hand; // First hand - if( left_empty && right_empty ) { - // Second hand - cut_dam += per_hand; + extra_damage += average ? ( rand_cut.first + rand_cut.second ) / 2.0f : rng( rand_cut.first, + rand_cut.second ); } + cut_dam += extra_damage; } + float dam = 0.0f; float ap = 0.0f; for( const bodypart_id &bp : get_all_body_parts() ) { @@ -1389,13 +1488,13 @@ void Character::roll_cut_damage( bool crit, damage_instance &di, bool average, di.add_damage( damage_type::CUT, cut_dam, arpen, armor_mult, cut_mul ); } -void Character::roll_stab_damage( bool crit, damage_instance &di, bool /*average*/, - const item &weap, float crit_mod ) const +void Character::roll_stab_damage( bool crit, damage_instance &di, bool average, + const item &weap, std::string attack_vector, float crit_mod ) const { - float cut_dam = mabuff_damage_bonus( damage_type::STAB ) + weap.damage_melee( damage_type::STAB ); + float stab_dam = mabuff_damage_bonus( damage_type::STAB ) + weap.damage_melee( damage_type::STAB ); + bool unarmed = attack_vector == "WEAPON"; int arpen = 0; - const bool unarmed = weap.is_unarmed_weapon(); int skill = get_skill_level( unarmed ? skill_unarmed : skill_stabbing ); if( has_active_bionic( bio_cqb ) ) { @@ -1403,30 +1502,66 @@ void Character::roll_stab_damage( bool crit, damage_instance &di, bool /*average } if( unarmed ) { - const bool left_empty = !natural_attack_restricted_on( bodypart_id( "hand_l" ) ); - const bool right_empty = !natural_attack_restricted_on( bodypart_id( "hand_r" ) ) && - weap.is_null(); - if( left_empty || right_empty ) { - float per_hand = 0.0f; + bool bp_unrestricted; + + if( attack_vector == "ARM" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "arm_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "arm_r" ) ) ); + } else if( attack_vector == "ELBOW" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "arm_elbow_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "arm_elbow_r" ) ) ); + } else if( attack_vector == "WRIST" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "hand_wrist_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "hand_wrist_r" ) ) ); + } else if( attack_vector == "SHOULDER" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "arm_shoulder_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "arm_shoulder_r" ) ) ); + } else if( attack_vector == "FOOT" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "foot_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "foot_r" ) ) ); + } else if( attack_vector == "LOWER_LEG" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "leg_lower_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "leg_lower_r" ) ) ); + } else if( attack_vector == "KNEE" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "leg_knee_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "leg_knee_r" ) ) ); + } else if( attack_vector == "HIP" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "leg_hip_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "leg_hip_r" ) ) ); + } else if( attack_vector == "HEAD" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "head" ) ); + } else if( attack_vector == "TORSO" ) { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "torso" ) ); + } else { + bp_unrestricted = !natural_attack_restricted_on( bodypart_id( "hand_l" ) ) || + ( !natural_attack_restricted_on( bodypart_id( "hand_r" ) ) && weap.is_null() ); + } + if( bp_unrestricted ) { + float extra_damage = 0.0f; for( const trait_id &mut : get_mutations() ) { - per_hand += mut->pierce_dmg_bonus; - - if( mut->flags.count( json_flag_UNARMED_BONUS ) > 0 && cut_bonus > 0 ) { - per_hand += std::min( skill / 2, 4 ); + if( mut->flags.count( json_flag_NEED_ACTIVE_TO_MELEE ) > 0 && !has_active_mutation( mut ) ) { + continue; + } + float unarmed_bonus = 0.0f; + const int pierce_bonus = mut->pierce_dmg_bonus; + if( mut->flags.count( json_flag_UNARMED_BONUS ) > 0 && pierce_bonus > 0 ) { + unarmed_bonus += std::min( get_skill_level( skill_unarmed ) / 2, 4 ); } + extra_damage += pierce_bonus + unarmed_bonus; + const std::pair rand_pierce = mut->rand_cut_bonus; + extra_damage += average ? ( rand_pierce.first + rand_pierce.second ) / 2.0f : rng( + rand_pierce.first, + rand_pierce.second ); } - if( has_bionic( bio_razors ) ) { - per_hand += 2; + if( attack_vector == "HAND" && has_bionic( bio_razors ) ) { + extra_damage += 2; } - cut_dam += per_hand; // First hand - if( left_empty && right_empty ) { - // Second hand - cut_dam += per_hand; - } + stab_dam += extra_damage; } + float dam = 0.0f; float ap = 0.0f; for( const bodypart_id &bp : get_all_body_parts() ) { @@ -1435,12 +1570,12 @@ void Character::roll_stab_damage( bool crit, damage_instance &di, bool /*average ap += bp->unarmed_arpen( damage_type::STAB ); } } - cut_dam += dam; + stab_dam += dam; arpen += ap; } - if( cut_dam <= 0 ) { + if( stab_dam <= 0 ) { return; // No negative stabbing! } @@ -1463,14 +1598,14 @@ void Character::roll_stab_damage( bool crit, damage_instance &di, bool /*average armor_mult = 1.f - 0.34f * crit_mod; } - di.add_damage( damage_type::STAB, cut_dam, arpen, armor_mult, stab_mul ); + di.add_damage( damage_type::STAB, stab_dam, arpen, armor_mult, stab_mul ); } void Character::roll_other_damage( bool /*crit*/, damage_instance &di, bool /*average*/, - const item &weap, float /*crit_mod*/ ) const + const item &weap, std::string attack_vector, float /*crit_mod*/ ) const { std::map dt_map = get_dt_map(); - const bool unarmed = weap.is_unarmed_weapon(); + bool unarmed = attack_vector == "WEAPON"; for( const std::pair &dt : dt_map ) { damage_type type_name = dt.second; @@ -1604,6 +1739,14 @@ matec_id Character::pick_technique( Creature &t, const item &weap, continue; } + // Does the player have a functional attack vector to deliver the technique? + std::vector shuffled_attack_vectors = tec.attack_vectors_random; + std::shuffle( shuffled_attack_vectors.begin(), shuffled_attack_vectors.end(), rng_get_engine() ); + if( martial_arts_data->get_valid_attack_vector( *this, tec.attack_vectors ) == "NONE" && + martial_arts_data->get_valid_attack_vector( *this, shuffled_attack_vectors ) == "NONE" ) { + continue; + } + if( tec.is_valid_character( *this ) ) { possible.push_back( tec.id );