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)