changes
This commit is contained in:
@@ -11,3 +11,13 @@
|
||||
#define ATTACK_TYPE_TACKLE (1<<4)
|
||||
/// Attack was from a parry counterattack. Do not attempt to parry-this!
|
||||
#define ATTACK_TYPE_PARRY_COUNTERATTACK (1<<5)
|
||||
|
||||
// Requires for datum definitions to not error with must be a constant statement when used in lists as text associative keys.
|
||||
// KEEP IN SYNC WITH ABOVE!
|
||||
|
||||
#define TEXT_ATTACK_TYPE_MELEE 1
|
||||
#define TEXT_ATTACK_TYPE_PROJECTILE 2
|
||||
#define TEXT_ATTACK_TYPE_UNARMED 4
|
||||
#define TEXT_ATTACK_TYPE_THROWN 8
|
||||
#define TEXT_ATTACK_TYPE_TACKLE 16
|
||||
#define TEXT_ATTACK_TYPE_PARRY_COUNTERATTACK 32
|
||||
|
||||
@@ -46,13 +46,9 @@ GLOBAL_LIST_INIT(dir2blockdir, list(
|
||||
#define PARRY_LOCK_ATTACKING (1<<2)
|
||||
|
||||
/// Parry effects.
|
||||
/// List association must be one of the things underneath
|
||||
#define PARRY_REFLEX_COUNTERATTACK "reflex_counter"
|
||||
// Uses active_parry_reflex_counter() on the mob (if unarmed)/item/martial art used to parry.
|
||||
#define PARRY_COUNTERATTACK_PROC "proc"
|
||||
// Automatically melee attacks back normally, LMB equivalent action of an harm intent attack.
|
||||
#define PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN "default"
|
||||
/// No list association
|
||||
/// Automatically melee attacks back normally, LMB equivalent action of an harm intent attack. List association should be defaulting to 1, being the attack damage multiplier for said counterattack
|
||||
#define PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN "melee_counterattack_chain"
|
||||
/// List association should be TRUE.
|
||||
#define PARRY_DISARM_ATTACKER "disarm_attacker"
|
||||
/// List association should be duration or null for just plain knockdown.
|
||||
#define PARRY_KNOCKDOWN_ATTACKER "knockdown_attacker"
|
||||
@@ -60,3 +56,5 @@ GLOBAL_LIST_INIT(dir2blockdir, list(
|
||||
#define PARRY_STAGGER_ATTACKER "stagger_attacker"
|
||||
/// List association should be amount of time to daze attacker.
|
||||
#define PARRY_DAZE_ATTACKER "daze_attacker"
|
||||
/// Set to TRUE in list association to ignore adjacency checks
|
||||
#define PARRY_COUNTERATTACK_IGNORE_ADJACENCY "ignore_adjacency"
|
||||
|
||||
@@ -171,16 +171,47 @@
|
||||
attack_verb = list("stabs", "punctures", "pierces", "pokes")
|
||||
hitsound = 'sound/weapons/rapierhit.ogg'
|
||||
total_mass = 0.4
|
||||
item_flags = ITEM_CAN_PARRY | NEEDS_PERMIT
|
||||
block_parry_data = /datum/block_parry_data/traitor_rapier
|
||||
|
||||
// Fast, efficient parry.
|
||||
/datum/block_parry_data/traitor_rapier
|
||||
parry_time_windup = 0.5
|
||||
parry_time_active = 5
|
||||
parry_time_spindown = 0
|
||||
parry_time_active_visual_override = 3
|
||||
parry_time_spindown_visual_override = 2
|
||||
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING
|
||||
parry_time_perfect = 0
|
||||
parry_time_perfect_leeway = 3
|
||||
parry_time_perfect_leeway_override = list(
|
||||
TEXT_ATTACK_TYPE_PROJECTILE = 1
|
||||
)
|
||||
parry_imperfect_falloff_percent_override = list(
|
||||
TEXT_ATTACK_TYPE_PROJECTILE = 50 // useless after 3rd decisecond
|
||||
)
|
||||
parry_imperfect_falloff_percent = 30
|
||||
parry_efficiency_to_counterattack = 100
|
||||
parry_efficiency_considered_successful = 1
|
||||
parry_efficiency_perfect = 100
|
||||
parry_data = list(
|
||||
PARRY_DISARM_ATTACKER = TRUE,
|
||||
PARRY_KNOCKDOWN_ATTACKER = 10
|
||||
)
|
||||
parry_failed_stagger_duration = 2 SECONDS
|
||||
parry_failed_clickcd_duration = CLICK_CD_RANGE
|
||||
parry_cooldown = 0
|
||||
|
||||
/obj/item/melee/rapier/active_parry_reflex_counter(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list, parry_efficiency, list/effect_text)
|
||||
. = ..()
|
||||
if((attack_type & ATTACK_TYPE_PROJECTILE) && (parry_efficiency >= 100))
|
||||
. |= BLOCK_SHOULD_REDIRECT
|
||||
return_list[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_DEFLECT
|
||||
|
||||
/obj/item/melee/rapier/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/butchering, 20, 65, 0)
|
||||
|
||||
/obj/item/melee/rapier/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(attack_type == ATTACK_TYPE_PROJECTILE)
|
||||
final_block_chance = 0
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/rapier/on_exit_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/rapier/B = S.parent
|
||||
if(istype(B))
|
||||
@@ -206,7 +237,7 @@
|
||||
var/loss = H.getStaminaLoss()
|
||||
H.Dizzy(10)
|
||||
H.adjustStaminaLoss(30)
|
||||
if((loss > 40) && prob(loss)) // if above 40, roll for sleep using 1% every 1 stamina damage
|
||||
if(CHECK_STAMCRIT(H) != NOT_STAMCRIT)
|
||||
H.Sleeping(180)
|
||||
|
||||
/obj/item/melee/classic_baton
|
||||
|
||||
@@ -275,7 +275,7 @@
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/w_class_on = WEIGHT_CLASS_BULKY
|
||||
item_flags = ITEM_CAN_PARRY | SLOWS_WHILE_IN_HAND
|
||||
item_flags = ITEM_CAN_PARRY | SLOWS_WHILE_IN_HAND |
|
||||
block_parry_data = /datum/block_parry_data/dual_esword
|
||||
force_unwielded = 3
|
||||
force_wielded = 34
|
||||
@@ -329,15 +329,10 @@
|
||||
parry_failed_clickcd_duration = CLICK_CD_MELEE
|
||||
parry_cooldown = 3 SECONDS
|
||||
|
||||
// KEV, WHY AREN'T YOU JUST PUTTING IT IN THE DEFINITION?!?!?!?!
|
||||
// I'LL TELL YOU WHY, BECAUSE BYOND DOESN'T CONSIDER "[(1<<0)]" A "CONSTANT EXPRESSION"
|
||||
// WHAT EVEN IS MORE CONSTANT THAN 1 BITSHIFTED TO THE LEFT BY 0 PLACES AS A STRING?
|
||||
/datum/block_parry_data/dual_esword/New()
|
||||
// more efficient vs projectiles
|
||||
block_stamina_efficiency_override = list(
|
||||
"[ATTACK_TYPE_PROJECTILE]" = 4
|
||||
"[TEXT_ATTACK_TYPE_PROJECTILE]" = 4
|
||||
)
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/dualsaber/suicide_act(mob/living/carbon/user)
|
||||
if(wielded)
|
||||
@@ -1070,8 +1065,8 @@
|
||||
force_wielded = 10
|
||||
throwforce = 15 //if you are a madman and finish someone off with this, power to you.
|
||||
throw_speed = 1
|
||||
item_flags = NO_MAT_REDEMPTION | SLOWS_WHILE_IN_HAND
|
||||
block_chance = 30
|
||||
item_flags = NO_MAT_REDEMPTION | SLOWS_WHILE_IN_HAND | ITEM_CAN_BLOCK | ITEM_CAN_PARRY
|
||||
block_parry_data = /datum/block_parry_data/electrostaff
|
||||
attack_verb = list("struck", "beaten", "thwacked", "pulped")
|
||||
total_mass = 5 //yeah this is a heavy thing, beating people with it while it's off is not going to do you any favors. (to curb stun-kill rampaging without it being on)
|
||||
var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell/high
|
||||
@@ -1086,6 +1081,46 @@
|
||||
var/stun_status_duration = 25
|
||||
var/stun_stam_cost = 3.5
|
||||
|
||||
// haha security desword time /s
|
||||
/datum/block_parry_data/electrostaff
|
||||
block_damage_absorption = 0
|
||||
block_damage_multiplier = 1
|
||||
block_attack_types = ~ATTACK_TYPE_PROJECTILE // only able to parry non projectiles
|
||||
block_damage_multiplier_override(
|
||||
TEXT_ATTACK_TYPE_MELEE = 0.5, // only useful on melee and unarmed
|
||||
TEXT_ATTACK_TYPE_UNARMED = 0.3
|
||||
)
|
||||
block_start_delay = 0.5 // near instantaneous block
|
||||
block_stamina_cost_per_second = 6
|
||||
block_stamina_efficiency = 2 // haha this is a horrible idea
|
||||
// more slowdown that deswords because security
|
||||
block_slowdown = 2
|
||||
// no attacking while blocking
|
||||
block_lock_attacking = TRUE
|
||||
|
||||
parry_time_windup = 1.5
|
||||
parry_time_active = 5
|
||||
parry_time_spindown = 0
|
||||
parry_time_spindown_visual_override = 1
|
||||
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING // no attacking while parrying
|
||||
parry_time_perfect = 0
|
||||
parry_time_perfect_leeway = 1.5
|
||||
parry_efficiency_perfect = 100
|
||||
parry_efficiency_perfect_override = list(
|
||||
TEXT_ATTACK_TYPE_PROJECTILE = 80 // no perfect projectile blocking
|
||||
)
|
||||
parry_imperfect_falloff_percent = 15
|
||||
parry_imperfect_falloff_percent_override = list(
|
||||
TEXT_ATTACK_TYPE_PROJECTILE = 35 // really crappy vs projectiles
|
||||
)
|
||||
parry_time_perfect_leeway_override = list(
|
||||
TEXT_ATTACK_TYPE_PROJECTILE = 1 // extremely harsh window for projectiles
|
||||
)
|
||||
// not extremely punishing to fail, but no spamming the parry.
|
||||
parry_cooldown = 5 SECONDS
|
||||
parry_failed_stagger_duration = 1.5 SECONDS
|
||||
parry_failed_clickcd_duration = 1 SECONDS
|
||||
|
||||
/obj/item/twohanded/electrostaff/Initialize(mapload)
|
||||
. = ..()
|
||||
if(ispath(cell))
|
||||
@@ -1101,11 +1136,6 @@
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
. = R.get_cell()
|
||||
|
||||
/obj/item/twohanded/electrostaff/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(!on || (!can_block_projectiles && (attack_type & ATTACK_TYPE_PROJECTILE)))
|
||||
return BLOCK_NONE
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/electrostaff/proc/min_hitcost()
|
||||
return min(stun_cost, lethal_cost)
|
||||
|
||||
|
||||
@@ -247,40 +247,38 @@
|
||||
var/mob/living/L = attacker
|
||||
var/datum/block_parry_data/data = get_parry_data()
|
||||
var/list/effect_text = list()
|
||||
if(data.parry_data[PARRY_REFLEX_COUNTERATTACK])
|
||||
switch(data.parry_data[PARRY_REFLEX_COUNTERATTACK])
|
||||
if(PARRY_COUNTERATTACK_PROC)
|
||||
switch(parrying)
|
||||
if(ITEM_PARRY)
|
||||
active_parry_item.active_parry_reflex_counter(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, parry_efficiency, effect_text)
|
||||
if(UNARMED_PARRY)
|
||||
active_parry_reflex_counter(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, parry_efficiency, effect_text)
|
||||
if(MARTIAL_PARRY)
|
||||
mind.martial_art.active_parry_reflex_counter(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, parry_efficiency, effect_text)
|
||||
if(PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN) // adjacent is probably a shit check but whatever.
|
||||
if(Adjacent(attacker))
|
||||
switch(parrying)
|
||||
if(ITEM_PARRY)
|
||||
active_parry_item.melee_attack_chain(src, attacker, null)
|
||||
effect_text += "reflexively counterattacking with [active_parry_item]"
|
||||
if(UNARMED_PARRY)
|
||||
UnarmedAttack(attacker)
|
||||
effect_text += "reflexively counterattacking in the process"
|
||||
if(MARTIAL_PARRY)
|
||||
UnarmedAttack(attacker)
|
||||
effect_text += "reflexively maneuvering to retaliate"
|
||||
if(data.parry_data[PARRY_DISARM_ATTACKER])
|
||||
L.drop_all_held_items()
|
||||
effect_text += "disarming"
|
||||
if(data.parry_data[PARRY_KNOCKDOWN_ATTACKER])
|
||||
L.DefaultCombatKnockdown(data.parry_data[PARRY_KNOCKDOWN_ATTACKER])
|
||||
effect_text += "knocking them to the ground"
|
||||
if(data.parry_data[PARRY_STAGGER_ATTACKER])
|
||||
L.Stagger(data.parry_data[PARRY_STAGGER_ATTACKER])
|
||||
effect_text += "staggering"
|
||||
if(data.parry_data[PARRY_DAZE_ATTACKER])
|
||||
L.Daze(data.parry_data[PARRY_DAZE_ATTACKER])
|
||||
effect_text += "dazing"
|
||||
// Always proc so items can override behavior easily
|
||||
switch(parrying)
|
||||
if(ITEM_PARRY)
|
||||
active_parry_item.active_parry_reflex_counter(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, parry_efficiency, effect_text)
|
||||
if(UNARMED_PARRY)
|
||||
active_parry_reflex_counter(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, parry_efficiency, effect_text)
|
||||
if(MARTIAL_PARRY)
|
||||
mind.martial_art.active_parry_reflex_counter(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, parry_efficiency, effect_text)
|
||||
if(Adjacent(attacker) || data.parry_data[PARRY_COUNTERATTACK_IGNORE_ADJACENCY])
|
||||
if(data.parry_data[PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN])
|
||||
switch(parrying)
|
||||
if(ITEM_PARRY)
|
||||
active_parry_item.melee_attack_chain(src, attacker, null, ATTACKCHAIN_PARRY_COUNTERATTACK, data.parry_data[PARRY_COUNTERATTACK_DAMAGE_MULTIPLIER])
|
||||
effect_text += "reflexively counterattacking with [active_parry_item]"
|
||||
if(UNARMED_PARRY) // WARNING: If you are using these two, the attackchain parry counterattack flags and damage multipliers are unimplemented. Be careful with how you handle this.
|
||||
UnarmedAttack(attacker)
|
||||
effect_text += "reflexively counterattacking in the process"
|
||||
if(MARTIAL_PARRY) // Not well implemeneted, recommend custom implementation using the martial art datums.
|
||||
UnarmedAttack(attacker)
|
||||
effect_text += "reflexively maneuvering to retaliate"
|
||||
if(data.parry_data[PARRY_DISARM_ATTACKER])
|
||||
L.drop_all_held_items()
|
||||
effect_text += "disarming"
|
||||
if(data.parry_data[PARRY_KNOCKDOWN_ATTACKER])
|
||||
L.DefaultCombatKnockdown(data.parry_data[PARRY_KNOCKDOWN_ATTACKER])
|
||||
effect_text += "knocking them to the ground"
|
||||
if(data.parry_data[PARRY_STAGGER_ATTACKER])
|
||||
L.Stagger(data.parry_data[PARRY_STAGGER_ATTACKER])
|
||||
effect_text += "staggering"
|
||||
if(data.parry_data[PARRY_DAZE_ATTACKER])
|
||||
L.Daze(data.parry_data[PARRY_DAZE_ATTACKER])
|
||||
effect_text += "dazing"
|
||||
return effect_text
|
||||
|
||||
/// Gets the datum/block_parry_data we're going to use to parry.
|
||||
|
||||
Reference in New Issue
Block a user