From c6ba7bfe1f2f15ce77d88931f8d7c44b5e8ab5c4 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 6 Mar 2021 18:06:53 -0700 Subject: [PATCH] changes --- code/__DEFINES/sound.dm | 6 +++- code/__DEFINES/status_effects.dm | 2 +- code/datums/status_effects/debuffs.dm | 8 ++--- code/datums/status_effects/status_effect.dm | 8 ----- code/game/sound.dm | 10 +++--- .../mob/living/carbon/human/human_defense.dm | 2 +- .../carbon/human/innate_abilities/blobform.dm | 2 -- .../modules/mob/living/living_active_parry.dm | 5 ++- code/modules/mob/living/living_block.dm | 2 ++ .../mob/living/living_blocking_parrying.dm | 35 +++++++++++++++++-- 10 files changed, 55 insertions(+), 25 deletions(-) diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index 1098a07b39..72543970ba 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -25,7 +25,11 @@ ///Percentage of sound's range where no falloff is applied #define SOUND_DEFAULT_FALLOFF_DISTANCE 1 //For a normal sound this would be 1 tile of no falloff ///The default exponent of sound falloff -#define SOUND_FALLOFF_EXPONENT 6 +#define SOUND_FALLOFF_EXPONENT 7.5 +/// Default distance multiplier for sounds +#define SOUND_DEFAULT_DISTANCE_MULTIPLIER 2.5 +/// Default range at which sound distance multiplier applies +#define SOUND_DEFAULT_MULTIPLIER_EFFECT_RANGE 7 //THIS SHOULD ALWAYS BE THE LOWEST ONE! //KEEP IT UPDATED diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index e2ace84156..db645f2a11 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -105,7 +105,7 @@ #define STATUS_EFFECT_FAKE_VIRUS /datum/status_effect/fake_virus //gives you fluff messages for cough, sneeze, headache, etc but without an actual virus -#define STATUS_EFFECT_NO_COMBAT_MODE /datum/status_effect/no_combat_mode //Wont allow combat mode and will disable it +#define STATUS_EFFECT_NO_COMBAT_MODE /datum/status_effect //Wont allow combat mode and will disable it #define STATUS_EFFECT_MESMERIZE /datum/status_effect/mesmerize //Just reskinned no_combat_mode #define STATUS_EFFECT_ELECTROSTAFF /datum/status_effect/electrostaff //slows down victim diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 1909327cc9..9585502264 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -127,18 +127,18 @@ desc = "You've fallen asleep. Wait a bit and you should wake up. Unless you don't, considering how helpless you are." icon_state = "asleep" -/datum/status_effect/no_combat_mode +/datum/status_effect id = "no_combat_mode" alert_type = null status_type = STATUS_EFFECT_REPLACE blocks_combatmode = TRUE -/datum/status_effect/no_combat_mode/on_creation(mob/living/new_owner, set_duration) +/datum/status_effect/on_creation(mob/living/new_owner, set_duration) if(isnum(set_duration)) duration = set_duration . = ..() -/datum/status_effect/no_combat_mode/robotic_emp +/datum/status_effect/robotic_emp id = "emp_no_combat_mode" /datum/status_effect/mesmerize @@ -148,13 +148,11 @@ /datum/status_effect/mesmerize/on_creation(mob/living/new_owner, set_duration) . = ..() ADD_TRAIT(owner, TRAIT_MUTE, "mesmerize") - ADD_TRAIT(owner, TRAIT_COMBAT_MODE_LOCKED, "mesmerize") owner.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/mesmerize) /datum/status_effect/mesmerize/on_remove() . = ..() REMOVE_TRAIT(owner, TRAIT_MUTE, "mesmerize") - REMOVE_TRAIT(owner, TRAIT_COMBAT_MODE_LOCKED, "mesmerize") owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/mesmerize) /datum/status_effect/mesmerize/on_creation(mob/living/new_owner, set_duration) diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm index 9dbbc1c469..b38b755f28 100644 --- a/code/datums/status_effects/status_effect.dm +++ b/code/datums/status_effects/status_effect.dm @@ -11,8 +11,6 @@ var/on_remove_on_mob_delete = FALSE //if we call on_remove() when the mob is deleted var/examine_text //If defined, this text will appear when the mob is examined - to use he, she etc. use "SUBJECTPRONOUN" and replace it in the examines themselves var/alert_type = /obj/screen/alert/status_effect //the alert thrown by the status effect, contains name and description - /// If this is TRUE, the user will have combt mode forcefully disabled while this is active. - var/blocks_combatmode = FALSE /// If this is TRUE, the user will have sprint forcefully disabled while this is active. var/blocks_sprint = FALSE var/obj/screen/alert/status_effect/linked_alert = null //the alert itself, if it exists @@ -61,8 +59,6 @@ /datum/status_effect/proc/on_apply() //Called whenever the buff is applied; returning FALSE will cause it to autoremove itself. SHOULD_CALL_PARENT(TRUE) - if(blocks_combatmode) - ADD_TRAIT(owner, TRAIT_COMBAT_MODE_LOCKED, src) if(blocks_sprint) ADD_TRAIT(owner, TRAIT_SPRINT_LOCKED, src) return TRUE @@ -74,8 +70,6 @@ /datum/status_effect/proc/on_remove() //Called whenever the buff expires or is removed; do note that at the point this is called, it is out of the owner's status_effects but owner is not yet null SHOULD_CALL_PARENT(TRUE) - if(blocks_combatmode) - REMOVE_TRAIT(owner, TRAIT_COMBAT_MODE_LOCKED, src) if(blocks_sprint) REMOVE_TRAIT(owner, TRAIT_SPRINT_LOCKED, src) return TRUE @@ -83,8 +77,6 @@ /datum/status_effect/proc/be_replaced() //Called instead of on_remove when a status effect is replaced by itself or when a status effect with on_remove_on_mob_delete = FALSE has its mob deleted owner.clear_alert(id) LAZYREMOVE(owner.status_effects, src) - if(blocks_combatmode) - REMOVE_TRAIT(owner, TRAIT_COMBAT_MODE_LOCKED, src) if(blocks_sprint) REMOVE_TRAIT(owner, TRAIT_SPRINT_LOCKED, src) owner = null diff --git a/code/game/sound.dm b/code/game/sound.dm index 1816336bd1..b233ebd6d2 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -43,7 +43,8 @@ falloff_distance - Distance at which falloff begins. Sound is at peak volume (in */ -/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff_exponent = SOUND_FALLOFF_EXPONENT, frequency = null, channel = 0, pressure_affected = TRUE, ignore_walls = TRUE, falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE, envwet = -10000, envdry = 0) +/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff_exponent = SOUND_FALLOFF_EXPONENT, frequency = null, channel = 0, pressure_affected = TRUE, ignore_walls = TRUE, + falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE, envwet = -10000, envdry = 0, distance_multiplier = SOUND_DEFAULT_DISTANCE_MULTIPLIER, distance_multiplier_min_range = SOUND_DEFAULT_MULTIPLIER_EFFECT_RANGE) if(isarea(source)) CRASH("playsound(): source is an area") @@ -83,11 +84,11 @@ falloff_distance - Distance at which falloff begins. Sound is at peak volume (in for(var/P in listeners) var/mob/M = P if(get_dist(M, turf_source) <= maxdistance) - M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, maxdistance, falloff_distance, null, envwet, envdry) + M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, maxdistance, falloff_distance, get_dist(M, turf_sounrce) <= distance_multiplier_min_range? 1 : distance_multiplier, envwet, envdry) for(var/P in SSmobs.dead_players_by_zlevel[source_z]) var/mob/M = P if(get_dist(M, turf_source) <= maxdistance) - M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, maxdistance, falloff_distance, null, envwet, envdry) + M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, maxdistance, falloff_distance, get_dist(M, turf_sounrce) <= distance_multiplier_min_range? 1 : distance_multiplier, envwet, envdry) /*! playsound @@ -108,7 +109,8 @@ distance_multiplier - Can be used to multiply the distance at which the sound is */ -/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff_exponent = SOUND_FALLOFF_EXPONENT, channel = 0, pressure_affected = TRUE, sound/S, max_distance, falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE, distance_multiplier = 1, envwet = -10000, envdry = 0) +/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff_exponent = SOUND_FALLOFF_EXPONENT, channel = 0, pressure_affected = TRUE, sound/S, max_distance, + falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE, distance_multiplier = SOUND_DEFAULT_DISTANCE_MULTIPLIER, envwet = -10000, envdry = 0) if(!client || !can_hear()) return diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index a74afc10f5..1174fcba70 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -409,7 +409,7 @@ return var/informed = FALSE if(isrobotic(src)) - apply_status_effect(/datum/status_effect/no_combat_mode/robotic_emp, severity / 20) + apply_status_effect(/datum/status_effect/robotic_emp, severity / 20) severity *= 0.5 var/do_not_stun = FALSE if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM)) diff --git a/code/modules/mob/living/carbon/human/innate_abilities/blobform.dm b/code/modules/mob/living/carbon/human/innate_abilities/blobform.dm index ed3c7e21d4..76abdf85fe 100644 --- a/code/modules/mob/living/carbon/human/innate_abilities/blobform.dm +++ b/code/modules/mob/living/carbon/human/innate_abilities/blobform.dm @@ -55,7 +55,6 @@ ADD_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT) ADD_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT) ADD_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT) - ADD_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT) ADD_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT) ADD_TRAIT(H, TRAIT_ARMOR_BROKEN, SLIMEPUDDLE_TRAIT) H.update_disabled_bodyparts(silent = TRUE) //silently update arms to be paralysed @@ -96,7 +95,6 @@ REMOVE_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT) REMOVE_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT) REMOVE_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT) - REMOVE_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT) REMOVE_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT) REMOVE_TRAIT(H, TRAIT_ARMOR_BROKEN, SLIMEPUDDLE_TRAIT) REMOVE_TRAIT(H, TRAIT_HUMAN_NO_RENDER, SLIMEPUDDLE_TRAIT) diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm index 571813f30e..a000bbab23 100644 --- a/code/modules/mob/living/living_active_parry.dm +++ b/code/modules/mob/living/living_active_parry.dm @@ -230,9 +230,12 @@ 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(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list()) +/mob/living/proc/run_parry(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), allow_auto = TRUE) var/stage = get_parry_stage() if(stage != PARRY_ACTIVE) + // If they're not currently parrying, attempt auto parry + if((stage == NOT_PARRYING) && allow_auto) + return attempt_auto_parry() return BLOCK_NONE var/datum/block_parry_data/data = get_parry_data() if(attack_type && (!(attack_type & data.parry_attack_types) || (attack_type & ATTACK_TYPE_PARRY_COUNTERATTACK))) // if this attack is from a parry do not parry it lest we infinite loop. diff --git a/code/modules/mob/living/living_block.dm b/code/modules/mob/living/living_block.dm index d32265e478..10427c20ec 100644 --- a/code/modules/mob/living/living_block.dm +++ b/code/modules/mob/living/living_block.dm @@ -37,6 +37,8 @@ var/results if(I == active_block_item) results = I.active_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list, attack_direction) + else if(I.can_passive_block()) + results = I.passive_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list, attack_direction) else results = I.run_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list) . |= results diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm index d1ccf7f0c4..0a0ef30f33 100644 --- a/code/modules/mob/living/living_blocking_parrying.dm +++ b/code/modules/mob/living/living_blocking_parrying.dm @@ -75,7 +75,7 @@ GLOBAL_LIST_EMPTY(block_parry_data) var/block_stamina_buffer_ratio = 1 /// Stamina dealt directly via UseStaminaBuffer() per SECOND of block. - var/block_stamina_cost_per_second = 1.5 + var/block_stamina_cost_per_second = 1 /// Prevent stamina buffer regeneration while block? var/block_no_stambuffer_regeneration = TRUE /// Prevent stamina regeneration while block? @@ -93,6 +93,13 @@ GLOBAL_LIST_EMPTY(block_parry_data) /// Sounds for blocking var/list/block_sounds = list('sound/block_parry/block_metal1.ogg' = 1, 'sound/block_parry/block_metal1.ogg' = 1) + // Autoblock + // Other than for overrides, this mostly just reads from the above vars + /// Can this item automatically block? + var/block_automatic_enabled = TRUE + /// Directions that you can autoblock in + var/block_automatic_directions = BLOCK_DIR_NORTH | BLOCK_DIR_NORTHEAST | BLOCK_DIR_NORTHWEST + /////////// PARRYING //////////// /// Prioriry for [mob/do_run_block()] while we're being used to parry. // None - Parry is always highest priority! @@ -106,7 +113,7 @@ GLOBAL_LIST_EMPTY(block_parry_data) var/parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING /// Parry windup duration in deciseconds. 0 to this is windup, afterwards is main stage. - var/parry_time_windup = 2 + var/parry_time_windup = 0 /// 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. This is between [parry_time_windup] and [parry_time_spindown] @@ -167,6 +174,30 @@ GLOBAL_LIST_EMPTY(block_parry_data) var/imperfect_parry_block_return_list var/failed_parry_block_return_list + // Auto parry + // Anything not specified like cooldowns/clickdelay respecting is pulled from above. + /// Can this data automatically parry + var/parry_automatic_enabled = TRUE + /// Hard autoparry cooldown + var/autoparry_cooldown_absolute = 3 SECONDS + /// Autoparry : Simulate a parry sequence starting at a certain tick, or simply simulate a single attack parry? + var/autoparry_sequence_simulation = FALSE + // Single attack simulation: + /// Parry cooldown to inflict on single-attack autoparry + var/autoparry_single_parry_cooldown = 3 SECONDS + /// Clickdelay to inflict on single-attack autoparry + var/autoparry_single_click_cooldown = 0 + /// Single attack autoparry - efficiency + var/autoparry_single_efficiency = 60 + /// Single attack autoparry - efficiency overrides by attack type, see above + var/list/autoparry_single_efficiency_override + // Parry sequence simulation: + /// Decisecond of sequence to start on. -1 to start to 0th tick of active parry window. + var/autoparry_sequence_start_time = -1 + /// Efficiency multiplier + var/autoparry_sequence_efficiency_multiplier = 0.8 + // Clickdelay/cooldown settings not included, as well as whether or not to lock attack/sprinting/etc. They will be pulled from the above. + /** * Quirky proc to get average of flags in list that are in attack_type because why is attack_type a flag. */