mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-19 19:13:30 +01:00
Merge remote-tracking branch 'upstream/master' into more_ss_ports
# Conflicts: # paradise.dme
This commit is contained in:
@@ -44,7 +44,7 @@ var/global/list/image/splatter_cache=list()
|
||||
if(B.blood_DNA)
|
||||
blood_DNA |= B.blood_DNA.Copy()
|
||||
qdel(B)
|
||||
dry_timer = addtimer(src, "dry", DRYING_TIME * (amount+1))
|
||||
dry_timer = addtimer(CALLBACK(src, .proc/dry), DRYING_TIME * (amount+1), TIMER_STOPPABLE)
|
||||
|
||||
/obj/effect/decal/cleanable/blood/Destroy()
|
||||
if(GAMEMODE_IS_CULT)
|
||||
|
||||
@@ -51,7 +51,7 @@ would spawn and follow the beaker, even if it is carried or thrown.
|
||||
for(var/i in 1 to number)
|
||||
if(total_effects > 20)
|
||||
return
|
||||
addtimer(src, "generate_effect", 0)
|
||||
INVOKE_ASYNC(src, .proc/generate_effect)
|
||||
|
||||
/datum/effect_system/proc/generate_effect()
|
||||
if(holder)
|
||||
@@ -67,7 +67,7 @@ would spawn and follow the beaker, even if it is carried or thrown.
|
||||
for(var/j in 1 to steps_amt)
|
||||
sleep(5)
|
||||
step(E,direction)
|
||||
addtimer(src, "decrement_total_effect", 20)
|
||||
addtimer(CALLBACK(src, .proc/decrement_total_effect), 20)
|
||||
|
||||
/datum/effect_system/proc/decrement_total_effect()
|
||||
total_effects--
|
||||
|
||||
@@ -58,4 +58,4 @@
|
||||
|
||||
/datum/effect_system/explosion/smoke/start()
|
||||
..()
|
||||
addtimer(src, "create_smoke", 5)
|
||||
addtimer(CALLBACK(src, .proc/create_smoke), 5)
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/kill_smoke()
|
||||
processing_objects.Remove(src)
|
||||
addtimer(src, "fade_out", 0)
|
||||
INVOKE_ASYNC(src, .proc/fade_out)
|
||||
QDEL_IN(src, 10)
|
||||
|
||||
/obj/effect/particle_effect/smoke/process()
|
||||
@@ -67,7 +67,7 @@
|
||||
if(C.smoke_delay)
|
||||
return FALSE
|
||||
C.smoke_delay++
|
||||
addtimer(src, "remove_smoke_delay", 10, FALSE, C)
|
||||
addtimer(CALLBACK(src, .proc/remove_smoke_delay, C), 10)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/remove_smoke_delay(mob/living/carbon/C)
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
else //if on the floor, glowshroom on-floor sprite
|
||||
icon_state = "[base_icon_state]f"
|
||||
|
||||
addtimer(src, "Spread", delay, FALSE)
|
||||
addtimer(CALLBACK(src, .proc/Spread), delay)
|
||||
|
||||
/obj/structure/glowshroom/proc/Spread()
|
||||
var/turf/ownturf = get_turf(src)
|
||||
@@ -117,7 +117,7 @@
|
||||
shrooms_planted++ //if we failed due to generation, don't try to plant one later
|
||||
if(shrooms_planted < myseed.yield) //if we didn't get all possible shrooms planted, try again later
|
||||
myseed.yield -= shrooms_planted
|
||||
addtimer(src, "Spread", delay, FALSE)
|
||||
addtimer(CALLBACK(src, .proc/Spread), delay)
|
||||
|
||||
/obj/structure/glowshroom/proc/CalcDir(turf/location = loc)
|
||||
var/direction = 16
|
||||
|
||||
@@ -208,7 +208,7 @@
|
||||
to_chat(I.owner, "<span class='warning'>Your photon projector implant overheats and deactivates!</span>")
|
||||
I.Retract()
|
||||
overheat = FALSE
|
||||
addtimer(src, "cooldown", flashcd * 2)
|
||||
addtimer(CALLBACK(src, .proc/cooldown), flashcd * 2)
|
||||
|
||||
/obj/item/flash/armimplant/try_use_flash(mob/user = null)
|
||||
if(overheat)
|
||||
@@ -216,7 +216,7 @@
|
||||
to_chat(I.owner, "<span class='warning'>Your photon projector is running too hot to be used again so quickly!</span>")
|
||||
return FALSE
|
||||
overheat = TRUE
|
||||
addtimer(src, "cooldown", flashcd)
|
||||
addtimer(CALLBACK(src, .proc/cooldown), flashcd)
|
||||
playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
|
||||
update_icon(1)
|
||||
return TRUE
|
||||
|
||||
@@ -271,7 +271,7 @@ var/global/list/default_medbay_channels = list(
|
||||
universal_speak = 1
|
||||
|
||||
/mob/living/automatedannouncer/New()
|
||||
lifetime_timer = addtimer(src, "autocleanup", SecondsToTicks(10))
|
||||
lifetime_timer = addtimer(CALLBACK(src, .proc/autocleanup), SecondsToTicks(10), TIMER_STOPPABLE)
|
||||
..()
|
||||
|
||||
/mob/living/automatedannouncer/Destroy()
|
||||
@@ -620,7 +620,7 @@ var/global/list/default_medbay_channels = list(
|
||||
/obj/item/radio/emp_act(severity)
|
||||
on = 0
|
||||
disable_timer++
|
||||
addtimer(src, "enable_radio", rand(100, 200))
|
||||
addtimer(CALLBACK(src, .proc/enable_radio), rand(100, 200))
|
||||
|
||||
if(listening)
|
||||
visible_message("<span class='warning'>[src] buzzes violently!</span>")
|
||||
|
||||
@@ -303,7 +303,7 @@
|
||||
|
||||
/obj/effect/decal/cleanable/ash/snappop_phoenix/New()
|
||||
. = ..()
|
||||
addtimer(src, "respawn", respawn_time)
|
||||
addtimer(CALLBACK(src, .proc/respawn), respawn_time)
|
||||
|
||||
/obj/effect/decal/cleanable/ash/snappop_phoenix/proc/respawn()
|
||||
new /obj/item/toy/snappop/phoenix(get_turf(src))
|
||||
|
||||
@@ -385,7 +385,7 @@ RCD
|
||||
buzz loudly!</b></span>","<span class='danger'><b>[src] begins \
|
||||
vibrating violently!</b></span>")
|
||||
// 5 seconds to get rid of it
|
||||
addtimer(src, "detonate_pulse_explode", 50)
|
||||
addtimer(CALLBACK(src, .proc/detonate_pulse_explode), 50)
|
||||
|
||||
/obj/item/rcd/proc/detonate_pulse_explode()
|
||||
explosion(src, 0, 0, 3, 1, flame_range = 1)
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
target.overlays += image_overlay
|
||||
if(!nadeassembly)
|
||||
to_chat(user, "<span class='notice'>You plant the bomb. Timer counting down from [det_time].</span>")
|
||||
addtimer(src, "prime", det_time*10)
|
||||
addtimer(CALLBACK(src, .proc/prime), det_time*10)
|
||||
|
||||
/obj/item/grenade/plastic/suicide_act(mob/user)
|
||||
message_admins("[key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) suicided with [src.name] at ([user.x],[user.y],[user.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)",0,1)
|
||||
|
||||
@@ -422,7 +422,7 @@
|
||||
message_admins("grenade primed by an assembly, attached by [key_name_admin(M)]<A HREF='?_src_=holder;adminmoreinfo=\ref[M]'>(?)</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[M]'>FLW</A>) and last touched by [key_name_admin(last)]<A HREF='?_src_=holder;adminmoreinfo=\ref[last]'>(?)</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[last]'>FLW</A>) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>[A.name] (JMP)</a>.")
|
||||
log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z])")
|
||||
else
|
||||
addtimer(src, "prime", det_time)
|
||||
addtimer(CALLBACK(src, .proc/prime), det_time)
|
||||
var/turf/DT = get_turf(src)
|
||||
var/area/DA = get_area(DT)
|
||||
log_game("A grenade detonated at [DA.name] ([DT.x], [DT.y], [DT.z])")
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
C.throw_mode_on()
|
||||
addtimer(src, "prime", det_time)
|
||||
addtimer(CALLBACK(src, .proc/prime), det_time)
|
||||
|
||||
/obj/item/grenade/iedcasing/prime() //Blowing that can up
|
||||
update_mob()
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
/obj/item/restraints/legcuffs/beartrap/energy/New()
|
||||
..()
|
||||
addtimer(src, "dissipate", 100)
|
||||
addtimer(CALLBACK(src, .proc/dissipate), 100)
|
||||
|
||||
/obj/item/restraints/legcuffs/beartrap/energy/proc/dissipate()
|
||||
if(!ismob(loc))
|
||||
|
||||
@@ -162,7 +162,7 @@
|
||||
being_shocked = TRUE
|
||||
var/power_bounced = power * 0.5
|
||||
tesla_zap(src, 3, power_bounced)
|
||||
addtimer(src, "reset_shocked", 10)
|
||||
addtimer(CALLBACK(src, .proc/reset_shocked), 10)
|
||||
|
||||
/obj/proc/reset_shocked()
|
||||
being_shocked = FALSE
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
to_chat(user, "<span class='warning'>Nothing interesting happens!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You emag the barsign. Takeover in progress...</span>")
|
||||
addtimer(src, "post_emag", 100)
|
||||
addtimer(CALLBACK(src, .proc/post_emag), 100)
|
||||
|
||||
/obj/structure/sign/barsign/proc/post_emag()
|
||||
if(broken || emagged)
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
return ..()
|
||||
|
||||
/obj/structure/grille/proc/build_window(obj/item/stack/sheet/S, mob/user)
|
||||
var/dir_to_set = NORTH
|
||||
if(!istype(S) || !user)
|
||||
return
|
||||
if(broken)
|
||||
@@ -160,59 +161,40 @@
|
||||
if(!getRelativeDirection(src, user) && (user.loc != loc)) //essentially a cardinal direction adjacent or sharing same loc check
|
||||
to_chat(user, "<span class='warning'>You can't reach.</span>")
|
||||
return
|
||||
if(/obj/structure/window/full in loc) //check for a full window already present (blocks the whole tile)
|
||||
to_chat(user, "<span class='warning'>There is already a full window there.</span>")
|
||||
return
|
||||
var/selection = alert(user, "What type of window would you like to place?", "Window Construction", "One Direction", "Full", "Cancel")
|
||||
if(selection == "Cancel")
|
||||
return
|
||||
if(selection == "Full")
|
||||
if(S.get_amount() < 2)
|
||||
to_chat(user, "<span class='warning'>You need at least two sheets of glass for that!</span>")
|
||||
if(loc == user.loc)
|
||||
dir_to_set = user.dir
|
||||
else
|
||||
if(x == user.x)
|
||||
if(y > user.y)
|
||||
dir_to_set = SOUTH
|
||||
else
|
||||
dir_to_set = NORTH
|
||||
else if(y == user.y)
|
||||
if(x > user.x)
|
||||
dir_to_set = WEST
|
||||
else
|
||||
dir_to_set = EAST
|
||||
for(var/obj/structure/window/WINDOW in loc)
|
||||
if(WINDOW.dir == dir_to_set)
|
||||
to_chat(user, "<span class='notice'>There is already a window facing this way there.</span>")
|
||||
return
|
||||
if(do_after(user, 20, target = src)) //glass doesn't have a toolspeed, so no multiplier
|
||||
if(broken || !anchored || !src) //make sure the grille is still intact, anchored, and exists!
|
||||
return
|
||||
if(S.get_amount() < 2) //make sure we still have enough for this!
|
||||
return
|
||||
if(!getRelativeDirection(src, user) && (user.loc != loc)) //make sure we can still do this from our location
|
||||
return
|
||||
var/obj/structure/window/W = new S.full_window(get_turf(src))
|
||||
S.use(2)
|
||||
W.anchored = 0
|
||||
W.state = 0
|
||||
to_chat(user, "<span class='notice'>You place [W] on [src].</span>")
|
||||
W.update_icon()
|
||||
return
|
||||
if(selection == "One Direction")
|
||||
var/dir_selection = input("Which direction will this window face?", "Direction") as null|anything in list("north", "east", "south", "west")
|
||||
if(!dir_selection)
|
||||
to_chat(user, "<span class='notice'>You start placing the window...</span>")
|
||||
if(do_after(user, 20, target = src))
|
||||
if(!loc || !anchored) //Grille destroyed or unanchored while waiting
|
||||
return
|
||||
var/temp_dir = text2dir(dir_selection)
|
||||
for(var/obj/structure/window/W in loc)
|
||||
if(istype(W, /obj/structure/window/full)) //double checking in case a full window was created while selecting direction
|
||||
to_chat(user, "<span class='warning'>There is already a full window there.</span>")
|
||||
for(var/obj/structure/window/WINDOW in loc)
|
||||
if(WINDOW.dir == dir_to_set)//checking this for a 2nd time to check if a window was made while we were waiting.
|
||||
to_chat(user, "<span class='notice'>There is already a window facing this way there.</span>")
|
||||
return
|
||||
if(W.dir == temp_dir) //to avoid building a window on top of an existing window
|
||||
to_chat(user, "<span class='warning'>There is already a window facing this direction there.</span>")
|
||||
return
|
||||
if(do_after(user, 20, target = src))
|
||||
if(broken || !anchored || !src) //make sure the grille is still intact, anchored, and exists!
|
||||
return
|
||||
if(S.get_amount() < 1) //make sure we still have enough fir this!
|
||||
to_chat(user, "<span class='warning'>You need at least one sheet of glass for that!</span>")
|
||||
return
|
||||
if(!getRelativeDirection(src, user) && (user.loc != loc)) //make sure we can still do this from our location
|
||||
return
|
||||
var/obj/structure/window/W = new S.created_window(get_turf(src))
|
||||
S.use(1)
|
||||
W.setDir(temp_dir)
|
||||
W.ini_dir = temp_dir
|
||||
W.anchored = 0
|
||||
W.state = 0
|
||||
to_chat(user, "<span class='notice'>You place [W] on [src].</span>")
|
||||
W.update_icon()
|
||||
return
|
||||
var/obj/structure/window/W = new S.created_window(get_turf(src))
|
||||
S.use(1)
|
||||
W.setDir(dir_to_set)
|
||||
W.ini_dir = dir_to_set
|
||||
W.anchored = 0
|
||||
W.state = 0
|
||||
to_chat(user, "<span class='notice'>You place the [W] on [src].</span>")
|
||||
W.update_icon()
|
||||
return
|
||||
|
||||
/obj/structure/grille/attacked_by(obj/item/I, mob/living/user)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
#define GUILLOTINE_BLADE_MAX_SHARP 10 // This is maxiumum sharpness that will decapitate without failure
|
||||
#define GUILLOTINE_DECAP_MIN_SHARP 7 // Minimum amount of sharpness for decapitation. Any less and it will just deal brute damage
|
||||
#define GUILLOTINE_ANIMATION_LENGTH 9 // How many deciseconds the animation is
|
||||
#define GUILLOTINE_BLADE_RAISED 1
|
||||
#define GUILLOTINE_BLADE_MOVING 2
|
||||
#define GUILLOTINE_BLADE_DROPPED 3
|
||||
#define GUILLOTINE_BLADE_SHARPENING 4
|
||||
#define GUILLOTINE_HEAD_OFFSET 16 // How much we need to move the player to center their head
|
||||
#define GUILLOTINE_LAYER_DIFF 1.2 // How much to increase/decrease a head when it's buckled/unbuckled
|
||||
#define GUILLOTINE_ACTIVATE_DELAY 30 // Delay for executing someone
|
||||
#define GUILLOTINE_WRENCH_DELAY 10
|
||||
#define GUILLOTINE_ACTION_INUSE 5
|
||||
#define GUILLOTINE_ACTION_WRENCH 6
|
||||
|
||||
/obj/structure/guillotine
|
||||
name = "guillotine"
|
||||
desc = "A large structure used to remove the heads of traitors and treasonists."
|
||||
icon = 'icons/obj/guillotine.dmi'
|
||||
icon_state = "guillotine_raised"
|
||||
can_buckle = TRUE
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
buckle_lying = FALSE
|
||||
layer = ABOVE_MOB_LAYER
|
||||
var/blade_status = GUILLOTINE_BLADE_RAISED
|
||||
var/blade_sharpness = GUILLOTINE_BLADE_MAX_SHARP // How sharp the blade is
|
||||
var/kill_count = 0
|
||||
var/force_clap = FALSE //You WILL clap if I want you to
|
||||
var/current_action = 0 // What's currently happening to the guillotine
|
||||
|
||||
/obj/structure/guillotine/examine(mob/user)
|
||||
..()
|
||||
|
||||
var/msg = ""
|
||||
|
||||
msg += "It is [anchored ? "wrenched to the floor." : "unsecured. A wrench should fix that."]<br/>"
|
||||
|
||||
if(blade_status == GUILLOTINE_BLADE_RAISED)
|
||||
msg += "The blade is raised, ready to fall, and"
|
||||
|
||||
if(blade_sharpness >= GUILLOTINE_DECAP_MIN_SHARP)
|
||||
msg += " looks sharp enough to decapitate without any resistance."
|
||||
else
|
||||
msg += " doesn't look particularly sharp. Perhaps a whetstone can be used to sharpen it."
|
||||
else
|
||||
msg += "The blade is hidden inside the stocks."
|
||||
|
||||
if(has_buckled_mobs())
|
||||
msg += "<br/>"
|
||||
msg += "Someone appears to be strapped in. You can help them out, or you can harm them by activating the guillotine."
|
||||
|
||||
to_chat(user, msg)
|
||||
|
||||
return msg
|
||||
|
||||
/obj/structure/guillotine/attack_hand(mob/user)
|
||||
add_fingerprint(user)
|
||||
|
||||
// Currently being used by something
|
||||
if(current_action)
|
||||
return
|
||||
|
||||
switch(blade_status)
|
||||
if(GUILLOTINE_BLADE_MOVING)
|
||||
return
|
||||
if(GUILLOTINE_BLADE_DROPPED)
|
||||
blade_status = GUILLOTINE_BLADE_MOVING
|
||||
icon_state = "guillotine_raise"
|
||||
addtimer(CALLBACK(src, .proc/raise_blade), GUILLOTINE_ANIMATION_LENGTH)
|
||||
return
|
||||
if(GUILLOTINE_BLADE_RAISED)
|
||||
if(has_buckled_mobs())
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
user.visible_message("<span class='warning'>[user] begins to pull the lever!</span>",
|
||||
"<span class='warning'>You begin to the pull the lever.</span>")
|
||||
current_action = GUILLOTINE_ACTION_INUSE
|
||||
|
||||
if(do_after(user, GUILLOTINE_ACTIVATE_DELAY, target = src) && blade_status == GUILLOTINE_BLADE_RAISED)
|
||||
current_action = 0
|
||||
blade_status = GUILLOTINE_BLADE_MOVING
|
||||
icon_state = "guillotine_drop"
|
||||
playsound(src, 'sound/items/unsheath.ogg', 100, 1)
|
||||
addtimer(CALLBACK(src, .proc/drop_blade, user), GUILLOTINE_ANIMATION_LENGTH - 2) // Minus two so we play the sound and decap faster
|
||||
else
|
||||
current_action = 0
|
||||
else
|
||||
unbuckle_mob()
|
||||
else
|
||||
blade_status = GUILLOTINE_BLADE_MOVING
|
||||
icon_state = "guillotine_drop"
|
||||
playsound(src, 'sound/items/unsheath.ogg', 100, 1)
|
||||
addtimer(CALLBACK(src, .proc/drop_blade), GUILLOTINE_ANIMATION_LENGTH)
|
||||
|
||||
/obj/structure/guillotine/proc/raise_blade()
|
||||
blade_status = GUILLOTINE_BLADE_RAISED
|
||||
icon_state = "guillotine_raised"
|
||||
|
||||
/obj/structure/guillotine/proc/drop_blade(mob/user)
|
||||
if(has_buckled_mobs() && blade_sharpness)
|
||||
var/mob/living/carbon/human/H = buckled_mob
|
||||
|
||||
if(!H)
|
||||
blade_status = GUILLOTINE_BLADE_DROPPED
|
||||
icon_state = "guillotine"
|
||||
return
|
||||
|
||||
var/obj/item/organ/external/head/head = H.get_organ("head")
|
||||
|
||||
if(QDELETED(head))
|
||||
blade_status = GUILLOTINE_BLADE_DROPPED
|
||||
icon_state = "guillotine"
|
||||
return
|
||||
|
||||
playsound(src, 'sound/weapons/bladeslice.ogg', 100, 1)
|
||||
if(blade_sharpness >= GUILLOTINE_DECAP_MIN_SHARP || head.brute_dam >= 100)
|
||||
head.droplimb()
|
||||
add_attack_logs(user, H, "beheaded with [src]")
|
||||
H.regenerate_icons()
|
||||
unbuckle_mob()
|
||||
kill_count += 1
|
||||
|
||||
var/blood_overlay = "bloody"
|
||||
|
||||
if(kill_count == 2)
|
||||
blood_overlay = "bloodier"
|
||||
else if(kill_count > 2)
|
||||
blood_overlay = "bloodiest"
|
||||
|
||||
blood_overlay = "guillotine_" + blood_overlay + "_overlay"
|
||||
overlays.Cut()
|
||||
overlays += mutable_appearance(icon, blood_overlay)
|
||||
|
||||
if(force_clap)
|
||||
// The crowd is pleased
|
||||
// The delay is to make large crowds have a longer lasting applause
|
||||
var/delay_offset = 0
|
||||
for(var/mob/living/carbon/human/HM in viewers(src, 7))
|
||||
addtimer(CALLBACK(HM, /mob/.proc/emote, "clap"), delay_offset * 0.3)
|
||||
delay_offset++
|
||||
else
|
||||
H.apply_damage(15 * blade_sharpness, BRUTE, head)
|
||||
add_attack_logs(user, H, "non-fatally dropped the blade on with [src]")
|
||||
H.emote("scream")
|
||||
|
||||
if(blade_sharpness > 1)
|
||||
blade_sharpness -= 1
|
||||
|
||||
blade_status = GUILLOTINE_BLADE_DROPPED
|
||||
icon_state = "guillotine"
|
||||
|
||||
/obj/structure/guillotine/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/whetstone))
|
||||
add_fingerprint(user)
|
||||
if(blade_status == GUILLOTINE_BLADE_SHARPENING)
|
||||
return
|
||||
|
||||
if(blade_status == GUILLOTINE_BLADE_RAISED)
|
||||
if(blade_sharpness < GUILLOTINE_BLADE_MAX_SHARP)
|
||||
blade_status = GUILLOTINE_BLADE_SHARPENING
|
||||
if(do_after(user, 7, target = src))
|
||||
blade_status = GUILLOTINE_BLADE_RAISED
|
||||
user.visible_message("<span class='notice'>[user] sharpens the large blade of the guillotine.</span>",
|
||||
"<span class='notice'>You sharpen the large blade of the guillotine.</span>")
|
||||
blade_sharpness += 1
|
||||
playsound(src, 'sound/items/Screwdriver.ogg', 100, 1)
|
||||
return
|
||||
else
|
||||
blade_status = GUILLOTINE_BLADE_RAISED
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The blade is sharp enough!</span>")
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to raise the blade in order to sharpen it!</span>")
|
||||
return
|
||||
if(iswrench(W))
|
||||
if(current_action)
|
||||
return
|
||||
|
||||
current_action = GUILLOTINE_ACTION_WRENCH
|
||||
|
||||
if(do_after(user, GUILLOTINE_WRENCH_DELAY, target = src))
|
||||
current_action = 0
|
||||
if(has_buckled_mobs())
|
||||
to_chat(user, "<span class='warning'>Can't unfasten, someone's strapped in!</span>")
|
||||
return
|
||||
|
||||
if(current_action)
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [src].</span>")
|
||||
anchored = !anchored
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
dir = SOUTH
|
||||
return TRUE
|
||||
else
|
||||
current_action = 0
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/structure/guillotine/buckle_mob(mob/living/M, force = 0)
|
||||
if(!anchored)
|
||||
to_chat(usr, "<span class='warning'>The [src] needs to be wrenched to the floor!</span>")
|
||||
return FALSE
|
||||
|
||||
if(!ishuman(M))
|
||||
to_chat(usr, "<span class='warning'>It doesn't look like they can fit into this properly!</span>")
|
||||
return FALSE // Can't decapitate non-humans
|
||||
|
||||
if(blade_status != GUILLOTINE_BLADE_RAISED)
|
||||
to_chat(usr, "<span class='warning'>You need to raise the blade before buckling someone in!</span>")
|
||||
return FALSE
|
||||
|
||||
if(..())
|
||||
M.pixel_y -= GUILLOTINE_HEAD_OFFSET // Offset their body so it looks like they're in the guillotine
|
||||
M.layer += GUILLOTINE_LAYER_DIFF
|
||||
|
||||
/obj/structure/guillotine/unbuckle_mob(force = 0)
|
||||
if(buckled_mob)
|
||||
buckled_mob.pixel_y += GUILLOTINE_HEAD_OFFSET // Move their body back
|
||||
buckled_mob.layer -= GUILLOTINE_LAYER_DIFF
|
||||
. = ..()
|
||||
|
||||
#undef GUILLOTINE_BLADE_MAX_SHARP
|
||||
#undef GUILLOTINE_DECAP_MIN_SHARP
|
||||
#undef GUILLOTINE_ANIMATION_LENGTH
|
||||
#undef GUILLOTINE_BLADE_RAISED
|
||||
#undef GUILLOTINE_BLADE_MOVING
|
||||
#undef GUILLOTINE_BLADE_DROPPED
|
||||
#undef GUILLOTINE_BLADE_SHARPENING
|
||||
#undef GUILLOTINE_HEAD_OFFSET
|
||||
#undef GUILLOTINE_LAYER_DIFF
|
||||
#undef GUILLOTINE_ACTIVATE_DELAY
|
||||
#undef GUILLOTINE_WRENCH_DELAY
|
||||
#undef GUILLOTINE_ACTION_INUSE
|
||||
#undef GUILLOTINE_ACTION_WRENCH
|
||||
@@ -376,7 +376,7 @@
|
||||
return
|
||||
// Don't break if they're just flying past
|
||||
if(AM.throwing)
|
||||
addtimer(src, "throw_check", 5, FALSE, AM)
|
||||
addtimer(CALLBACK(src, .proc/throw_check, AM), 5)
|
||||
else
|
||||
check_break(AM)
|
||||
|
||||
|
||||
@@ -249,9 +249,11 @@
|
||||
var/ismist = 0 //needs a var so we can make it linger~
|
||||
var/watertemp = "normal" //freezing, normal, or boiling
|
||||
var/mobpresent = 0 //true if there is a mob on the shower's loc, this is to ease process()
|
||||
var/datum/looping_sound/showering/soundloop
|
||||
|
||||
/obj/machinery/shower/New(turf/T, newdir = SOUTH, building = FALSE)
|
||||
..()
|
||||
soundloop = new(list(src), FALSE)
|
||||
if(building)
|
||||
dir = newdir
|
||||
pixel_x = 0
|
||||
@@ -264,8 +266,8 @@
|
||||
layer = FLY_LAYER
|
||||
|
||||
/obj/machinery/shower/Destroy()
|
||||
if(mymist)
|
||||
QDEL_NULL(mymist)
|
||||
QDEL_NULL(mymist)
|
||||
QDEL_NULL(soundloop)
|
||||
return ..()
|
||||
|
||||
//add heat controls? when emagged, you can freeze to death in it?
|
||||
@@ -282,6 +284,7 @@
|
||||
on = !on
|
||||
update_icon()
|
||||
if(on)
|
||||
soundloop.start()
|
||||
if(M.loc == loc)
|
||||
wash(M)
|
||||
check_heat(M)
|
||||
@@ -289,6 +292,8 @@
|
||||
for(var/atom/movable/G in src.loc)
|
||||
G.clean_blood()
|
||||
G.water_act(100, convertHeat(), src)
|
||||
else
|
||||
soundloop.stop()
|
||||
|
||||
/obj/machinery/shower/attackby(obj/item/I as obj, mob/user as mob, params)
|
||||
if(I.type == /obj/item/analyzer)
|
||||
@@ -338,9 +343,9 @@
|
||||
mist_time = 70 //7 seconds on freezing temperature to disperse existing mist
|
||||
if(watertemp == "boiling")
|
||||
mist_time = 20 //2 seconds on boiling temperature to build up mist
|
||||
addtimer(src, "update_mist", mist_time)
|
||||
addtimer(CALLBACK(src, .proc/update_mist), mist_time)
|
||||
else
|
||||
addtimer(src, "update_mist", 250) //25 seconds for mist to disperse after being turned off
|
||||
addtimer(CALLBACK(src, .proc/update_mist), 250) //25 seconds for mist to disperse after being turned off
|
||||
|
||||
/obj/machinery/shower/proc/update_mist()
|
||||
if(on)
|
||||
|
||||
Reference in New Issue
Block a user