From 70b8d833c0bfa2daa1f43b888ce732b6cb761a4a Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 28 Feb 2021 00:00:14 -0700
Subject: [PATCH 01/43] changes
---
code/__HELPERS/do_after.dm | 47 +++++++++--------
code/_onclick/item_attack.dm | 2 +-
.../configuration/entries/game_options.dm | 9 ++++
code/datums/status_effects/debuffs.dm | 12 ++++-
code/game/objects/effects/decals/misc.dm | 51 +++++++++++++++++++
code/modules/mob/living/carbon/carbon.dm | 20 +++++++-
code/modules/mob/living/carbon/human/human.dm | 6 +--
.../mob/living/carbon/human/species.dm | 3 +-
code/modules/mob/living/say.dm | 21 +++++---
.../movespeed/modifiers/status_effects.dm | 6 +++
code/modules/ninja/suit/suit.dm | 4 +-
.../projectiles/ammunition/energy/stun.dm | 4 ++
.../projectiles/guns/energy/energy_gun.dm | 14 ++++-
.../projectiles/projectile/energy/stun.dm | 14 ++---
.../reagents/reagent_containers/spray.dm | 51 +++----------------
15 files changed, 173 insertions(+), 91 deletions(-)
diff --git a/code/__HELPERS/do_after.dm b/code/__HELPERS/do_after.dm
index c65cd80394..550eea65c0 100644
--- a/code/__HELPERS/do_after.dm
+++ b/code/__HELPERS/do_after.dm
@@ -1,23 +1,24 @@
/**
- * Higher overhead "advanced" version of do_after.
- * @params
- * - atom/user is the atom doing the action or the "physical" user
- * - delay is time in deciseconds
- * - atom/target is the atom the action is being done to, defaults to user
- * - do_after_flags see __DEFINES/flags/do_after.dm for details.
- * - datum/callback/extra_checks - Every time this ticks, extra_checks() is invoked with (user, delay, target, time_left, do_after_flags, required_mobility_flags, required_combat_flags, mob_redirect, stage, initially_held_item, tool).
- * Stage can be DO_AFTER_STARTING, DO_AFTER_PROGRESSING, DO_AFTER_FINISHING
- * If it returns DO_AFTER_STOP, this breaks.
- * If it returns nothing, all other checks are done.
- * If it returns DO_AFTER_PROCEED, all other checks are ignored.
- * - required_mobility_flags is checked with CHECK_ALL_MOBILITY. Will immediately fail if the user isn't a mob.
- * - requried_combat_flags is checked with CHECK_MULTIPLE_BITFIELDS. Will immediately fail if the user isn't a mob.
- * - mob/living/mob_redirect - advanced option: If this is specified, movement and mobility/combat flag checks will use this instead of user. Progressbars will also go to this.
- * - obj/item/tool - The tool we're using. See do_after flags for details.
- */
-#define INVOKE_CALLBACK cb_return = extra_checks?.Invoke(user, delay, target, world.time - starttime, do_after_flags, required_mobility_flags, required_combat_flags, mob_redirect, stage, initially_held_item, tool)
+ * Higher overhead "advanced" version of do_after.
+ * @params
+ * - atom/user is the atom doing the action or the "physical" user
+ * - delay is time in deciseconds
+ * - atom/target is the atom the action is being done to, defaults to user
+ * - do_after_flags see __DEFINES/flags/do_after.dm for details.
+ * - datum/callback/extra_checks - Every time this ticks, extra_checks() is invoked with (user, delay, target, time_left, do_after_flags, required_mobility_flags, required_combat_flags, mob_redirect, stage, initially_held_item, tool, passed_in).
+ * Stage can be DO_AFTER_STARTING, DO_AFTER_PROGRESSING, DO_AFTER_FINISHING
+ * If it returns DO_AFTER_STOP, this breaks.
+ * If it returns nothing, all other checks are done.
+ * If it returns DO_AFTER_PROCEED, all other checks are ignored.
+ * passed_in is a list[PROGRESS_MULTIPLIER], for modification.
+ * - required_mobility_flags is checked with CHECK_ALL_MOBILITY. Will immediately fail if the user isn't a mob.
+ * - requried_combat_flags is checked with CHECK_MULTIPLE_BITFIELDS. Will immediately fail if the user isn't a mob.
+ * - mob/living/mob_redirect - advanced option: If this is specified, movement and mobility/combat flag checks will use this instead of user. Progressbars will also go to this.
+ * - obj/item/tool - The tool we're using. See do_after flags for details.
+ */
+#define INVOKE_CALLBACK cb_return = extra_checks?.Invoke(user, delay, target, timeleft, do_after_flags, required_mobility_flags, required_combat_flags, mob_redirect, stage, initially_held_item, tool, passed_in)
#define CHECK_FLAG_FAILURE ((required_mobility_flags || required_combat_flags) && (!living_user || (required_mobility_flags && !CHECK_ALL_MOBILITY(living_user, required_mobility_flags)) || (required_combat_flags && !CHECK_MULTIPLE_BITFIELDS(living_user.combat_flags, required_combat_flags))))
-#define TIMELEFT (world.time - starttime)
+#define TIMELEFT (timeleft)
/proc/do_after_advanced(atom/user, delay, atom/target, do_after_flags, datum/callback/extra_checks, required_mobility_flags, required_combat_flags, mob/living/mob_redirect, obj/item/tool)
// CHECK AND SET VARIABLES
if(!user)
@@ -40,8 +41,7 @@
return FALSE
if(!(do_after_flags & DO_AFTER_NO_COEFFICIENT) && living_user)
delay *= living_user.cached_multiplicative_actions_slowdown
- var/starttime = world.time
- var/endtime = world.time + delay
+ var/timeleft = delay
var/obj/item/initially_held_item = mob_redirect?.get_active_held_item()
var/atom/movable/AM_user = ismovable(user) && user
var/drifting = AM_user?.Process_Spacemove(NONE) && AM_user.inertia_dir
@@ -70,13 +70,18 @@
var/locchanged
var/ctu
var/ctt
- while(world.time < endtime)
+ var/tick_time = world.time
+ var/list/passed_in = list(1)
+ while(timeleft > 0)
stoplag(1)
+ var/timepassed = world.time - tick_time
+ timepassed = world.time
progbar?.update(TIMELEFT)
if(QDELETED(user) || QDELETED(target) || (user.loc == null) || (target.loc == null))
. = FALSE
break
INVOKE_CALLBACK
+ timeleft -= timepassed * passed_in[1]
if(cb_return == DO_AFTER_STOP)
. = FALSE
break
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 7a614da07b..bedb0f6dec 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -255,7 +255,7 @@
if(!isnull(stagger_force))
return stagger_force
/// totally not an untested, arbitrary equation.
- return clamp((1.5 + (w_class/5)) * ((force_override || force) / 1.5), 0, 10 SECONDS)
+ return clamp((1.5 + (w_class/5)) * ((force_override || force) / 1.5), 0, 10 SECONDS) * CONFIG_GET(number/melee_stagger_factor)
/obj/item/proc/do_stagger_action(mob/living/target, mob/living/user, force_override)
if(!CHECK_BITFIELD(target.status_flags, CANSTAGGER))
diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
index 4034722417..f6a3388c01 100644
--- a/code/controllers/configuration/entries/game_options.dm
+++ b/code/controllers/configuration/entries/game_options.dm
@@ -262,6 +262,15 @@
/mob/living/carbon/alien/humanoid/royal/queen = 2
)
+/datum/config_entry/number/sprintless_stagger_slowdown
+ config_entry_value = 0
+
+/datum/config_entry/number/melee_stagger_factor
+ config_entry_value = 1
+
+/datum/config_entry/number/sprintless_off_balance_slowdown
+ config_entry_value = 0.85
+
/datum/config_entry/number/movedelay //Used for modifying movement speed for mobs.
abstract_type = /datum/config_entry/number/movedelay
integer = FALSE
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index fe59bbe14a..1909327cc9 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -95,21 +95,31 @@
/datum/status_effect/staggered/on_creation(mob/living/new_owner, set_duration)
if(isnum(set_duration))
duration = set_duration
+ if(!CONFIG_GET(flag/sprint_enabled))
+ new_owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/status_effect/stagger, TRUE, CONFIG_GET(number/sprintless_stagger_slowdown))
+ return ..()
+
+/datum/status_effect/staggered/on_remove()
+ owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/stagger)
return ..()
/datum/status_effect/off_balance
id = "offbalance"
+ blocks_sprint = TRUE
alert_type = null
/datum/status_effect/off_balance/on_creation(mob/living/new_owner, set_duration)
if(isnum(set_duration))
duration = set_duration
+ if(!CONFIG_GET(flag/sprint_enabled))
+ new_owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/status_effect/off_balance, TRUE, CONFIG_GET(number/sprintless_off_balance_slowdown))
return ..()
/datum/status_effect/off_balance/on_remove()
var/active_item = owner.get_active_held_item()
if(is_type_in_typecache(active_item, GLOB.shove_disarming_types))
owner.visible_message("[owner.name] regains their grip on \the [active_item]!", "You regain your grip on \the [active_item]", null, COMBAT_MESSAGE_RANGE)
+ owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/off_balance)
return ..()
/obj/screen/alert/status_effect/asleep
@@ -162,7 +172,7 @@
id = "tased"
alert_type = null
var/movespeed_mod = /datum/movespeed_modifier/status_effect/tased
- var/stamdmg_per_ds = 0 //a 20 duration would do 20 stamdmg, disablers do 24 or something
+ var/stamdmg_per_ds = 1 //a 20 duration would do 20 stamdmg, disablers do 24 or something
var/last_tick = 0 //fastprocess processing speed is a goddamn sham, don't trust it.
/datum/status_effect/electrode/on_creation(mob/living/new_owner, set_duration)
diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm
index 8f46d5cc46..514fcdd68a 100644
--- a/code/game/objects/effects/decals/misc.dm
+++ b/code/game/objects/effects/decals/misc.dm
@@ -19,10 +19,61 @@
icon = 'icons/obj/chempuff.dmi'
pass_flags = PASSTABLE | PASSGRILLE
layer = FLY_LAYER
+ var/stream = FALSE
+ var/speed = 1
+ var/range = 3
+ var/hits_left = 3
+ var/range_left = 3
/obj/effect/decal/chempuff/blob_act(obj/structure/blob/B)
return
+/obj/effect/decal/chempuff/Initialize(mapload, stream_mode, speed, range, hits_left)
+ . = ..()
+ stream = stream_mode
+ src.speed = speed
+ src.range = scc.range_left = range
+ src.hits_left = hits_left
+
+/obj/effect/decal/chempuff/proc/hit_thing(atom/A)
+ if(A == src || A.invisibility)
+ return
+ if(!hits_left)
+ return
+ if(stream)
+ if(ismob(A))
+ var/mob/M = A
+ if(!M.lying || !range_left)
+ reagents.reaction(M, VAPOR)
+ hits_left--
+ else
+ if(!range_left)
+ reagents.reaction(A, VAPOR)
+ else
+ reagents.reaction(A)
+ if(ismob(A))
+ hits_left--
+
+/obj/effect/decal/chempuff/Crossed(atom/movable/AM, oldloc)
+ . = ..()
+ hit_thing(AM)
+
+/obj/effect/decal/chempuff/proc/run(atom/target)
+ for(var/i in 1 to range)
+ range_left--
+ if(!isturf(loc))
+ break
+ for(var/atom/T in loc)
+ hit_thing(T)
+ if(!hits_left || !isturf(loc))
+ break
+ if(hits_left && isturf(loc) && (!stream || !range_left))
+ reagents.reaction(loc, VAPOR)
+ hits_left--
+ if(!hits_left)
+ break
+ qdel(src)
+
/obj/effect/decal/fakelattice
name = "lattice"
desc = "A lightweight support lattice."
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index f143f6302d..c7a2d611d6 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -358,10 +358,11 @@
return
I.item_flags |= BEING_REMOVED
breakouttime = I.breakouttime
+ var/datum/cuffbreak_checker/cuffbreak_checker = new(get_turf(src))
if(!cuff_break)
visible_message("[src] attempts to remove [I]!")
to_chat(src, "You attempt to remove [I]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)")
- if(do_after(src, breakouttime, 0, target = src, required_mobility_flags = MOBILITY_RESIST))
+ if(do_after_advanced(src, breakouttime, src, NONE, CALLBACK(cuffbreak_checker, /datum/cuffbreak_checker.proc/check_movement), required_mobility_flags = MOBILITY_RESIST))
clear_cuffs(I, cuff_break)
else
to_chat(src, "You fail to remove [I]!")
@@ -370,15 +371,30 @@
breakouttime = 50
visible_message("[src] is trying to break [I]!")
to_chat(src, "You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)")
- if(do_after(src, breakouttime, 0, target = src))
+ if(do_after_advanced(src, breakouttime, src, NONE, CALLBACK(cuffbreak_checker, /datum/cuffbreak_checker.proc/check_movement), required_mobility_flags = MOBILITY_RESIST))
clear_cuffs(I, cuff_break)
else
to_chat(src, "You fail to break [I]!")
else if(cuff_break == INSTANT_CUFFBREAK)
clear_cuffs(I, cuff_break)
+
+ QDEL_NULL(cuffbreak_checker)
I.item_flags &= ~BEING_REMOVED
+/datum/cuffbreak_checker
+ var/turf/last
+
+/datum/cuffbreak_checker/New(turf/initial_turf)
+ last = initial_turf
+
+/datum/cuffbreak_checker/proc/check_movement(atom/user, delay, atom/target, time_left, do_after_flags, required_mobility_flags, required_combat_flags, mob_redirect, stage, initially_held_item, tool, list/passed_in)
+ if(get_turf(user) != last)
+ last = get_turf(user)
+ passed_in[1] = 0.5
+ else
+ passed_in[1] = 1
+
/mob/living/carbon/proc/uncuff()
if (handcuffed)
var/obj/item/W = handcuffed
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 8660e115a6..6190518963 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1053,10 +1053,10 @@
return
if(!HAS_TRAIT(src, TRAIT_IGNOREDAMAGESLOWDOWN)) //if we want to ignore slowdown from damage, but not from equipment
var/scaling = maxHealth / 100
- var/health_deficiency = ((maxHealth / scaling) - (health / scaling) + (getStaminaLoss()*0.75))//CIT CHANGE - reduces the impact of staminaloss and makes stamina buffer influence it
+ var/health_deficiency = max(((maxHealth / scaling) - (health / scaling)), (getStaminaLoss()*0.75))
if(health_deficiency >= 40)
- add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, (health_deficiency-39) / 75)
- add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, (health_deficiency-39) / 25)
+ add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, (health_deficiency - 15) / 75)
+ add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, (health_deficiency - 15) / 25)
else
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index a7e305201d..8bae43848d 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -1834,6 +1834,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(CHECK_MOBILITY(target, MOBILITY_STAND))
target.adjustStaminaLoss(5)
+ else
+ target.adjustStaminaLoss(target.getStaminaLoss() > 75? 5 : 75)
if(target.is_shove_knockdown_blocked())
return
@@ -1876,7 +1878,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
target.visible_message("[user.name] shoves [target.name]!",
"[user.name] shoves you!", null, COMBAT_MESSAGE_RANGE, null,
user, "You shove [target.name]!")
- target.Stagger(SHOVE_STAGGER_DURATION)
var/obj/item/target_held_item = target.get_active_held_item()
if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types))
target_held_item = null
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 9646796802..d72b8c904a 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -266,16 +266,10 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
eavesdrop_range = EAVESDROP_EXTRA_RANGE
var/list/listening = get_hearers_in_view(message_range+eavesdrop_range, source)
var/list/the_dead = list()
- var/list/yellareas //CIT CHANGE - adds the ability for yelling to penetrate walls and echo throughout areas
- if(!eavesdrop_range && say_test(message) == "2") //CIT CHANGE - ditto
- yellareas = get_areas_in_range(message_range*0.5, source) //CIT CHANGE - ditto
+
for(var/_M in GLOB.player_list)
var/mob/M = _M
if(M.stat != DEAD) //not dead, not important
- if(yellareas) //CIT CHANGE - see above. makes yelling penetrate walls
- var/area/A = get_area(M) //CIT CHANGE - ditto
- if(istype(A) && A.ambientsounds != SPACE && (A in yellareas)) //CIT CHANGE - ditto
- listening |= M //CIT CHANGE - ditto
continue
if(!M.client || !client) //client is so that ghosts don't have to listen to mice
continue
@@ -302,6 +296,9 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
AM.Hear(rendered, src, message_language, message, null, spans, message_mode, source)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_LIVING_SAY_SPECIAL, src, message)
+ if(!eavesdrop_range && say_test(message) == "2") // Yell hook
+ process_yelling(listening, rendered, src, message_language, message, spans, message_mode, source)
+
//speech bubble
var/list/speech_bubble_recipients = list()
for(var/mob/M in listening)
@@ -311,6 +308,14 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_recipients, 30)
+/atom/movable/proc/process_yelling(list/already_heard, rendered, atom/movable/speaker, datum/language/message_language, list/spans, message_mode, obj/source)
+ var/list/overhearing = list()
+#warn todo: yelling
+ overhearing -= already_heard
+ for(var/_AM in overhearing)
+ var/atom/movable/AM = _AM
+ AM.Hear(rendered, speaker, message_language, message, null, spans, message_mode, source)
+
/mob/proc/binarycheck()
return FALSE
@@ -333,7 +338,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/obj/item/bodypart/rightarm = get_bodypart(BODY_ZONE_R_ARM)
if(HAS_TRAIT(src, TRAIT_MUTE) && get_selected_language() != /datum/language/signlanguage)
return 0
-
+
if (get_selected_language() == /datum/language/signlanguage)
var/left_disabled = FALSE
var/right_disabled = FALSE
diff --git a/code/modules/movespeed/modifiers/status_effects.dm b/code/modules/movespeed/modifiers/status_effects.dm
index 4c710cb483..d174524898 100644
--- a/code/modules/movespeed/modifiers/status_effects.dm
+++ b/code/modules/movespeed/modifiers/status_effects.dm
@@ -42,3 +42,9 @@
/datum/movespeed_modifier/status_effect/mkultra
multiplicative_slowdown = -2
blacklisted_movetypes= FLYING|FLOATING
+
+/datum/movespeed_modifier/status_effect/staggered
+ variable = TRUE
+
+/datum/movespeed_modifier/status_effect/off_balance
+ variable = TRUE
diff --git a/code/modules/ninja/suit/suit.dm b/code/modules/ninja/suit/suit.dm
index b46f30b4fb..ed711771bf 100644
--- a/code/modules/ninja/suit/suit.dm
+++ b/code/modules/ninja/suit/suit.dm
@@ -118,7 +118,7 @@ Contents:
ADD_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT)
n_shoes = H.shoes
ADD_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT)
- n_shoes.slowdown--
+ n_shoes.slowdown -= 0.5
n_gloves = H.gloves
ADD_TRAIT(n_gloves, TRAIT_NODROP, NINJA_SUIT_TRAIT)
return TRUE
@@ -139,7 +139,7 @@ Contents:
REMOVE_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT)
if(n_shoes)
REMOVE_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT)
- n_shoes.slowdown++
+ n_shoes.slowdown += 0.5
if(n_gloves)
n_gloves.icon_state = "s-ninja"
n_gloves.item_state = "s-ninja"
diff --git a/code/modules/projectiles/ammunition/energy/stun.dm b/code/modules/projectiles/ammunition/energy/stun.dm
index f063672654..aa889c10bf 100644
--- a/code/modules/projectiles/ammunition/energy/stun.dm
+++ b/code/modules/projectiles/ammunition/energy/stun.dm
@@ -9,6 +9,10 @@
projectile_type = /obj/item/projectile/energy/electrode/security
e_cost = 100
+/obj/item/ammo_casing/energy/electrode/hos
+ projectile_type = /obj/item/projectile/energy/electrode/hos
+ e_cost = 100
+
/obj/item/ammo_casing/energy/electrode/spec
e_cost = 100
diff --git a/code/modules/projectiles/guns/energy/energy_gun.dm b/code/modules/projectiles/guns/energy/energy_gun.dm
index 45bc3a79dc..ae78423813 100644
--- a/code/modules/projectiles/guns/energy/energy_gun.dm
+++ b/code/modules/projectiles/guns/energy/energy_gun.dm
@@ -48,13 +48,23 @@
/obj/item/gun/energy/e_gun/hos
name = "\improper X-01 MultiPhase Energy Gun"
- desc = "This is an expensive, modern recreation of an antique laser gun. This gun has several unique firemodes, but lacks the ability to recharge over time in exchange for inbuilt advanced firearm EMP shielding."
+ desc = "This is an expensive, modern recreation of an antique laser gun. This gun has several unique firemodes, but lacks the ability to recharge over time in exchange for inbuilt advanced firearm EMP shielding. Right click in combat mode to fire a taser shot with a cooldown."
icon_state = "hoslaser"
force = 10
- ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser/hos, /obj/item/ammo_casing/energy/ion/hos)
+ ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser/hos, /obj/item/ammo_casing/energy/ion/hos, /obj/item/ammo_casing/energy/electrode/hos)
ammo_x_offset = 4
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
+/obj/item/gun/energy/e_gun/hos/altafterattack(atom/target, mob/user, proximity_flag, params)
+ . = TRUE
+ if(last_altfire + altfire_delay > world.time)
+ return
+ var/current_index = current_firemode_index
+ set_firemode_to_type(/obj/item/ammo_casing/energy/electrode)
+ process_afterattack(target, user, proximity_flag, params)
+ set_firemode_index(current_index)
+ last_altfire = world.time
+
/obj/item/gun/energy/e_gun/hos/emp_act(severity)
return
diff --git a/code/modules/projectiles/projectile/energy/stun.dm b/code/modules/projectiles/projectile/energy/stun.dm
index 83b753e0a3..6f272dab40 100644
--- a/code/modules/projectiles/projectile/energy/stun.dm
+++ b/code/modules/projectiles/projectile/energy/stun.dm
@@ -37,15 +37,17 @@
..()
/obj/item/projectile/energy/electrode/security
- tase_duration = 30
+ tase_duration = 40
knockdown = 0
- stamina = 10
+ stamina = 0
knockdown_stamoverride = 0
knockdown_stam_max = 0
strong_tase = FALSE
/obj/item/projectile/energy/electrode/security/hos
- knockdown = 100
- knockdown_stamoverride = 30
- knockdown_stam_max = null
- tase_duration = 10
+ tase_duration = 40
+ knockdown = 0
+ stamina = 0
+ knockdown_stamoverride = 0
+ knockdown_stam_max = 0
+ strong_tase = FALSE
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index eb3b80b693..20fe6b7bc8 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -18,7 +18,8 @@
var/spray_range = 3 //the range of tiles the sprayer will reach when in spray mode.
var/stream_range = 1 //the range of tiles the sprayer will reach when in stream mode.
var/stream_amount = 10 //the amount of reagents transfered when in stream mode.
- var/spray_delay = 3 //The amount of sleep() delay between each chempuff step.
+ /// Amount of time it takes for a spray to completely travel.
+ var/spray_delay = 8
/// Last world.time of spray
var/last_spray = 0
/// Spray cooldown
@@ -72,58 +73,20 @@
if((last_spray + spray_cooldown) > world.time)
return
var/range = clamp(get_dist(src, A), 1, current_range)
- var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src))
+ var/wait_step = CEILING(spray_delay * INVERSE(range), world.tick_lag)
+ var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src), stream_mode, wait_step, range, stream_mode? 1 : range)
+ log_reagent("SPRAY: [key_name(usr)] fired [src] ([REF(src)]) [COORD(T)] at [A] ([REF(A)]) [COORD(A)] (chempuff: [D.reagents.log_list()])")
D.create_reagents(amount_per_transfer_from_this, NONE, NO_REAGENTS_VALUE)
- var/puff_reagent_left = range //how many turf, mob or dense objet we can react with before we consider the chem puff consumed
if(stream_mode)
reagents.trans_to(D, amount_per_transfer_from_this)
- puff_reagent_left = 1
else
reagents.trans_to(D, amount_per_transfer_from_this, 1/range)
D.color = mix_color_from_reagents(D.reagents.reagent_list)
var/turf/T = get_turf(src)
if(!T)
return
- log_reagent("SPRAY: [key_name(usr)] fired [src] ([REF(src)]) [COORD(T)] at [A] ([REF(A)]) [COORD(A)] (chempuff: [D.reagents.log_list()])")
- var/wait_step = max(round(2+ spray_delay * INVERSE(range)), 2)
last_spray = world.time
- INVOKE_ASYNC(src, .proc/do_spray, A, wait_step, D, range, puff_reagent_left)
- return TRUE
-
-/obj/item/reagent_containers/spray/proc/do_spray(atom/A, wait_step, obj/effect/decal/chempuff/D, range, puff_reagent_left)
- var/range_left = range
- for(var/i=0, i 0 && (!stream_mode || !range_left))
- D.reagents.reaction(get_turf(D), VAPOR)
- puff_reagent_left -= 1
-
- if(puff_reagent_left <= 0) // we used all the puff so we delete it.
- qdel(D)
- return
- qdel(D)
+ D.run((A)
/obj/item/reagent_containers/spray/attack_self(mob/user)
stream_mode = !stream_mode
@@ -207,7 +170,7 @@
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
volume = 40
stream_range = 4
- spray_delay = 1
+ spray_delay = 2
amount_per_transfer_from_this = 5
list_reagents = list(/datum/reagent/consumable/condensedcapsaicin = 40)
From e483ce8dfc060bfe37e9543c8102a49c1071aa67 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 28 Feb 2021 00:05:32 -0700
Subject: [PATCH 02/43] changes
---
code/modules/reagents/reagent_containers/spray.dm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index 20fe6b7bc8..6f4b0b37e8 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -86,7 +86,7 @@
if(!T)
return
last_spray = world.time
- D.run((A)
+ D.run(A)
/obj/item/reagent_containers/spray/attack_self(mob/user)
stream_mode = !stream_mode
From 70c828f74d26789c02b1456e0a87eb0e76c8741d Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 28 Feb 2021 00:27:14 -0700
Subject: [PATCH 03/43] changes
---
code/__DEFINES/combat/block.dm | 2 ++
code/datums/martial/sleeping_carp.dm | 4 ++--
code/game/objects/items/dualsaber.dm | 2 --
code/game/objects/items/electrostaff.dm | 10 +++++-----
code/game/objects/items/melee/energy.dm | 6 +++---
code/game/objects/items/melee/misc.dm | 4 ++--
code/game/objects/items/weaponry.dm | 18 ++++++++++++------
.../objects/structures/beds_chairs/chair.dm | 2 +-
.../clock_weapons/ratvarian_spear.dm | 2 +-
.../mob/living/carbon/human/human_defines.dm | 2 +-
.../modules/mob/living/carbon/human/species.dm | 8 ++------
code/modules/mob/living/living_active_parry.dm | 2 +-
.../mob/living/living_blocking_parrying.dm | 2 +-
code/modules/smithing/finished_items.dm | 4 ++--
14 files changed, 35 insertions(+), 33 deletions(-)
diff --git a/code/__DEFINES/combat/block.dm b/code/__DEFINES/combat/block.dm
index bc85947d71..9be4aaa2bf 100644
--- a/code/__DEFINES/combat/block.dm
+++ b/code/__DEFINES/combat/block.dm
@@ -63,6 +63,8 @@
#define BLOCK_RETURN_MITIGATION_PERCENT "partial_mitigation"
/// Used internally by run_parry proc, use on an on_active_parry() proc to override parrying efficiency.
#define BLOCK_RETURN_OVERRIDE_PARRY_EFFICIENCY "override_parry_efficiency"
+/// Used internally by run_parry proc, use on an on_active_parry() proc to prevent counterattacks
+#define BLOCK_RETURN_FORCE_NO_PARRY_COUNTERATTACK "no_parry_counterattack"
/// Always set to 100 by run_block() if BLOCK_SUCCESS is in return value. Otherwise, defaults to mitigation percent if not set. Used by projectile/proc/on_hit().
#define BLOCK_RETURN_PROJECTILE_BLOCK_PERCENTAGE "projectile_block_percentage"
diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm
index 5881c76827..e926da78d0 100644
--- a/code/datums/martial/sleeping_carp.dm
+++ b/code/datums/martial/sleeping_carp.dm
@@ -144,8 +144,8 @@
parry_time_active_visual_override = 3
parry_time_spindown_visual_override = 12
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK //can attack while
- parry_time_perfect = 2.5 // first ds isn't perfect
- parry_time_perfect_leeway = 1.5
+ parry_time_perfect = 2.5
+ parry_time_perfect_leeway = 2.5
parry_imperfect_falloff_percent = 5
parry_efficiency_to_counterattack = 100
parry_efficiency_considered_successful = 65 // VERY generous
diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm
index 3d62a98ddf..86522b9587 100644
--- a/code/game/objects/items/dualsaber.dm
+++ b/code/game/objects/items/dualsaber.dm
@@ -69,7 +69,6 @@
parry_time_perfect = 2 // first ds isn't perfect
parry_time_perfect_leeway = 1
parry_imperfect_falloff_percent = 10
- parry_efficiency_to_counterattack = 100
parry_efficiency_considered_successful = 25 // VERY generous
parry_failed_stagger_duration = 3 SECONDS
parry_failed_clickcd_duration = CLICK_CD_MELEE
@@ -369,7 +368,6 @@
parry_time_perfect = 1
parry_time_perfect_leeway = 1
parry_imperfect_falloff_percent = 7.5
- parry_efficiency_to_counterattack = 100
parry_efficiency_considered_successful = 80
parry_efficiency_perfect = 120
parry_efficiency_perfect_override = list(
diff --git a/code/game/objects/items/electrostaff.dm b/code/game/objects/items/electrostaff.dm
index 31aaff12b5..71cebc38c6 100644
--- a/code/game/objects/items/electrostaff.dm
+++ b/code/game/objects/items/electrostaff.dm
@@ -45,15 +45,15 @@
// no attacking while blocking
block_lock_attacking = TRUE
- parry_time_windup = 1
- parry_time_active = 5
+ parry_time_windup = 0
+ parry_time_active = 7
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 = 0.5
- parry_efficiency_perfect = 100
- parry_imperfect_falloff_percent = 1
+ parry_efficiency_perfect = 85
+ parry_imperfect_falloff_percent = 10
parry_imperfect_falloff_percent_override = list(
TEXT_ATTACK_TYPE_PROJECTILE = 45 // really crappy vs projectiles
)
@@ -61,7 +61,7 @@
TEXT_ATTACK_TYPE_PROJECTILE = 1 // extremely harsh window for projectiles
)
// not extremely punishing to fail, but no spamming the parry.
- parry_cooldown = 2.5 SECONDS
+ parry_cooldown = 1.5 SECONDS
parry_failed_stagger_duration = 1.5 SECONDS
parry_failed_clickcd_duration = 1 SECONDS
diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm
index 55546a7f9c..f1201dca4f 100644
--- a/code/game/objects/items/melee/energy.dm
+++ b/code/game/objects/items/melee/energy.dm
@@ -121,7 +121,7 @@
parry_time_perfect = 2.5 // first ds isn't perfect
parry_time_perfect_leeway = 1.5
parry_imperfect_falloff_percent = 5
- parry_efficiency_to_counterattack = 100
+ parry_efficiency_to_counterattack = INFINITY
parry_efficiency_considered_successful = 65 // VERY generous
parry_efficiency_perfect = 100
parry_failed_stagger_duration = 4 SECONDS
@@ -149,8 +149,8 @@
/obj/item/melee/transforming/energy/sword/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
. = ..()
- if(parry_efficiency >= 80) // perfect parry
- block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER
+ if(parry_efficiency >= 100) // perfect parry
+ block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_DEFLECT
. |= BLOCK_SHOULD_REDIRECT
/obj/item/melee/transforming/energy/sword/cyborg
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index 15d10c4d11..d2dea3c502 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -81,7 +81,7 @@
parry_imperfect_falloff_percent = 30
parry_efficiency_perfect = 100
parry_failed_stagger_duration = 3 SECONDS
- parry_failed_clickcd_duration = 2 SECONDS
+ parry_failed_clickcd_duration = 1 SECONDS
/obj/item/melee/sabre/Initialize()
. = ..()
@@ -192,7 +192,7 @@
TEXT_ATTACK_TYPE_PROJECTILE = 50 // useless after 3rd decisecond
)
parry_imperfect_falloff_percent = 30
- parry_efficiency_to_counterattack = 100
+ parry_efficiency_to_counterattack = INFINITY
parry_efficiency_considered_successful = 1
parry_efficiency_perfect = 100
parry_data = list(
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index 554ea81974..a826900871 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -315,6 +315,12 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
bare_wound_bonus = 0
wound_bonus = 0
+/obj/item/melee/bokken/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
+ . = ..()
+ if(!istype(object, /obj/item/melee/bokken))
+ // no counterattack.
+ block_return[BLOCK_RETURN_FORCE_NO_PARRY_COUNTERATTACK] = TRUE
+
/datum/block_parry_data/bokken // fucked up parry data, emphasizing quicker, shorter parries
parry_stamina_cost = 10 // be wise about when you parry, though, else you won't be able to fight enough to make it count
parry_time_windup = 0
@@ -417,7 +423,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
desc = "A misnomer of sorts, this is effectively a blunt katana made from steelwood, a dense organic wood derived from steelcaps. Why steelwood? Druids can use it. Duh."
icon_state = "bokken_steel"
item_state = "bokken_steel"
- force = 12
+ force = 12
stamina_damage_increment = 3
/obj/item/melee/bokken/waki
@@ -427,7 +433,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
item_state = "wakibokken"
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_NORMAL
- force = 6
+ force = 6
stamina_damage_increment = 4
block_parry_data = /datum/block_parry_data/bokken/waki
default_parry_data = /datum/block_parry_data/bokken/waki
@@ -442,7 +448,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
parry_time_perfect_leeway = 1
parry_imperfect_falloff_percent = 7.5
parry_efficiency_to_counterattack = 120
- parry_efficiency_considered_successful = 65
+ parry_efficiency_considered_successful = 65
parry_efficiency_perfect = 120
parry_efficiency_perfect_override = list(
TEXT_ATTACK_TYPE_PROJECTILE = 30,
@@ -455,10 +461,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/datum/block_parry_data/bokken/waki/quick_parry //For the parry spammer in you
parry_stamina_cost = 2 // Slam that parry button
parry_time_active = 2.5
- parry_time_perfect = 1
+ parry_time_perfect = 1
parry_time_perfect_leeway = 1
parry_failed_stagger_duration = 1 SECONDS
- parry_failed_clickcd_duration = 1 SECONDS
+ parry_failed_clickcd_duration = 1 SECONDS
/datum/block_parry_data/bokken/waki/quick_parry/proj
parry_efficiency_perfect_override = list()
@@ -468,7 +474,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
desc = "A misnomer of sorts, this is effectively a blunt wakizashi made from steelwood, a dense organic wood derived from steelcaps. Why steelwood? Druids can use it. Duh."
icon_state = "wakibokken_steel"
item_state = "wakibokken_steel"
- force = 8
+ force = 8
stamina_damage_increment = 2
/obj/item/melee/bokken/debug
diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm
index 76ab086eb2..89f018f291 100644
--- a/code/game/objects/structures/beds_chairs/chair.dm
+++ b/code/game/objects/structures/beds_chairs/chair.dm
@@ -348,7 +348,7 @@
parry_time_perfect = 1.5
parry_time_perfect_leeway = 1
parry_imperfect_falloff_percent = 7.5
- parry_efficiency_to_counterattack = 100
+ parry_efficiency_to_counterattack = INFINITY
parry_efficiency_considered_successful = 50
parry_efficiency_perfect = 120
parry_efficiency_perfect_override = list(
diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
index aa69478217..d0f63ac887 100644
--- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
+++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
@@ -90,7 +90,7 @@
parry_time_perfect = 2
parry_efficiency_perfect = 110 //Very low leeway for counterattacks...
parry_efficiency_considered_successful = 0.8
- parry_efficiency_to_counterattack = 1
+ parry_efficiency_to_counterattack = 110
parry_cooldown = 15 //But also very low cooldown..
parry_failed_stagger_duration = 2 SECONDS //And relatively small penalties for failing.
parry_failed_clickcd_duration = 1 SECONDS
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 66d3154ee3..10abc87237 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -140,7 +140,7 @@
)
parry_efficiency_considered_successful = 0.01
- parry_efficiency_to_counterattack = 0.01
+ parry_efficiency_to_counterattack = INFINITY // no counterattacks
parry_max_attacks = INFINITY
parry_failed_cooldown_duration = 1.5 SECONDS
parry_failed_stagger_duration = 1 SECONDS
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 8bae43848d..7851631b33 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -1559,12 +1559,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
else
user.do_attack_animation(target, ATTACK_EFFECT_DISARM)
- if(HAS_TRAIT(user, TRAIT_PUGILIST))//CITADEL CHANGE - makes disarmspam cause staminaloss, pugilists can do it almost effortlessly
- if(!user.UseStaminaBuffer(1, warn = TRUE))
- return
- else
- if(!user.UseStaminaBuffer(1, warn = TRUE))
- return
+ if(!user.UseStaminaBuffer(1, warn = TRUE))
+ return
if(attacker_style && attacker_style.disarm_act(user,target))
return TRUE
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index 10f8aaf2f4..513fe43747 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -281,7 +281,7 @@
pacifist_counter_check = (!active_parry_item.force || active_parry_item.damtype == STAMINA)
else
pacifist_counter_check = FALSE //Both martial and unarmed counter attacks generally are harmful, so no need to have the same line twice.
- if(efficiency >= data.parry_efficiency_to_counterattack && pacifist_counter_check)
+ if(efficiency >= data.parry_efficiency_to_counterattack && pacifist_counter_check && !return_list[BLOCK_RETURN_FORCE_NO_PARRY_COUNTERATTACK])
effect_text = run_parry_countereffects(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency)
if(data.parry_flags & PARRY_DEFAULT_HANDLE_FEEDBACK)
handle_parry_feedback(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, effect_text)
diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm
index 9e974177e5..d1ccf7f0c4 100644
--- a/code/modules/mob/living/living_blocking_parrying.dm
+++ b/code/modules/mob/living/living_blocking_parrying.dm
@@ -139,7 +139,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Efficiency must be at least this to be considered successful
var/parry_efficiency_considered_successful = 0.1
/// Efficiency must be at least this to run automatic counterattack
- var/parry_efficiency_to_counterattack = 0.1
+ var/parry_efficiency_to_counterattack = INFINITY
/// Maximum attacks to parry successfully or unsuccessfully (but not efficiency < 0) during active period, hitting this immediately ends the sequence.
var/parry_max_attacks = INFINITY
/// Visual icon state override for parrying
diff --git a/code/modules/smithing/finished_items.dm b/code/modules/smithing/finished_items.dm
index 20eaee8a08..06953f462c 100644
--- a/code/modules/smithing/finished_items.dm
+++ b/code/modules/smithing/finished_items.dm
@@ -209,7 +209,7 @@
parry_time_perfect = 2
parry_time_perfect_leeway = 0.75
parry_imperfect_falloff_percent = 7.5
- parry_efficiency_to_counterattack = 100
+ parry_efficiency_to_counterattack = INFINITY
parry_efficiency_considered_successful = 80
parry_efficiency_perfect = 120
parry_failed_stagger_duration = 3 SECONDS
@@ -270,7 +270,7 @@
parry_time_windup = 0
parry_time_spindown = 0
parry_imperfect_falloff_percent = 0
- parry_efficiency_to_counterattack = 100
+ parry_efficiency_to_counterattack = INFINITY
parry_efficiency_considered_successful = 120
parry_efficiency_perfect = 120
parry_data = list(PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 4)
From 8e249eed4f73f96ade820a6c2094b0a9fddbebf3 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 28 Feb 2021 00:33:10 -0700
Subject: [PATCH 04/43] changes
---
code/game/objects/items/stunbaton.dm | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
index cc01e6aaee..11c8716bc2 100644
--- a/code/game/objects/items/stunbaton.dm
+++ b/code/game/objects/items/stunbaton.dm
@@ -19,6 +19,8 @@
var/stamforce = 35
var/turned_on = FALSE
var/knockdown = TRUE
+ /// block percent needed to prevent knockdown/disarm
+ var/block_percent_to_counter = 60
var/obj/item/stock_parts/cell/cell
var/hitcost = 750
var/throw_hit_chance = 35
@@ -180,6 +182,7 @@
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE
var/stunpwr = stamforce
+ var/countered = return_list[BLOCK_RETURN_MITIGATION_PERCENT] > block_percent_to_counter
stunpwr = block_calculate_resultant_damage(stunpwr, return_list)
var/obj/item/stock_parts/cell/our_cell = get_cell()
if(!our_cell)
@@ -200,10 +203,10 @@
return FALSE
if(!disarming)
- if(knockdown)
+ if(knockdown && !countered)
L.DefaultCombatKnockdown(50, override_stamdmg = 0) //knockdown
L.adjustStaminaLoss(stunpwr)
- else
+ else if(!countered)
L.drop_all_held_items() //no knockdown/stamina damage, instead disarm.
L.apply_effect(EFFECT_STUTTER, stamforce)
@@ -211,9 +214,13 @@
if(user)
L.lastattacker = user.real_name
L.lastattackerckey = user.ckey
- L.visible_message("[user] has [disarming? "disarmed" : "stunned"] [L] with [src]!", \
+ if(!countered)
+ L.visible_message("[user] has [disarming? "disarmed" : "stunned"] [L] with [src]!", \
"[user] has [disarming? "disarmed" : "stunned"] you with [src]!")
- log_combat(user, L, disarming? "disarmed" : "stunned")
+ else
+ L.visible_message("[user] tries to [disarming? "disarm" : "stun"] [L] with [src], but is deflected!", \
+ "[user] tries to [disarming? "disarm" : "stun"] you with [src], but is deflected!")
+ log_combat(user, L, disarming? "disarmed" : "stunned" + countered? " (countered)" : "")
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
@@ -306,7 +313,8 @@
w_class = WEIGHT_CLASS_BULKY
force = 3
throwforce = 5
- stamforce = 25
+ stamforce = 35
+ block_percent_to_counter = 45
hitcost = 1000
throw_hit_chance = 10
slot_flags = ITEM_SLOT_BACK
From e43838739de292f12c48d2d6e095955e2f218b9b Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 28 Feb 2021 00:37:39 -0700
Subject: [PATCH 05/43] changes
---
code/game/objects/items/melee/misc.dm | 8 ++++++--
code/game/objects/items/stunbaton.dm | 6 +++---
code/modules/mob/living/status_procs.dm | 6 ++++--
3 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index d2dea3c502..a6e85fadb8 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -260,6 +260,8 @@
var/stam_dmg = 30
var/cooldown_check = 0 // Used internally, you don't want to modify
var/cooldown = 13 // Default wait time until can stun again.
+ /// block mitigation needed to prevent knockdown/disarms
+ var/block_percent_to_counter = 50
var/stun_time_silicon = 60 // How long it stuns silicons for - 6 seconds.
var/affect_silicon = FALSE // Does it stun silicons.
var/on_sound // "On" sound, played when switching between able to stun or not.
@@ -354,7 +356,8 @@
if(cooldown_check < world.time)
if(!UseStaminaBufferStandard(user, STAM_COST_BATON_MOB_MULT, warn = TRUE))
return DISCARD_LAST_ACTION
- if(target.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, null) & BLOCK_SUCCESS)
+ var/list/block_return = list()
+ if(target.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, block_return) & BLOCK_SUCCESS)
playsound(target, 'sound/weapons/genhit.ogg', 50, 1)
return
if(ishuman(target))
@@ -365,7 +368,8 @@
if(stun_animation)
user.do_attack_animation(target)
playsound(get_turf(src), on_stun_sound, 75, 1, -1)
- target.DefaultCombatKnockdown(softstun_ds, TRUE, FALSE, hardstun_ds, stam_dmg)
+ var/countered = block_return[BLOCK_RETURN_MITIGATION_PERCENT] > block_percent_to_counter
+ target.DefaultCombatKnockdown(softstun_ds, TRUE, FALSE, countered? 0 : hardstun_ds, stam_dmg, !countered)
additional_effects_carbon(target, user)
log_combat(user, target, "stunned", src)
add_fingerprint(user)
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
index 11c8716bc2..862b2c8c3e 100644
--- a/code/game/objects/items/stunbaton.dm
+++ b/code/game/objects/items/stunbaton.dm
@@ -20,7 +20,7 @@
var/turned_on = FALSE
var/knockdown = TRUE
/// block percent needed to prevent knockdown/disarm
- var/block_percent_to_counter = 60
+ var/block_percent_to_counter = 50
var/obj/item/stock_parts/cell/cell
var/hitcost = 750
var/throw_hit_chance = 35
@@ -204,7 +204,7 @@
if(!disarming)
if(knockdown && !countered)
- L.DefaultCombatKnockdown(50, override_stamdmg = 0) //knockdown
+ L.DefaultCombatKnockdown(50, override_stamdmg = 0, knocktofloor = !countered) //knockdown
L.adjustStaminaLoss(stunpwr)
else if(!countered)
L.drop_all_held_items() //no knockdown/stamina damage, instead disarm.
@@ -314,7 +314,7 @@
force = 3
throwforce = 5
stamforce = 35
- block_percent_to_counter = 45
+ block_percent_to_counter = 30
hitcost = 1000
throw_hit_chance = 10
slot_flags = ITEM_SLOT_BACK
diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm
index 87fd0cf609..389f5ee5b5 100644
--- a/code/modules/mob/living/status_procs.dm
+++ b/code/modules/mob/living/status_procs.dm
@@ -4,7 +4,8 @@
// ignore_castun = same logic as Paralyze() in general
// override_duration = If this is set, does Paralyze() for this duration.
// override_stam = If this is set, does this amount of stamina damage.
-/mob/living/proc/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg)
+// knocktofloor - whether to knock them to the ground
+/mob/living/proc/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg, knocktofloor = TRUE)
if(!iscarbon(src))
return Paralyze(amount, updating, ignore_canknockdown)
if(!ignore_canknockdown && !(status_flags & CANKNOCKDOWN))
@@ -13,7 +14,8 @@
buckled.unbuckle_mob(src)
var/drop_items = amount > 80 //80 is cutoff for old item dropping behavior
var/stamdmg = isnull(override_stamdmg)? (amount * 0.25) : override_stamdmg
- KnockToFloor(drop_items, TRUE, updating)
+ if(knocktofloor)
+ KnockToFloor(drop_items, TRUE, updating)
adjustStaminaLoss(stamdmg)
if(!isnull(override_hardstun))
Paralyze(override_hardstun)
From 8fc1dc9c2994b48ec77aa8ac21c4449f8b0e8fc9 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 28 Feb 2021 00:40:04 -0700
Subject: [PATCH 06/43] changes
---
code/game/objects/effects/decals/misc.dm | 1 +
code/modules/mob/living/say.dm | 2 +-
code/modules/movespeed/modifiers/status_effects.dm | 2 +-
code/modules/projectiles/guns/energy/energy_gun.dm | 2 ++
code/modules/reagents/reagent_containers/spray.dm | 1 +
5 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm
index 514fcdd68a..53ad432121 100644
--- a/code/game/objects/effects/decals/misc.dm
+++ b/code/game/objects/effects/decals/misc.dm
@@ -59,6 +59,7 @@
hit_thing(AM)
/obj/effect/decal/chempuff/proc/run(atom/target)
+ set waitfor = FALSE
for(var/i in 1 to range)
range_left--
if(!isturf(loc))
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index d72b8c904a..148c66043f 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -308,7 +308,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_recipients, 30)
-/atom/movable/proc/process_yelling(list/already_heard, rendered, atom/movable/speaker, datum/language/message_language, list/spans, message_mode, obj/source)
+/atom/movable/proc/process_yelling(list/already_heard, rendered, atom/movable/speaker, datum/language/message_language, message, list/spans, message_mode, obj/source)
var/list/overhearing = list()
#warn todo: yelling
overhearing -= already_heard
diff --git a/code/modules/movespeed/modifiers/status_effects.dm b/code/modules/movespeed/modifiers/status_effects.dm
index d174524898..ed8eaf1303 100644
--- a/code/modules/movespeed/modifiers/status_effects.dm
+++ b/code/modules/movespeed/modifiers/status_effects.dm
@@ -43,7 +43,7 @@
multiplicative_slowdown = -2
blacklisted_movetypes= FLYING|FLOATING
-/datum/movespeed_modifier/status_effect/staggered
+/datum/movespeed_modifier/status_effect/stagger
variable = TRUE
/datum/movespeed_modifier/status_effect/off_balance
diff --git a/code/modules/projectiles/guns/energy/energy_gun.dm b/code/modules/projectiles/guns/energy/energy_gun.dm
index ae78423813..294040b040 100644
--- a/code/modules/projectiles/guns/energy/energy_gun.dm
+++ b/code/modules/projectiles/guns/energy/energy_gun.dm
@@ -54,6 +54,8 @@
ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser/hos, /obj/item/ammo_casing/energy/ion/hos, /obj/item/ammo_casing/energy/electrode/hos)
ammo_x_offset = 4
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
+ var/last_altfire = 0
+ var/altfire_delay = 0
/obj/item/gun/energy/e_gun/hos/altafterattack(atom/target, mob/user, proximity_flag, params)
. = TRUE
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index 6f4b0b37e8..3f62829b32 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -75,6 +75,7 @@
var/range = clamp(get_dist(src, A), 1, current_range)
var/wait_step = CEILING(spray_delay * INVERSE(range), world.tick_lag)
var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src), stream_mode, wait_step, range, stream_mode? 1 : range)
+ var/turf/T = get_turf(src)
log_reagent("SPRAY: [key_name(usr)] fired [src] ([REF(src)]) [COORD(T)] at [A] ([REF(A)]) [COORD(A)] (chempuff: [D.reagents.log_list()])")
D.create_reagents(amount_per_transfer_from_this, NONE, NO_REAGENTS_VALUE)
if(stream_mode)
From 519c6942528dad73d1f5ec1d5fc59e6b7260c5dd Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 28 Feb 2021 00:44:56 -0700
Subject: [PATCH 07/43] removes combat mode effects
---
.../configuration/entries/stamina_combat.dm | 6 +-----
code/datums/components/combat_mode.dm | 5 -----
code/datums/martial/_martial.dm | 4 ----
code/game/objects/items/shields.dm | 2 --
code/modules/mob/living/carbon/carbon.dm | 4 ----
code/modules/mob/living/carbon/human/species.dm | 11 -----------
code/modules/mob/living/carbon/life.dm | 3 +--
code/modules/mob/living/living_active_block.dm | 7 -------
code/modules/mob/living/living_active_parry.dm | 5 -----
code/modules/mob/living/stamina_buffer.dm | 3 +--
10 files changed, 3 insertions(+), 47 deletions(-)
diff --git a/code/controllers/configuration/entries/stamina_combat.dm b/code/controllers/configuration/entries/stamina_combat.dm
index 65580899f1..5c2c9d7ec5 100644
--- a/code/controllers/configuration/entries/stamina_combat.dm
+++ b/code/controllers/configuration/entries/stamina_combat.dm
@@ -12,11 +12,7 @@
/// Base regeneration per second
/datum/config_entry/number/stamina_combat/base_regeneration
- config_entry_value = 0.5
-
-/// Combat mode regeneration per second
-/datum/config_entry/number/stamina_combat/combat_regeneration
- config_entry_value = 5
+ config_entry_value = 3.5
/// After out_of_combat_timer elapses, additionally regenerate this percent of total stamina per second. Unaffected by combat mode.
/datum/config_entry/number/stamina_combat/percent_regeneration_out_of_combat
diff --git a/code/datums/components/combat_mode.dm b/code/datums/components/combat_mode.dm
index 29d90fd509..576d012093 100644
--- a/code/datums/components/combat_mode.dm
+++ b/code/datums/components/combat_mode.dm
@@ -128,11 +128,6 @@
if((mode_flags & COMBAT_MODE_ACTIVE) && L.client)
L.setDir(lastmousedir, ismousemovement = TRUE)
-/// Added movement delay if moving backward.
-/datum/component/combat_mode/proc/on_client_move(mob/source, client/client, direction, n, oldloc, added_delay)
- if(oldloc != n && direction == REVERSE_DIR(source.dir))
- client.move_delay += added_delay*0.5
-
///Changes the user direction to (try) match the pointer.
/datum/component/combat_mode/proc/onMouseMove(mob/source, object, location, control, params)
if(source.client.show_popup_menus)
diff --git a/code/datums/martial/_martial.dm b/code/datums/martial/_martial.dm
index bc48e82395..19cfc7691d 100644
--- a/code/datums/martial/_martial.dm
+++ b/code/datums/martial/_martial.dm
@@ -43,12 +43,8 @@
/datum/martial_art/proc/damage_roll(mob/living/carbon/human/A, mob/living/carbon/human/D)
//Here we roll for our damage to be added into the damage var in the various attack procs. This is changed depending on whether we are in combat mode, lying down, or if our target is in combat mode.
var/damage = rand(A.dna.species.punchdamagelow, A.dna.species.punchdamagehigh)
- if(SEND_SIGNAL(D, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
- damage *= 1.2
if(!CHECK_MOBILITY(A, MOBILITY_STAND))
damage *= 0.7
- if(SEND_SIGNAL(A, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
- damage *= 0.8
return damage
/datum/martial_art/proc/teach(mob/living/carbon/human/H, make_temporary = FALSE)
diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm
index 5c3e4fd612..9841a29ae0 100644
--- a/code/game/objects/items/shields.dm
+++ b/code/game/objects/items/shields.dm
@@ -120,8 +120,6 @@
return TRUE
/obj/item/shield/proc/user_shieldbash(mob/living/user, atom/target, harmful)
- if(!SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) //Combat mode has to be enabled for shield bashing
- return FALSE
if(!(shield_flags & SHIELD_CAN_BASH))
to_chat(user, "[src] can't be used to shield bash!")
return FALSE
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index c7a2d611d6..4462780996 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -475,10 +475,6 @@
if(HAS_TRAIT(src, TRAIT_CLUMSY))
modifier -= 40 //Clumsy people are more likely to hit themselves -Honk!
- //CIT CHANGES START HERE
- else if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
- modifier -= 50
-
if(modifier < 100)
dropItemToGround(I)
//END OF CIT CHANGES
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 7851631b33..07f35f9ce0 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -1429,12 +1429,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/punchedbrute = target.getBruteLoss()
//CITADEL CHANGES - makes resting and disabled combat mode reduce punch damage, makes being out of combat mode result in you taking more damage
- if(!SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
- damage *= 1.2
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
damage *= 0.65
- if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
- damage *= 0.8
//END OF CITADEL CHANGES
var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.zone_selected))
@@ -1578,12 +1574,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
log_combat(user, target, "disarmed out of grab from")
return
var/randn = rand(1, 100)
- if(SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) // CITADEL CHANGE
- randn += -10 //CITADEL CHANGE - being out of combat mode makes it easier for you to get disarmed
if(!CHECK_MOBILITY(user, MOBILITY_STAND)) //CITADEL CHANGE
randn += 100 //CITADEL CHANGE - No kosher disarming if you're resting
- if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) //CITADEL CHANGE
- randn += 25 //CITADEL CHANGE - Makes it harder to disarm outside of combat mode
if(user.pulling == target)
randn -= 20 //If you have the time to get someone in a grab, you should have a greater chance at snatching the thing in their hand. Will be made completely obsolete by the grab rework but i've got a poor track record for releasing big projects on time so w/e i guess
if(HAS_TRAIT(user, TRAIT_PUGILIST))
@@ -1788,9 +1780,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(IS_STAMCRIT(user))
to_chat(user, "You're too exhausted for that.")
return
- if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
- to_chat(user, "You need combat mode to be active to that!")
- return
if(user.IsKnockdown() || user.IsParalyzed() || user.IsStun())
to_chat(user, "You can't seem to force yourself up right now!")
return
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 9885efd7c7..07204bdebe 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -510,9 +510,8 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
//this updates all special effects: stun, sleeping, knockdown, druggy, stuttering, etc..
/mob/living/carbon/handle_status_effects()
..()
- var/combat_mode = SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)
if(getStaminaLoss() && !HAS_TRAIT(src, TRAIT_NO_STAMINA_REGENERATION))
- adjustStaminaLoss((!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? STAM_RECOVERY_STAM_CRIT : STAM_RECOVERY_RESTING) : STAM_RECOVERY_NORMAL) * (combat_mode? 0.25 : 1))
+ adjustStaminaLoss((!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? STAM_RECOVERY_STAM_CRIT : STAM_RECOVERY_RESTING) : STAM_RECOVERY_NORMAL))
if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT) && incomingstammult != 1)
incomingstammult = max(0.01, incomingstammult)
diff --git a/code/modules/mob/living/living_active_block.dm b/code/modules/mob/living/living_active_block.dm
index db472df388..ad42a3e477 100644
--- a/code/modules/mob/living/living_active_block.dm
+++ b/code/modules/mob/living/living_active_block.dm
@@ -48,8 +48,6 @@
animate(src, pixel_x = get_standard_pixel_x_offset(), pixel_y = get_standard_pixel_y_offset(), time = 2.5, FALSE, SINE_EASING | EASE_IN)
/mob/living/proc/continue_starting_active_block()
- if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
- return DO_AFTER_STOP
return (combat_flags & COMBAT_FLAG_ACTIVE_BLOCK_STARTING)? DO_AFTER_CONTINUE : DO_AFTER_STOP
/mob/living/get_standard_pixel_x_offset()
@@ -100,11 +98,6 @@
if(!I.can_active_block())
to_chat(src, "[I] is either not capable of being used to actively block, or is not currently in a state that can! (Try wielding it if it's twohanded, for example.)")
return
- // QOL: Attempt to toggle on combat mode if it isn't already
- SEND_SIGNAL(src, COMSIG_ENABLE_COMBAT_MODE)
- if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
- to_chat(src, "You must be in combat mode to actively block!")
- return FALSE
var/datum/block_parry_data/data = I.get_block_parry_data()
var/delay = data.block_start_delay
combat_flags |= COMBAT_FLAG_ACTIVE_BLOCK_STARTING
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index 513fe43747..571813f30e 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -74,11 +74,6 @@
if(!method)
to_chat(src, "You have nothing to parry with!")
return FALSE
- //QOL: Try to enable combat mode if it isn't already
- SEND_SIGNAL(src, COMSIG_ENABLE_COMBAT_MODE)
- if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
- to_chat(src, "You must be in combat mode to parry!")
- return FALSE
data = return_block_parry_datum(data)
var/full_parry_duration = data.parry_time_windup + data.parry_time_active + data.parry_time_spindown
// no system in place to "fallback" if out of the 3 the top priority one can't parry due to constraints but something else can.
diff --git a/code/modules/mob/living/stamina_buffer.dm b/code/modules/mob/living/stamina_buffer.dm
index a410df582b..91811e048a 100644
--- a/code/modules/mob/living/stamina_buffer.dm
+++ b/code/modules/mob/living/stamina_buffer.dm
@@ -35,11 +35,10 @@
return
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/out_of_combat_timer, out_of_combat_timer)
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/base_regeneration, base_regeneration)
- CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/combat_regeneration, combat_regeneration)
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/percent_regeneration_out_of_combat, percent_regeneration_out_of_combat)
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/post_action_penalty_delay, post_action_penalty_delay)
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/post_action_penalty_factor, post_action_penalty_factor)
- var/base_regen = (SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))? base_regeneration : combat_regeneration
+ var/base_regen = base_regeneration
var/time_since_last_action = world.time - stamina_buffer_last_use
var/action_penalty = ((time_since_last_action) < (post_action_penalty_delay * 10))? post_action_penalty_factor : 1
var/out_of_combat_bonus = (time_since_last_action < (out_of_combat_timer * 10))? 0 : ((buffer_max * percent_regeneration_out_of_combat * 0.01))
From 5d37871cd211e8ce4a5dbbc29229d72ca4ff1380 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 28 Feb 2021 00:47:24 -0700
Subject: [PATCH 08/43] changes
---
code/modules/mob/living/living_active_block.dm | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/code/modules/mob/living/living_active_block.dm b/code/modules/mob/living/living_active_block.dm
index ad42a3e477..5c184313ee 100644
--- a/code/modules/mob/living/living_active_block.dm
+++ b/code/modules/mob/living/living_active_block.dm
@@ -54,17 +54,17 @@
. = ..()
if(combat_flags & (COMBAT_FLAG_ACTIVE_BLOCK_STARTING | COMBAT_FLAG_ACTIVE_BLOCKING))
if(dir & EAST)
- . += 8
+ . += 4
if(dir & WEST)
- . -= 8
+ . -= 4
/mob/living/get_standard_pixel_y_offset()
. = ..()
if(combat_flags & (COMBAT_FLAG_ACTIVE_BLOCK_STARTING | COMBAT_FLAG_ACTIVE_BLOCKING))
if(dir & NORTH)
- . += 8
+ . += 4
if(dir & SOUTH)
- . -= 8
+ . -= 4
/**
* Proc called by keybindings to toggle active blocking.
From 0f35f01a9bdbfae8cf34bc28a4de837d586773c4 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 28 Feb 2021 00:58:13 -0700
Subject: [PATCH 09/43] changes
---
code/modules/surgery/bodyparts/_bodyparts.dm | 15 ++++++++++++---
code/modules/surgery/bodyparts/parts.dm | 20 ++++++++++++--------
2 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 962bc8c1ce..d6379e1166 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -32,6 +32,8 @@
var/max_stamina_damage = 0
var/incoming_stam_mult = 1 //Multiplier for incoming staminaloss, decreases when taking staminaloss when the limb is disabled, resets back to 1 when limb is no longer disabled.
var/max_damage = 0
+ /// Threshold at which we are disabled. Defaults to max_damage if unset.
+ var/disable_threshold
var/stam_heal_tick = 0 //per Life(). Defaults to 0 due to citadel changes
var/brute_reduction = 0 //Subtracted to brute damage taken
@@ -494,6 +496,12 @@
return
set_disabled(is_disabled(silent), silent)
+/**
+ * Gets the damage at which point we're disabled.
+ */
+/obj/item/bodypart/proc/get_disable_threshold()
+ return isnull(disable_threshold)? max_damage : disable_threshold
+
/obj/item/bodypart/proc/is_disabled(silent = FALSE)
if(!owner)
return
@@ -503,15 +511,16 @@
var/datum/wound/W = i
if(W.disabling)
return BODYPART_DISABLED_WOUND
+ var/disable_threshold = get_disable_threshold()
if(can_dismember() && !HAS_TRAIT(owner, TRAIT_NODISMEMBER))
. = disabled //inertia, to avoid limbs healing 0.1 damage and being re-enabled
- if(get_damage(TRUE) >= max_damage * (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) ? 0.6 : 1)) //Easy limb disable disables the limb at 40% health instead of 0%
+ if(get_damage(TRUE) >= disable_threshold * (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) ? 0.6 : 1)) //Easy limb disable disables the limb at 40% health instead of 0%
if(!last_maxed && !silent)
owner.emote("scream")
last_maxed = TRUE
- if(!is_organic_limb(FALSE) || stamina_dam >= max_damage)
+ if(!is_organic_limb(FALSE) || stamina_dam >= disable_threshold)
return BODYPART_DISABLED_DAMAGE
- else if(disabled && (get_damage(TRUE) <= (max_damage * 0.8))) // reenabled at 80% now instead of 50% as of wounds update
+ else if(disabled && (get_damage(TRUE) <= (disable_threshold * 0.8))) // reenabled at 80% now instead of 50% as of wounds update
last_maxed = FALSE
return BODYPART_NOT_DISABLED
else
diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm
index 86288564ae..8c7553d8e3 100644
--- a/code/modules/surgery/bodyparts/parts.dm
+++ b/code/modules/surgery/bodyparts/parts.dm
@@ -59,12 +59,13 @@
one though."
icon_state = "default_human_l_arm"
attack_verb = list("slapped", "punched")
- max_damage = 50
+ max_damage = 150
+ disable_threshold = 75
max_stamina_damage = 50
body_zone = BODY_ZONE_L_ARM
body_part = ARM_LEFT
aux_icons = list(BODY_ZONE_PRECISE_L_HAND = HANDS_PART_LAYER, "l_hand_behind" = BODY_BEHIND_LAYER)
- body_damage_coeff = 0.75
+ body_damage_coeff = 0.25
held_index = 1
px_x = -6
px_y = 0
@@ -120,11 +121,12 @@
among humans missing their right arm."
icon_state = "default_human_r_arm"
attack_verb = list("slapped", "punched")
- max_damage = 50
+ max_damage = 150
+ disable_threshold = 75
body_zone = BODY_ZONE_R_ARM
body_part = ARM_RIGHT
aux_icons = list(BODY_ZONE_PRECISE_R_HAND = HANDS_PART_LAYER, "r_hand_behind" = BODY_BEHIND_LAYER)
- body_damage_coeff = 0.75
+ body_damage_coeff = 0.25
held_index = 2
px_x = 6
px_y = 0
@@ -182,10 +184,11 @@
luck. In this instance, it probably would not have helped."
icon_state = "default_human_l_leg"
attack_verb = list("kicked", "stomped")
- max_damage = 50
+ max_damage = 150
+ disable_threshold = 75
body_zone = BODY_ZONE_L_LEG
body_part = LEG_LEFT
- body_damage_coeff = 0.75
+ body_damage_coeff = 0.25
px_x = -2
px_y = 12
stam_heal_tick = STAM_RECOVERY_LIMB
@@ -240,10 +243,11 @@
// alternative spellings of 'pokey' are availible
icon_state = "default_human_r_leg"
attack_verb = list("kicked", "stomped")
- max_damage = 50
+ max_damage = 150
+ disable_threshold = 75
body_zone = BODY_ZONE_R_LEG
body_part = LEG_RIGHT
- body_damage_coeff = 0.75
+ body_damage_coeff = 0.25
px_x = 2
px_y = 12
max_stamina_damage = 50
From e7981c0a44b51a4b2fb271b1a5e4cf7bcfc50530 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 28 Feb 2021 01:02:18 -0700
Subject: [PATCH 10/43] changes
---
code/datums/wounds/pierce.dm | 10 +++++-----
code/datums/wounds/slash.dm | 10 +++++-----
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm
index 56c60b31d7..b26728c377 100644
--- a/code/datums/wounds/pierce.dm
+++ b/code/datums/wounds/pierce.dm
@@ -128,7 +128,7 @@
initial_flow = 1.5
gauzed_clot_rate = 0.8
internal_bleeding_chance = 30
- internal_bleeding_coefficient = 1.25
+ internal_bleeding_coefficient = 1
threshold_minimum = 40
threshold_penalty = 15
status_effect_type = /datum/status_effect/wound/pierce/moderate
@@ -142,10 +142,10 @@
occur_text = "looses a violent spray of blood, revealing a pierced wound"
sound_effect = 'sound/effects/wounds/pierce2.ogg'
severity = WOUND_SEVERITY_SEVERE
- initial_flow = 2.25
+ initial_flow = 2
gauzed_clot_rate = 0.6
internal_bleeding_chance = 60
- internal_bleeding_coefficient = 1.5
+ internal_bleeding_coefficient = 1.25
threshold_minimum = 60
threshold_penalty = 25
status_effect_type = /datum/status_effect/wound/pierce/severe
@@ -159,10 +159,10 @@
occur_text = "blasts apart, sending chunks of viscera flying in all directions"
sound_effect = 'sound/effects/wounds/pierce3.ogg'
severity = WOUND_SEVERITY_CRITICAL
- initial_flow = 3
+ initial_flow = 2.7
gauzed_clot_rate = 0.4
internal_bleeding_chance = 80
- internal_bleeding_coefficient = 1.75
+ internal_bleeding_coefficient = 1.5
threshold_minimum = 110
threshold_penalty = 40
status_effect_type = /datum/status_effect/wound/pierce/critical
diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm
index 9044835272..6a631ab8f4 100644
--- a/code/datums/wounds/slash.dm
+++ b/code/datums/wounds/slash.dm
@@ -253,7 +253,7 @@
occur_text = "is cut open, slowly leaking blood"
sound_effect = 'sound/effects/wounds/blood1.ogg'
severity = WOUND_SEVERITY_MODERATE
- initial_flow = 1.5
+ initial_flow = 1.25
minimum_flow = 0.375
max_per_type = 3
clot_rate = 0.12
@@ -270,8 +270,8 @@
occur_text = "is ripped open, veins spurting blood"
sound_effect = 'sound/effects/wounds/blood2.ogg'
severity = WOUND_SEVERITY_SEVERE
- initial_flow = 2.4375
- minimum_flow = 2.0625
+ initial_flow = 2
+ minimum_flow = 1.75
clot_rate = 0.07
max_per_type = 4
threshold_minimum = 60
@@ -288,8 +288,8 @@
occur_text = "is torn open, spraying blood wildly"
sound_effect = 'sound/effects/wounds/blood3.ogg'
severity = WOUND_SEVERITY_CRITICAL
- initial_flow = 3.1875
- minimum_flow = 3
+ initial_flow = 2.75
+ minimum_flow = 2.5
clot_rate = -0.05 // critical cuts actively get worse instead of better
max_per_type = 5
threshold_minimum = 90
From 0f161784252cd6ee53ffc280002138f81427dbf7 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 28 Feb 2021 02:43:32 -0700
Subject: [PATCH 11/43] changes
---
code/__HELPERS/do_after.dm | 2 +-
code/game/objects/effects/decals/misc.dm | 2 +-
code/modules/mob/living/carbon/alien/status_procs.dm | 2 +-
code/modules/mob/living/carbon/human/status_procs.dm | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/code/__HELPERS/do_after.dm b/code/__HELPERS/do_after.dm
index 550eea65c0..c0c07e3620 100644
--- a/code/__HELPERS/do_after.dm
+++ b/code/__HELPERS/do_after.dm
@@ -51,6 +51,7 @@
var/dy = initial_dy
// DO OUR STARTING CHECKS
var/cb_return
+ var/list/passed_in = list(1)
INVOKE_CALLBACK
if(cb_return == DO_AFTER_STOP)
return FALSE
@@ -71,7 +72,6 @@
var/ctu
var/ctt
var/tick_time = world.time
- var/list/passed_in = list(1)
while(timeleft > 0)
stoplag(1)
var/timepassed = world.time - tick_time
diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm
index 53ad432121..7ed90253c8 100644
--- a/code/game/objects/effects/decals/misc.dm
+++ b/code/game/objects/effects/decals/misc.dm
@@ -32,7 +32,7 @@
. = ..()
stream = stream_mode
src.speed = speed
- src.range = scc.range_left = range
+ src.range = src.range_left = range
src.hits_left = hits_left
/obj/effect/decal/chempuff/proc/hit_thing(atom/A)
diff --git a/code/modules/mob/living/carbon/alien/status_procs.dm b/code/modules/mob/living/carbon/alien/status_procs.dm
index 71d61cab25..e20b20ef3d 100644
--- a/code/modules/mob/living/carbon/alien/status_procs.dm
+++ b/code/modules/mob/living/carbon/alien/status_procs.dm
@@ -2,7 +2,7 @@
//The effects include: stun, knockdown, unconscious, sleeping, resting, jitteriness, dizziness, ear damage,
// eye damage, eye_blind, eye_blurry, druggy, TRAIT_BLIND trait, and TRAIT_NEARSIGHT trait.
-/mob/living/carbon/alien/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg)
+/mob/living/carbon/alien/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg, knocktofloor)
return //no
/////////////////////////////////// STUN ////////////////////////////////////
diff --git a/code/modules/mob/living/carbon/human/status_procs.dm b/code/modules/mob/living/carbon/human/status_procs.dm
index 7892380d8b..ec961da4dd 100644
--- a/code/modules/mob/living/carbon/human/status_procs.dm
+++ b/code/modules/mob/living/carbon/human/status_procs.dm
@@ -3,7 +3,7 @@
amount = dna.species.spec_stun(src,amount)
return ..()
-/mob/living/carbon/human/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg)
+/mob/living/carbon/human/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg, knocktofloor)
amount = dna.species.spec_stun(src,amount)
return ..()
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 12/43] 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.
*/
From cf7d428ac6b8f1324dd0ad3962987cbd38d2488e Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sat, 6 Mar 2021 18:11:40 -0700
Subject: [PATCH 13/43] changes
---
code/modules/mob/living/living_active_parry.dm | 2 +-
code/modules/mob/living/living_block.dm | 2 +-
code/modules/mob/living/living_blocking_parrying.dm | 4 ++++
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index a000bbab23..c15b56afe8 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -234,7 +234,7 @@
var/stage = get_parry_stage()
if(stage != PARRY_ACTIVE)
// If they're not currently parrying, attempt auto parry
- if((stage == NOT_PARRYING) && allow_auto)
+ if((stage == NOT_PARRYING) && allow_auto && !SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
return attempt_auto_parry()
return BLOCK_NONE
var/datum/block_parry_data/data = get_parry_data()
diff --git a/code/modules/mob/living/living_block.dm b/code/modules/mob/living/living_block.dm
index 10427c20ec..99e74916da 100644
--- a/code/modules/mob/living/living_block.dm
+++ b/code/modules/mob/living/living_block.dm
@@ -37,7 +37,7 @@
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())
+ else if(I.can_passive_block() && !SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
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)
diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm
index 0a0ef30f33..1fd2ad2615 100644
--- a/code/modules/mob/living/living_blocking_parrying.dm
+++ b/code/modules/mob/living/living_blocking_parrying.dm
@@ -99,6 +99,10 @@ GLOBAL_LIST_EMPTY(block_parry_data)
var/block_automatic_enabled = TRUE
/// Directions that you can autoblock in
var/block_automatic_directions = BLOCK_DIR_NORTH | BLOCK_DIR_NORTHEAST | BLOCK_DIR_NORTHWEST
+ /// Effectiveness multiplier for automated block
+ var/block_automatic_mitigation_multiplier = 0.33
+ /// Stamina cost multiplier for automated block
+ var/block_automatic_stamina_multiplier = 1
/////////// PARRYING ////////////
/// Prioriry for [mob/do_run_block()] while we're being used to parry.
From 5d1cda26dc60cc1621dd7509e3841f55cb1a7e41 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sat, 6 Mar 2021 18:15:37 -0700
Subject: [PATCH 14/43] changes
---
code/modules/mob/living/living_blocking_parrying.dm | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm
index 1fd2ad2615..1ed490b0d8 100644
--- a/code/modules/mob/living/living_blocking_parrying.dm
+++ b/code/modules/mob/living/living_blocking_parrying.dm
@@ -97,6 +97,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
// Other than for overrides, this mostly just reads from the above vars
/// Can this item automatically block?
var/block_automatic_enabled = TRUE
+#warn have autoblock items warn user on pickup
/// Directions that you can autoblock in
var/block_automatic_directions = BLOCK_DIR_NORTH | BLOCK_DIR_NORTHEAST | BLOCK_DIR_NORTHWEST
/// Effectiveness multiplier for automated block
@@ -180,8 +181,10 @@ GLOBAL_LIST_EMPTY(block_parry_data)
// Auto parry
// Anything not specified like cooldowns/clickdelay respecting is pulled from above.
- /// Can this data automatically parry
- var/parry_automatic_enabled = TRUE
+ /// Can this data automatically parry? This is off by default because this is something that requires thought to balance.
+ var/parry_automatic_enabled = FALSE
+#warn implement autoparry in items
+#warn have autoparry items warn user on pickup
/// 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?
From 15dd80a0851f07ebc50240b9bfcd55cc01727cfc Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sat, 20 Mar 2021 13:39:59 -0700
Subject: [PATCH 15/43] less awful
---
.../objects/items/robot/robot_upgrades.dm | 2 +-
.../projectiles/ammunition/energy/laser.dm | 3 ++
.../boxes_magazines/internal/misc.dm | 6 ---
.../guns/ballistic/laser_gatling.dm | 38 ++++++++++---------
code/modules/surgery/bodyparts/_bodyparts.dm | 2 +-
5 files changed, 25 insertions(+), 26 deletions(-)
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index 291fc30aa2..ed92623a37 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -681,7 +681,7 @@ as performing this in action() will cause the upgrade to end up in the borg inst
action_icon_state = "Chevron_State_0"
var/currentState = 0
- var/maxReduction = 1
+ var/maxReduction = 0.5
/obj/effect/proc_holder/silicon/cyborg/vtecControl/Trigger(mob/living/silicon/robot/user)
diff --git a/code/modules/projectiles/ammunition/energy/laser.dm b/code/modules/projectiles/ammunition/energy/laser.dm
index f6eca57e29..5b727d76de 100644
--- a/code/modules/projectiles/ammunition/energy/laser.dm
+++ b/code/modules/projectiles/ammunition/energy/laser.dm
@@ -2,6 +2,9 @@
projectile_type = /obj/item/projectile/beam/laser
select_name = "kill"
+/obj/item/ammo_casing/energy/laser/minigun
+ click_cooldown_override = 2
+
/obj/item/ammo_casing/energy/lasergun
projectile_type = /obj/item/projectile/beam/laser
e_cost = 83
diff --git a/code/modules/projectiles/boxes_magazines/internal/misc.dm b/code/modules/projectiles/boxes_magazines/internal/misc.dm
index 2b87557b39..76f3c88381 100644
--- a/code/modules/projectiles/boxes_magazines/internal/misc.dm
+++ b/code/modules/projectiles/boxes_magazines/internal/misc.dm
@@ -3,9 +3,3 @@
ammo_type = /obj/item/ammo_casing/caseless/magspear
caliber = "speargun"
max_ammo = 1
-
-/obj/item/ammo_box/magazine/internal/minigun
- name = "gatling gun fusion core"
- ammo_type = /obj/item/ammo_casing/caseless/laser/gatling
- caliber = "gatling"
- max_ammo = 5000
diff --git a/code/modules/projectiles/guns/ballistic/laser_gatling.dm b/code/modules/projectiles/guns/ballistic/laser_gatling.dm
index 244bc5b124..2abb7b720f 100644
--- a/code/modules/projectiles/guns/ballistic/laser_gatling.dm
+++ b/code/modules/projectiles/guns/ballistic/laser_gatling.dm
@@ -11,19 +11,19 @@
righthand_file = 'icons/mob/inhands/equipment/backpack_righthand.dmi'
slot_flags = ITEM_SLOT_BACK
w_class = WEIGHT_CLASS_HUGE
- var/obj/item/gun/ballistic/minigun/gun
+ var/obj/item/gun/energy/minigun/gun
var/armed = 0 //whether the gun is attached, 0 is attached, 1 is the gun is wielded.
var/overheat = 0
- var/overheat_max = 40
+ var/overheat_max = 50
var/heat_diffusion = 1
/obj/item/minigunpack/Initialize()
. = ..()
gun = new(src)
- START_PROCESSING(SSobj, src)
+ START_PROCESSING(SSfastprocess, src)
/obj/item/minigunpack/Destroy()
- STOP_PROCESSING(SSobj, src)
+ STOP_PROCESSING(SSfastprocess, src)
return ..()
/obj/item/minigunpack/process()
@@ -72,7 +72,6 @@
var/obj/screen/inventory/hand/H = over_object
M.putItemFromInventoryInHandIfPossible(src, H.held_index)
-
/obj/item/minigunpack/update_icon_state()
if(armed)
icon_state = "notholstered"
@@ -92,7 +91,7 @@
user.update_inv_back()
-/obj/item/gun/ballistic/minigun
+/obj/item/gun/energy/minigun
name = "laser gatling gun"
desc = "An advanced laser cannon with an incredible rate of fire. Requires a bulky backpack power source to use."
icon = 'icons/obj/guns/minigun.dmi'
@@ -103,17 +102,20 @@
slot_flags = null
w_class = WEIGHT_CLASS_HUGE
custom_materials = null
- burst_size = 3
- automatic = 0
- fire_delay = 1
+ automatic = 0.5
+ fire_delay = 2
+ ammo_type = list(
+ /obj/item/ammo_casing/energy/laser
+ )
+
weapon_weight = WEAPON_HEAVY
fire_sound = 'sound/weapons/laser.ogg'
- mag_type = /obj/item/ammo_box/magazine/internal/minigun
- casing_ejector = FALSE
+ charge_sections = 0
+ shaded_charge = 0
item_flags = NEEDS_PERMIT | SLOWS_WHILE_IN_HAND
var/obj/item/minigunpack/ammo_pack
-/obj/item/gun/ballistic/minigun/Initialize()
+/obj/item/gun/energy/minigun/Initialize()
if(istype(loc, /obj/item/minigunpack)) //We should spawn inside an ammo pack so let's use that one.
ammo_pack = loc
else
@@ -121,29 +123,29 @@
return ..()
-/obj/item/gun/ballistic/minigun/attack_self(mob/living/user)
+/obj/item/gun/energy/minigun/attack_self(mob/living/user)
return
-/obj/item/gun/ballistic/minigun/dropped(mob/user)
+/obj/item/gun/energy/minigun/dropped(mob/user)
. = ..()
if(ammo_pack)
ammo_pack.attach_gun(user)
else
qdel(src)
-/obj/item/gun/ballistic/minigun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
+/obj/item/gun/energy/minigun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
if(ammo_pack)
if(ammo_pack.overheat < ammo_pack.overheat_max)
- ammo_pack.overheat += burst_size
+ ammo_pack.overheat++
..()
else
to_chat(user, "The gun's heat sensor locked the trigger to prevent lens damage.")
-/obj/item/gun/ballistic/minigun/afterattack(atom/target, mob/living/user, flag, params)
+/obj/item/gun/energy/minigun/afterattack(atom/target, mob/living/user, flag, params)
if(!ammo_pack || ammo_pack.loc != user)
to_chat(user, "You need the backpack power source to fire the gun!")
. = ..()
-/obj/item/gun/ballistic/minigun/dropped(mob/living/user)
+/obj/item/gun/energy/minigun/dropped(mob/living/user)
. = ..()
ammo_pack.attach_gun(user)
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index d6379e1166..9144eefdbc 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -211,7 +211,7 @@
switch(animal_origin)
if(ALIEN_BODYPART,LARVA_BODYPART) //aliens take some additional burn //nothing can burn with so much snowflake code around
- burn *= 1.2
+ burn *= 1.5
/*
// START WOUND HANDLING
From 604a6efeca05b2148625bbe50648bb945947b4f9 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sat, 20 Mar 2021 13:45:39 -0700
Subject: [PATCH 16/43] baton change
---
code/datums/martial/sleeping_carp.dm | 16 ++++++++--------
code/game/objects/items/stunbaton.dm | 2 +-
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm
index e926da78d0..f41529564d 100644
--- a/code/datums/martial/sleeping_carp.dm
+++ b/code/datums/martial/sleeping_carp.dm
@@ -181,14 +181,14 @@
REMOVE_TRAIT(H, TRAIT_PIERCEIMMUNE, SLEEPING_CARP_TRAIT)
REMOVE_TRAIT(H, TRAIT_NODISMEMBER, SLEEPING_CARP_TRAIT)
REMOVE_TRAIT(H, TRAIT_TASED_RESISTANCE, SLEEPING_CARP_TRAIT)
- H.physiology.brute_mod = initial(H.physiology.brute_mod)
- H.physiology.burn_mod = initial(H.physiology.burn_mod)
- H.physiology.stamina_mod = initial(H.physiology.stamina_mod)
- H.physiology.stun_mod = initial(H.physiology.stun_mod)
- H.physiology.pressure_mod = initial(H.physiology.pressure_mod) //no more carpies
- H.physiology.cold_mod = initial(H.physiology.cold_mod)
- H.physiology.heat_mod = initial(H.physiology.heat_mod)
- H.physiology.stamina_buffer_mod = initial(H.physiology.stamina_buffer_mod)
+ H.physiology.brute_mod *= (1/0.4) //brute is really not gonna cut it
+ H.physiology.burn_mod *= (1/0.7) //burn is distinctly more useful against them than brute but they're still resistant
+ H.physiology.stamina_mod *= (1/0.4) //You take less stamina damage overall, but you do not reduce the damage from stun batons as much
+ H.physiology.stun_mod *= (1/0.3) //for those rare stuns
+ H.physiology.pressure_mod *= (1/0.3) //go hang out with carp
+ H.physiology.cold_mod *= (1/0.3) //cold mods are different to burn mods, they do stack however
+ H.physiology.heat_mod *= (1/2) //this is mostly so sleeping carp has a viable weakness. Cooking them alive. Setting them on fire and heating them will be their biggest weakness. The reason for this is....filet jokes.
+ H.physiology.stamina_buffer_mod *= (1/0.75) //to help with some stamina
H.faction -= "carp" //:(
/mob/living/carbon/human/proc/sleeping_carp_help()
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
index 862b2c8c3e..bbc962ebb7 100644
--- a/code/game/objects/items/stunbaton.dm
+++ b/code/game/objects/items/stunbaton.dm
@@ -205,7 +205,7 @@
if(!disarming)
if(knockdown && !countered)
L.DefaultCombatKnockdown(50, override_stamdmg = 0, knocktofloor = !countered) //knockdown
- L.adjustStaminaLoss(stunpwr)
+ L.apply_damage(stunpwr, STAMINA, BODY_ZONE_CHEST)
else if(!countered)
L.drop_all_held_items() //no knockdown/stamina damage, instead disarm.
From 427919d1479c824699985e1c31c09fea70f2ad19 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sat, 20 Mar 2021 13:57:48 -0700
Subject: [PATCH 17/43] whew
---
code/game/objects/items/dualsaber.dm | 2 +-
code/game/objects/items/shields.dm | 2 +-
.../changeling/powers/mutations.dm | 2 +-
.../modules/mob/living/living_active_block.dm | 34 +++++++++++++------
.../mob/living/living_blocking_parrying.dm | 2 +-
5 files changed, 27 insertions(+), 15 deletions(-)
diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm
index 86522b9587..01e68a6516 100644
--- a/code/game/objects/items/dualsaber.dm
+++ b/code/game/objects/items/dualsaber.dm
@@ -73,7 +73,7 @@
parry_failed_stagger_duration = 3 SECONDS
parry_failed_clickcd_duration = CLICK_CD_MELEE
-/obj/item/dualsaber/active_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction)
+/obj/item/dualsaber/directional_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction)
if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object))
block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER
return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT
diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm
index 9841a29ae0..deb8a8ac7d 100644
--- a/code/game/objects/items/shields.dm
+++ b/code/game/objects/items/shields.dm
@@ -446,7 +446,7 @@
return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT
return ..()
-/obj/item/shield/energy/active_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction)
+/obj/item/shield/energy/directional_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction)
if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object))
block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_DEFLECT
return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT
diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm
index 5b6a7648c8..0d1496039a 100644
--- a/code/modules/antagonists/changeling/powers/mutations.dm
+++ b/code/modules/antagonists/changeling/powers/mutations.dm
@@ -466,7 +466,7 @@
block_return[BLOCK_RETURN_BLOCK_CAPACITY] = (block_return[BLOCK_RETURN_BLOCK_CAPACITY] || 0) + remaining_uses
return ..()
-/obj/item/shield/changeling/active_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
+/obj/item/shield/changeling/directional_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
. = ..()
if(--remaining_uses < 1)
if(ishuman(loc))
diff --git a/code/modules/mob/living/living_active_block.dm b/code/modules/mob/living/living_active_block.dm
index 5c184313ee..719fa4bc53 100644
--- a/code/modules/mob/living/living_active_block.dm
+++ b/code/modules/mob/living/living_active_block.dm
@@ -140,7 +140,7 @@
/**
* Calculates FINAL ATTACK DAMAGE after mitigation
*/
-/obj/item/proc/active_block_calculate_final_damage(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
+/obj/item/proc/active_block_calculate_final_damage(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, passive = FALSE)
var/datum/block_parry_data/data = get_block_parry_data()
var/absorption = data.attack_type_list_scan(data.block_damage_absorption_override, attack_type)
var/efficiency = data.attack_type_list_scan(data.block_damage_multiplier_override, attack_type)
@@ -149,7 +149,7 @@
if(isnull(absorption))
absorption = data.block_damage_absorption
if(isnull(efficiency))
- efficiency = data.block_damage_multiplier
+ efficiency = data.block_damage_multiplier * (passive? data.block_automatic_mitigation_multiplier : 1)
if(isnull(limit))
limit = data.block_damage_limit
// now we calculate damage to reduce.
@@ -165,7 +165,7 @@
return final_damage
/// 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)
+/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, passive = FALSE)
var/datum/block_parry_data/data = get_block_parry_data()
var/efficiency = data.attack_type_list_scan(data.block_stamina_efficiency_override, attack_type)
if(isnull(efficiency))
@@ -175,7 +175,7 @@
multiplier = data.attack_type_list_scan(data.block_resting_stamina_penalty_multiplier_override, attack_type)
if(isnull(multiplier))
multiplier = data.block_resting_stamina_penalty_multiplier
- return (damage_blocked / efficiency) * multiplier
+ return (damage_blocked / efficiency) * multiplier * (passive? data.block_automatic_stamina_multiplier : 1)
/// 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)
@@ -207,6 +207,18 @@
return
/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, override_direction)
+ return directional_block(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return, override_direction)
+
+/obj/item/proc/can_passive_block()
+ if(!block_parry_data || !(item_flags & ITEM_CAN_BLOCK))
+ return FALSE
+ var/datum/block_parry_data/data = return_block_parry_datum(block_parry_data)
+ return data.block_automatic_enabled
+
+/obj/item/proc/passive_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction)
+ return directional_block(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return, override_direction, TRUE)
+
+/obj/item/proc/directional_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction, passive = FALSE)
if(!can_active_block())
return BLOCK_NONE
var/datum/block_parry_data/data = get_block_parry_data()
@@ -221,12 +233,12 @@
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))
+ else if(!can_block_direction(owner.dir, incoming_direction, passive))
return BLOCK_NONE
block_return[BLOCK_RETURN_ACTIVE_BLOCK] = TRUE
- var/final_damage = active_block_calculate_final_damage(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
+ var/final_damage = active_block_calculate_final_damage(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return, passive)
var/damage_blocked = damage - final_damage
- var/stamina_cost = active_block_stamina_cost(owner, object, damage_blocked, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
+ var/stamina_cost = active_block_stamina_cost(owner, object, damage_blocked, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return, passive)
active_block_do_stamina_damage(owner, object, stamina_cost, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
block_return[BLOCK_RETURN_ACTIVE_BLOCK_DAMAGE_MITIGATED] = damage - final_damage
block_return[BLOCK_RETURN_SET_DAMAGE_TO] = final_damage
@@ -254,9 +266,9 @@
/**
* Gets the block direction bitflags of what we can block.
*/
-/obj/item/proc/blockable_directions()
+/obj/item/proc/blockable_directions(passive = FALSE)
var/datum/block_parry_data/data = get_block_parry_data()
- return data.can_block_directions
+ return passive? data.block_automatic_directions : data.can_block_directions
/**
* Checks if we can block from a specific direction from our direction.
@@ -265,14 +277,14 @@
* * our_dir - our direction.
* * their_dir - their direction. Must be a single direction, or NONE for an attack from the same tile. This is incoming direction.
*/
-/obj/item/proc/can_block_direction(our_dir, their_dir)
+/obj/item/proc/can_block_direction(our_dir, their_dir, passive = FALSE)
their_dir = turn(their_dir, 180)
if(our_dir != NORTH)
var/turn_angle = dir2angle(our_dir)
// dir2angle(), ss13 proc is clockwise so dir2angle(EAST) == 90
// turn(), byond proc is counterclockwise so turn(NORTH, 90) == WEST
their_dir = turn(their_dir, turn_angle)
- return (DIR2BLOCKDIR(their_dir) & blockable_directions())
+ return (DIR2BLOCKDIR(their_dir) & blockable_directions(passive))
/**
* can_block_direction but for "compound" directions to check all of them and return the number of directions that were blocked.
diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm
index 1ed490b0d8..b273324028 100644
--- a/code/modules/mob/living/living_blocking_parrying.dm
+++ b/code/modules/mob/living/living_blocking_parrying.dm
@@ -100,7 +100,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
#warn have autoblock items warn user on pickup
/// Directions that you can autoblock in
var/block_automatic_directions = BLOCK_DIR_NORTH | BLOCK_DIR_NORTHEAST | BLOCK_DIR_NORTHWEST
- /// Effectiveness multiplier for automated block
+ /// Effectiveness multiplier for automated block. Only applies to efficiency, absorption and limits stay the same!
var/block_automatic_mitigation_multiplier = 0.33
/// Stamina cost multiplier for automated block
var/block_automatic_stamina_multiplier = 1
From 957c1fcc5dfe2e0c19664200eb6cb171c887efaf Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sat, 20 Mar 2021 14:09:23 -0700
Subject: [PATCH 18/43] okay
---
code/datums/components/combat_mode.dm | 3 +--
code/game/sound.dm | 4 ++--
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/code/datums/components/combat_mode.dm b/code/datums/components/combat_mode.dm
index 576d012093..ac18becb67 100644
--- a/code/datums/components/combat_mode.dm
+++ b/code/datums/components/combat_mode.dm
@@ -90,7 +90,6 @@
source.playsound_local(source, 'sound/misc/ui_toggle.ogg', 50, FALSE, pressure_affected = FALSE) //Sound from interbay!
RegisterSignal(source, COMSIG_MOB_CLIENT_MOUSEMOVE, .proc/onMouseMove)
RegisterSignal(source, COMSIG_MOVABLE_MOVED, .proc/on_move)
- RegisterSignal(source, COMSIG_MOB_CLIENT_MOVE, .proc/on_client_move)
if(hud_icon)
hud_icon.combat_on = TRUE
hud_icon.update_icon()
@@ -115,7 +114,7 @@
to_chat(source, self_message)
if(playsound)
source.playsound_local(source, 'sound/misc/ui_toggleoff.ogg', 50, FALSE, pressure_affected = FALSE) //Slightly modified version of the toggleon sound!
- UnregisterSignal(source, list(COMSIG_MOB_CLIENT_MOUSEMOVE, COMSIG_MOVABLE_MOVED, COMSIG_MOB_CLIENT_MOVE))
+ UnregisterSignal(source, list(COMSIG_MOB_CLIENT_MOUSEMOVE, COMSIG_MOVABLE_MOVED))
if(hud_icon)
hud_icon.combat_on = FALSE
hud_icon.update_icon()
diff --git a/code/game/sound.dm b/code/game/sound.dm
index b233ebd6d2..3a65d47f3f 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -84,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, get_dist(M, turf_sounrce) <= distance_multiplier_min_range? 1 : distance_multiplier, envwet, envdry)
+ M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, maxdistance, falloff_distance, get_dist(M, turf_source) <= 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, get_dist(M, turf_sounrce) <= distance_multiplier_min_range? 1 : distance_multiplier, envwet, envdry)
+ M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, maxdistance, falloff_distance, get_dist(M, turf_source) <= distance_multiplier_min_range? 1 : distance_multiplier, envwet, envdry)
/*! playsound
From efa4139aff51c0b0f27936a3bc0ff5e43ed823bc Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sat, 20 Mar 2021 14:17:13 -0700
Subject: [PATCH 19/43] math fix
---
code/game/objects/items/dualsaber.dm | 6 +++---
code/modules/mob/living/living_active_block.dm | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm
index 01e68a6516..5ae79b3c3a 100644
--- a/code/game/objects/items/dualsaber.dm
+++ b/code/game/objects/items/dualsaber.dm
@@ -41,7 +41,7 @@
/datum/block_parry_data/dual_esword // please run at the man going apeshit with his funny doublesword
can_block_directions = BLOCK_DIR_NORTH | BLOCK_DIR_NORTHEAST | BLOCK_DIR_NORTHWEST | BLOCK_DIR_WEST | BLOCK_DIR_EAST
- block_damage_absorption = 2
+ block_damage_absorption = 5
block_damage_multiplier = 0.15
block_damage_multiplier_override = list(
ATTACK_TYPE_MELEE = 0.25
@@ -59,7 +59,7 @@
)
parry_time_windup = 0
- parry_time_active = 8
+ parry_time_active = 12
parry_time_spindown = 0
// we want to signal to players the most dangerous phase, the time when automatic counterattack is a thing.
parry_time_windup_visual_override = 1
@@ -82,7 +82,7 @@
/obj/item/dualsaber/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
. = ..()
if(parry_efficiency >= 90) // perfect parry
- block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER
+ block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_DEFLECT
. |= BLOCK_SHOULD_REDIRECT
/obj/item/dualsaber/Initialize()
diff --git a/code/modules/mob/living/living_active_block.dm b/code/modules/mob/living/living_active_block.dm
index 719fa4bc53..e6f9a569a3 100644
--- a/code/modules/mob/living/living_active_block.dm
+++ b/code/modules/mob/living/living_active_block.dm
@@ -149,7 +149,7 @@
if(isnull(absorption))
absorption = data.block_damage_absorption
if(isnull(efficiency))
- efficiency = data.block_damage_multiplier * (passive? data.block_automatic_mitigation_multiplier : 1)
+ efficiency = data.block_damage_multiplier * (passive? (1 / data.block_automatic_mitigation_multiplier) : 1)
if(isnull(limit))
limit = data.block_damage_limit
// now we calculate damage to reduce.
From 02b52e61429250e01c2f1b699c0ddc3ba74d8b3a Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sat, 20 Mar 2021 16:02:26 -0700
Subject: [PATCH 20/43] framework
---
code/_onclick/drag_drop.dm | 5 +-
code/datums/martial/sleeping_carp.dm | 2 +
code/game/objects/items.dm | 15 +++
code/game/objects/items/electrostaff.dm | 1 -
code/game/objects/items/melee/misc.dm | 23 ++--
code/modules/client/client_defines.dm | 4 +
.../modules/mob/living/living_active_block.dm | 2 +-
.../modules/mob/living/living_active_parry.dm | 117 +++++++++++++-----
.../mob/living/living_blocking_parrying.dm | 17 +--
code/modules/mob/living/living_defines.dm | 2 +
code/modules/surgery/bodyparts/_bodyparts.dm | 2 +-
11 files changed, 132 insertions(+), 58 deletions(-)
diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm
index 8e2e0c3fb5..43f2581de8 100644
--- a/code/_onclick/drag_drop.dm
+++ b/code/_onclick/drag_drop.dm
@@ -94,6 +94,10 @@
mouseControlObject = control
if(mob)
SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOUSEMOVE, object, location, control, params)
+ // god forgive me for i have sinned - used for autoparry. currently at 5 objects.
+ mousedOverObjects[object] = world.time
+ if(mousedOverObjects.len > 7)
+ mousedOverObjects.Cut(1, 2)
..()
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
@@ -115,7 +119,6 @@
if(active_mousedown_item)
active_mousedown_item.onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
-
/obj/item/proc/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
return
diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm
index f41529564d..d6e2b1a2c0 100644
--- a/code/datums/martial/sleeping_carp.dm
+++ b/code/datums/martial/sleeping_carp.dm
@@ -151,7 +151,9 @@
parry_efficiency_considered_successful = 65 // VERY generous
parry_efficiency_perfect = 100
parry_failed_stagger_duration = 4 SECONDS
+ parry_failed_cooldown_duration = 2 SECONDS
parry_cooldown = 0.5 SECONDS
+ parry_flags = NONE
/mob/living/carbon/human/UseStaminaBuffer(amount, warn = FALSE, considered_action = TRUE)
amount *= physiology? physiology.stamina_buffer_mod : 1
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 8a09bca0bf..c3b0ab0d26 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -453,6 +453,21 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
SHOULD_CALL_PARENT(TRUE)
SEND_SIGNAL(src, COMSIG_ITEM_PICKUP, user)
item_flags |= IN_INVENTORY
+ if(combat_flags & (ITEM_CAN_BLOCK | ITEM_CAN_PARRY) && user.client && !(type in user.client.block_parry_hinted))
+ var/list/dat = list("You have picked up an item that can be used to block and/or parry:")
+ // cit change - parry/block feedback
+ var/datum/block_parry_data/data = return_block_parry_datum(block_parry_data)
+ if(combat_flags & ITEM_CAN_BLOCK)
+ dat += "[src] can be used to block damage using directional block. Press your active block keybind to use it."
+ if(data.block_automatic_enabled)
+ dat += "[src] is also capable of automatically blocking damage, if you are facing the right direction (usually towards your attacker)!"
+ if(combat_flags & ITEM_CAN_PARRY)
+ dat += "[src] can be used to parry damage using active parry. Pressed your active parry keybind to initiate a timed parry sequence."
+ if(data.parry_automatic_enabled)
+ dat += "[src] is also capable of automatically parrying an incoming attack, if your mouse is over your attacker at the time if you being hit in a direct, melee attack."
+ dat += "Examine [src] to get a full readout of its block/parry stats."
+ to_chat(user, dat.Join("
"))
+ user.client.block_parry_hinted |= type
// called when "found" in pockets and storage items. Returns 1 if the search should end.
/obj/item/proc/on_found(mob/finder)
diff --git a/code/game/objects/items/electrostaff.dm b/code/game/objects/items/electrostaff.dm
index 71cebc38c6..52b5c556c9 100644
--- a/code/game/objects/items/electrostaff.dm
+++ b/code/game/objects/items/electrostaff.dm
@@ -61,7 +61,6 @@
TEXT_ATTACK_TYPE_PROJECTILE = 1 // extremely harsh window for projectiles
)
// not extremely punishing to fail, but no spamming the parry.
- parry_cooldown = 1.5 SECONDS
parry_failed_stagger_duration = 1.5 SECONDS
parry_failed_clickcd_duration = 1 SECONDS
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index 1043876061..c361c1e20d 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -72,15 +72,16 @@
block_parry_data = /datum/block_parry_data/captain_saber
/datum/block_parry_data/captain_saber
- parry_time_windup = 0.5
- parry_time_active = 4
- parry_time_spindown = 1
+ parry_time_windup = 0
+ parry_time_active = 6
+ parry_time_spindown = 0
parry_time_perfect = 0.75
parry_time_perfect_leeway = 0.75
parry_imperfect_falloff_percent = 30
parry_efficiency_perfect = 100
parry_failed_stagger_duration = 3 SECONDS
parry_failed_clickcd_duration = 1 SECONDS
+ parry_flags = NONE
/obj/item/melee/sabre/Initialize()
. = ..()
@@ -176,28 +177,22 @@
// Fast, efficient parry.
/datum/block_parry_data/traitor_rapier
- parry_time_windup = 0.5
- parry_time_active = 5
+ parry_time_windup = 0
+ parry_time_active = 6
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 = 1
+ parry_time_perfect_leeway = 1
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 = INFINITY
parry_efficiency_considered_successful = 1
parry_efficiency_perfect = 100
- parry_data = list(
- PARRY_DISARM_ATTACKER = TRUE,
- PARRY_KNOCKDOWN_ATTACKER = 10
- )
+ parry_stamina_cost = 5
parry_failed_stagger_duration = 2 SECONDS
parry_failed_clickcd_duration = CLICK_CD_RANGE
parry_cooldown = 0
diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm
index 241cd6be93..a4d94e994c 100644
--- a/code/modules/client/client_defines.dm
+++ b/code/modules/client/client_defines.dm
@@ -183,3 +183,7 @@
//world.time of when the crew manifest can be accessed
var/crew_manifest_delay
+ /// Should go in persistent round player data sometime. This tracks what items have already warned the user on pickup that they can block/parry.
+ var/list/block_parry_hinted = list()
+ /// moused over objects, currently capped at 7. this is awful, and should be replaced with a component to track it using signals for parrying at some point.
+ var/list/moused_over_objects = list()
diff --git a/code/modules/mob/living/living_active_block.dm b/code/modules/mob/living/living_active_block.dm
index e6f9a569a3..9ccaeb6c59 100644
--- a/code/modules/mob/living/living_active_block.dm
+++ b/code/modules/mob/living/living_active_block.dm
@@ -268,7 +268,7 @@
*/
/obj/item/proc/blockable_directions(passive = FALSE)
var/datum/block_parry_data/data = get_block_parry_data()
- return passive? data.block_automatic_directions : data.can_block_directions
+ return (!isnull(data.block_automatic_directions) && passive)? data.block_automatic_directions : data.can_block_directions
/**
* Checks if we can block from a specific direction from our direction.
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index c15b56afe8..bdd6174314 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -14,18 +14,57 @@
/**
* Initiates a parrying sequence.
*/
-/mob/living/proc/initiate_parry_sequence()
+/mob/living/proc/initiate_parry_sequence(silent = FALSE, list/override_method_data)
if(parrying)
- return // already parrying
+ return FALSE // already parrying
if(!(mobility_flags & MOBILITY_USE))
- to_chat(src, "You can't move your arms!")
- return
+ if(!silent)
+ to_chat(src, "You can't move your arms!")
+ return FALSE
if(!(combat_flags & COMBAT_FLAG_PARRY_CAPABLE))
- to_chat(src, "You are not something that can parry attacks.")
- return
+ if(!silent)
+ to_chat(src, "You are not something that can parry attacks.")
+ return FALSE
if(!(mobility_flags & MOBILITY_STAND))
- to_chat(src, "You aren't able to parry without solid footing!")
- return
+ if(!silent)
+ to_chat(src, "You aren't able to parry without solid footing!")
+ return FALSE
+ var/datum/block_parry_data/data
+ var/list/determined = override_method_data || determine_parry_method(FALSE, FALSE)
+ if(!islist(determined))
+ return FALSE
+ var/method = determined[1]
+ data = return_block_parry_datum(determined[2])
+ var/full_parry_duration = data.parry_time_windup + data.parry_time_active + data.parry_time_spindown
+ // no system in place to "fallback" if out of the 3 the top priority one can't parry due to constraints but something else can.
+ // can always implement it later, whatever.
+ if((data.parry_respect_clickdelay && !CheckActionCooldown()) || ((parry_end_time_last + data.parry_cooldown) > world.time))
+ if(!silent)
+ to_chat(src, "You are not ready to parry (again)!")
+ return FALSE
+ // Point of no return, make sure everything is set.
+ parrying = method
+ if(method == ITEM_PARRY)
+ active_parry_item = using_item
+ if(!UseStaminaBuffer(data.parry_stamina_cost, TRUE))
+ return FALSE
+ parry_start_time = world.time
+ successful_parries = list()
+ successful_parry_counterattacks = list()
+ addtimer(CALLBACK(src, .proc/end_parry_sequence), full_parry_duration)
+ if(data.parry_flags & PARRY_LOCK_ATTACKING)
+ ADD_TRAIT(src, TRAIT_MOBILITY_NOUSE, ACTIVE_PARRY_TRAIT)
+ if(data.parry_flags & PARRY_LOCK_SPRINTING)
+ ADD_TRAIT(src, TRAIT_SPRINT_LOCKED, ACTIVE_PARRY_TRAIT)
+ handle_parry_starting_effects(data)
+ return TRUE
+
+/**
+ * Massive snowflake proc for getting something to parry with.
+ *
+ * @return list of [method, data, tool], where method is the parry method define, data is the block_parry_data var that must be run through return_block_parry_data, and tool is the concept/object/martial art/etc used.
+ */
+/mob/living/proc/determine_parry_method(silent = TRUE, autoparry = FALSE)
// Prioritize item, then martial art, then unarmed.
// yanderedev else if time
var/obj/item/using_item = get_active_held_item()
@@ -55,7 +94,8 @@
var/list/other_items = list()
var/list/override = list()
if(SEND_SIGNAL(src, COMSIG_LIVING_ACTIVE_PARRY_START, method, tool, other_items, override) & COMPONENT_PREVENT_PARRY_START)
- to_chat(src, "Something is preventing you from parrying!")
+ if(!silent)
+ to_chat(src, "Something is preventing you from parrying!")
return
if(length(override))
var/datum/thing = override[1]
@@ -72,30 +112,10 @@
method = ITEM_PARRY
data = using_item.block_parry_data
if(!method)
- to_chat(src, "You have nothing to parry with!")
+ if(!silent)
+ to_chat(src, "You have nothing to parry with!")
return FALSE
- data = return_block_parry_datum(data)
- var/full_parry_duration = data.parry_time_windup + data.parry_time_active + data.parry_time_spindown
- // no system in place to "fallback" if out of the 3 the top priority one can't parry due to constraints but something else can.
- // can always implement it later, whatever.
- if((data.parry_respect_clickdelay && !CheckActionCooldown()) || ((parry_end_time_last + data.parry_cooldown) > world.time))
- to_chat(src, "You are not ready to parry (again)!")
- return FALSE
- // Point of no return, make sure everything is set.
- parrying = method
- if(method == ITEM_PARRY)
- active_parry_item = using_item
- if(!UseStaminaBuffer(data.parry_stamina_cost, TRUE))
- return FALSE
- parry_start_time = world.time
- successful_parries = list()
- addtimer(CALLBACK(src, .proc/end_parry_sequence), full_parry_duration)
- if(data.parry_flags & PARRY_LOCK_ATTACKING)
- ADD_TRAIT(src, TRAIT_MOBILITY_NOUSE, ACTIVE_PARRY_TRAIT)
- if(data.parry_flags & PARRY_LOCK_SPRINTING)
- ADD_TRAIT(src, TRAIT_SPRINT_LOCKED, ACTIVE_PARRY_TRAIT)
- handle_parry_starting_effects(data)
- return TRUE
+ return list(method, data, tool)
/**
* Tries to find a backup parry item.
@@ -141,6 +161,7 @@
parry_start_time = 0
parry_end_time_last = world.time + (successful? 0 : data.parry_failed_cooldown_duration)
successful_parries = null
+ successful_parry_counterattacks = null
/**
* Handles starting effects for parrying.
@@ -200,6 +221,35 @@
*/
/datum/martial_art/proc/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)
+/**
+ * Attempts to automatically parry an attacker.
+ */
+/mob/living/proc/attempt_auto_parry()
+ // determine how we'll parry
+ var/list/determined = determine_parry_method(TRUE, TRUE)
+ if(!islist(determined))
+ return FALSE
+ var/method = determined[1]
+ var/datum/block_parry_data/data = return_block_parry_datum(determined[2])
+ if(!data.parry_automatic_enabled)
+ return FALSE
+ // before doing anything, check if the user moused over them properly
+
+ // if that works, try to start parry
+ // first, check cooldowns
+
+ // now, depending on if we're doing a single simulation or a full sequence
+ if(data.autoparry_sequence_simulation)
+ // for full sequence simulation
+ initiate_parry_sequence(TRUE, determined)
+ if(data.autoparry_sequence_start_time == -1)
+ parry_start_time = world.time - data.parry_time_windup
+ else
+ parry_start_time = world.time - data.autoparry_sequence_start_time
+ else
+ // for single attack block
+
+
/**
* Gets the stage of our parry sequence we're currently in.
*/
@@ -279,7 +329,7 @@
pacifist_counter_check = (!active_parry_item.force || active_parry_item.damtype == STAMINA)
else
pacifist_counter_check = FALSE //Both martial and unarmed counter attacks generally are harmful, so no need to have the same line twice.
- if(efficiency >= data.parry_efficiency_to_counterattack && pacifist_counter_check && !return_list[BLOCK_RETURN_FORCE_NO_PARRY_COUNTERATTACK])
+ if(efficiency >= data.parry_efficiency_to_counterattack && pacifist_counter_check && !return_list[BLOCK_RETURN_FORCE_NO_PARRY_COUNTERATTACK] && (!(attacker in successful_parry_counterattacks) && !data.parry_allow_repeated_counterattacks))
effect_text = run_parry_countereffects(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency)
if(data.parry_flags & PARRY_DEFAULT_HANDLE_FEEDBACK)
handle_parry_feedback(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, effect_text)
@@ -303,6 +353,7 @@
var/mob/living/L = attacker
var/datum/block_parry_data/data = get_parry_data()
var/list/effect_text = list()
+ successful_parry_counterattacks |= attacker
// Always proc so items can override behavior easily
switch(parrying)
if(ITEM_PARRY)
diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm
index b273324028..36fb160e0f 100644
--- a/code/modules/mob/living/living_blocking_parrying.dm
+++ b/code/modules/mob/living/living_blocking_parrying.dm
@@ -98,15 +98,15 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Can this item automatically block?
var/block_automatic_enabled = TRUE
#warn have autoblock items warn user on pickup
- /// Directions that you can autoblock in
- var/block_automatic_directions = BLOCK_DIR_NORTH | BLOCK_DIR_NORTHEAST | BLOCK_DIR_NORTHWEST
+ /// Directions that you can autoblock in. Null to default to normal directions.
+ var/block_automatic_directions = null
/// Effectiveness multiplier for automated block. Only applies to efficiency, absorption and limits stay the same!
var/block_automatic_mitigation_multiplier = 0.33
/// Stamina cost multiplier for automated block
var/block_automatic_stamina_multiplier = 1
/////////// PARRYING ////////////
- /// Prioriry for [mob/do_run_block()] while we're being used to parry.
+ /// Priority for [mob/do_run_block()] while we're being used to parry.
// None - Parry is always highest priority!
/// Parry doesn't work if you aren't able to otherwise attack due to clickdelay
var/parry_respect_clickdelay = TRUE
@@ -178,12 +178,13 @@ GLOBAL_LIST_EMPTY(block_parry_data)
var/perfect_parry_block_return_list
var/imperfect_parry_block_return_list
var/failed_parry_block_return_list
+ /// Allow multiple counterattacks per parry sequence. Bad idea.
+ var/parry_allow_repeated_counterattacks = FALSE
// Auto parry
// Anything not specified like cooldowns/clickdelay respecting is pulled from above.
/// Can this data automatically parry? This is off by default because this is something that requires thought to balance.
var/parry_automatic_enabled = FALSE
-#warn implement autoparry in items
#warn have autoparry items warn user on pickup
/// Hard autoparry cooldown
var/autoparry_cooldown_absolute = 3 SECONDS
@@ -195,16 +196,17 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Clickdelay to inflict on single-attack autoparry
var/autoparry_single_click_cooldown = 0
/// Single attack autoparry - efficiency
- var/autoparry_single_efficiency = 60
+ var/autoparry_single_efficiency = 75
/// 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.
+ /// ADVANCED - Autoparry requirement for time since last moused over for a specific object
+ var/autoparry_mouse_delay_maximum = 0.5
+
/**
* Quirky proc to get average of flags in list that are in attack_type because why is attack_type a flag.
*/
@@ -346,6 +348,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
RENDER_VARIABLE_SIMPLE(parry_cooldown, "Deciseconds it has to be since the last time a parry sequence ended for you before you can parry again.")
RENDER_VARIABLE_SIMPLE(parry_failed_stagger_duration, "Deciseconds you are staggered for at the of the parry sequence if you do not successfully parry anything.")
RENDER_VARIABLE_SIMPLE(parry_failed_clickcd_duration, "Deciseconds you are put on attack cooldown at the end of the parry sequence if you do not successfully parry anything.")
+ dat += ""
dat += ""
return dat.Join("")
#undef RENDER_VARIABLE_SIMPLE
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 386f1174e1..14acf72f57 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -52,6 +52,8 @@
var/parry_end_time_last = 0
/// Successful parries within the current parry cycle. It's a list of efficiency percentages.
var/list/successful_parries
+ /// Current parry counterattacks. Makes sure we can only counterattack someone once per parry.
+ var/list/successful_parry_counterattacks
var/confused = 0 //Makes the mob move in random directions.
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 9144eefdbc..83c587b81d 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -211,7 +211,7 @@
switch(animal_origin)
if(ALIEN_BODYPART,LARVA_BODYPART) //aliens take some additional burn //nothing can burn with so much snowflake code around
- burn *= 1.5
+ burn *= 1.75
/*
// START WOUND HANDLING
From 1fd06a89b749a0e73aeff4c51ddc304b13641a1d Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sat, 20 Mar 2021 16:27:52 -0700
Subject: [PATCH 21/43] Oh Boy
---
code/__DEFINES/dcs/signals.dm | 3 +++
code/datums/components/identification.dm | 1 +
code/game/objects/items.dm | 11 ++++++-----
.../objects/items/devices/traitordevices.dm | 18 +++++++++++++-----
4 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 13e6c5772a..c36e21ae06 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -550,3 +550,6 @@
// twitch plays
/// Returns direction: (wipe_votes)
#define COMSIG_TWITCH_PLAYS_MOVEMENT_DATA "twitch_plays_movement_data"
+
+// /datum/component/identification signals
+#define COMSIG_IDENTIFICATION_KNOWLEDGE_CHECK "id_knowledge_check" // (mob/user) - returns a value from ID_COMPONENT_KNOWLEDGE_NONE to ID_COMPONENT_KNOWLEDGE_FULL
diff --git a/code/datums/components/identification.dm b/code/datums/components/identification.dm
index f7dc211504..474363b85b 100644
--- a/code/datums/components/identification.dm
+++ b/code/datums/components/identification.dm
@@ -24,6 +24,7 @@
identification_method_flags = id_method_flags
/datum/component/identification/RegisterWithParent()
+ RegisterSignal(parent, COMSIG_IDENFICATION_KNOWLEDGE_CHECK, .proc/check_knowledge)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
if(identification_effect_flags & ID_COMPONENT_EFFECT_NO_ACTIONS)
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index c3b0ab0d26..330865c5b7 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -511,12 +511,13 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
*/
/obj/item/proc/equipped(mob/user, slot, initial = FALSE)
SHOULD_CALL_PARENT(TRUE)
- SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot)
+ var/signal_flags = SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot)
current_equipped_slot = slot
- for(var/X in actions)
- var/datum/action/A = X
- if(item_action_slot_check(slot, user, A)) //some items only give their actions buttons when in a specific slot.
- A.Grant(user)
+ if(!(signal_flags & COMPONENT_NO_GRANT_ACTIONS))
+ for(var/X in actions)
+ var/datum/action/A = X
+ if(item_action_slot_check(slot, user, A)) //some items only give their actions buttons when in a specific slot.
+ A.Grant(user)
item_flags |= IN_INVENTORY
// if(!initial)
// if(equip_sound && (slot_flags & slot))
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index 70edd3f43d..6fb3aef083 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -79,21 +79,27 @@ effective or pretty fucking useless.
var/ui_x = 320
var/ui_y = 335
+/obj/item/healthanalyzer/rad_laser/Initialize()
+ . = ..()
+ AddComponent(/datum/component/identification/syndicate, ID_COMPONENT_DEL_ON_IDENTIFY, ID_COMPONENT_EFFECT_NO_ACTIONS, ID_COMPONENT_IDENTIFY_WITH_DECONSTRUCTOR)
+
/obj/item/healthanalyzer/rad_laser/attack(mob/living/M, mob/living/user)
if(!stealth || !irradiate)
- ..()
+ return ..()
+ var/knowledge = SEND_SIGNAL(COMSIG_IDENTIFICATION_KNOWLEDGE_CHECK, user) == ID_COMPONENT_KNOWLEDGE_FULL
if(!irradiate)
return
if(!used)
- log_combat(user, M, "irradiated", src)
+ log_combat(user, M, "[knowledge? "" : "unknowingly "]irradiated", src)
var/cooldown = get_cooldown()
used = TRUE
icon_state = "health1"
addtimer(VARSET_CALLBACK(src, used, FALSE), cooldown)
addtimer(VARSET_CALLBACK(src, icon_state, "health"), cooldown)
- to_chat(user, "Successfully irradiated [M].")
+ if(knowledge)
+ to_chat(user, "Successfully irradiated [M].")
addtimer(CALLBACK(src, .proc/radiation_aftereffect, M), (wavelength+(intensity*4))*5)
- else
+ else if(knowledge)
to_chat(user, "The radioactive microlaser is still recharging.")
/obj/item/healthanalyzer/rad_laser/proc/radiation_aftereffect(mob/living/M)
@@ -110,7 +116,9 @@ effective or pretty fucking useless.
interact(user)
/obj/item/healthanalyzer/rad_laser/interact(mob/user)
- ui_interact(user)
+ var/knowledge = SEND_SIGNAL(COMSIG_IDENTIFICATION_KNOWLEDGE_CHECK, user) == ID_COMPONENT_KNOWLEDGE_FULL
+ if(knowledge)
+ ui_interact(user)
/obj/item/healthanalyzer/rad_laser/ui_state(mob/user)
return GLOB.hands_state
From 7ccb5bc711fb1339c6a05ed5b2f1e2778fb244db Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Mon, 26 Apr 2021 14:21:59 -0700
Subject: [PATCH 22/43] fixes
---
code/datums/components/identification.dm | 2 +-
code/datums/status_effects/debuffs.dm | 2 +-
code/game/objects/items.dm | 6 +++---
code/game/objects/items/devices/traitordevices.dm | 2 +-
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/code/datums/components/identification.dm b/code/datums/components/identification.dm
index 474363b85b..59b98b57ac 100644
--- a/code/datums/components/identification.dm
+++ b/code/datums/components/identification.dm
@@ -24,7 +24,7 @@
identification_method_flags = id_method_flags
/datum/component/identification/RegisterWithParent()
- RegisterSignal(parent, COMSIG_IDENFICATION_KNOWLEDGE_CHECK, .proc/check_knowledge)
+ RegisterSignal(parent, COMSIG_IDENTIFICATION_KNOWLEDGE_CHECK, .proc/check_knowledge)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
if(identification_effect_flags & ID_COMPONENT_EFFECT_NO_ACTIONS)
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index 27de3bd702..d01d3a1454 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -190,9 +190,9 @@
/datum/status_effect/electrode/no_combat_mode
id = "tased_strong"
movespeed_mod = /datum/movespeed_modifier/status_effect/tased/no_combat_mode
- blocks_combatmode = TRUE
stamdmg_per_ds = 1
+
//OTHER DEBUFFS
/datum/status_effect/his_wrath //does minor damage over time unless holding His Grace
id = "his_wrath"
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 330865c5b7..5dd9b9928c 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -453,15 +453,15 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
SHOULD_CALL_PARENT(TRUE)
SEND_SIGNAL(src, COMSIG_ITEM_PICKUP, user)
item_flags |= IN_INVENTORY
- if(combat_flags & (ITEM_CAN_BLOCK | ITEM_CAN_PARRY) && user.client && !(type in user.client.block_parry_hinted))
+ if(item_flags & (ITEM_CAN_BLOCK | ITEM_CAN_PARRY) && user.client && !(type in user.client.block_parry_hinted))
var/list/dat = list("You have picked up an item that can be used to block and/or parry:")
// cit change - parry/block feedback
var/datum/block_parry_data/data = return_block_parry_datum(block_parry_data)
- if(combat_flags & ITEM_CAN_BLOCK)
+ if(item_flags & ITEM_CAN_BLOCK)
dat += "[src] can be used to block damage using directional block. Press your active block keybind to use it."
if(data.block_automatic_enabled)
dat += "[src] is also capable of automatically blocking damage, if you are facing the right direction (usually towards your attacker)!"
- if(combat_flags & ITEM_CAN_PARRY)
+ if(item_flags & ITEM_CAN_PARRY)
dat += "[src] can be used to parry damage using active parry. Pressed your active parry keybind to initiate a timed parry sequence."
if(data.parry_automatic_enabled)
dat += "[src] is also capable of automatically parrying an incoming attack, if your mouse is over your attacker at the time if you being hit in a direct, melee attack."
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index 6e3a73f25c..6e06a87ac3 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -116,7 +116,7 @@ effective or pretty fucking useless.
interact(user)
/obj/item/healthanalyzer/rad_laser/interact(mob/user)
- var/knowledge = SEND_SIGNAL(COMSIG_IDENTIFICATION_KNOWLEDGE_CHECK, user) == ID_COMPONENT_KNOWLEDGE_FULL
+ var/knowledge = SEND_SIGNAL(src, COMSIG_IDENTIFICATION_KNOWLEDGE_CHECK, user) == ID_COMPONENT_KNOWLEDGE_FULL
if(knowledge)
ui_interact(user)
From 02b40589fe6125b09e6ca6c3ba4d559346fcf204 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Mon, 26 Apr 2021 22:46:16 -0700
Subject: [PATCH 23/43] conflict gone
---
code/game/objects/items/stunbaton.dm | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
index 13b091bd94..a733c282c6 100644
--- a/code/game/objects/items/stunbaton.dm
+++ b/code/game/objects/items/stunbaton.dm
@@ -19,7 +19,7 @@
var/stamina_loss_amount = 35
var/turned_on = FALSE
var/knockdown = TRUE
- /// block percent needed to prevent knockdown/disarm - UNUSED RIGHT NOW
+ /// block percent needed to prevent knockdown/disarm
var/block_percent_to_counter = 50
var/obj/item/stock_parts/cell/cell
var/hitcost = 750
@@ -221,12 +221,12 @@
if(user && !user.UseStaminaBuffer(getweight(user, STAM_COST_BATON_MOB_MULT), warn = TRUE))
return FALSE
-<<<<<<< HEAD
- if(!disarming)
- if(knockdown && !countered)
- L.DefaultCombatKnockdown(50, override_stamdmg = 0, knocktofloor = !countered) //knockdown
- L.apply_damage(stunpwr, STAMINA, BODY_ZONE_CHEST)
- else if(!countered)
+ if(shoving && COOLDOWN_FINISHED(src, shove_cooldown) && !HAS_TRAIT(L, TRAIT_IWASBATONED)) //Rightclicking applies a knockdown, but only once every couple of seconds, based on the cooldown_duration var. If they were recently knocked down, they can't be knocked down again by a baton.
+ L.DefaultCombatKnockdown(50, override_stamdmg = 0)
+ L.apply_status_effect(STATUS_EFFECT_TASED_WEAK, status_duration) //Even if they shove themselves up, they're still slowed.
+ L.apply_status_effect(STATUS_EFFECT_OFF_BALANCE, status_duration) //They're very likely to drop items if shoved briefly after a knockdown.
+ shoved = TRUE
+ COOLDOWN_START(src, shove_cooldown, cooldown_duration)
ADD_TRAIT(L, TRAIT_IWASBATONED, STATUS_EFFECT_TRAIT) //Prevents swapping to a new baton to avoid the cooldown by just acquiring more batons
addtimer(TRAIT_CALLBACK_REMOVE(L, TRAIT_IWASBATONED, STATUS_EFFECT_TRAIT), cooldown_duration)
playsound(loc, 'sound/weapons/zapbang.ogg', 50, 1, -1)
@@ -241,12 +241,12 @@
L.visible_message("[user] has [shoved ? "brutally stunned" : "stunned"] [L] with [src]!", \
"[user] has [shoved ? "brutally stunnned" : "stunned"] you with [src]!")
log_combat(user, L, shoved ? "stunned and attempted knockdown" : "stunned")
->>>>>>> citadel/master
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
if(ishuman(L))
var/mob/living/carbon/human/H = L
+ H.forcesay(GLOB.hit_appends)
return TRUE
From 8fe45263c589a2c1394fed00662fbc9be867df7e Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Mon, 26 Apr 2021 22:58:30 -0700
Subject: [PATCH 24/43] whew
---
code/_onclick/drag_drop.dm | 6 ++--
code/datums/status_effects/debuffs.dm | 7 +++++
.../objects/items/devices/traitordevices.dm | 2 +-
.../modules/mob/living/living_active_parry.dm | 29 +++++++++++++++----
.../mob/living/living_blocking_parrying.dm | 2 --
5 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm
index 43f2581de8..43451bd056 100644
--- a/code/_onclick/drag_drop.dm
+++ b/code/_onclick/drag_drop.dm
@@ -95,9 +95,9 @@
if(mob)
SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOUSEMOVE, object, location, control, params)
// god forgive me for i have sinned - used for autoparry. currently at 5 objects.
- mousedOverObjects[object] = world.time
- if(mousedOverObjects.len > 7)
- mousedOverObjects.Cut(1, 2)
+ moused_over_objects[object] = world.time
+ if(moused_over_objects.len > 7)
+ moused_over_objects.Cut(1, 2)
..()
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index d01d3a1454..7fc7da2ef7 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -127,6 +127,13 @@
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/grouped/stasis
+ id = "stasis"
+ duration = -1
+ tick_interval = 10
+ var/last_dead_time
+
/datum/status_effect/robotic_emp
id = "emp_no_combat_mode"
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index 6e06a87ac3..ac79b3b887 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -85,7 +85,7 @@ effective or pretty fucking useless.
/obj/item/healthanalyzer/rad_laser/attack(mob/living/M, mob/living/user)
if(!stealth || !irradiate)
return ..()
- var/knowledge = SEND_SIGNAL(COMSIG_IDENTIFICATION_KNOWLEDGE_CHECK, user) == ID_COMPONENT_KNOWLEDGE_FULL
+ var/knowledge = SEND_SIGNAL(src, COMSIG_IDENTIFICATION_KNOWLEDGE_CHECK, user) == ID_COMPONENT_KNOWLEDGE_FULL
if(!irradiate)
return
if(!used)
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index bdd6174314..e062a60aa8 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -35,6 +35,7 @@
return FALSE
var/method = determined[1]
data = return_block_parry_datum(determined[2])
+ var/datum/tool = determined[3]
var/full_parry_duration = data.parry_time_windup + data.parry_time_active + data.parry_time_spindown
// no system in place to "fallback" if out of the 3 the top priority one can't parry due to constraints but something else can.
// can always implement it later, whatever.
@@ -224,7 +225,7 @@
/**
* Attempts to automatically parry an attacker.
*/
-/mob/living/proc/attempt_auto_parry()
+/mob/living/proc/attempt_auto_parry(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list())
// determine how we'll parry
var/list/determined = determine_parry_method(TRUE, TRUE)
if(!islist(determined))
@@ -234,6 +235,16 @@
if(!data.parry_automatic_enabled)
return FALSE
// before doing anything, check if the user moused over them properly
+ if(!client)
+ return FALSE
+ var/found = FALSE
+ for(var/i in client.moused_over_objects)
+ if(i == object)
+ if((client.moused_over_objects[i] + (data.autoparry_mouse_delay_maximum SECONDS)) >= world.time)
+ found = TRUE
+ break
+ if(!found)
+ return FALSE
// if that works, try to start parry
// first, check cooldowns
@@ -246,9 +257,11 @@
parry_start_time = world.time - data.parry_time_windup
else
parry_start_time = world.time - data.autoparry_sequence_start_time
+ return TRUE
else
// for single attack block
-
+ #warn single attack block
+ return FALSE
/**
* Gets the stage of our parry sequence we're currently in.
@@ -282,13 +295,17 @@
/// 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(), allow_auto = TRUE)
var/stage = get_parry_stage()
+ if(attack_type & ATTACK_TYPE_PARRY_COUNTERATTACK)
+ return BLOCK_NONE // don't infinite loop
if(stage != PARRY_ACTIVE)
// If they're not currently parrying, attempt auto parry
- if((stage == NOT_PARRYING) && allow_auto && !SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
- return attempt_auto_parry()
- return BLOCK_NONE
+ if(stage == NOT_PARRYING)
+ if(!allow_auto || SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE) || !attempt_auto_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list))
+ return BLOCK_NONE
+ else
+ 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.
+ if(attack_type && !(attack_type & data.parry_attack_types))
return BLOCK_NONE
var/efficiency = data.get_parry_efficiency(attack_type, get_parry_time())
switch(parrying)
diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm
index 36fb160e0f..453f521575 100644
--- a/code/modules/mob/living/living_blocking_parrying.dm
+++ b/code/modules/mob/living/living_blocking_parrying.dm
@@ -97,7 +97,6 @@ GLOBAL_LIST_EMPTY(block_parry_data)
// Other than for overrides, this mostly just reads from the above vars
/// Can this item automatically block?
var/block_automatic_enabled = TRUE
-#warn have autoblock items warn user on pickup
/// Directions that you can autoblock in. Null to default to normal directions.
var/block_automatic_directions = null
/// Effectiveness multiplier for automated block. Only applies to efficiency, absorption and limits stay the same!
@@ -185,7 +184,6 @@ GLOBAL_LIST_EMPTY(block_parry_data)
// Anything not specified like cooldowns/clickdelay respecting is pulled from above.
/// Can this data automatically parry? This is off by default because this is something that requires thought to balance.
var/parry_automatic_enabled = FALSE
-#warn have autoparry items warn user on pickup
/// 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?
From eb2c12ceee9c518bb3f6255d4c39af8c495d9147 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Mon, 26 Apr 2021 23:10:10 -0700
Subject: [PATCH 25/43] yell wip
---
code/__HELPERS/game.dm | 14 ++++++++++++++
code/modules/mob/living/say.dm | 3 ++-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index b9f180ac4a..745b12e84f 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -270,6 +270,20 @@
SEND_SIGNAL(A, COMSIG_ATOM_HEARER_IN_VIEW, processing, .)
processing += A.contents
+/proc/get_hearers_in_range(R, atom/source)
+ var/turf/T = get_turf(source)
+ . = list()
+ if(!T)
+ return
+ var/list/processing = range(R, source)
+ var/i = 0
+ while(i < length(processing))
+ var/atom/A = processing[++i]
+ if(A.flags_1 & HEAR_1)
+ . += A
+ SEND_SIGNAL(A, COMSIG_ATOM_HEARER_IN_VIEW, processing, .)
+ processing += A.contents
+
//viewers() but with a signal, for blacklisting.
/proc/fov_viewers(depth = world.view, atom/center)
if(!center)
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index cad1bdf1d6..2f90f04cef 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -311,7 +311,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
/atom/movable/proc/process_yelling(list/already_heard, rendered, atom/movable/speaker, datum/language/message_language, message, list/spans, message_mode, obj/source)
var/list/overhearing = list()
-#warn todo: yelling
+ overhearing = yelling_wavefill(src, 35)
+ overhearing = get_hearers_in_view(35, src) | get_hearers_in_range(5, src)
overhearing -= already_heard
for(var/_AM in overhearing)
var/atom/movable/AM = _AM
From a415453540887b5757b72bb7c3a2db874b6c6dcb Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Mon, 26 Apr 2021 23:29:37 -0700
Subject: [PATCH 26/43] ripping off my own code
---
code/__HELPERS/yelling.dm | 134 ++++++++++++++++++
code/game/turfs/closed.dm | 9 +-
code/game/turfs/turf.dm | 11 ++
.../modules/mob/living/living_active_parry.dm | 2 +-
code/modules/mob/living/say.dm | 2 +-
tgstation.dme | 1 +
6 files changed, 155 insertions(+), 4 deletions(-)
create mode 100644 code/__HELPERS/yelling.dm
diff --git a/code/__HELPERS/yelling.dm b/code/__HELPERS/yelling.dm
new file mode 100644
index 0000000000..e9a2697c87
--- /dev/null
+++ b/code/__HELPERS/yelling.dm
@@ -0,0 +1,134 @@
+/datum/yelling_wavefill
+ var/stop = FALSE
+ var/list/atom/collected
+
+/datum/yelling_wavefill/Destroy(force, ...)
+ stop = TRUE
+ return ..()
+
+/datum/yelling_wavefill/proc/run(atom/source, dist = 50)
+ collected = list()
+ do_run(source, dist)
+ // gc
+ if(QDELETED(src))
+ collected = null
+
+// blatantly copied from wave explosion code
+/datum/yelling_wavefill/proc/do_run(atom/source, dist)
+ var/list/edges = list(source = (NORTH|SOUTH|EAST|WEST))
+ var/list/powers = list(source = dist)
+ var/list/processed_last = list()
+ var/turf/T
+ var/turf/expanding
+ var/power
+ var/dir
+ var/returned
+#define RUN_YELL(_T, _P, _D) \
+ returned = max(powers[_T] - _T.get_yelling_resistance() - 1, 0); \
+ _T.maptext = "[returned]";
+
+ var/list/turf/edges_next = list()
+ var/list/turf/powers_next = list()
+ var/list/turf/powers_returned = list()
+ var/list/turf/diagonals = list()
+ var/list/turf/diagonal_powers = list()
+ var/list/turf/diagonal_powers_max = list()
+
+ while(edges.len)
+ // process cardinals
+ for(var/i in edges)
+ T = i
+ power = powers[T]
+ dir = edges[T]
+ RUN_YELL(T, power, dir)
+ powers_returned[T] = returned
+ if(returned)
+ // get hearing atoms
+ else
+ continue
+
+ // diagonal power calc when multiple things hit one diagonal
+#define CALCULATE_DIAGONAL_POWER(existing, adding, maximum) min(maximum, existing + adding)
+ // diagonal hitting cardinal expansion
+#define CALCULATE_DIAGONAL_CROSS_POWER(existing, adding) max(existing, adding)
+ // insanity define to mark the next set of cardinals.
+#define CARDINAL_MARK(ndir, cdir, edir) \
+ if(edir & cdir) { \
+ expanding = get_step(T,ndir); \
+ if(expanding && !processed_last[expanding] && !edges[expanding]) { \
+ powers_next[expanding] = max(powers_next[expanding], returned); \
+ edges_next[expanding] = (cdir | edges_next[expanding]); \
+ }; \
+ };
+
+#define DIAGONAL_SUBSTEP(ndir, cdir, edir) \
+ expanding = get_step(T,ndir); \
+ if(expanding && !processed_last[expanding] && !edges[expanding]) { \
+ if(!edges_next[expanding]) { \
+ diagonal_powers_max[expanding] = max(diagonal_powers_max[expanding], returned, powers[T]); \
+ diagonal_powers[expanding] = CALCULATE_DIAGONAL_POWER(diagonal_powers[expanding], returned, diagonal_powers_max[expanding]); \
+ diagonals[expanding] = (cdir | diagonals[expanding]); \
+ }; \
+ else { \
+ powers_next[expanding] = CALCULATE_DIAGONAL_CROSS_POWER(powers_next[expanding], returned); \
+ }; \
+ };
+
+#define DIAGONAL_MARK(ndir, cdir, edir) \
+ if(edir & cdir) { \
+ DIAGONAL_SUBSTEP(turn(ndir, 90), turn(cdir, 90), edir); \
+ DIAGONAL_SUBSTEP(turn(ndir, -90), turn(cdir, -90), edir); \
+ };
+ CARDINAL_MARK(NORTH, NORTH, dir)
+ CARDINAL_MARK(SOUTH, SOUTH, dir)
+ CARDINAL_MARK(EAST, EAST, dir)
+ CARDINAL_MARK(WEST, WEST, dir)
+ CHECK_TICK
+
+ // to_chat(world, "DEBUG: cycle mid edges_next [english_list_assoc(edges_next)]")
+
+ // Sweep after cardinals for diagonals
+ for(var/i in edges)
+ T = i
+ power = powers[T]
+ dir = edges[T]
+ returned = powers_returned[T]
+ DIAGONAL_MARK(NORTH, NORTH, dir)
+ DIAGONAL_MARK(SOUTH, SOUTH, dir)
+ DIAGONAL_MARK(EAST, EAST, dir)
+ DIAGONAL_MARK(WEST, WEST, dir)
+ CHECK_TICK
+
+ // to_chat(world, "DEBUG: cycle mid diagonals [english_list_assoc(diagonals)]")
+
+ // Process diagonals:
+ for(var/i in diagonals)
+ T = i
+ power = diagonal_powers[T]
+ dir = diagonals[T]
+ RUN_YELL(T, power, dir)
+ if(!returned)
+ continue
+ CARDINAL_MARK(NORTH, NORTH, dir)
+ CARDINAL_MARK(SOUTH, SOUTH, dir)
+ CARDINAL_MARK(EAST, EAST, dir)
+ CARDINAL_MARK(WEST, WEST, dir)
+ CHECK_TICK
+
+ // to_chat(world, "DEBUG: cycle end edges_next [english_list_assoc(edges_next)]")
+
+ // flush lists
+ processed_last = edges + diagonals
+ edges = edges_next
+ powers = powers_next
+
+#undef RUN_YELL
+#undef DIAGONAL_SUBSTEP
+#undef DIAGONAL_MARK
+#undef CARDINAL_MARK
+
+/proc/yelling_wavefill(atom/source, dist = 50)
+ var/datum/yelling_wavefill/Y = new
+ Y.run(source, dist)
+ return Y.collected || list()
+
diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm
index be0c444541..9c6dbf1912 100644
--- a/code/game/turfs/closed.dm
+++ b/code/game/turfs/closed.dm
@@ -6,6 +6,8 @@
blocks_air = 1
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
rad_insulation = RAD_MEDIUM_INSULATION
+ /// How much we block yelling
+ var/yelling_resistance = 40
/turf/closed/Initialize()
. = ..()
@@ -198,16 +200,19 @@
desc = "A wall made out of a strange metal. The squares on it pulse in a predictable pattern."
icon = 'icons/turf/walls/hierophant_wall.dmi'
icon_state = "wall"
-
+
/turf/closed/indestructible/rock/glacierrock
name = "unaturally hard ice wall"
desc = "Ice, hardened over thousands of years, you're not breaking through this."
icon = 'icons/turf/walls.dmi'
icon_state = "snow_rock"
-
+
/turf/closed/indestructible/rock/glacierrock/blue
name = "blue ice wall"
desc = "The incredible compressive forces that formed this sturdy ice wall gave it a blue color."
icon = 'icons/turf/walls.dmi'
icon_state = "ice"
canSmoothWith = list(/turf/closed/indestructible/rock/glacierrock/blue)
+
+/turf/closed/get_yelling_resistance()
+ return yelling_resistance
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 0808408192..7e61364e2a 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -594,3 +594,14 @@ GLOBAL_LIST_EMPTY(station_turfs)
. = ..()
if(. != BULLET_ACT_FORCE_PIERCE)
. = BULLET_ACT_TURF
+
+/turf/proc/get_yelling_resistance()
+ . = 0
+ // don't bother checking fulltile, we don't need accuracy
+ var/obj/structure/window/W = locate() in src
+ if(W)
+ . += 7
+ for(var/obj/machinery/door/D in src)
+ if(!D.density)
+ continue
+ . += D.opacity? 7 : 15
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index e062a60aa8..32bc5fd59d 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -46,7 +46,7 @@
// Point of no return, make sure everything is set.
parrying = method
if(method == ITEM_PARRY)
- active_parry_item = using_item
+ active_parry_item = tool
if(!UseStaminaBuffer(data.parry_stamina_cost, TRUE))
return FALSE
parry_start_time = world.time
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 2f90f04cef..949a47e50c 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -312,7 +312,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
/atom/movable/proc/process_yelling(list/already_heard, rendered, atom/movable/speaker, datum/language/message_language, message, list/spans, message_mode, obj/source)
var/list/overhearing = list()
overhearing = yelling_wavefill(src, 35)
- overhearing = get_hearers_in_view(35, src) | get_hearers_in_range(5, src)
+ // overhearing = get_hearers_in_view(35, src) | get_hearers_in_range(5, src)
overhearing -= already_heard
for(var/_AM in overhearing)
var/atom/movable/AM = _AM
diff --git a/tgstation.dme b/tgstation.dme
index 017bd393e7..30229b1cda 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -199,6 +199,7 @@
#include "code\__HELPERS\vector.dm"
#include "code\__HELPERS\verbs.dm"
#include "code\__HELPERS\view.dm"
+#include "code\__HELPERS\yelling.dm"
#include "code\__HELPERS\sorts\__main.dm"
#include "code\__HELPERS\sorts\InsertSort.dm"
#include "code\__HELPERS\sorts\MergeSort.dm"
From 1585d1c2be0bb483ca979d579b816fb1c6adb1c5 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Mon, 26 Apr 2021 23:32:33 -0700
Subject: [PATCH 27/43] fixes
---
code/__HELPERS/yelling.dm | 37 ++++++++++---------
code/modules/mining/equipment/survival_pod.dm | 2 +-
.../modules/mob/living/living_active_parry.dm | 1 -
.../projectiles/ammunition/energy/stun.dm | 3 +-
.../{ballistic => energy}/laser_gatling.dm | 1 -
.../reagents/reagent_containers/spray.dm | 5 +--
6 files changed, 23 insertions(+), 26 deletions(-)
rename code/modules/projectiles/guns/{ballistic => energy}/laser_gatling.dm (99%)
diff --git a/code/__HELPERS/yelling.dm b/code/__HELPERS/yelling.dm
index e9a2697c87..cf8ca52417 100644
--- a/code/__HELPERS/yelling.dm
+++ b/code/__HELPERS/yelling.dm
@@ -6,7 +6,7 @@
stop = TRUE
return ..()
-/datum/yelling_wavefill/proc/run(atom/source, dist = 50)
+/datum/yelling_wavefill/proc/run_wavefill(atom/source, dist = 50)
collected = list()
do_run(source, dist)
// gc
@@ -14,6 +14,7 @@
collected = null
// blatantly copied from wave explosion code
+// check explosion2.dm for what this does and how it works.
/datum/yelling_wavefill/proc/do_run(atom/source, dist)
var/list/edges = list(source = (NORTH|SOUTH|EAST|WEST))
var/list/powers = list(source = dist)
@@ -34,24 +35,8 @@
var/list/turf/diagonal_powers = list()
var/list/turf/diagonal_powers_max = list()
- while(edges.len)
- // process cardinals
- for(var/i in edges)
- T = i
- power = powers[T]
- dir = edges[T]
- RUN_YELL(T, power, dir)
- powers_returned[T] = returned
- if(returned)
- // get hearing atoms
- else
- continue
-
- // diagonal power calc when multiple things hit one diagonal
#define CALCULATE_DIAGONAL_POWER(existing, adding, maximum) min(maximum, existing + adding)
- // diagonal hitting cardinal expansion
#define CALCULATE_DIAGONAL_CROSS_POWER(existing, adding) max(existing, adding)
- // insanity define to mark the next set of cardinals.
#define CARDINAL_MARK(ndir, cdir, edir) \
if(edir & cdir) { \
expanding = get_step(T,ndir); \
@@ -79,6 +64,22 @@
DIAGONAL_SUBSTEP(turn(ndir, 90), turn(cdir, 90), edir); \
DIAGONAL_SUBSTEP(turn(ndir, -90), turn(cdir, -90), edir); \
};
+
+ while(edges.len)
+ // to_chat(world, "DEBUG: cycle start edges [english_list_assoc(edges)]")
+
+ // process cardinals
+ for(var/i in edges)
+ T = i
+ power = powers[T]
+ dir = edges[T]
+ RUN_YELL(T, power, dir)
+ powers_returned[T] = returned
+ if(returned)
+ // get hearing atoms
+ else
+ continue
+
CARDINAL_MARK(NORTH, NORTH, dir)
CARDINAL_MARK(SOUTH, SOUTH, dir)
CARDINAL_MARK(EAST, EAST, dir)
@@ -129,6 +130,6 @@
/proc/yelling_wavefill(atom/source, dist = 50)
var/datum/yelling_wavefill/Y = new
- Y.run(source, dist)
+ Y.run_wavefill(source, dist)
return Y.collected || list()
diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm
index fff971c953..777f1bfc3b 100644
--- a/code/modules/mining/equipment/survival_pod.dm
+++ b/code/modules/mining/equipment/survival_pod.dm
@@ -299,7 +299,7 @@
/obj/item/energy_katana,
/obj/item/hierophant_club,
/obj/item/his_grace,
- /obj/item/gun/ballistic/minigun,
+ /obj/item/gun/energy/minigun,
/obj/item/gun/ballistic/automatic/l6_saw,
/obj/item/gun/magic/staff/chaos,
/obj/item/gun/magic/staff/spellblade,
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index 32bc5fd59d..57866bacbe 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -230,7 +230,6 @@
var/list/determined = determine_parry_method(TRUE, TRUE)
if(!islist(determined))
return FALSE
- var/method = determined[1]
var/datum/block_parry_data/data = return_block_parry_datum(determined[2])
if(!data.parry_automatic_enabled)
return FALSE
diff --git a/code/modules/projectiles/ammunition/energy/stun.dm b/code/modules/projectiles/ammunition/energy/stun.dm
index aa889c10bf..cb7f80d949 100644
--- a/code/modules/projectiles/ammunition/energy/stun.dm
+++ b/code/modules/projectiles/ammunition/energy/stun.dm
@@ -10,7 +10,7 @@
e_cost = 100
/obj/item/ammo_casing/energy/electrode/hos
- projectile_type = /obj/item/projectile/energy/electrode/hos
+ projectile_type = /obj/item/projectile/energy/electrode/security/hos
e_cost = 100
/obj/item/ammo_casing/energy/electrode/spec
@@ -20,7 +20,6 @@
fire_sound = 'sound/weapons/gunshot.ogg'
e_cost = 100
-
/obj/item/ammo_casing/energy/electrode/old
e_cost = 1000
diff --git a/code/modules/projectiles/guns/ballistic/laser_gatling.dm b/code/modules/projectiles/guns/energy/laser_gatling.dm
similarity index 99%
rename from code/modules/projectiles/guns/ballistic/laser_gatling.dm
rename to code/modules/projectiles/guns/energy/laser_gatling.dm
index 2abb7b720f..716cc6f31d 100644
--- a/code/modules/projectiles/guns/ballistic/laser_gatling.dm
+++ b/code/modules/projectiles/guns/energy/laser_gatling.dm
@@ -90,7 +90,6 @@
update_icon()
user.update_inv_back()
-
/obj/item/gun/energy/minigun
name = "laser gatling gun"
desc = "An advanced laser cannon with an incredible rate of fire. Requires a bulky backpack power source to use."
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index 3f62829b32..de4151a82d 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -76,6 +76,8 @@
var/wait_step = CEILING(spray_delay * INVERSE(range), world.tick_lag)
var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src), stream_mode, wait_step, range, stream_mode? 1 : range)
var/turf/T = get_turf(src)
+ if(!T)
+ return
log_reagent("SPRAY: [key_name(usr)] fired [src] ([REF(src)]) [COORD(T)] at [A] ([REF(A)]) [COORD(A)] (chempuff: [D.reagents.log_list()])")
D.create_reagents(amount_per_transfer_from_this, NONE, NO_REAGENTS_VALUE)
if(stream_mode)
@@ -83,9 +85,6 @@
else
reagents.trans_to(D, amount_per_transfer_from_this, 1/range)
D.color = mix_color_from_reagents(D.reagents.reagent_list)
- var/turf/T = get_turf(src)
- if(!T)
- return
last_spray = world.time
D.run(A)
From d547aa7ff1db5cb955dea4d36f82e9eb49c07ea9 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Mon, 26 Apr 2021 23:37:26 -0700
Subject: [PATCH 28/43] almost compiling
---
code/__HELPERS/yelling.dm | 2 +-
code/game/objects/effects/decals/misc.dm | 2 +-
code/modules/reagents/reagent_containers/spray.dm | 2 +-
tgstation.dme | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/code/__HELPERS/yelling.dm b/code/__HELPERS/yelling.dm
index cf8ca52417..d4d6e5ac95 100644
--- a/code/__HELPERS/yelling.dm
+++ b/code/__HELPERS/yelling.dm
@@ -25,7 +25,7 @@
var/dir
var/returned
#define RUN_YELL(_T, _P, _D) \
- returned = max(powers[_T] - _T.get_yelling_resistance() - 1, 0); \
+ returned = max(_P - _T.get_yelling_resistance() - 1, 0); \
_T.maptext = "[returned]";
var/list/turf/edges_next = list()
diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm
index 7ed90253c8..6b90cfd62c 100644
--- a/code/game/objects/effects/decals/misc.dm
+++ b/code/game/objects/effects/decals/misc.dm
@@ -58,7 +58,7 @@
. = ..()
hit_thing(AM)
-/obj/effect/decal/chempuff/proc/run(atom/target)
+/obj/effect/decal/chempuff/proc/run_puff(atom/target)
set waitfor = FALSE
for(var/i in 1 to range)
range_left--
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index de4151a82d..b90815d543 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -86,7 +86,7 @@
reagents.trans_to(D, amount_per_transfer_from_this, 1/range)
D.color = mix_color_from_reagents(D.reagents.reagent_list)
last_spray = world.time
- D.run(A)
+ D.run_puff(A)
/obj/item/reagent_containers/spray/attack_self(mob/user)
stream_mode = !stream_mode
diff --git a/tgstation.dme b/tgstation.dme
index 30229b1cda..f7069d4783 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -3111,7 +3111,6 @@
#include "code\modules\projectiles\guns\ballistic\automatic.dm"
#include "code\modules\projectiles\guns\ballistic\bow.dm"
#include "code\modules\projectiles\guns\ballistic\derringer.dm"
-#include "code\modules\projectiles\guns\ballistic\laser_gatling.dm"
#include "code\modules\projectiles\guns\ballistic\launchers.dm"
#include "code\modules\projectiles\guns\ballistic\magweapon.dm"
#include "code\modules\projectiles\guns\ballistic\pistol.dm"
@@ -3122,6 +3121,7 @@
#include "code\modules\projectiles\guns\energy\energy_gun.dm"
#include "code\modules\projectiles\guns\energy\kinetic_accelerator.dm"
#include "code\modules\projectiles\guns\energy\laser.dm"
+#include "code\modules\projectiles\guns\energy\laser_gatling.dm"
#include "code\modules\projectiles\guns\energy\megabuster.dm"
#include "code\modules\projectiles\guns\energy\mounted.dm"
#include "code\modules\projectiles\guns\energy\plasma_cit.dm"
From a60f801f69c1031bbf4cc38a326c06fa7579e803 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Wed, 12 May 2021 04:23:53 -0700
Subject: [PATCH 29/43] e
---
code/modules/mob/living/living_active_parry.dm | 3 ++-
code/modules/mob/living/living_blocking_parrying.dm | 4 ----
code/modules/mob/living/living_defines.dm | 2 ++
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index 57866bacbe..d8f5edefb8 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -231,7 +231,7 @@
if(!islist(determined))
return FALSE
var/datum/block_parry_data/data = return_block_parry_datum(determined[2])
- if(!data.parry_automatic_enabled)
+ if(!data.parry_automatic_enabled || (last_autoparry > (world.time + data.autoparry_cooldown_absolute)))
return FALSE
// before doing anything, check if the user moused over them properly
if(!client)
@@ -249,6 +249,7 @@
// first, check cooldowns
// now, depending on if we're doing a single simulation or a full sequence
+ last_autoparry = world.time
if(data.autoparry_sequence_simulation)
// for full sequence simulation
initiate_parry_sequence(TRUE, determined)
diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm
index 453f521575..d32ef5a2ac 100644
--- a/code/modules/mob/living/living_blocking_parrying.dm
+++ b/code/modules/mob/living/living_blocking_parrying.dm
@@ -189,10 +189,6 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// 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 = 75
/// Single attack autoparry - efficiency overrides by attack type, see above
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 14acf72f57..94f4ff60a3 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -50,6 +50,8 @@
var/obj/effect/abstract/parry/parry_visual_effect
/// world.time of last parry end
var/parry_end_time_last = 0
+ /// Last autoparry
+ var/last_autoparry = 0
/// Successful parries within the current parry cycle. It's a list of efficiency percentages.
var/list/successful_parries
/// Current parry counterattacks. Makes sure we can only counterattack someone once per parry.
From 2d763a9ab307c9f2ed382a485da7819f881bdf8b Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Mon, 7 Jun 2021 16:37:19 -0700
Subject: [PATCH 30/43] auto
---
code/modules/mob/living/living_active_parry.dm | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index d8f5edefb8..2b4b0ecbac 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -229,13 +229,13 @@
// determine how we'll parry
var/list/determined = determine_parry_method(TRUE, TRUE)
if(!islist(determined))
- return FALSE
+ return BLOCK_NONE
var/datum/block_parry_data/data = return_block_parry_datum(determined[2])
if(!data.parry_automatic_enabled || (last_autoparry > (world.time + data.autoparry_cooldown_absolute)))
- return FALSE
+ return BLOCK_NONE
// before doing anything, check if the user moused over them properly
if(!client)
- return FALSE
+ return BLOCK_NONE
var/found = FALSE
for(var/i in client.moused_over_objects)
if(i == object)
@@ -243,7 +243,7 @@
found = TRUE
break
if(!found)
- return FALSE
+ return BLOCK_NONE
// if that works, try to start parry
// first, check cooldowns
@@ -257,7 +257,8 @@
parry_start_time = world.time - data.parry_time_windup
else
parry_start_time = world.time - data.autoparry_sequence_start_time
- return TRUE
+ // recurse back to original
+ return run_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, FALSE)
else
// for single attack block
#warn single attack block
@@ -300,8 +301,8 @@
if(stage != PARRY_ACTIVE)
// If they're not currently parrying, attempt auto parry
if(stage == NOT_PARRYING)
- if(!allow_auto || SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE) || !attempt_auto_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list))
- return BLOCK_NONE
+ if(!allow_auto || SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
+ return attempt_auto_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)
else
return BLOCK_NONE
var/datum/block_parry_data/data = get_parry_data()
From d67c4d9fa889da263c8baca1c8037fbdc21e94fc Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Mon, 7 Jun 2021 16:45:51 -0700
Subject: [PATCH 31/43] hacky
---
.../modules/mob/living/living_active_parry.dm | 67 ++++++++++++++++---
1 file changed, 57 insertions(+), 10 deletions(-)
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index 2b4b0ecbac..b0e1f7d9ef 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -195,17 +195,17 @@
/**
* Called when an attack is parried using this, whether or not the parry was successful.
*/
-/obj/item/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
+/obj/item/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time, autoparry = FALSE)
/**
* Called when an attack is parried innately, whether or not the parry was successful.
*/
-/mob/living/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
+/mob/living/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time, autoparry = FALSE)
/**
* Called when an attack is parried using this, whether or not the parry was successful.
*/
-/datum/martial_art/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
+/datum/martial_art/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time, autoparry = FALSE)
/**
* Called when an attack is parried and block_parra_data indicates to use a proc to handle counterattack.
@@ -233,6 +233,8 @@
var/datum/block_parry_data/data = return_block_parry_datum(determined[2])
if(!data.parry_automatic_enabled || (last_autoparry > (world.time + data.autoparry_cooldown_absolute)))
return BLOCK_NONE
+ if(attack_type && !(attack_type & data.parry_attack_types))
+ return BLOCK_NONE
// before doing anything, check if the user moused over them properly
if(!client)
return BLOCK_NONE
@@ -260,9 +262,52 @@
// recurse back to original
return run_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, FALSE)
else
- // for single attack block
- #warn single attack block
- return FALSE
+ // yes, this is mostly a copypaste of run_parry.
+ var/efficiency = data.attack_type_list_scan(data.autoparry_single_efficiency_override, attack_type)
+ if(isnull(efficiency))
+ efficiency = data.autoparry_single_efficiency
+ var/method = determined[1]
+ switch(parrying)
+ if(ITEM_PARRY)
+ var/obj/item/I = determined[3]
+ . = I.on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, null, TRUE)
+ if(UNARMED_PARRY)
+ . = on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, null, TRUE)
+ if(MARTIAL_PARRY)
+ . = mind.martial_art.on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, null, TRUE)
+ if(!isnull(return_list[BLOCK_RETURN_OVERRIDE_PARRY_EFFICIENCY])) // one of our procs overrode
+ efficiency = return_list[BLOCK_RETURN_OVERRIDE_PARRY_EFFICIENCY]
+ if(efficiency <= 0) // Do not allow automatically handled/standardized parries that increase damage for now.
+ return
+ . |= BLOCK_SHOULD_PARTIAL_MITIGATE
+ if(efficiency >= data.parry_efficiency_perfect)
+ . |= data.perfect_parry_block_return_flags
+ if(data.perfect_parry_block_return_list)
+ return_list |= data.perfect_parry_block_return_list
+ else if(efficiency >= data.parry_efficiency_considered_successful)
+ . |= data.imperfect_parry_block_return_flags
+ if(data.imperfect_parry_block_return_list)
+ return_list |= data.imperfect_parry_block_return_list
+ else
+ . |= data.failed_parry_block_return_flags
+ if(data.failed_parry_block_return_list)
+ return_list |= data.failed_parry_block_return_list
+ if(isnull(return_list[BLOCK_RETURN_MITIGATION_PERCENT])) // if one of the on_active_parry procs overrode. We don't have to worry about interference since parries are the first thing checked in the [do_run_block()] sequence.
+ return_list[BLOCK_RETURN_MITIGATION_PERCENT] = clamp(efficiency, 0, 100) // do not allow > 100% or < 0% for now.
+ if((return_list[BLOCK_RETURN_MITIGATION_PERCENT] >= 100) || (damage <= 0))
+ . |= BLOCK_SUCCESS
+ var/list/effect_text
+ var/pacifist_counter_check = TRUE
+ if(HAS_TRAIT(src, TRAIT_PACIFISM))
+ switch(parrying)
+ if(ITEM_PARRY)
+ pacifist_counter_check = (!active_parry_item.force || active_parry_item.damtype == STAMINA)
+ else
+ pacifist_counter_check = FALSE //Both martial and unarmed counter attacks generally are harmful, so no need to have the same line twice.
+ if(efficiency >= data.parry_efficiency_to_counterattack && pacifist_counter_check && !return_list[BLOCK_RETURN_FORCE_NO_PARRY_COUNTERATTACK] && (!(attacker in successful_parry_counterattacks) && !data.parry_allow_repeated_counterattacks))
+ effect_text = run_parry_countereffects(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, data)
+ if(data.parry_flags & PARRY_DEFAULT_HANDLE_FEEDBACK)
+ handle_parry_feedback(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, effect_text)
/**
* Gets the stage of our parry sequence we're currently in.
@@ -355,8 +400,9 @@
if(length(successful_parries) >= data.parry_max_attacks)
end_parry_sequence()
-/mob/living/proc/handle_parry_feedback(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency, list/effect_text)
- var/datum/block_parry_data/data = get_parry_data()
+/mob/living/proc/handle_parry_feedback(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency, list/effect_text, datum/block_parry_data/data)
+ if(!data)
+ data = get_parry_data()
var/knockdown_check = FALSE
if(data.parry_data[PARRY_KNOCKDOWN_ATTACKER] && parry_efficiency >= data.parry_efficiency_to_counterattack)
knockdown_check = TRUE
@@ -365,11 +411,12 @@
visible_message("[src] parries [attack_text][length(effect_text)? ", [english_list(effect_text)] [attacker]" : ""][length(effect_text) && knockdown_check? " and" : ""][knockdown_check? " knocking them to the ground" : ""]!")
/// 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(), parry_efficiency)
+/mob/living/proc/run_parry_countereffects(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency, datum/block_parry_data/data)
if(!isliving(attacker))
return
var/mob/living/L = attacker
- var/datum/block_parry_data/data = get_parry_data()
+ if(!data)
+ data = get_parry_data()
var/list/effect_text = list()
successful_parry_counterattacks |= attacker
// Always proc so items can override behavior easily
From b3382a8fe22351d10b0bddb77af3fea784d09f2c Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Mon, 7 Jun 2021 16:49:27 -0700
Subject: [PATCH 32/43] local testing time
---
code/__HELPERS/yelling.dm | 2 ++
code/datums/explosion2.dm | 4 ++++
2 files changed, 6 insertions(+)
diff --git a/code/__HELPERS/yelling.dm b/code/__HELPERS/yelling.dm
index d4d6e5ac95..6fc9cd7846 100644
--- a/code/__HELPERS/yelling.dm
+++ b/code/__HELPERS/yelling.dm
@@ -125,6 +125,8 @@
#undef RUN_YELL
#undef DIAGONAL_SUBSTEP
+#undef CALCULATE_DIAGONAL_POWER
+#undef CALCULATE_DIAGONAL_CROSS_POWER
#undef DIAGONAL_MARK
#undef CARDINAL_MARK
diff --git a/code/datums/explosion2.dm b/code/datums/explosion2.dm
index 75f65e4b23..9a9f2b40cf 100644
--- a/code/datums/explosion2.dm
+++ b/code/datums/explosion2.dm
@@ -372,6 +372,10 @@
#undef WEX_ACT
+#undef CALCULATE_DIAGONAL_POWER
+#undef CALCULATE_DIAGONAL_CROSS_POWER
+#undef CARDINAL_MARK_NOCHECK
+
#undef DIAGONAL_SUBSTEP
#undef DIAGONAL_MARK
#undef CARDINAL_MARK
From 1a800cc470e3e8e469549e1abdfba708e6d96be8 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Mon, 7 Jun 2021 19:40:16 -0700
Subject: [PATCH 33/43] modifications
---
code/__HELPERS/yelling.dm | 6 ++++--
code/game/objects/items/dualsaber.dm | 2 --
code/game/objects/items/electrostaff.dm | 1 -
code/game/objects/items/melee/energy.dm | 3 +++
code/game/objects/items/melee/misc.dm | 1 -
code/game/objects/items/shields.dm | 7 +++++--
code/game/objects/items/weaponry.dm | 2 --
.../clock_weapons/ratvarian_spear.dm | 1 -
code/modules/clothing/gloves/miscellaneous.dm | 5 ++---
.../mining/equipment/kinetic_crusher.dm | 1 -
code/modules/mob/living/living_active_parry.dm | 18 ++++++++++--------
.../mob/living/living_blocking_parrying.dm | 6 +++---
code/modules/smithing/finished_items.dm | 3 ++-
13 files changed, 29 insertions(+), 27 deletions(-)
diff --git a/code/__HELPERS/yelling.dm b/code/__HELPERS/yelling.dm
index 6fc9cd7846..6987aef262 100644
--- a/code/__HELPERS/yelling.dm
+++ b/code/__HELPERS/yelling.dm
@@ -16,8 +16,10 @@
// blatantly copied from wave explosion code
// check explosion2.dm for what this does and how it works.
/datum/yelling_wavefill/proc/do_run(atom/source, dist)
- var/list/edges = list(source = (NORTH|SOUTH|EAST|WEST))
- var/list/powers = list(source = dist)
+ var/list/edges = list()
+ edges[source] = (NORTH|SOUTH|EAST|WEST)
+ var/list/powers = list()
+ powers[source] = dist
var/list/processed_last = list()
var/turf/T
var/turf/expanding
diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm
index 5ae79b3c3a..eea189c3be 100644
--- a/code/game/objects/items/dualsaber.dm
+++ b/code/game/objects/items/dualsaber.dm
@@ -71,7 +71,6 @@
parry_imperfect_falloff_percent = 10
parry_efficiency_considered_successful = 25 // VERY generous
parry_failed_stagger_duration = 3 SECONDS
- parry_failed_clickcd_duration = CLICK_CD_MELEE
/obj/item/dualsaber/directional_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction)
if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object))
@@ -374,7 +373,6 @@
TEXT_ATTACK_TYPE_PROJECTILE = 30,
)
parry_failed_stagger_duration = 3 SECONDS
- parry_failed_clickcd_duration = 2 SECONDS
/obj/item/dualsaber/hypereutactic/chaplain/ComponentInitialize()
. = ..()
diff --git a/code/game/objects/items/electrostaff.dm b/code/game/objects/items/electrostaff.dm
index 2828841b22..9bb12d18b8 100644
--- a/code/game/objects/items/electrostaff.dm
+++ b/code/game/objects/items/electrostaff.dm
@@ -62,7 +62,6 @@
)
// not extremely punishing to fail, but no spamming the parry.
parry_failed_stagger_duration = 1.5 SECONDS
- parry_failed_clickcd_duration = 1 SECONDS
/obj/item/electrostaff/Initialize(mapload)
. = ..()
diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm
index f1201dca4f..1be570b62b 100644
--- a/code/game/objects/items/melee/energy.dm
+++ b/code/game/objects/items/melee/energy.dm
@@ -126,6 +126,9 @@
parry_efficiency_perfect = 100
parry_failed_stagger_duration = 4 SECONDS
parry_cooldown = 0.5 SECONDS
+ parry_automatic_enabled = TRUE
+ autoparry_single_efficiency = 65
+ autoparry_cooldown_absolute = 3 SECONDS
/obj/item/melee/transforming/energy/sword/Initialize(mapload)
. = ..()
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index a981ad98a0..6278eb5f36 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -194,7 +194,6 @@
parry_efficiency_perfect = 100
parry_stamina_cost = 5
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)
diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm
index d5b3674564..9aed545509 100644
--- a/code/game/objects/items/shields.dm
+++ b/code/game/objects/items/shields.dm
@@ -34,6 +34,10 @@
block_damage_absorption = 5
block_resting_stamina_penalty_multiplier = 2
block_projectile_mitigation = 75
+ block_damage_absorption_override = list(
+ TEXT_ATTACK_TYPE_TACKLE = INFINITY,
+ TEXT_ATTACK_TYPE_THROWN = 10
+ )
/obj/item/shield/examine(mob/user)
. = ..()
@@ -374,11 +378,10 @@
/obj/item/shield/riot/flash/on_shield_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
. = ..()
- if (. && !embedded_flash.crit_fail)
+ if (. && damage && !embedded_flash.crit_fail)
embedded_flash.activate()
update_icon()
-
/obj/item/shield/riot/flash/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/assembly/flash/handheld))
var/obj/item/assembly/flash/handheld/flash = W
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index 4ee9427ec8..37bdc33659 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -364,7 +364,6 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
parry_time_perfect = 2.5 // however...
parry_time_perfect_leeway = 2 // the entire time, the parry is perfect
parry_failed_stagger_duration = 1 SECONDS
- parry_failed_clickcd_duration = 1 SECONDS // more forgiving punishments for missed parries
// still, don't fucking miss your parries or you're down stamina and staggered to shit
/datum/block_parry_data/bokken/quick_parry/proj
@@ -481,7 +480,6 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
parry_time_perfect = 1
parry_time_perfect_leeway = 1
parry_failed_stagger_duration = 1 SECONDS
- parry_failed_clickcd_duration = 1 SECONDS
/datum/block_parry_data/bokken/waki/quick_parry/proj
parry_efficiency_perfect_override = list()
diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
index d0f63ac887..b702b19566 100644
--- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
+++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
@@ -93,4 +93,3 @@
parry_efficiency_to_counterattack = 110
parry_cooldown = 15 //But also very low cooldown..
parry_failed_stagger_duration = 2 SECONDS //And relatively small penalties for failing.
- parry_failed_clickcd_duration = 1 SECONDS
diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm
index a337439931..d96ded67d2 100644
--- a/code/modules/clothing/gloves/miscellaneous.dm
+++ b/code/modules/clothing/gloves/miscellaneous.dm
@@ -224,10 +224,9 @@
parry_efficiency_considered_successful = 0.01
parry_efficiency_to_counterattack = INFINITY // no auto counter
parry_max_attacks = INFINITY
- parry_failed_cooldown_duration = 2.25 SECONDS
- parry_failed_stagger_duration = 2.25 SECONDS
+ parry_failed_cooldown_duration = 1.5 SECONDS
+ parry_failed_stagger_duration = 1.5 SECONDS
parry_cooldown = 0
- parry_failed_clickcd_duration = 0
/obj/item/clothing/gloves/fingerless/pugilist/mauler
name = "mauler gauntlets"
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
index 859ea58d26..ddec9232ce 100644
--- a/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -196,7 +196,6 @@
parry_imperfect_falloff_percent = 20
parry_efficiency_to_counterattack = 100 // perfect parry or you're cringe
parry_failed_stagger_duration = 1.5 SECONDS // a good time to reconsider your actions...
- parry_failed_clickcd_duration = 1.5 SECONDS // or your failures
/obj/item/kinetic_crusher/glaive/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time) // if you're dumb enough to go for a parry...
var/turf/proj_turf = owner.loc // destabilizer bolt, ignoring cooldown
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index b0e1f7d9ef..a673b81203 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -238,12 +238,13 @@
// before doing anything, check if the user moused over them properly
if(!client)
return BLOCK_NONE
- var/found = FALSE
- for(var/i in client.moused_over_objects)
- if(i == object)
- if((client.moused_over_objects[i] + (data.autoparry_mouse_delay_maximum SECONDS)) >= world.time)
- found = TRUE
- break
+ var/found = attacker == client.mouseObject
+ if(!found)
+ for(var/i in client.moused_over_objects)
+ if(i == object)
+ if((client.moused_over_objects[i] + (data.autoparry_mouse_delay_maximum)) >= world.time)
+ found = TRUE
+ break
if(!found)
return BLOCK_NONE
@@ -267,7 +268,7 @@
if(isnull(efficiency))
efficiency = data.autoparry_single_efficiency
var/method = determined[1]
- switch(parrying)
+ switch(method)
if(ITEM_PARRY)
var/obj/item/I = determined[3]
. = I.on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, null, TRUE)
@@ -347,7 +348,8 @@
// If they're not currently parrying, attempt auto parry
if(stage == NOT_PARRYING)
if(!allow_auto || SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
- return attempt_auto_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)
+ return BLOCK_NONE
+ return attempt_auto_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)
else
return BLOCK_NONE
var/datum/block_parry_data/data = get_parry_data()
diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm
index d32ef5a2ac..3a828e0c81 100644
--- a/code/modules/mob/living/living_blocking_parrying.dm
+++ b/code/modules/mob/living/living_blocking_parrying.dm
@@ -108,7 +108,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Priority for [mob/do_run_block()] while we're being used to parry.
// None - Parry is always highest priority!
/// Parry doesn't work if you aren't able to otherwise attack due to clickdelay
- var/parry_respect_clickdelay = TRUE
+ var/parry_respect_clickdelay = FALSE
/// Parry stamina cost
var/parry_stamina_cost = 5
/// Attack types we can block
@@ -164,7 +164,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Stagger duration post-parry if you fail to parry an attack
var/parry_failed_stagger_duration = 3.5 SECONDS
/// Clickdelay duration post-parry if you fail to parry an attack
- var/parry_failed_clickcd_duration = 2 SECONDS
+ var/parry_failed_clickcd_duration = 0 SECONDS
/// Parry cooldown post-parry if failed. This is ADDED to parry_cooldown!!!
var/parry_failed_cooldown_duration = 0 SECONDS
@@ -199,7 +199,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
// Clickdelay/cooldown settings not included, as well as whether or not to lock attack/sprinting/etc. They will be pulled from the above.
/// ADVANCED - Autoparry requirement for time since last moused over for a specific object
- var/autoparry_mouse_delay_maximum = 0.5
+ var/autoparry_mouse_delay_maximum = 0.5 SECONDS
/**
* Quirky proc to get average of flags in list that are in attack_type because why is attack_type a flag.
diff --git a/code/modules/smithing/finished_items.dm b/code/modules/smithing/finished_items.dm
index 06953f462c..27be8c034d 100644
--- a/code/modules/smithing/finished_items.dm
+++ b/code/modules/smithing/finished_items.dm
@@ -266,7 +266,6 @@
parry_time_perfect = 2
parry_time_perfect_leeway = 2
parry_failed_stagger_duration = 3 SECONDS
- parry_failed_clickcd_duration = 3 SECONDS
parry_time_windup = 0
parry_time_spindown = 0
parry_imperfect_falloff_percent = 0
@@ -274,6 +273,8 @@
parry_efficiency_considered_successful = 120
parry_efficiency_perfect = 120
parry_data = list(PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 4)
+ parry_automatic_enabled = TRUE
+ autoparry_single_efficiency = 75
//unique hammers
/obj/item/melee/smith/hammer/toolbox
From 2f9492945d9c5e5d0ad23ad9dd586616479f68db Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Mon, 7 Jun 2021 19:45:58 -0700
Subject: [PATCH 34/43] sigh
---
code/__HELPERS/yelling.dm | 1 +
1 file changed, 1 insertion(+)
diff --git a/code/__HELPERS/yelling.dm b/code/__HELPERS/yelling.dm
index 6987aef262..2dc2d0aec6 100644
--- a/code/__HELPERS/yelling.dm
+++ b/code/__HELPERS/yelling.dm
@@ -16,6 +16,7 @@
// blatantly copied from wave explosion code
// check explosion2.dm for what this does and how it works.
/datum/yelling_wavefill/proc/do_run(atom/source, dist)
+ source = get_turf(source)
var/list/edges = list()
edges[source] = (NORTH|SOUTH|EAST|WEST)
var/list/powers = list()
From b6bb20842fe2ad29249647171cb58260b92a8156 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 13 Jun 2021 00:50:00 -0700
Subject: [PATCH 35/43] Yelling works
---
code/__HELPERS/yelling.dm | 42 +++++++++++--------
code/datums/explosion2.dm | 31 ++++----------
code/game/atoms_movable.dm | 2 +
code/game/turfs/closed.dm | 8 ++--
code/game/turfs/turf.dm | 2 +-
.../mob/living/living_blocking_parrying.dm | 2 +-
code/modules/mob/living/say.dm | 2 +-
7 files changed, 44 insertions(+), 45 deletions(-)
diff --git a/code/__HELPERS/yelling.dm b/code/__HELPERS/yelling.dm
index 2dc2d0aec6..7fec64c276 100644
--- a/code/__HELPERS/yelling.dm
+++ b/code/__HELPERS/yelling.dm
@@ -19,6 +19,7 @@
source = get_turf(source)
var/list/edges = list()
edges[source] = (NORTH|SOUTH|EAST|WEST)
+ collected += typecache_filter_list(source.contents, GLOB.typecache_living)
var/list/powers = list()
powers[source] = dist
var/list/processed_last = list()
@@ -28,22 +29,23 @@
var/dir
var/returned
#define RUN_YELL(_T, _P, _D) \
- returned = max(_P - _T.get_yelling_resistance() - 1, 0); \
- _T.maptext = "[returned]";
+ returned = max(_P - max(_T.get_yelling_resistance(_P), 0) - 1, 0);
+ // _T.maptext = "[returned]";
- var/list/turf/edges_next = list()
- var/list/turf/powers_next = list()
- var/list/turf/powers_returned = list()
- var/list/turf/diagonals = list()
- var/list/turf/diagonal_powers = list()
- var/list/turf/diagonal_powers_max = list()
+ var/list/turf/edges_next
+ var/list/turf/powers_next
+ var/list/turf/powers_returned
+ var/list/turf/diagonals
+ var/list/turf/diagonal_powers
+ var/list/turf/diagonal_powers_max
+ var/safety = 1000
#define CALCULATE_DIAGONAL_POWER(existing, adding, maximum) min(maximum, existing + adding)
#define CALCULATE_DIAGONAL_CROSS_POWER(existing, adding) max(existing, adding)
#define CARDINAL_MARK(ndir, cdir, edir) \
if(edir & cdir) { \
expanding = get_step(T,ndir); \
- if(expanding && !processed_last[expanding] && !edges[expanding]) { \
+ if(expanding && isnull(processed_last[expanding]) && isnull(edges[expanding])) { \
powers_next[expanding] = max(powers_next[expanding], returned); \
edges_next[expanding] = (cdir | edges_next[expanding]); \
}; \
@@ -51,7 +53,7 @@
#define DIAGONAL_SUBSTEP(ndir, cdir, edir) \
expanding = get_step(T,ndir); \
- if(expanding && !processed_last[expanding] && !edges[expanding]) { \
+ if(expanding && isnull(processed_last[expanding]) && isnull(edges[expanding])) { \
if(!edges_next[expanding]) { \
diagonal_powers_max[expanding] = max(diagonal_powers_max[expanding], returned, powers[T]); \
diagonal_powers[expanding] = CALCULATE_DIAGONAL_POWER(diagonal_powers[expanding], returned, diagonal_powers_max[expanding]); \
@@ -69,6 +71,12 @@
};
while(edges.len)
+ edges_next = list()
+ powers_next = list()
+ powers_returned = list()
+ diagonals = list()
+ diagonal_powers = list()
+ diagonal_powers_max = list()
// to_chat(world, "DEBUG: cycle start edges [english_list_assoc(edges)]")
// process cardinals
@@ -78,8 +86,8 @@
dir = edges[T]
RUN_YELL(T, power, dir)
powers_returned[T] = returned
- if(returned)
- // get hearing atoms
+ if(returned >= 1)
+ collected |= typecache_filter_list(T.contents, GLOB.typecache_living)
else
continue
@@ -87,7 +95,6 @@
CARDINAL_MARK(SOUTH, SOUTH, dir)
CARDINAL_MARK(EAST, EAST, dir)
CARDINAL_MARK(WEST, WEST, dir)
- CHECK_TICK
// to_chat(world, "DEBUG: cycle mid edges_next [english_list_assoc(edges_next)]")
@@ -101,7 +108,6 @@
DIAGONAL_MARK(SOUTH, SOUTH, dir)
DIAGONAL_MARK(EAST, EAST, dir)
DIAGONAL_MARK(WEST, WEST, dir)
- CHECK_TICK
// to_chat(world, "DEBUG: cycle mid diagonals [english_list_assoc(diagonals)]")
@@ -111,13 +117,12 @@
power = diagonal_powers[T]
dir = diagonals[T]
RUN_YELL(T, power, dir)
- if(!returned)
+ if(returned < 1)
continue
CARDINAL_MARK(NORTH, NORTH, dir)
CARDINAL_MARK(SOUTH, SOUTH, dir)
CARDINAL_MARK(EAST, EAST, dir)
CARDINAL_MARK(WEST, WEST, dir)
- CHECK_TICK
// to_chat(world, "DEBUG: cycle end edges_next [english_list_assoc(edges_next)]")
@@ -126,6 +131,10 @@
edges = edges_next
powers = powers_next
+ // sleep(2.5)
+ if(!--safety)
+ CRASH("Yelling ran out of safety.")
+
#undef RUN_YELL
#undef DIAGONAL_SUBSTEP
#undef CALCULATE_DIAGONAL_POWER
@@ -137,4 +146,3 @@
var/datum/yelling_wavefill/Y = new
Y.run_wavefill(source, dist)
return Y.collected || list()
-
diff --git a/code/datums/explosion2.dm b/code/datums/explosion2.dm
index 9a9f2b40cf..d3429bdebe 100644
--- a/code/datums/explosion2.dm
+++ b/code/datums/explosion2.dm
@@ -283,14 +283,11 @@
// insanity define to mark the next set of cardinals.
#define CARDINAL_MARK(ndir, cdir, edir) \
if(edir & cdir) { \
- CARDINAL_MARK_NOCHECK(ndir, cdir, edir); \
- };
-
-#define CARDINAL_MARK_NOCHECK(ndir, cdir, edir) \
- expanding = get_step(T,ndir); \
- if(expanding && !exploded_last[expanding] && !edges[expanding]) { \
- powers_next[expanding] = max(powers_next[expanding], returned); \
- edges_next[expanding] = (cdir | edges_next[expanding]); \
+ expanding = get_step(T,ndir); \
+ if(expanding && !exploded_last[expanding] && !edges[expanding]) { \
+ powers_next[expanding] = max(powers_next[expanding], returned); \
+ edges_next[expanding] = (cdir | edges_next[expanding]); \
+ }; \
};
// insanity define to do diagonal marking as 2 substeps
@@ -308,24 +305,15 @@
};
// insanity define to mark the diagonals that would otherwise be missed
-#define DIAGONAL_MARK(ndir, cdir, edir) \
- if(edir & cdir) { \
- DIAGONAL_MARK_NOCHECK(ndir, cdir, edir); \
- };
-
// this only works because right now, WEX_DIR_X is the same as a byond dir
// and we know we're only passing in one dir at a time.
// if this ever stops being the case, and explosions break when you touch this, now you know why.
-#define DIAGONAL_MARK_NOCHECK(ndir, cdir, edir) \
- DIAGONAL_SUBSTEP(turn(ndir, 90), turn(cdir, 90), edir); \
- DIAGONAL_SUBSTEP(turn(ndir, -90), turn(cdir, -90), edir);
-
- // mark
-#define MARK(ndir, cdir, edir) \
+#define DIAGONAL_MARK(ndir, cdir, edir) \
if(edir & cdir) { \
- CARDINAL_MARK_NOCHECK(ndir, cdir, edir); \
- DIAGONAL_MARK_NOCHECK(ndir, cdir, edir); \
+ DIAGONAL_SUBSTEP(turn(ndir, 90), turn(cdir, 90), edir); \
+ DIAGONAL_SUBSTEP(turn(ndir, -90), turn(cdir, -90), edir); \
};
+
CARDINAL_MARK(NORTH, WEX_DIR_NORTH, dir)
CARDINAL_MARK(SOUTH, WEX_DIR_SOUTH, dir)
CARDINAL_MARK(EAST, WEX_DIR_EAST, dir)
@@ -379,4 +367,3 @@
#undef DIAGONAL_SUBSTEP
#undef DIAGONAL_MARK
#undef CARDINAL_MARK
-#undef MARK
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 098f1a2ea0..bcae3059e0 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -57,6 +57,8 @@
/// Should we use tooltips, if the thing does not have the code implemented `get_tooltip_data()`, it will default to examine(src)
var/tooltips = FALSE
+ /// How loudly we yell
+ var/yell_power = 35
/atom/movable/Initialize(mapload)
diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm
index 46d0bd9486..7af6c6780e 100644
--- a/code/game/turfs/closed.dm
+++ b/code/game/turfs/closed.dm
@@ -9,7 +9,9 @@
wave_explosion_block = 10
wave_explosion_multiply = 0.75
/// How much we block yelling
- var/yelling_resistance = 40
+ var/yelling_resistance = 15
+ /// how much of inbound yelling to dampen
+ var/yelling_dampen = 0.5
/turf/closed/Initialize()
. = ..()
@@ -217,5 +219,5 @@
icon_state = "ice"
canSmoothWith = list(/turf/closed/indestructible/rock/glacierrock/blue)
-/turf/closed/get_yelling_resistance()
- return yelling_resistance
+/turf/closed/get_yelling_resistance(power)
+ return yelling_resistance + (power * yelling_dampen)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 29b2db20ba..f8e2a2e18f 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -613,7 +613,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
if(. != BULLET_ACT_FORCE_PIERCE)
. = BULLET_ACT_TURF
-/turf/proc/get_yelling_resistance()
+/turf/proc/get_yelling_resistance(power)
. = 0
// don't bother checking fulltile, we don't need accuracy
var/obj/structure/window/W = locate() in src
diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm
index 3a828e0c81..d69b40be16 100644
--- a/code/modules/mob/living/living_blocking_parrying.dm
+++ b/code/modules/mob/living/living_blocking_parrying.dm
@@ -114,7 +114,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Attack types we can block
var/parry_attack_types = ALL
/// Parry flags
- var/parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING
+ var/parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK
/// Parry windup duration in deciseconds. 0 to this is windup, afterwards is main stage.
var/parry_time_windup = 0
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 949a47e50c..9f39fe492b 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -311,7 +311,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
/atom/movable/proc/process_yelling(list/already_heard, rendered, atom/movable/speaker, datum/language/message_language, message, list/spans, message_mode, obj/source)
var/list/overhearing = list()
- overhearing = yelling_wavefill(src, 35)
+ overhearing = yelling_wavefill(src, yell_power)
// overhearing = get_hearers_in_view(35, src) | get_hearers_in_range(5, src)
overhearing -= already_heard
for(var/_AM in overhearing)
From 5c44cc22f481fece783803a0255dd67ba9ec4801 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 13 Jun 2021 00:54:15 -0700
Subject: [PATCH 36/43] attempt examinate
---
code/_onclick/click.dm | 3 +++
code/modules/keybindings/keybind/mob.dm | 12 ++++++++++++
2 files changed, 15 insertions(+)
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 935fbce301..d24aa06806 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -288,6 +288,9 @@
return
/atom/proc/ShiftClick(mob/user)
+ attempt_examinate(user)
+
+/atom/proc/attempt_examinate(mob/user)
var/flags = SEND_SIGNAL(src, COMSIG_CLICK_SHIFT, user) | SEND_SIGNAL(user, COMSIG_MOB_CLICKED_SHIFT_ON, src)
if(!(flags & COMPONENT_DENY_EXAMINATE) && user.client && (user.client.eye == user || user.client.eye == user.loc || flags & COMPONENT_ALLOW_EXAMINATE))
user.examinate(src)
diff --git a/code/modules/keybindings/keybind/mob.dm b/code/modules/keybindings/keybind/mob.dm
index 257ccc37e6..85862ee14f 100644
--- a/code/modules/keybindings/keybind/mob.dm
+++ b/code/modules/keybindings/keybind/mob.dm
@@ -76,3 +76,15 @@
else
user.mob.dropItemToGround(I)
return TRUE
+
+/datum/keybinding/mob/examine_immediate
+ hotkey_keys = list()
+ classic_keys = list()
+ name = "examine_immediate"
+ full_name = "Examine (Immediate)"
+ description = "Immediately examine anything you're hovering your mouse over."
+
+/datum/keybinding/mob/examine_immediate/down(client/user)
+ var/atom/A = user.mosueObject
+ if(A)
+ A.attempt_examinate(user.mob))
From e84f7ae4ac3510b943feb02f61023ef8f3abc6db Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 13 Jun 2021 01:16:44 -0700
Subject: [PATCH 37/43] fix
---
code/__HELPERS/yelling.dm | 14 ++++++++------
code/modules/keybindings/keybind/mob.dm | 4 ++--
code/modules/mob/living/say.dm | 1 +
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/code/__HELPERS/yelling.dm b/code/__HELPERS/yelling.dm
index 7fec64c276..3134e866be 100644
--- a/code/__HELPERS/yelling.dm
+++ b/code/__HELPERS/yelling.dm
@@ -4,14 +4,13 @@
/datum/yelling_wavefill/Destroy(force, ...)
stop = TRUE
+ collected = null // don't cut it, something else is probably using it now!
return ..()
/datum/yelling_wavefill/proc/run_wavefill(atom/source, dist = 50)
collected = list()
do_run(source, dist)
- // gc
- if(QDELETED(src))
- collected = null
+ // to_chat(world, "DEBUG: collected [english_list(collected)]")
// blatantly copied from wave explosion code
// check explosion2.dm for what this does and how it works.
@@ -29,7 +28,7 @@
var/dir
var/returned
#define RUN_YELL(_T, _P, _D) \
- returned = max(_P - max(_T.get_yelling_resistance(_P), 0) - 1, 0);
+ returned = max(_P - max(_T.get_yelling_resistance(_P), 0) - 1, 0); // \
// _T.maptext = "[returned]";
var/list/turf/edges_next
@@ -117,7 +116,9 @@
power = diagonal_powers[T]
dir = diagonals[T]
RUN_YELL(T, power, dir)
- if(returned < 1)
+ if(returned >= 1)
+ collected |= typecache_filter_list(T.contents, GLOB.typecache_living)
+ else
continue
CARDINAL_MARK(NORTH, NORTH, dir)
CARDINAL_MARK(SOUTH, SOUTH, dir)
@@ -145,4 +146,5 @@
/proc/yelling_wavefill(atom/source, dist = 50)
var/datum/yelling_wavefill/Y = new
Y.run_wavefill(source, dist)
- return Y.collected || list()
+ . = Y.collected
+ qdel(Y)
diff --git a/code/modules/keybindings/keybind/mob.dm b/code/modules/keybindings/keybind/mob.dm
index 85862ee14f..15911d831e 100644
--- a/code/modules/keybindings/keybind/mob.dm
+++ b/code/modules/keybindings/keybind/mob.dm
@@ -85,6 +85,6 @@
description = "Immediately examine anything you're hovering your mouse over."
/datum/keybinding/mob/examine_immediate/down(client/user)
- var/atom/A = user.mosueObject
+ var/atom/A = user.mouseObject
if(A)
- A.attempt_examinate(user.mob))
+ A.attempt_examinate(user.mob)
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 9f39fe492b..6e24f9f1e4 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -314,6 +314,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
overhearing = yelling_wavefill(src, yell_power)
// overhearing = get_hearers_in_view(35, src) | get_hearers_in_range(5, src)
overhearing -= already_heard
+ // to_chat(world, "DEBUG: overhearing [english_list(overhearing)]")
for(var/_AM in overhearing)
var/atom/movable/AM = _AM
AM.Hear(rendered, speaker, message_language, message, null, spans, message_mode, source)
From e7f5f80fb19c130c1abfab129e5b3f44a20a1308 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 13 Jun 2021 15:34:47 -0700
Subject: [PATCH 38/43] yelling
---
code/__HELPERS/yelling.dm | 6 +++---
code/game/atoms_movable.dm | 5 +++--
code/game/turfs/closed.dm | 4 ++--
code/game/turfs/space/space.dm | 2 ++
code/game/turfs/turf.dm | 15 +++++++++++----
code/modules/mob/living/say.dm | 5 +++++
6 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/code/__HELPERS/yelling.dm b/code/__HELPERS/yelling.dm
index 3134e866be..94ebfb7726 100644
--- a/code/__HELPERS/yelling.dm
+++ b/code/__HELPERS/yelling.dm
@@ -44,15 +44,15 @@
#define CARDINAL_MARK(ndir, cdir, edir) \
if(edir & cdir) { \
expanding = get_step(T,ndir); \
- if(expanding && isnull(processed_last[expanding]) && isnull(edges[expanding])) { \
+ if(expanding && (isnull(processed_last[expanding]) || (processed_last[expanding] < (power - 5))) && (isnull(edges[expanding]) || (edges[expanding] < (power - 5)))) { \
powers_next[expanding] = max(powers_next[expanding], returned); \
- edges_next[expanding] = (cdir | edges_next[expanding]); \
+ edges_next[expanding] = cdir; \
}; \
};
#define DIAGONAL_SUBSTEP(ndir, cdir, edir) \
expanding = get_step(T,ndir); \
- if(expanding && isnull(processed_last[expanding]) && isnull(edges[expanding])) { \
+ if(expanding && (isnull(processed_last[expanding])) && (isnull(edges[expanding]))) { \
if(!edges_next[expanding]) { \
diagonal_powers_max[expanding] = max(diagonal_powers_max[expanding], returned, powers[T]); \
diagonal_powers[expanding] = CALCULATE_DIAGONAL_POWER(diagonal_powers[expanding], returned, diagonal_powers_max[expanding]); \
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index bcae3059e0..155a462295 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -58,8 +58,9 @@
/// Should we use tooltips, if the thing does not have the code implemented `get_tooltip_data()`, it will default to examine(src)
var/tooltips = FALSE
/// How loudly we yell
- var/yell_power = 35
-
+ var/yell_power = 50
+ /// last time we yelled
+ var/last_yell = 0
/atom/movable/Initialize(mapload)
. = ..()
diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm
index 7af6c6780e..3b2762c0c4 100644
--- a/code/game/turfs/closed.dm
+++ b/code/game/turfs/closed.dm
@@ -9,9 +9,9 @@
wave_explosion_block = 10
wave_explosion_multiply = 0.75
/// How much we block yelling
- var/yelling_resistance = 15
+ var/yelling_resistance = 5
/// how much of inbound yelling to dampen
- var/yelling_dampen = 0.5
+ var/yelling_dampen = 0.75
/turf/closed/Initialize()
. = ..()
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index b1a4efc97e..b566b7efbf 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -274,6 +274,8 @@
destination_y = dest_y
destination_z = dest_z
+/turf/open/space/get_yelling_resistance(power)
+ return INFINITY // no sound through space for crying out loud
/turf/open/space/transparent
baseturfs = /turf/open/space/transparent/openspace
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index f8e2a2e18f..1bc2050685 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -616,10 +616,17 @@ GLOBAL_LIST_EMPTY(station_turfs)
/turf/proc/get_yelling_resistance(power)
. = 0
// don't bother checking fulltile, we don't need accuracy
- var/obj/structure/window/W = locate() in src
- if(W)
- . += 7
+ var/obj/window = locate(/obj/structure/window) in src
+ if(!window)
+ window = locate(/obj/machinery/door/window) in src
+ if(window)
+ . += 5 // windows are minimally resistant
+ // if there's more than one someone fucked up as that shouldn't happen
+ var/obj/machinery/door/D = locate() in src
+ if(D?.density)
+ . += D.opacity? 30 : 20 // glass doors are slightly more resistant to screaming
for(var/obj/machinery/door/D in src)
if(!D.density)
continue
- . += D.opacity? 7 : 15
+ break
+ . += D.opacity? 30 :
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 6e24f9f1e4..84c2bf9e66 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -310,8 +310,13 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_recipients, 30)
/atom/movable/proc/process_yelling(list/already_heard, rendered, atom/movable/speaker, datum/language/message_language, message, list/spans, message_mode, obj/source)
+ if(last_yell > (world.time - 10))
+ to_chat(src, "Your voice doesn't project as far as you try to yell in such quick succession.") // yeah no, no spamming an expensive floodfill.
+ return
+ last_yell = world.time
var/list/overhearing = list()
overhearing = yelling_wavefill(src, yell_power)
+ log_say("YELL: [ismob(src)? key_name(src) : src] yelled [message] with overhearing mobs [overhearing]")
// overhearing = get_hearers_in_view(35, src) | get_hearers_in_range(5, src)
overhearing -= already_heard
// to_chat(world, "DEBUG: overhearing [english_list(overhearing)]")
From 8224546cfca20013dbcaef1ce827c6927ebb6953 Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 13 Jun 2021 15:36:20 -0700
Subject: [PATCH 39/43] ok
---
code/modules/mob/living/say.dm | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 84c2bf9e66..1a925e8eaf 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -315,10 +315,19 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
return
last_yell = world.time
var/list/overhearing = list()
+ var/list/overhearing_text = list()
overhearing = yelling_wavefill(src, yell_power)
- log_say("YELL: [ismob(src)? key_name(src) : src] yelled [message] with overhearing mobs [overhearing]")
+ if(!overhearing.len)
+ overhearing_text = "none"
+ else
+ for(var/mob/M as anything in overhearing)
+ overhearing_text += key_name(M)
+ overhearing_text = english_list(overhearing_text)
+ log_say("YELL: [ismob(src)? key_name(src) : src] yelled [message] with overhearing mobs [overhearing_text]")
// overhearing = get_hearers_in_view(35, src) | get_hearers_in_range(5, src)
overhearing -= already_heard
+ if(!overhearing.len)
+ return
// to_chat(world, "DEBUG: overhearing [english_list(overhearing)]")
for(var/_AM in overhearing)
var/atom/movable/AM = _AM
From b04a580e1de3e775576193fe9a96a8dd1861939c Mon Sep 17 00:00:00 2001
From: silicons <2003111+silicons@users.noreply.github.com>
Date: Sun, 13 Jun 2021 22:19:06 -0700
Subject: [PATCH 40/43] it works
---
code/__HELPERS/yelling.dm | 12 ++++++------
code/game/turfs/closed.dm | 4 ++--
code/game/turfs/turf.dm | 9 ++-------
tgui/public/tgui-common.bundle.js | 2 +-
4 files changed, 11 insertions(+), 16 deletions(-)
diff --git a/code/__HELPERS/yelling.dm b/code/__HELPERS/yelling.dm
index 94ebfb7726..8bb7690694 100644
--- a/code/__HELPERS/yelling.dm
+++ b/code/__HELPERS/yelling.dm
@@ -21,14 +21,15 @@
collected += typecache_filter_list(source.contents, GLOB.typecache_living)
var/list/powers = list()
powers[source] = dist
- var/list/processed_last = list()
+ var/list/processed = list()
var/turf/T
var/turf/expanding
var/power
var/dir
var/returned
#define RUN_YELL(_T, _P, _D) \
- returned = max(_P - max(_T.get_yelling_resistance(_P), 0) - 1, 0); // \
+ returned = max(_P - max(_T.get_yelling_resistance(_P), 0) - 1, 0); \
+ processed[_T] = returned; // \
// _T.maptext = "[returned]";
var/list/turf/edges_next
@@ -44,15 +45,15 @@
#define CARDINAL_MARK(ndir, cdir, edir) \
if(edir & cdir) { \
expanding = get_step(T,ndir); \
- if(expanding && (isnull(processed_last[expanding]) || (processed_last[expanding] < (power - 5))) && (isnull(edges[expanding]) || (edges[expanding] < (power - 5)))) { \
+ if(expanding && (isnull(processed[expanding]) || (processed[expanding] < (power - 3)))) { \
powers_next[expanding] = max(powers_next[expanding], returned); \
- edges_next[expanding] = cdir; \
+ edges_next[expanding] = (cdir | edges_next[expanding]); \
}; \
};
#define DIAGONAL_SUBSTEP(ndir, cdir, edir) \
expanding = get_step(T,ndir); \
- if(expanding && (isnull(processed_last[expanding])) && (isnull(edges[expanding]))) { \
+ if(expanding && (isnull(processed[expanding]) || (processed[expanding] < (power - 3)))) { \
if(!edges_next[expanding]) { \
diagonal_powers_max[expanding] = max(diagonal_powers_max[expanding], returned, powers[T]); \
diagonal_powers[expanding] = CALCULATE_DIAGONAL_POWER(diagonal_powers[expanding], returned, diagonal_powers_max[expanding]); \
@@ -128,7 +129,6 @@
// to_chat(world, "DEBUG: cycle end edges_next [english_list_assoc(edges_next)]")
// flush lists
- processed_last = edges + diagonals
edges = edges_next
powers = powers_next
diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm
index 3b2762c0c4..dc06062276 100644
--- a/code/game/turfs/closed.dm
+++ b/code/game/turfs/closed.dm
@@ -9,9 +9,9 @@
wave_explosion_block = 10
wave_explosion_multiply = 0.75
/// How much we block yelling
- var/yelling_resistance = 5
+ var/yelling_resistance = 10
/// how much of inbound yelling to dampen
- var/yelling_dampen = 0.75
+ var/yelling_dampen = 0.5
/turf/closed/Initialize()
. = ..()
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 1bc2050685..d64d421065 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -620,13 +620,8 @@ GLOBAL_LIST_EMPTY(station_turfs)
if(!window)
window = locate(/obj/machinery/door/window) in src
if(window)
- . += 5 // windows are minimally resistant
+ . += 4 // windows are minimally resistant
// if there's more than one someone fucked up as that shouldn't happen
var/obj/machinery/door/D = locate() in src
if(D?.density)
- . += D.opacity? 30 : 20 // glass doors are slightly more resistant to screaming
- for(var/obj/machinery/door/D in src)
- if(!D.density)
- continue
- break
- . += D.opacity? 30 :
+ . += D.opacity? 29 : 19 // glass doors are slightly more resistant to screaming
diff --git a/tgui/public/tgui-common.bundle.js b/tgui/public/tgui-common.bundle.js
index 6fea6086cb..fe8b6fe0dd 100644
--- a/tgui/public/tgui-common.bundle.js
+++ b/tgui/public/tgui-common.bundle.js
@@ -1 +1 @@
-(self.webpackChunktgui_workspace=self.webpackChunktgui_workspace||[]).push([[962],{15453:function(e){"use strict";e.exports=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e}},25401:function(e,t,n){"use strict";var r=n(99766);e.exports=function(e){if(!r(e)&&null!==e)throw TypeError("Can't set "+String(e)+" as a prototype");return e}},63142:function(e,t,n){"use strict";var r=n(55090),o=n(73072),i=n(19965),u=r("unscopables"),a=Array.prototype;a[u]==undefined&&i.f(a,u,{configurable:!0,value:o(null)}),e.exports=function(e){a[u][e]=!0}},78838:function(e,t,n){"use strict";var r=n(93294).charAt;e.exports=function(e,t,n){return t+(n?r(e,t).length:1)}},48246:function(e){"use strict";e.exports=function(e,t,n){if(!(e instanceof t))throw TypeError("Incorrect "+(n?n+" ":"")+"invocation");return e}},34699:function(e,t,n){"use strict";var r=n(99766);e.exports=function(e){if(!r(e))throw TypeError(String(e)+" is not an object");return e}},56097:function(e){"use strict";e.exports="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof DataView},77066:function(e,t,n){"use strict";var r,o=n(56097),i=n(15289),u=n(93156),a=n(99766),c=n(13375),s=n(45423),l=n(57068),f=n(55103),d=n(19965).f,p=n(11993),h=n(62743),g=n(55090),v=n(94633),m=u.Int8Array,y=m&&m.prototype,b=u.Uint8ClampedArray,E=b&&b.prototype,D=m&&p(m),x=y&&p(y),w=Object.prototype,C=w.isPrototypeOf,_=g("toStringTag"),k=v("TYPED_ARRAY_TAG"),S=o&&!!h&&"Opera"!==s(u.opera),A=!1,N={Int8Array:1,Uint8Array:1,Uint8ClampedArray:1,Int16Array:2,Uint16Array:2,Int32Array:4,Uint32Array:4,Float32Array:4,Float64Array:8},F={BigInt64Array:8,BigUint64Array:8},B=function(e){if(!a(e))return!1;var t=s(e);return"DataView"===t||c(N,t)||c(F,t)},O=function(e){if(!a(e))return!1;var t=s(e);return c(N,t)||c(F,t)};for(r in N)u[r]||(S=!1);if((!S||"function"!=typeof D||D===Function.prototype)&&(D=function(){throw TypeError("Incorrect invocation")},S))for(r in N)u[r]&&h(u[r],D);if((!S||!x||x===w)&&(x=D.prototype,S))for(r in N)u[r]&&h(u[r].prototype,x);if(S&&p(E)!==x&&h(E,x),i&&!c(x,_))for(r in A=!0,d(x,_,{get:function(){return a(this)?this[k]:undefined}}),N)u[r]&&l(u[r],k,r);e.exports={NATIVE_ARRAY_BUFFER_VIEWS:S,TYPED_ARRAY_TAG:A&&k,aTypedArray:function(e){if(O(e))return e;throw TypeError("Target is not a typed array")},aTypedArrayConstructor:function(e){if(h){if(C.call(D,e))return e}else for(var t in N)if(c(N,r)){var n=u[t];if(n&&(e===n||C.call(n,e)))return e}throw TypeError("Target is not a typed array constructor")},exportTypedArrayMethod:function(e,t,n){if(i){if(n)for(var r in N){var o=u[r];o&&c(o.prototype,e)&&delete o.prototype[e]}x[e]&&!n||f(x,e,n?t:S&&y[e]||t)}},exportTypedArrayStaticMethod:function(e,t,n){var r,o;if(i){if(h){if(n)for(r in N)(o=u[r])&&c(o,e)&&delete o[e];if(D[e]&&!n)return;try{return f(D,e,n?t:S&&m[e]||t)}catch(a){}}for(r in N)!(o=u[r])||o[e]&&!n||f(o,e,t)}},isView:B,isTypedArray:O,TypedArray:D,TypedArrayPrototype:x}},3011:function(e,t,n){"use strict";var r=n(93156),o=n(15289),i=n(56097),u=n(57068),a=n(1165),c=n(62213),s=n(48246),l=n(30150),f=n(19047),d=n(20306),p=n(58383),h=n(11993),g=n(62743),v=n(68715).f,m=n(19965).f,y=n(83759),b=n(33698),E=n(90206),D=E.get,x=E.set,w="ArrayBuffer",C="DataView",_="Wrong index",k=r.ArrayBuffer,S=k,A=r.DataView,N=A&&A.prototype,F=Object.prototype,B=r.RangeError,O=p.pack,T=p.unpack,I=function(e){return[255&e]},M=function(e){return[255&e,e>>8&255]},V=function(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]},R=function(e){return e[3]<<24|e[2]<<16|e[1]<<8|e[0]},L=function(e){return O(e,23,4)},P=function(e){return O(e,52,8)},j=function(e,t){m(e.prototype,t,{get:function(){return D(this)[t]}})},z=function(e,t,n,r){var o=d(n),i=D(e);if(o+t>i.byteLength)throw B(_);var u=D(i.buffer).bytes,a=o+i.byteOffset,c=u.slice(a,a+t);return r?c:c.reverse()},K=function(e,t,n,r,o,i){var u=d(n),a=D(e);if(u+t>a.byteLength)throw B(_);for(var c=D(a.buffer).bytes,s=u+a.byteOffset,l=r(+o),f=0;fH;)(U=$[H++])in S||u(S,U,k[U]);Y.constructor=S}g&&h(N)!==F&&g(N,F);var W=new A(new S(2)),G=N.setInt8;W.setInt8(0,2147483648),W.setInt8(1,2147483649),!W.getInt8(0)&&W.getInt8(1)||a(N,{setInt8:function(e,t){G.call(this,e,t<<24>>24)},setUint8:function(e,t){G.call(this,e,t<<24>>24)}},{unsafe:!0})}else S=function(e){s(this,S,w);var t=d(e);x(this,{bytes:y.call(new Array(t),0),byteLength:t}),o||(this.byteLength=t)},A=function(e,t,n){s(this,A,C),s(e,S,C);var r=D(e).byteLength,i=l(t);if(i<0||i>r)throw B("Wrong offset");if(i+(n=n===undefined?r-i:f(n))>r)throw B("Wrong length");x(this,{buffer:e,byteLength:n,byteOffset:i}),o||(this.buffer=e,this.byteLength=n,this.byteOffset=i)},o&&(j(S,"byteLength"),j(A,"buffer"),j(A,"byteLength"),j(A,"byteOffset")),a(A.prototype,{getInt8:function(e){return z(this,1,e)[0]<<24>>24},getUint8:function(e){return z(this,1,e)[0]},getInt16:function(e){var t=z(this,2,e,arguments.length>1?arguments[1]:undefined);return(t[1]<<8|t[0])<<16>>16},getUint16:function(e){var t=z(this,2,e,arguments.length>1?arguments[1]:undefined);return t[1]<<8|t[0]},getInt32:function(e){return R(z(this,4,e,arguments.length>1?arguments[1]:undefined))},getUint32:function(e){return R(z(this,4,e,arguments.length>1?arguments[1]:undefined))>>>0},getFloat32:function(e){return T(z(this,4,e,arguments.length>1?arguments[1]:undefined),23)},getFloat64:function(e){return T(z(this,8,e,arguments.length>1?arguments[1]:undefined),52)},setInt8:function(e,t){K(this,1,e,I,t)},setUint8:function(e,t){K(this,1,e,I,t)},setInt16:function(e,t){K(this,2,e,M,t,arguments.length>2?arguments[2]:undefined)},setUint16:function(e,t){K(this,2,e,M,t,arguments.length>2?arguments[2]:undefined)},setInt32:function(e,t){K(this,4,e,V,t,arguments.length>2?arguments[2]:undefined)},setUint32:function(e,t){K(this,4,e,V,t,arguments.length>2?arguments[2]:undefined)},setFloat32:function(e,t){K(this,4,e,L,t,arguments.length>2?arguments[2]:undefined)},setFloat64:function(e,t){K(this,8,e,P,t,arguments.length>2?arguments[2]:undefined)}});b(S,w),b(A,C),e.exports={ArrayBuffer:S,DataView:A}},90838:function(e,t,n){"use strict";var r=n(62314),o=n(60248),i=n(19047),u=Math.min;e.exports=[].copyWithin||function(e,t){var n=r(this),a=i(n.length),c=o(e,a),s=o(t,a),l=arguments.length>2?arguments[2]:undefined,f=u((l===undefined?a:o(l,a))-s,a-c),d=1;for(s0;)s in n?n[c]=n[s]:delete n[c],c+=d,s+=d;return n}},83759:function(e,t,n){"use strict";var r=n(62314),o=n(60248),i=n(19047);e.exports=function(e){for(var t=r(this),n=i(t.length),u=arguments.length,a=o(u>1?arguments[1]:undefined,n),c=u>2?arguments[2]:undefined,s=c===undefined?n:o(c,n);s>a;)t[a++]=e;return t}},83679:function(e,t,n){"use strict";var r=n(73846).forEach,o=n(67481)("forEach");e.exports=o?[].forEach:function(e){return r(this,e,arguments.length>1?arguments[1]:undefined)}},18703:function(e,t,n){"use strict";var r=n(6738),o=n(62314),i=n(83180),u=n(71713),a=n(19047),c=n(92996),s=n(3933);e.exports=function(e){var t,n,l,f,d,p,h=o(e),g="function"==typeof this?this:Array,v=arguments.length,m=v>1?arguments[1]:undefined,y=m!==undefined,b=s(h),E=0;if(y&&(m=r(m,v>2?arguments[2]:undefined,2)),b==undefined||g==Array&&u(b))for(n=new g(t=a(h.length));t>E;E++)p=y?m(h[E],E):h[E],c(n,E,p);else for(d=(f=b.call(h)).next,n=new g;!(l=d.call(f)).done;E++)p=y?i(f,m,[l.value,E],!0):l.value,c(n,E,p);return n.length=E,n}},38682:function(e,t,n){"use strict";var r=n(75018),o=n(19047),i=n(60248),u=function(e){return function(t,n,u){var a,c=r(t),s=o(c.length),l=i(u,s);if(e&&n!=n){for(;s>l;)if((a=c[l++])!=a)return!0}else for(;s>l;l++)if((e||l in c)&&c[l]===n)return e||l||0;return!e&&-1}};e.exports={includes:u(!0),indexOf:u(!1)}},73846:function(e,t,n){"use strict";var r=n(6738),o=n(98475),i=n(62314),u=n(19047),a=n(89130),c=[].push,s=function(e){var t=1==e,n=2==e,s=3==e,l=4==e,f=6==e,d=7==e,p=5==e||f;return function(h,g,v,m){for(var y,b,E=i(h),D=o(E),x=r(g,v,3),w=u(D.length),C=0,_=m||a,k=t?_(h,w):n||d?_(h,0):undefined;w>C;C++)if((p||C in D)&&(b=x(y=D[C],C,E),e))if(t)k[C]=b;else if(b)switch(e){case 3:return!0;case 5:return y;case 6:return C;case 2:c.call(k,y)}else switch(e){case 4:return!1;case 7:c.call(k,y)}return f?-1:s||l?l:k}};e.exports={forEach:s(0),map:s(1),filter:s(2),some:s(3),every:s(4),find:s(5),findIndex:s(6),filterOut:s(7)}},95180:function(e,t,n){"use strict";var r=n(75018),o=n(30150),i=n(19047),u=n(67481),a=Math.min,c=[].lastIndexOf,s=!!c&&1/[1].lastIndexOf(1,-0)<0,l=u("lastIndexOf"),f=s||!l;e.exports=f?function(e){if(s)return c.apply(this,arguments)||0;var t=r(this),n=i(t.length),u=n-1;for(arguments.length>1&&(u=a(u,o(arguments[1]))),u<0&&(u=n+u);u>=0;u--)if(u in t&&t[u]===e)return u||0;return-1}:c},35876:function(e,t,n){"use strict";var r=n(62213),o=n(55090),i=n(51976),u=o("species");e.exports=function(e){return i>=51||!r((function(){var t=[];return(t.constructor={})[u]=function(){return{foo:1}},1!==t[e](Boolean).foo}))}},67481:function(e,t,n){"use strict";var r=n(62213);e.exports=function(e,t){var n=[][e];return!!n&&r((function(){n.call(null,t||function(){throw 1},1)}))}},90047:function(e,t,n){"use strict";var r=n(15453),o=n(62314),i=n(98475),u=n(19047),a=function(e){return function(t,n,a,c){r(n);var s=o(t),l=i(s),f=u(s.length),d=e?f-1:0,p=e?-1:1;if(a<2)for(;;){if(d in l){c=l[d],d+=p;break}if(d+=p,e?d<0:f<=d)throw TypeError("Reduce of empty array with no initial value")}for(;e?d>=0:f>d;d+=p)d in l&&(c=n(c,l[d],d,s));return c}};e.exports={left:a(!1),right:a(!0)}},89130:function(e,t,n){"use strict";var r=n(99766),o=n(73707),i=n(55090)("species");e.exports=function(e,t){var n;return o(e)&&("function"!=typeof(n=e.constructor)||n!==Array&&!o(n.prototype)?r(n)&&null===(n=n[i])&&(n=undefined):n=undefined),new(n===undefined?Array:n)(0===t?0:t)}},83180:function(e,t,n){"use strict";var r=n(34699),o=n(6816);e.exports=function(e,t,n,i){try{return i?t(r(n)[0],n[1]):t(n)}catch(u){throw o(e),u}}},84673:function(e,t,n){"use strict";var r=n(55090)("iterator"),o=!1;try{var i=0,u={next:function(){return{done:!!i++}},"return":function(){o=!0}};u[r]=function(){return this},Array.from(u,(function(){throw 2}))}catch(a){}e.exports=function(e,t){if(!t&&!o)return!1;var n=!1;try{var i={};i[r]=function(){return{next:function(){return{done:n=!0}}}},e(i)}catch(a){}return n}},74803:function(e){"use strict";var t={}.toString;e.exports=function(e){return t.call(e).slice(8,-1)}},45423:function(e,t,n){"use strict";var r=n(94274),o=n(74803),i=n(55090)("toStringTag"),u="Arguments"==o(function(){return arguments}());e.exports=r?o:function(e){var t,n,r;return e===undefined?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(n){}}(t=Object(e),i))?n:u?o(t):"Object"==(r=o(t))&&"function"==typeof t.callee?"Arguments":r}},36579:function(e,t,n){"use strict";var r=n(19965).f,o=n(73072),i=n(1165),u=n(6738),a=n(48246),c=n(32732),s=n(490),l=n(83360),f=n(15289),d=n(33214).fastKey,p=n(90206),h=p.set,g=p.getterFor;e.exports={getConstructor:function(e,t,n,s){var l=e((function(e,r){a(e,l,t),h(e,{type:t,index:o(null),first:undefined,last:undefined,size:0}),f||(e.size=0),r!=undefined&&c(r,e[s],{that:e,AS_ENTRIES:n})})),p=g(t),v=function(e,t,n){var r,o,i=p(e),u=m(e,t);return u?u.value=n:(i.last=u={index:o=d(t,!0),key:t,value:n,previous:r=i.last,next:undefined,removed:!1},i.first||(i.first=u),r&&(r.next=u),f?i.size++:e.size++,"F"!==o&&(i.index[o]=u)),e},m=function(e,t){var n,r=p(e),o=d(t);if("F"!==o)return r.index[o];for(n=r.first;n;n=n.next)if(n.key==t)return n};return i(l.prototype,{clear:function(){for(var e=p(this),t=e.index,n=e.first;n;)n.removed=!0,n.previous&&(n.previous=n.previous.next=undefined),delete t[n.index],n=n.next;e.first=e.last=undefined,f?e.size=0:this.size=0},"delete":function(e){var t=this,n=p(t),r=m(t,e);if(r){var o=r.next,i=r.previous;delete n.index[r.index],r.removed=!0,i&&(i.next=o),o&&(o.previous=i),n.first==r&&(n.first=o),n.last==r&&(n.last=i),f?n.size--:t.size--}return!!r},forEach:function(e){for(var t,n=p(this),r=u(e,arguments.length>1?arguments[1]:undefined,3);t=t?t.next:n.first;)for(r(t.value,t.key,this);t&&t.removed;)t=t.previous},has:function(e){return!!m(this,e)}}),i(l.prototype,n?{get:function(e){var t=m(this,e);return t&&t.value},set:function(e,t){return v(this,0===e?0:e,t)}}:{add:function(e){return v(this,e=0===e?0:e,e)}}),f&&r(l.prototype,"size",{get:function(){return p(this).size}}),l},setStrong:function(e,t,n){var r=t+" Iterator",o=g(t),i=g(r);s(e,t,(function(e,t){h(this,{type:r,target:e,state:o(e),kind:t,last:undefined})}),(function(){for(var e=i(this),t=e.kind,n=e.last;n&&n.removed;)n=n.previous;return e.target&&(e.last=n=n?n.next:e.state.first)?"keys"==t?{value:n.key,done:!1}:"values"==t?{value:n.value,done:!1}:{value:[n.key,n.value],done:!1}:(e.target=undefined,{value:undefined,done:!0})}),n?"entries":"values",!n,!0),l(t)}}},60079:function(e,t,n){"use strict";var r=n(1165),o=n(33214).getWeakData,i=n(34699),u=n(99766),a=n(48246),c=n(32732),s=n(73846),l=n(13375),f=n(90206),d=f.set,p=f.getterFor,h=s.find,g=s.findIndex,v=0,m=function(e){return e.frozen||(e.frozen=new y)},y=function(){this.entries=[]},b=function(e,t){return h(e.entries,(function(e){return e[0]===t}))};y.prototype={get:function(e){var t=b(this,e);if(t)return t[1]},has:function(e){return!!b(this,e)},set:function(e,t){var n=b(this,e);n?n[1]=t:this.entries.push([e,t])},"delete":function(e){var t=g(this.entries,(function(t){return t[0]===e}));return~t&&this.entries.splice(t,1),!!~t}},e.exports={getConstructor:function(e,t,n,s){var f=e((function(e,r){a(e,f,t),d(e,{type:t,id:v++,frozen:undefined}),r!=undefined&&c(r,e[s],{that:e,AS_ENTRIES:n})})),h=p(t),g=function(e,t,n){var r=h(e),u=o(i(t),!0);return!0===u?m(r).set(t,n):u[r.id]=n,e};return r(f.prototype,{"delete":function(e){var t=h(this);if(!u(e))return!1;var n=o(e);return!0===n?m(t)["delete"](e):n&&l(n,t.id)&&delete n[t.id]},has:function(e){var t=h(this);if(!u(e))return!1;var n=o(e);return!0===n?m(t).has(e):n&&l(n,t.id)}}),r(f.prototype,n?{get:function(e){var t=h(this);if(u(e)){var n=o(e);return!0===n?m(t).get(e):n?n[t.id]:undefined}},set:function(e,t){return g(this,e,t)}}:{add:function(e){return g(this,e,!0)}}),f}}},31912:function(e,t,n){"use strict";var r=n(10629),o=n(93156),i=n(76799),u=n(55103),a=n(33214),c=n(32732),s=n(48246),l=n(99766),f=n(62213),d=n(84673),p=n(33698),h=n(65136);e.exports=function(e,t,n){var g=-1!==e.indexOf("Map"),v=-1!==e.indexOf("Weak"),m=g?"set":"add",y=o[e],b=y&&y.prototype,E=y,D={},x=function(e){var t=b[e];u(b,e,"add"==e?function(e){return t.call(this,0===e?0:e),this}:"delete"==e?function(e){return!(v&&!l(e))&&t.call(this,0===e?0:e)}:"get"==e?function(e){return v&&!l(e)?undefined:t.call(this,0===e?0:e)}:"has"==e?function(e){return!(v&&!l(e))&&t.call(this,0===e?0:e)}:function(e,n){return t.call(this,0===e?0:e,n),this})};if(i(e,"function"!=typeof y||!(v||b.forEach&&!f((function(){(new y).entries().next()})))))E=n.getConstructor(t,e,g,m),a.REQUIRED=!0;else if(i(e,!0)){var w=new E,C=w[m](v?{}:-0,1)!=w,_=f((function(){w.has(1)})),k=d((function(e){new y(e)})),S=!v&&f((function(){for(var e=new y,t=5;t--;)e[m](t,t);return!e.has(-0)}));k||((E=t((function(t,n){s(t,E,e);var r=h(new y,t,E);return n!=undefined&&c(n,r[m],{that:r,AS_ENTRIES:g}),r}))).prototype=b,b.constructor=E),(_||S)&&(x("delete"),x("has"),g&&x("get")),(S||C)&&x(m),v&&b.clear&&delete b.clear}return D[e]=E,r({global:!0,forced:E!=y},D),p(E,e),v||n.setStrong(E,e,g),E}},7924:function(e,t,n){"use strict";var r=n(13375),o=n(92506),i=n(48378),u=n(19965);e.exports=function(e,t){for(var n=o(t),a=u.f,c=i.f,s=0;s"+u+""+t+">"}},47155:function(e,t,n){"use strict";var r=n(37916).IteratorPrototype,o=n(73072),i=n(42831),u=n(33698),a=n(17080),c=function(){return this};e.exports=function(e,t,n){var s=t+" Iterator";return e.prototype=o(r,{next:i(1,n)}),u(e,s,!1,!0),a[s]=c,e}},57068:function(e,t,n){"use strict";var r=n(15289),o=n(19965),i=n(42831);e.exports=r?function(e,t,n){return o.f(e,t,i(1,n))}:function(e,t,n){return e[t]=n,e}},42831:function(e){"use strict";e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},92996:function(e,t,n){"use strict";var r=n(57391),o=n(19965),i=n(42831);e.exports=function(e,t,n){var u=r(t);u in e?o.f(e,u,i(0,n)):e[u]=n}},33743:function(e,t,n){"use strict";var r=n(62213),o=n(52274).start,i=Math.abs,u=Date.prototype,a=u.getTime,c=u.toISOString;e.exports=r((function(){return"0385-07-25T07:06:39.999Z"!=c.call(new Date(-50000000000001))}))||!r((function(){c.call(new Date(NaN))}))?function(){if(!isFinite(a.call(this)))throw RangeError("Invalid time value");var e=this,t=e.getUTCFullYear(),n=e.getUTCMilliseconds(),r=t<0?"-":t>9999?"+":"";return r+o(i(t),r?6:4,0)+"-"+o(e.getUTCMonth()+1,2,0)+"-"+o(e.getUTCDate(),2,0)+"T"+o(e.getUTCHours(),2,0)+":"+o(e.getUTCMinutes(),2,0)+":"+o(e.getUTCSeconds(),2,0)+"."+o(n,3,0)+"Z"}:c},57029:function(e,t,n){"use strict";var r=n(34699),o=n(57391);e.exports=function(e){if("string"!==e&&"number"!==e&&"default"!==e)throw TypeError("Incorrect hint");return o(r(this),"number"!==e)}},490:function(e,t,n){"use strict";var r=n(10629),o=n(47155),i=n(11993),u=n(62743),a=n(33698),c=n(57068),s=n(55103),l=n(55090),f=n(27689),d=n(17080),p=n(37916),h=p.IteratorPrototype,g=p.BUGGY_SAFARI_ITERATORS,v=l("iterator"),m="keys",y="values",b="entries",E=function(){return this};e.exports=function(e,t,n,l,p,D,x){o(n,t,l);var w,C,_,k=function(e){if(e===p&&B)return B;if(!g&&e in N)return N[e];switch(e){case m:case y:case b:return function(){return new n(this,e)}}return function(){return new n(this)}},S=t+" Iterator",A=!1,N=e.prototype,F=N[v]||N["@@iterator"]||p&&N[p],B=!g&&F||k(p),O="Array"==t&&N.entries||F;if(O&&(w=i(O.call(new e)),h!==Object.prototype&&w.next&&(f||i(w)===h||(u?u(w,h):"function"!=typeof w[v]&&c(w,v,E)),a(w,S,!0,!0),f&&(d[S]=E))),p==y&&F&&F.name!==y&&(A=!0,B=function(){return F.call(this)}),f&&!x||N[v]===B||c(N,v,B),d[t]=B,p)if(C={values:k(y),keys:D?B:k(m),entries:k(b)},x)for(_ in C)(g||A||!(_ in N))&&s(N,_,C[_]);else r({target:t,proto:!0,forced:g||A},C);return C}},49712:function(e,t,n){"use strict";var r=n(10483),o=n(13375),i=n(43384),u=n(19965).f;e.exports=function(e){var t=r.Symbol||(r.Symbol={});o(t,e)||u(t,e,{value:i.f(e)})}},15289:function(e,t,n){"use strict";var r=n(62213);e.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},17765:function(e,t,n){"use strict";var r=n(93156),o=n(99766),i=r.document,u=o(i)&&o(i.createElement);e.exports=function(e){return u?i.createElement(e):{}}},88621:function(e,t,n){"use strict";var r=n(22909);e.exports=/(iphone|ipod|ipad).*applewebkit/i.test(r)},80597:function(e,t,n){"use strict";var r=n(74803),o=n(93156);e.exports="process"==r(o.process)},68486:function(e,t,n){"use strict";var r=n(22909);e.exports=/web0s(?!.*chrome)/i.test(r)},22909:function(e,t,n){"use strict";var r=n(1555);e.exports=r("navigator","userAgent")||""},51976:function(e,t,n){"use strict";var r,o,i=n(93156),u=n(22909),a=i.process,c=a&&a.versions,s=c&&c.v8;s?o=(r=s.split("."))[0]+r[1]:u&&(!(r=u.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=u.match(/Chrome\/(\d+)/))&&(o=r[1]),e.exports=o&&+o},92002:function(e){"use strict";e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},10629:function(e,t,n){"use strict";var r=n(93156),o=n(48378).f,i=n(57068),u=n(55103),a=n(16731),c=n(7924),s=n(76799);e.exports=function(e,t){var n,l,f,d,p,h=e.target,g=e.global,v=e.stat;if(n=g?r:v?r[h]||a(h,{}):(r[h]||{}).prototype)for(l in t){if(d=t[l],f=e.noTargetGet?(p=o(n,l))&&p.value:n[l],!s(g?l:h+(v?".":"#")+l,e.forced)&&f!==undefined){if(typeof d==typeof f)continue;c(d,f)}(e.sham||f&&f.sham)&&i(d,"sham",!0),u(n,l,d,e)}}},62213:function(e){"use strict";e.exports=function(e){try{return!!e()}catch(t){return!0}}},63905:function(e,t,n){"use strict";n(16431);var r=n(55103),o=n(62213),i=n(55090),u=n(69107),a=n(57068),c=i("species"),s=!o((function(){var e=/./;return e.exec=function(){var e=[];return e.groups={a:"7"},e},"7"!=="".replace(e,"$")})),l="$0"==="a".replace(/./,"$0"),f=i("replace"),d=!!/./[f]&&""===/./[f]("a","$0"),p=!o((function(){var e=/(?:)/,t=e.exec;e.exec=function(){return t.apply(this,arguments)};var n="ab".split(e);return 2!==n.length||"a"!==n[0]||"b"!==n[1]}));e.exports=function(e,t,n,f){var h=i(e),g=!o((function(){var t={};return t[h]=function(){return 7},7!=""[e](t)})),v=g&&!o((function(){var t=!1,n=/a/;return"split"===e&&((n={}).constructor={},n.constructor[c]=function(){return n},n.flags="",n[h]=/./[h]),n.exec=function(){return t=!0,null},n[h](""),!t}));if(!g||!v||"replace"===e&&(!s||!l||d)||"split"===e&&!p){var m=/./[h],y=n(h,""[e],(function(e,t,n,r,o){return t.exec===u?g&&!o?{done:!0,value:m.call(t,n,r)}:{done:!0,value:e.call(n,t,r)}:{done:!1}}),{REPLACE_KEEPS_$0:l,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:d}),b=y[0],E=y[1];r(String.prototype,e,b),r(RegExp.prototype,h,2==t?function(e,t){return E.call(e,this,t)}:function(e){return E.call(e,this)})}f&&a(RegExp.prototype[h],"sham",!0)}},67767:function(e,t,n){"use strict";var r=n(73707),o=n(19047),i=n(6738);e.exports=function u(e,t,n,a,c,s,l,f){for(var d,p=c,h=0,g=!!l&&i(l,f,3);h0&&r(d))p=u(e,t,d,o(d.length),p,s-1)-1;else{if(p>=9007199254740991)throw TypeError("Exceed the acceptable array length");e[p]=d}p++}h++}return p}},41830:function(e,t,n){"use strict";var r=n(62213);e.exports=!r((function(){return Object.isExtensible(Object.preventExtensions({}))}))},6738:function(e,t,n){"use strict";var r=n(15453);e.exports=function(e,t,n){if(r(e),t===undefined)return e;switch(n){case 0:return function(){return e.call(t)};case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,o){return e.call(t,n,r,o)}}return function(){return e.apply(t,arguments)}}},67043:function(e,t,n){"use strict";var r=n(15453),o=n(99766),i=[].slice,u={},a=function(e,t,n){if(!(t in u)){for(var r=[],o=0;o]*>)/g,a=/\$([$&'`]|\d\d?)/g;e.exports=function(e,t,n,c,s,l){var f=n+e.length,d=c.length,p=a;return s!==undefined&&(s=r(s),p=u),i.call(l,p,(function(r,i){var u;switch(i.charAt(0)){case"$":return"$";case"&":return e;case"`":return t.slice(0,n);case"'":return t.slice(f);case"<":u=s[i.slice(1,-1)];break;default:var a=+i;if(0===a)return r;if(a>d){var l=o(a/10);return 0===l?r:l<=d?c[l-1]===undefined?i.charAt(1):c[l-1]+i.charAt(1):r}u=c[a-1]}return u===undefined?"":u}))}},93156:function(e,t,n){"use strict";var r=function(e){return e&&e.Math==Math&&e};e.exports=r("object"==typeof globalThis&&globalThis)||r("object"==typeof window&&window)||r("object"==typeof self&&self)||r("object"==typeof n.g&&n.g)||function(){return this}()||Function("return this")()},13375:function(e){"use strict";var t={}.hasOwnProperty;e.exports=function(e,n){return t.call(e,n)}},97204:function(e){"use strict";e.exports={}},31538:function(e,t,n){"use strict";var r=n(93156);e.exports=function(e,t){var n=r.console;n&&n.error&&(1===arguments.length?n.error(e):n.error(e,t))}},73214:function(e,t,n){"use strict";var r=n(1555);e.exports=r("document","documentElement")},76689:function(e,t,n){"use strict";var r=n(15289),o=n(62213),i=n(17765);e.exports=!r&&!o((function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},58383:function(e){"use strict";var t=Math.abs,n=Math.pow,r=Math.floor,o=Math.log,i=Math.LN2;e.exports={pack:function(e,u,a){var c,s,l,f=new Array(a),d=8*a-u-1,p=(1<>1,g=23===u?n(2,-24)-n(2,-77):0,v=e<0||0===e&&1/e<0?1:0,m=0;for((e=t(e))!=e||e===Infinity?(s=e!=e?1:0,c=p):(c=r(o(e)/i),e*(l=n(2,-c))<1&&(c--,l*=2),(e+=c+h>=1?g/l:g*n(2,1-h))*l>=2&&(c++,l/=2),c+h>=p?(s=0,c=p):c+h>=1?(s=(e*l-1)*n(2,u),c+=h):(s=e*n(2,h-1)*n(2,u),c=0));u>=8;f[m++]=255&s,s/=256,u-=8);for(c=c<0;f[m++]=255&c,c/=256,d-=8);return f[--m]|=128*v,f},unpack:function(e,t){var r,o=e.length,i=8*o-t-1,u=(1<>1,c=i-7,s=o-1,l=e[s--],f=127&l;for(l>>=7;c>0;f=256*f+e[s],s--,c-=8);for(r=f&(1<<-c)-1,f>>=-c,c+=t;c>0;r=256*r+e[s],s--,c-=8);if(0===f)f=1-a;else{if(f===u)return r?NaN:l?-Infinity:Infinity;r+=n(2,t),f-=a}return(l?-1:1)*r*n(2,f-t)}}},98475:function(e,t,n){"use strict";var r=n(62213),o=n(74803),i="".split;e.exports=r((function(){return!Object("z").propertyIsEnumerable(0)}))?function(e){return"String"==o(e)?i.call(e,""):Object(e)}:Object},65136:function(e,t,n){"use strict";var r=n(99766),o=n(62743);e.exports=function(e,t,n){var i,u;return o&&"function"==typeof(i=t.constructor)&&i!==n&&r(u=i.prototype)&&u!==n.prototype&&o(e,u),e}},59601:function(e,t,n){"use strict";var r=n(41030),o=Function.toString;"function"!=typeof r.inspectSource&&(r.inspectSource=function(e){return o.call(e)}),e.exports=r.inspectSource},33214:function(e,t,n){"use strict";var r=n(97204),o=n(99766),i=n(13375),u=n(19965).f,a=n(94633),c=n(41830),s=a("meta"),l=0,f=Object.isExtensible||function(){return!0},d=function(e){u(e,s,{value:{objectID:"O"+ ++l,weakData:{}}})},p=e.exports={REQUIRED:!1,fastKey:function(e,t){if(!o(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e;if(!i(e,s)){if(!f(e))return"F";if(!t)return"E";d(e)}return e[s].objectID},getWeakData:function(e,t){if(!i(e,s)){if(!f(e))return!0;if(!t)return!1;d(e)}return e[s].weakData},onFreeze:function(e){return c&&p.REQUIRED&&f(e)&&!i(e,s)&&d(e),e}};r[s]=!0},90206:function(e,t,n){"use strict";var r,o,i,u=n(60768),a=n(93156),c=n(99766),s=n(57068),l=n(13375),f=n(41030),d=n(67543),p=n(97204),h=a.WeakMap;if(u){var g=f.state||(f.state=new h),v=g.get,m=g.has,y=g.set;r=function(e,t){return t.facade=e,y.call(g,e,t),t},o=function(e){return v.call(g,e)||{}},i=function(e){return m.call(g,e)}}else{var b=d("state");p[b]=!0,r=function(e,t){return t.facade=e,s(e,b,t),t},o=function(e){return l(e,b)?e[b]:{}},i=function(e){return l(e,b)}}e.exports={set:r,get:o,has:i,enforce:function(e){return i(e)?o(e):r(e,{})},getterFor:function(e){return function(t){var n;if(!c(t)||(n=o(t)).type!==e)throw TypeError("Incompatible receiver, "+e+" required");return n}}}},71713:function(e,t,n){"use strict";var r=n(55090),o=n(17080),i=r("iterator"),u=Array.prototype;e.exports=function(e){return e!==undefined&&(o.Array===e||u[i]===e)}},73707:function(e,t,n){"use strict";var r=n(74803);e.exports=Array.isArray||function(e){return"Array"==r(e)}},76799:function(e,t,n){"use strict";var r=n(62213),o=/#|\.prototype\./,i=function(e,t){var n=a[u(e)];return n==s||n!=c&&("function"==typeof t?r(t):!!t)},u=i.normalize=function(e){return String(e).replace(o,".").toLowerCase()},a=i.data={},c=i.NATIVE="N",s=i.POLYFILL="P";e.exports=i},92285:function(e,t,n){"use strict";var r=n(99766),o=Math.floor;e.exports=function(e){return!r(e)&&isFinite(e)&&o(e)===e}},99766:function(e){"use strict";e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},27689:function(e){"use strict";e.exports=!1},10874:function(e,t,n){"use strict";var r=n(99766),o=n(74803),i=n(55090)("match");e.exports=function(e){var t;return r(e)&&((t=e[i])!==undefined?!!t:"RegExp"==o(e))}},32732:function(e,t,n){"use strict";var r=n(34699),o=n(71713),i=n(19047),u=n(6738),a=n(3933),c=n(6816),s=function(e,t){this.stopped=e,this.result=t};e.exports=function(e,t,n){var l,f,d,p,h,g,v,m=n&&n.that,y=!(!n||!n.AS_ENTRIES),b=!(!n||!n.IS_ITERATOR),E=!(!n||!n.INTERRUPTED),D=u(t,m,1+y+E),x=function(e){return l&&c(l),new s(!0,e)},w=function(e){return y?(r(e),E?D(e[0],e[1],x):D(e[0],e[1])):E?D(e,x):D(e)};if(b)l=e;else{if("function"!=typeof(f=a(e)))throw TypeError("Target is not iterable");if(o(f)){for(d=0,p=i(e.length);p>d;d++)if((h=w(e[d]))&&h instanceof s)return h;return new s(!1)}l=f.call(e)}for(g=l.next;!(v=g.call(l)).done;){try{h=w(v.value)}catch(C){throw c(l),C}if("object"==typeof h&&h&&h instanceof s)return h}return new s(!1)}},6816:function(e,t,n){"use strict";var r=n(34699);e.exports=function(e){var t=e["return"];if(t!==undefined)return r(t.call(e)).value}},37916:function(e,t,n){"use strict";var r,o,i,u=n(62213),a=n(11993),c=n(57068),s=n(13375),l=n(55090),f=n(27689),d=l("iterator"),p=!1;[].keys&&("next"in(i=[].keys())?(o=a(a(i)))!==Object.prototype&&(r=o):p=!0);var h=r==undefined||u((function(){var e={};return r[d].call(e)!==e}));h&&(r={}),f&&!h||s(r,d)||c(r,d,(function(){return this})),e.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:p}},17080:function(e){"use strict";e.exports={}},78216:function(e){"use strict";var t=Math.expm1,n=Math.exp;e.exports=!t||t(10)>22025.465794806718||t(10)<22025.465794806718||-2e-17!=t(-2e-17)?function(e){return 0==(e=+e)?e:e>-1e-6&&e<1e-6?e+e*e/2:n(e)-1}:t},69945:function(e,t,n){"use strict";var r=n(57845),o=Math.abs,i=Math.pow,u=i(2,-52),a=i(2,-23),c=i(2,127)*(2-a),s=i(2,-126);e.exports=Math.fround||function(e){var t,n,i=o(e),l=r(e);return ic||n!=n?l*Infinity:l*n}},90738:function(e){"use strict";var t=Math.log;e.exports=Math.log1p||function(e){return(e=+e)>-1e-8&&e<1e-8?e-e*e/2:t(1+e)}},57845:function(e){"use strict";e.exports=Math.sign||function(e){return 0==(e=+e)||e!=e?e:e<0?-1:1}},74317:function(e,t,n){"use strict";var r,o,i,u,a,c,s,l,f=n(93156),d=n(48378).f,p=n(24446).set,h=n(88621),g=n(68486),v=n(80597),m=f.MutationObserver||f.WebKitMutationObserver,y=f.document,b=f.process,E=f.Promise,D=d(f,"queueMicrotask"),x=D&&D.value;x||(r=function(){var e,t;for(v&&(e=b.domain)&&e.exit();o;){t=o.fn,o=o.next;try{t()}catch(n){throw o?u():i=undefined,n}}i=undefined,e&&e.enter()},h||v||g||!m||!y?E&&E.resolve?(s=E.resolve(undefined),l=s.then,u=function(){l.call(s,r)}):u=v?function(){b.nextTick(r)}:function(){p.call(f,r)}:(a=!0,c=y.createTextNode(""),new m(r).observe(c,{characterData:!0}),u=function(){c.data=a=!a})),e.exports=x||function(e){var t={fn:e,next:undefined};i&&(i.next=t),o||(o=t,u()),i=t}},77085:function(e,t,n){"use strict";var r=n(93156);e.exports=r.Promise},19530:function(e,t,n){"use strict";var r=n(62213);e.exports=!!Object.getOwnPropertySymbols&&!r((function(){return!String(Symbol())}))},60768:function(e,t,n){"use strict";var r=n(93156),o=n(59601),i=r.WeakMap;e.exports="function"==typeof i&&/native code/.test(o(i))},604:function(e,t,n){"use strict";var r=n(15453),o=function(e){var t,n;this.promise=new e((function(e,r){if(t!==undefined||n!==undefined)throw TypeError("Bad Promise constructor");t=e,n=r})),this.resolve=r(t),this.reject=r(n)};e.exports.f=function(e){return new o(e)}},90225:function(e,t,n){"use strict";var r=n(10874);e.exports=function(e){if(r(e))throw TypeError("The method doesn't accept regular expressions");return e}},5366:function(e,t,n){"use strict";var r=n(93156).isFinite;e.exports=Number.isFinite||function(e){return"number"==typeof e&&r(e)}},5868:function(e,t,n){"use strict";var r=n(93156),o=n(52420).trim,i=n(98398),u=r.parseFloat,a=1/u(i+"-0")!=-Infinity;e.exports=a?function(e){var t=o(String(e)),n=u(t);return 0===n&&"-"==t.charAt(0)?-0:n}:u},94219:function(e,t,n){"use strict";var r=n(93156),o=n(52420).trim,i=n(98398),u=r.parseInt,a=/^[+-]?0[Xx]/,c=8!==u(i+"08")||22!==u(i+"0x16");e.exports=c?function(e,t){var n=o(String(e));return u(n,t>>>0||(a.test(n)?16:10))}:u},3669:function(e,t,n){"use strict";var r=n(15289),o=n(62213),i=n(91165),u=n(84491),a=n(21058),c=n(62314),s=n(98475),l=Object.assign,f=Object.defineProperty;e.exports=!l||o((function(){if(r&&1!==l({b:1},l(f({},"a",{enumerable:!0,get:function(){f(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var e={},t={},n=Symbol(),o="abcdefghijklmnopqrst";return e[n]=7,o.split("").forEach((function(e){t[e]=e})),7!=l({},e)[n]||i(l({},t)).join("")!=o}))?function(e,t){for(var n=c(e),o=arguments.length,l=1,f=u.f,d=a.f;o>l;)for(var p,h=s(arguments[l++]),g=f?i(h).concat(f(h)):i(h),v=g.length,m=0;v>m;)p=g[m++],r&&!d.call(h,p)||(n[p]=h[p]);return n}:l},73072:function(e,t,n){"use strict";var r,o=n(34699),i=n(54550),u=n(92002),a=n(97204),c=n(73214),s=n(17765),l=n(67543),f=l("IE_PROTO"),d=function(){},p=function(e){return"