save memory..
This commit is contained in:
@@ -29,6 +29,23 @@ GLOBAL_LIST_INIT(dir2blockdir, list(
|
||||
#define ITEM_PARRY "item"
|
||||
|
||||
/// Parry phase we're in
|
||||
#define PARRY_WINDUP "windup"
|
||||
#define PARRY_ACTIVE "main"
|
||||
#define PARRY_SPINDOWN "spindown"
|
||||
#define NOT_PARRYING 0
|
||||
#define PARRY_WINDUP 1
|
||||
#define PARRY_ACTIVE 2
|
||||
#define PARRY_SPINDOWN 3
|
||||
|
||||
/// 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
|
||||
#define PARRY_DISARM_ATTACKER "disarm_attacker"
|
||||
/// List association should be duration or null for just plain knockdown.
|
||||
#define PARRY_KNOCKDOWN_ATTACKER "knockdown_attacker"
|
||||
/// List association should be duration.
|
||||
#define PARRY_STAGGER_ATTACKER "stagger_attacker"
|
||||
/// List association should be amount to increase clickcd of attacker to.
|
||||
#define PARRY_CLICKCD_ATTACKER "clickcd_attacker"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
var/allow_temp_override = TRUE //if this martial art can be overridden by temporary martial arts
|
||||
/// Can we be used to unarmed parry?
|
||||
var/can_martial_parry = FALSE
|
||||
/// Set this variable to something not null, this'll be the preferred unarmed parry in most cases if [can_martial_parry] is TRUE.
|
||||
/// Set this variable to something not null, this'll be the preferred unarmed parry in most cases if [can_martial_parry] is TRUE. YOU MUST RUN [get_block_parry_data(this)] INSTEAD OF DIRECTLY ACCESSING!
|
||||
var/datum/block_parry_data/block_parry_data
|
||||
|
||||
/datum/martial_art/proc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
|
||||
@@ -110,6 +110,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
/* Our block parry data. Should be set in init, or something if you are using it.
|
||||
* This won't be accessed without ITEM_CAN_BLOCK or ITEM_CAN_PARRY so do not set it unless you have to to save memory.
|
||||
* If you decide it's a good idea to leave this unset while turning the flags on, you will runtime. Enjoy.
|
||||
* If this is set to a path, it'll run get_block_parry_data(path). YOU MUST RUN [get_block_parry_data(this)] INSTEAD OF DIRECTLY ACCESSING!
|
||||
*/
|
||||
var/datum/block_parry_data/block_parry_data
|
||||
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
active_block_item = null
|
||||
REMOVE_TRAIT(src, TRAIT_MOBILITY_NOUSE, ACTIVE_BLOCK_TRAIT)
|
||||
remove_movespeed_modifier(MOVESPEED_ID_ACTIVE_BLOCK)
|
||||
if(timeToNextMove() < I.block_parry_data.block_end_click_cd_add)
|
||||
changeNext_move(I.block_parry_data.block_end_click_cd_add)
|
||||
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)
|
||||
active_block_effect_end()
|
||||
return TRUE
|
||||
|
||||
@@ -26,13 +27,14 @@
|
||||
return FALSE
|
||||
if(!(I in held_items))
|
||||
return FALSE
|
||||
if(!istype(I.block_parry_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 block_parry_data: [I.block_parry_data]!")
|
||||
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]!")
|
||||
active_blocking = TRUE
|
||||
active_block_item = I
|
||||
if(I.block_parry_data.block_lock_attacking)
|
||||
if(I.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.block_parry_data.block_slowdown, blacklisted_movetypes = FLOATING)
|
||||
add_movespeed_modifier(MOVESPEED_ID_ACTIVE_BLOCK, TRUE, 100, override = TRUE, multiplicative_slowdown = I.data.block_slowdown, blacklisted_movetypes = FLOATING)
|
||||
active_block_effect_start()
|
||||
return TRUE
|
||||
|
||||
@@ -60,16 +62,17 @@
|
||||
|
||||
/// 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/absorption = block_parry_data.block_damage_absorption_override[attack_type]
|
||||
var/efficiency = block_parry_data.block_damage_multiplier_override[attack_type]
|
||||
var/limit = block_parry_data.block_damage_limit_override[attack_type]
|
||||
var/datum/block_parry_data/data = get_block_parry_data(I.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]
|
||||
// must use isnulls to handle 0's.
|
||||
if(isnull(absorption))
|
||||
absorption = block_parry_data.block_damage_absorption
|
||||
absorption = data.block_damage_absorption
|
||||
if(isnull(efficiency))
|
||||
efficiency = block_parry_data.block_damage_multiplier
|
||||
efficiency = data.block_damage_multiplier
|
||||
if(isnull(limit))
|
||||
limit = block_parry_data.block_damage_limit
|
||||
limit = data.block_damage_limit
|
||||
// now we calculate damage to reduce.
|
||||
var/final_damage = 0
|
||||
// apply limit
|
||||
@@ -84,13 +87,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/efficiency = block_parry_data.block_stamina_efficiency_override[attack_type]
|
||||
var/datum/block_parry_data/data = get_block_parry_data(I.block_parry_data)
|
||||
var/efficiency = data.block_stamina_efficiency_override[attack_type]
|
||||
if(isnull(efficiency))
|
||||
efficiency = block_parry_data.block_stamina_efficiency
|
||||
efficiency = data.block_stamina_efficiency
|
||||
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)
|
||||
var/datum/block_parry_data/data = get_block_parry_data(I.block_parry_data)
|
||||
if(iscarbon(owner))
|
||||
var/mob/living/carbon/C = owner
|
||||
var/held_index = C.get_held_index_of_item(src)
|
||||
@@ -98,9 +103,9 @@
|
||||
if(!BP?.body_zone)
|
||||
return C.adjustStaminaLossBuffered(stamina_amount) //nah
|
||||
var/zone = BP.body_zone
|
||||
var/stamina_to_zone = block_parry_data.block_stamina_limb_ratio * stamina_amount
|
||||
var/stamina_to_zone = data.block_stamina_limb_ratio * stamina_amount
|
||||
var/stamina_to_chest = stamina_amount - stamina_to_zone
|
||||
var/stamina_buffered = stamina_to_chest * block_parry_data.block_stamina_buffer_ratio
|
||||
var/stamina_buffered = stamina_to_chest * data.block_stamina_buffer_ratio
|
||||
stamina_to_chest -= stamina_buffered
|
||||
C.apply_damage(stamina_to_zone, STAMINA, zone)
|
||||
C.apply_damage(stamina_to_chest, STAMINA, BODY_ZONE_CHEST)
|
||||
@@ -143,7 +148,8 @@
|
||||
* Gets the list of directions we can block. Include DOWN to block attacks from our same tile.
|
||||
*/
|
||||
/obj/item/proc/blockable_directions()
|
||||
return block_parry_data.can_block_directions
|
||||
var/datum/block_parry_data/data = get_block_parry_data(I.block_parry_data)
|
||||
return data.can_block_directions
|
||||
|
||||
/**
|
||||
* Checks if we can block from a specific direction from our direction.
|
||||
|
||||
@@ -11,18 +11,20 @@
|
||||
var/parry_while_unarmed = FALSE
|
||||
/// Should we prioritize martial art parrying when unarmed?
|
||||
var/parry_prioritize_martial = TRUE
|
||||
/// Our block_parry_data for unarmed blocks/parries. Currently only used for parrying, as unarmed block isn't implemented yet.
|
||||
/// Our block_parry_data for unarmed blocks/parries. Currently only used for parrying, as unarmed block isn't implemented yet. YOU MUST RUN [get_block_parry_data(this)] INSTEAD OF DIRECTLY ACCESSING!
|
||||
var/datum/block_parry_data/block_parry_data
|
||||
|
||||
GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
|
||||
/proc/get_block_parry_data(type_or_id)
|
||||
if(ispath(type_or_id))
|
||||
. = GLOB.block_parry_data["[type_or_id]"]
|
||||
/proc/get_block_parry_data(datum/block_parry_data/type_id_datum)
|
||||
if(istype(type_id_datum))
|
||||
return type_id_datum
|
||||
if(ispath(type_id_datum))
|
||||
. = GLOB.block_parry_data["[type_id_datum]"]
|
||||
if(!.)
|
||||
. = GLOB.block_parry_data["[type_or_id]"] = new type_or_id
|
||||
. = GLOB.block_parry_data["[type_id_datum]"] = new type_id_datum
|
||||
else //text id
|
||||
return GLOB.block_parry_data["[type_or_id]"]
|
||||
return GLOB.block_parry_data["[type_id_datum]"]
|
||||
|
||||
/proc/set_block_parry_data(id, datum/block_parry_data/data)
|
||||
if(ispath(id))
|
||||
@@ -81,43 +83,78 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
/// Prioriry for [mob/do_run_block()] while we're being used to parry.
|
||||
// None - Parry is always highest priority!
|
||||
|
||||
/// Parry windup duration in deciseconds
|
||||
/// Parry windup duration in deciseconds. 0 to this is windup, afterwards is main stage.
|
||||
var/parry_time_windup = 2
|
||||
/// Parry spindown duration in deciseconds
|
||||
/// Parry spindown duration in deciseconds. main stage end to this is the spindown stage, afterwards the parry fully ends.
|
||||
var/parry_time_spindown = 3
|
||||
/// Main parry window in deciseconds
|
||||
/// Main parry window in deciseconds. This is between [parry_time_windup] and [parry_time_spindown]
|
||||
var/parry_time_active = 5
|
||||
/// Perfect parry window in deciseconds from the main window. 3 with main 5 = perfect on third decisecond of main window.
|
||||
/// Perfect parry window in deciseconds from the start of the main window. 3 with main 5 = perfect on third decisecond of main window.
|
||||
var/parry_time_perfect = 2.5
|
||||
/// Time on both sides of perfect parry that still counts as well, perfect
|
||||
/// 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)
|
||||
var/list/parry_time_perfect_leeway_override
|
||||
/// Parry "efficiency" falloff in percent per decisecond once perfect window is over.
|
||||
var/parry_time_imperfect_falloff_percent = 20
|
||||
var/parry_imperfect_falloff_percent = 20
|
||||
/// [parry_imperfect_falloff_percent] override for attack types, list(ATTACK_TYPE_DEFINE = deciseconds)
|
||||
var/list/parry_time_imperfect_falloff_percent_override
|
||||
var/list/parry_imperfect_falloff_percent_override
|
||||
/// Efficiency in percent on perfect parry.
|
||||
var/parry_efficiency_perfect = 120
|
||||
/// Flags for things like what kind of counter we do if successful and such
|
||||
var/parry_flags = PARRY_FLAGS_DEFAULT
|
||||
|
||||
/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
|
||||
var/datum/block_parry_data/data = get_parry_data()
|
||||
var/windup_end = data.parry_time_windup
|
||||
var/active_end = windup + data.parry_time_active
|
||||
var/spindown_end = active + data.parry_time_spindown
|
||||
switch(get_parry_time())
|
||||
if(0 to windup_end)
|
||||
return PARRY_WINDUP
|
||||
if(windup_end to active_end)
|
||||
return PARRY_ACTIVE
|
||||
if(active_end to spindown_end)
|
||||
return PARRY_SPINDOWN
|
||||
return NOT_PARRYING
|
||||
|
||||
/mob/living/proc/get_parry_efficiency(attack_type)
|
||||
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]
|
||||
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]
|
||||
if(isnull(falloff))
|
||||
falloff = data.parry_imperfect_falloff_percent
|
||||
. -= falloff * difference
|
||||
|
||||
/mob/living/proc/get_parry_time()
|
||||
return world.time - parry_start_time
|
||||
|
||||
/// same return values as normal blocking, called with absolute highest priority in the block "chain".
|
||||
/mob/living/proc/run_parry(real_attack = TRUE, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list())
|
||||
|
||||
/// Gets the datum/block_parry_data we're going to use to parry.
|
||||
/mob/living/proc/get_parry_data()
|
||||
if(parrying == ITEM_PARRY)
|
||||
return active_parry_item.block_parry_data
|
||||
return get_block_parry_data(active_parry_item.block_parry_data)
|
||||
else if(parrying == UNARMED_PARRY)
|
||||
return block_parry_data
|
||||
return get_block_parry_data(block_parry_data)
|
||||
else if(parrying == MARTIAL_PARRY)
|
||||
return mind.martial_art.block_parry_data
|
||||
return get_block_parry_data(mind.martial_art.block_parry_data)
|
||||
|
||||
#define UNARMED_PARRY
|
||||
#define MARTIAL_PARRY
|
||||
#define ITEM_PARRY
|
||||
|
||||
|
||||
Reference in New Issue
Block a user