save memory..

This commit is contained in:
kevinz000
2020-03-26 14:13:18 -07:00
parent 135ca27281
commit 8fe064da74
5 changed files with 101 additions and 40 deletions
+20 -3
View File
@@ -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"
+1 -1
View File
@@ -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)
+1
View File
@@ -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
+23 -17
View File
@@ -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