progress..
This commit is contained in:
@@ -64,6 +64,8 @@
|
||||
|
||||
handle_gravity()
|
||||
|
||||
handle_block_parry(seconds)
|
||||
|
||||
if(machine)
|
||||
machine.check_eye(src)
|
||||
|
||||
|
||||
@@ -10,15 +10,17 @@
|
||||
stop_active_blocking()
|
||||
return ..()
|
||||
|
||||
/mob/living/proc/stop_active_blocking()
|
||||
/mob/living/proc/stop_active_blocking(was_forced = FALSE)
|
||||
if(!active_blocking)
|
||||
return FALSE
|
||||
var/obj/item/I = active_block_item
|
||||
active_blocking = FALSE
|
||||
active_block_item = null
|
||||
REMOVE_TRAIT(src, TRAIT_MOBILITY_NOUSE, ACTIVE_BLOCK_TRAIT)
|
||||
remove_movespeed_modifier(MOVESPEED_ID_ACTIVE_BLOCK)
|
||||
var/datum/block_parry_data/data = get_block_parry_data(I.block_parry_data)
|
||||
if(timeToNextMove() < I.data.block_end_click_cd_add)
|
||||
changeNext_move(I.data.block_end_click_cd_add)
|
||||
if(timeToNextMove() < data.block_end_click_cd_add)
|
||||
changeNext_move(data.block_end_click_cd_add)
|
||||
active_block_effect_end()
|
||||
return TRUE
|
||||
|
||||
@@ -28,13 +30,13 @@
|
||||
if(!(I in held_items))
|
||||
return FALSE
|
||||
var/datum/block_parry_data/data = get_block_parry_data(I.block_parry_data)
|
||||
if(!istype(I.data)) //Typecheck because if an admin/coder screws up varediting or something we do not want someone being broken forever, the CRASH logs feedback so we know what happened.
|
||||
CRASH("start_active_blocking called with an item with no valid data: [I.data]!")
|
||||
if(!istype(data)) //Typecheck because if an admin/coder screws up varediting or something we do not want someone being broken forever, the CRASH logs feedback so we know what happened.
|
||||
CRASH("start_active_blocking called with an item with no valid data: [I] --> [I.block_parry_data]!")
|
||||
active_blocking = TRUE
|
||||
active_block_item = I
|
||||
if(I.data.block_lock_attacking)
|
||||
if(data.block_lock_attacking)
|
||||
ADD_TRAIT(src, TRAIT_MOBILITY_NOMOVE, ACTIVE_BLOCK_TRAIT)
|
||||
add_movespeed_modifier(MOVESPEED_ID_ACTIVE_BLOCK, TRUE, 100, override = TRUE, multiplicative_slowdown = I.data.block_slowdown, blacklisted_movetypes = FLOATING)
|
||||
add_movespeed_modifier(MOVESPEED_ID_ACTIVE_BLOCK, TRUE, 100, override = TRUE, multiplicative_slowdown = data.block_slowdown, blacklisted_movetypes = FLOATING)
|
||||
active_block_effect_start()
|
||||
return TRUE
|
||||
|
||||
@@ -67,9 +69,9 @@
|
||||
/// The amount of damage that is blocked.
|
||||
/obj/item/proc/active_block_damage_mitigation(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
var/datum/block_parry_data/data = get_block_parry_data(block_parry_data)
|
||||
var/absorption = data.block_damage_absorption_override[attack_type]
|
||||
var/efficiency = data.block_damage_multiplier_override[attack_type]
|
||||
var/limit = data.block_damage_limit_override[attack_type]
|
||||
var/absorption = data.block_damage_absorption_override["[attack_type]"]
|
||||
var/efficiency = data.block_damage_multiplier_override["[attack_type]"]
|
||||
var/limit = data.block_damage_limit_override["[attack_type]"]
|
||||
// must use isnulls to handle 0's.
|
||||
if(isnull(absorption))
|
||||
absorption = data.block_damage_absorption
|
||||
@@ -92,10 +94,15 @@
|
||||
/// Amount of stamina from damage blocked. Note that the damage argument is damage_blocked.
|
||||
/obj/item/proc/active_block_stamina_cost(mob/living/owner, atom/object, damage_blocked, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
var/datum/block_parry_data/data = get_block_parry_data(block_parry_data)
|
||||
var/efficiency = data.block_stamina_efficiency_override[attack_type]
|
||||
var/efficiency = data.block_stamina_efficiency_override["[attack_type]"]
|
||||
if(isnull(efficiency))
|
||||
efficiency = data.block_stamina_efficiency
|
||||
return damage_blocked / efficiency
|
||||
var/multiplier = 1
|
||||
if(!CHECK_MOBILITY(owner, MOBILITY_STAND))
|
||||
multiplier = data.block_resting_stamina_penalty_multiplier_override["["[attack_type]"]"]
|
||||
if(isnull(multiplier))
|
||||
multiplier = data.block_resting_stamina_penalty_multiplier
|
||||
return (damage_blocked / efficiency)
|
||||
|
||||
/// Apply the stamina damage to our user, notice how damage argument is stamina_amount.
|
||||
/obj/item/proc/active_block_do_stamina_damage(mob/living/owner, atom/object, stamina_amount, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
@@ -119,13 +126,13 @@
|
||||
|
||||
/obj/item/proc/active_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(!CHECK_BITFIELD(item_flags, ITEM_CAN_BLOCK))
|
||||
return
|
||||
if(!CHECK_BITFIELD(item_flags, ITEM_CAN_BLOCK))
|
||||
return
|
||||
var/incoming_direction = get_dir(get_turf(attacker) || get_turf(object), src)
|
||||
if(!can_block_direction(owner.dir, incoming_direction))
|
||||
return
|
||||
return BLOCK_NONE
|
||||
var/datum/block_parry_data/data = get_block_parry_data(block_parry_data)
|
||||
var/incoming_direction = get_dir(get_turf(attacker) || get_turf(object), src)
|
||||
if(!CHECK_MOBILITY(owner, MOBILITY_STAND) && !(data.block_resting_attack_types_anydir & attack_type) && (!(data.block_resting_attack_types_directional & attack_type) || !can_block_direction(owner.dir, incoming_direction)))
|
||||
return BLOCK_NONE
|
||||
else if(!can_block_direction(owner.dir, incoming_direction))
|
||||
return BLOCK_NONE
|
||||
block_return[BLOCK_RETURN_ACTIVE_BLOCK] = TRUE
|
||||
var/damage_mitigated = active_block_damage_mitigation(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
|
||||
var/final_damage = max(0, damage - damage_mitigated)
|
||||
|
||||
@@ -34,6 +34,9 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
/// Carries data like list data that would be a waste of memory if we initialized the list on every /item as we can cache datums easier.
|
||||
/datum/block_parry_data
|
||||
/////////// BLOCKING ////////////
|
||||
|
||||
/// NOTE: FOR ATTACK_TYPE_DEFINE, you MUST wrap it in "[DEFINE_HERE]"! The defines are bitflags, and therefore, NUMBERS!
|
||||
|
||||
/// See defines.
|
||||
var/can_block_directions = BLOCK_DIR_NORTH | BLOCK_DIR_NORTHEAST | BLOCK_DIR_NORTHWEST
|
||||
/// Our slowdown added while blocking
|
||||
@@ -47,17 +50,17 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
|
||||
/// Amount of "free" damage blocking absorbs
|
||||
var/block_damage_absorption = 10
|
||||
/// Override absorption, list(ATTACK_TYPE_DEFINE = absorption), see [block_damage_absorption]
|
||||
/// Override absorption, list("[ATTACK_TYPE_DEFINE]" = absorption), see [block_damage_absorption]
|
||||
var/list/block_damage_absorption_override
|
||||
|
||||
/// Ratio of damage block above absorption amount, coefficient, lower is better, this is multiplied by damage to determine how much is blocked.
|
||||
var/block_damage_multiplier = 0.5
|
||||
/// Override damage overrun efficiency, list(ATTACK_TYPE_DEFINE = absorption), see [block_damage_efficiency]
|
||||
/// Override damage overrun efficiency, list("[ATTACK_TYPE_DEFINE]" = absorption), see [block_damage_efficiency]
|
||||
var/list/block_damage_multiplier_override
|
||||
|
||||
/// Upper bound of damage block, anything above this will go right through.
|
||||
var/block_damage_limit = 80
|
||||
/// Override upper bound of damage block, list(ATTACK_TYPE_DEFINE = absorption), see [block_damage_limit]
|
||||
/// Override upper bound of damage block, list("[ATTACK_TYPE_DEFINE]" = absorption), see [block_damage_limit]
|
||||
var/list/block_damage_limit_override
|
||||
|
||||
/*
|
||||
@@ -69,7 +72,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
|
||||
/// Default damage-to-stamina coefficient, higher is better. This is based on amount of damage BLOCKED, not initial damage, to prevent damage from "double dipping".
|
||||
var/block_stamina_efficiency = 2
|
||||
/// Override damage-to-stamina coefficient, see [block_efficiency], this should be list(ATTACK_TYPE_DEFINE = coefficient_number)
|
||||
/// Override damage-to-stamina coefficient, see [block_efficiency], this should be list("[ATTACK_TYPE_DEFINE]" = coefficient_number)
|
||||
var/list/block_stamina_efficiency_override
|
||||
/// Ratio of stamina incurred by blocking that goes to the arm holding the object instead of the chest. Has no effect if this is not held in hand.
|
||||
var/block_stamina_limb_ratio = 0.5
|
||||
@@ -79,6 +82,15 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
/// Stamina dealt directly via adjustStaminaLossBuffered() per SECOND of block.
|
||||
var/block_stamina_cost_per_second = 1.5
|
||||
|
||||
/// Bitfield for attack types that we can block while down. This will work in any direction.
|
||||
var/block_resting_attack_types_anydir = ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED | ATTACK_TYPE_TACKLE
|
||||
/// Bitfield for attack types that we can block while down but only in our normal directions.
|
||||
var/block_resting_attack_types_directional = ATTACK_TYPE_PROJECTILE | ATTACK_TYPE_THROWN
|
||||
/// Multiplier to stamina damage taken for attacks blocked while downed.
|
||||
var/block_resting_stamina_penalty_multiplier = 1.5
|
||||
/// Override list for multiplier to stamina damage taken for attacks blocked while down. list("[ATTACK_TYPE_DEFINE]" = multiplier_number)
|
||||
var/list/block_resting_stamina_penalty_multiplier_override
|
||||
|
||||
/// Sounds for blocking
|
||||
var/list/block_sounds = list('sound/block_parry/block_metal1.ogg' = 1, 'sound/block_parry/block_metal1.ogg' = 1)
|
||||
|
||||
@@ -96,11 +108,11 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
var/parry_time_perfect = 2.5
|
||||
/// Time on both sides of perfect parry that still counts as part of the perfect window.
|
||||
var/parry_time_perfect_leeway = 1
|
||||
/// [parry_time_perfect_leeway] override for attack types, list(ATTACK_TYPE_DEFINE = deciseconds)
|
||||
/// [parry_time_perfect_leeway] override for attack types, list("[ATTACK_TYPE_DEFINE]" = deciseconds)
|
||||
var/list/parry_time_perfect_leeway_override
|
||||
/// Parry "efficiency" falloff in percent per decisecond once perfect window is over.
|
||||
var/parry_imperfect_falloff_percent = 20
|
||||
/// [parry_imperfect_falloff_percent] override for attack types, list(ATTACK_TYPE_DEFINE = deciseconds)
|
||||
/// [parry_imperfect_falloff_percent] override for attack types, list("[ATTACK_TYPE_DEFINE]" = deciseconds)
|
||||
var/list/parry_imperfect_falloff_percent_override
|
||||
/// Efficiency in percent on perfect parry.
|
||||
var/parry_efficiency_perfect = 120
|
||||
@@ -109,11 +121,17 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
PARRY_REFLEX_COUNTERATTACK = PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN
|
||||
)
|
||||
|
||||
/mob/living/proc/handle_block_parry(seconds = 1)
|
||||
if(active_blocking)
|
||||
var/datum/block_parry_data/data = get_block_parry_data(active_block_item.block_parry_data)
|
||||
adjustStaminaLossBuffered(data.block_stamina_cost_per_second * seconds)
|
||||
|
||||
/obj/item/proc/active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(!CHECK_BITFIELD(item_flags, ITEM_CAN_PARRY))
|
||||
return
|
||||
/// Yadda yadda WIP access block/parry data...
|
||||
|
||||
/*
|
||||
/mob/living/proc/get_parry_stage()
|
||||
if(!parrying)
|
||||
return NOT_PARRYING
|
||||
@@ -134,15 +152,15 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
var/datum/block_parry_data/data = get_parry_data()
|
||||
if(get_parry_stage() != PARRY_ACTIVE)
|
||||
return 0
|
||||
var/difference = abs(get_parry_time() - (data.parry_time_perfect + data.parry_time_windup)
|
||||
var/leeway = data.parry_time_perfect_leeway_override[attack_type]
|
||||
var/difference = abs(get_parry_time() - (data.parry_time_perfect + data.parry_time_windup))
|
||||
var/leeway = data.parry_time_perfect_leeway_override["[attack_type]"]
|
||||
if(isnull(leeway))
|
||||
leeway = data.parry_time_perfect_leeway
|
||||
difference -= leeway
|
||||
. = data.parry_efficiency_perfect
|
||||
if(difference <= 0)
|
||||
return
|
||||
var/falloff = data.parry_imperfect_falloff_percent_override[attack_type]
|
||||
var/falloff = data.parry_imperfect_falloff_percent_override["[attack_type]"]
|
||||
if(isnull(falloff))
|
||||
falloff = data.parry_imperfect_falloff_percent
|
||||
. -= falloff * difference
|
||||
@@ -155,7 +173,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
|
||||
/// Run counterattack if any
|
||||
/mob/living/proc/run_parry_countereffects(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list())
|
||||
var/datum/block_parry_data = get_parry_data()
|
||||
var/datum/block_parry_data/data = get_parry_data()
|
||||
if(data.parry_data[PARRY_REFLEX_COUNTERATTACK])
|
||||
switch(data.parry_data[PARRY_REFLEX_COUNTERATTACK])
|
||||
if(PARRY_COUNTERATTACK_PROC)
|
||||
@@ -184,5 +202,5 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
return get_block_parry_data(block_parry_data)
|
||||
else if(parrying == MARTIAL_PARRY)
|
||||
return get_block_parry_data(mind.martial_art.block_parry_data)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
to_chat(src, was_forced? "<span class='warning'>Your muscles are forcibly relaxed!</span>" : "<span class='warning'>You relax your muscles.</span>")
|
||||
if(update_icon)
|
||||
update_combat_mode_icon()
|
||||
stop_active_blocking(TRUE)
|
||||
|
||||
/mob/living/proc/enable_combat_mode(silent = TRUE, was_forced = FALSE, visible = FALSE, update_icon = TRUE)
|
||||
if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)
|
||||
|
||||
Reference in New Issue
Block a user