diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm
index f5f3c6554f..3edaaf900f 100644
--- a/code/ATMOSPHERICS/components/unary/vent_pump.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm
@@ -380,7 +380,7 @@
to_chat(user, "Now welding the vent.")
if(do_after(user, 20 * WT.toolspeed))
if(!src || !WT.isOn()) return
- playsound(src.loc, WT.usesound, 50, 1)
+ playsound(src, WT.usesound, 50, 1)
if(!welded)
user.visible_message("\The [user] welds the vent shut.", "You weld the vent shut.", "You hear welding.")
welded = 1
diff --git a/code/ATMOSPHERICS/pipes/simple.dm b/code/ATMOSPHERICS/pipes/simple.dm
index 215f3498b7..e0f6f7d951 100644
--- a/code/ATMOSPHERICS/pipes/simple.dm
+++ b/code/ATMOSPHERICS/pipes/simple.dm
@@ -78,7 +78,7 @@
/obj/machinery/atmospherics/pipe/simple/proc/burst()
src.visible_message("\The [src] bursts!");
- playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
+ playsound(src, 'sound/effects/bang.ogg', 25, 1)
var/datum/effect/effect/system/smoke_spread/smoke = new
smoke.set_up(1,0, src.loc, 0)
smoke.start()
diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm
index 59837bbe5f..4d92a42c35 100644
--- a/code/ZAS/Airflow.dm
+++ b/code/ZAS/Airflow.dm
@@ -97,7 +97,7 @@ atom/movable/proc/airflow_hit(atom/A)
mob/airflow_hit(atom/A)
for(var/mob/M in hearers(src))
M.show_message("\The [src] slams into \a [A]!",1,"You hear a loud slam!",2)
- playsound(src.loc, "smash.ogg", 25, 1, -1)
+ playsound(src, "smash.ogg", 25, 1, -1)
var/weak_amt = istype(A,/obj/item) ? A:w_class : rand(1,5) //Heheheh
Weaken(weak_amt)
. = ..()
@@ -105,7 +105,7 @@ mob/airflow_hit(atom/A)
obj/airflow_hit(atom/A)
for(var/mob/M in hearers(src))
M.show_message("\The [src] slams into \a [A]!",1,"You hear a loud slam!",2)
- playsound(src.loc, "smash.ogg", 25, 1, -1)
+ playsound(src, "smash.ogg", 25, 1, -1)
. = ..()
obj/item/airflow_hit(atom/A)
@@ -115,7 +115,7 @@ obj/item/airflow_hit(atom/A)
mob/living/carbon/human/airflow_hit(atom/A)
// for(var/mob/M in hearers(src))
// M.show_message("[src] slams into [A]!",1,"You hear a loud slam!",2)
- playsound(src.loc, "punch", 25, 1, -1)
+ playsound(src, "punch", 25, 1, -1)
if (prob(33))
loc:add_blood(src)
bloody_body(src)
diff --git a/code/__defines/_planes+layers.dm b/code/__defines/_planes+layers.dm
index a8e3951a3e..c2d33e0726 100644
--- a/code/__defines/_planes+layers.dm
+++ b/code/__defines/_planes+layers.dm
@@ -67,6 +67,7 @@ What is the naming convention for planes or layers?
#define UNDERWATER_LAYER 2.5 // Anything on this layer will render under the water layer.
#define WATER_LAYER 3.0 // Layer for water overlays.
#define ABOVE_TURF_LAYER 3.1 // Snow and wallmounted/floormounted equipment
+ #define TURF_DECAL_LAYER 3.2 // Mapped in floor decals, not automatic edges/corners
#define DECAL_PLANE -44 // Permanent decals
#define DIRTY_PLANE -43 // Nonpermanent decals
#define BLOOD_PLANE -42 // Blood is really dirty, but we can do special stuff if we separate it
diff --git a/code/__defines/flags.dm b/code/__defines/flags.dm
index e59dac70c5..2ff8f44dba 100644
--- a/code/__defines/flags.dm
+++ b/code/__defines/flags.dm
@@ -29,8 +29,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define OPENCONTAINER (1<<4) // Is an open container for chemistry purposes.
#define PHORONGUARD (1<<5) // Does not get contaminated by phoron.
#define NOREACT (1<<6) // Reagents don't react inside this container.
-#define PROXMOVE (1<<7)// Does this object require proximity checking in Enter()?
-#define OVERLAY_QUEUED (1<<8)// Atom queued to SSoverlay for COMPILE_OVERLAYS
+#define OVERLAY_QUEUED (1<<7)// Atom queued to SSoverlay for COMPILE_OVERLAYS
//Flags for items (equipment) - Used in /obj/item/var/item_flags
#define THICKMATERIAL (1<<0) // Prevents syringes, parapens and hyposprays if equipped to slot_suit or slot_head.
diff --git a/code/__defines/is_helpers.dm b/code/__defines/is_helpers.dm
index d7bab37345..d7aaed2ce8 100644
--- a/code/__defines/is_helpers.dm
+++ b/code/__defines/is_helpers.dm
@@ -19,6 +19,8 @@
#define isorgan(A) istype(A, /obj/item/organ/external)
+#define isstorage(A) istype(A, /obj/item/weapon/storage)
+
//---------------
//#define isarea(D) istype(D, /area) //Built in
@@ -54,4 +56,4 @@
//---------------
//#define isturf(D) istype(D, /turf) //Built in
#define isopenspace(A) istype(A, /turf/simulated/open)
-#define isspace(A) istype(A, /turf/space)
+#define isspace(A) istype(A, /turf/space)
diff --git a/code/__defines/items_clothing.dm b/code/__defines/items_clothing.dm
index ffbda3e298..27250bc9a2 100644
--- a/code/__defines/items_clothing.dm
+++ b/code/__defines/items_clothing.dm
@@ -17,28 +17,28 @@
#define SLOT_BELT 0x200
#define SLOT_BACK 0x400
#define SLOT_POCKET 0x800 // This is to allow items with a w_class of 3 or 4 to fit in pockets.
-#define SLOT_DENYPOCKET 0x1000 // This is to deny items with a w_class of 2 or 1 from fitting in pockets.
+#define SLOT_DENYPOCKET 0x1000 // This is to deny items with a w_class of 2 or 1 from fitting in pockets.
#define SLOT_TWOEARS 0x2000
#define SLOT_TIE 0x4000
-#define SLOT_HOLSTER 0x8000 //16th bit - higher than this will overflow
+#define SLOT_HOLSTER 0x8000 //24 bit - higher than 0x80000 will overflow
-#define ACCESSORY_SLOT_UTILITY 0x1
-#define ACCESSORY_SLOT_WEAPON 0x2
+#define ACCESSORY_SLOT_UTILITY 0x1
+#define ACCESSORY_SLOT_WEAPON 0x2
#define ACCESSORY_SLOT_ARMBAND 0x4
-#define ACCESSORY_SLOT_DECOR 0x8
-#define ACCESSORY_SLOT_MEDAL 0x20
-#define ACCESSORY_SLOT_TIE 0x40
-#define ACCESSORY_SLOT_INSIGNIA 0x80
-#define ACCESSORY_SLOT_OVER 0x100
+#define ACCESSORY_SLOT_RANK 0x8
+#define ACCESSORY_SLOT_DEPT 0x20
+#define ACCESSORY_SLOT_DECOR 0x40
+#define ACCESSORY_SLOT_MEDAL 0x80
+#define ACCESSORY_SLOT_TIE 0x100
+#define ACCESSORY_SLOT_INSIGNIA 0x200
+#define ACCESSORY_SLOT_OVER 0x400
//Should these really be 'accessory' accessories
-#define ACCESSORY_SLOT_ARMOR_C 0x200
-#define ACCESSORY_SLOT_ARMOR_A 0x400
-#define ACCESSORY_SLOT_ARMOR_L 0x800
-#define ACCESSORY_SLOT_ARMOR_S 0x1000
-#define ACCESSORY_SLOT_ARMOR_M 0x2000
-#define ACCESSORY_SLOT_HELM_C 0x4000
-
-#define ACCESSORY_SLOT_TORSO (ACCESSORY_SLOT_UTILITY|ACCESSORY_SLOT_WEAPON)
+#define ACCESSORY_SLOT_ARMOR_C 0x800
+#define ACCESSORY_SLOT_ARMOR_A 0x1000
+#define ACCESSORY_SLOT_ARMOR_L 0x2000
+#define ACCESSORY_SLOT_ARMOR_S 0x4000
+#define ACCESSORY_SLOT_ARMOR_M 0x8000
+#define ACCESSORY_SLOT_HELM_C 0x10000 //24 bit - higher than 0x80000 will overflow
// Bitmasks for the /obj/item/var/flags_inv variable. These determine when a piece of clothing hides another, i.e. a helmet hiding glasses.
// WARNING: The following flags apply only to the external suit!
diff --git a/code/__defines/lighting.dm b/code/__defines/lighting.dm
index 8ad6fdfcf5..ca8eac889f 100644
--- a/code/__defines/lighting.dm
+++ b/code/__defines/lighting.dm
@@ -82,6 +82,7 @@
#define LIGHT_COLOR_INCANDESCENT_TUBE "#FFFEB8"
#define LIGHT_COLOR_INCANDESCENT_BULB "#FFDDBB"
#define LIGHT_COLOR_INCANDESCENT_FLASHLIGHT "#FFCC66"
+#define LIGHT_COLOR_NIGHTSHIFT "#EFCC86"
//Fake ambient occlusion filter
#define AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, offset=3, color="#04080F80")
diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm
index 3737d92c3d..dbe66b1243 100644
--- a/code/__defines/machinery.dm
+++ b/code/__defines/machinery.dm
@@ -18,6 +18,7 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called
#define USE_POWER_ACTIVE 2 // Machine is using power at its active power level
// Channel numbers for power.
+#define CURRENT_CHANNEL -1 // Passed as an argument this means "use whatever current channel is"
#define EQUIP 1
#define LIGHT 2
#define ENVIRON 3
diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index 84d0ac1307..20695d6534 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -372,3 +372,8 @@ var/global/list/##LIST_NAME = list();\
// Used by radios to indicate that they have sent a message via something other than subspace
#define RADIO_CONNECTION_FAIL 0
#define RADIO_CONNECTION_NON_SUBSPACE 1
+
+#define JOB_CARBON 0x1
+#define JOB_SILICON_ROBOT 0x2
+#define JOB_SILICON_AI 0x4
+#define JOB_SILICON 0x6 // 2|4, probably don't set jobs to this, but good for checking
diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm
index fd55905300..0fa2532bf9 100644
--- a/code/__defines/subsystems.dm
+++ b/code/__defines/subsystems.dm
@@ -68,8 +68,9 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_ASSETS -3
#define INIT_ORDER_PLANETS -4
#define INIT_ORDER_HOLOMAPS -5
-#define INIT_ORDER_OVERLAY -6
-#define INIT_ORDER_ALARM -7
+#define INIT_ORDER_NIGHTSHIFT -6
+#define INIT_ORDER_OVERLAY -7
+#define INIT_ORDER_ALARM -8
#define INIT_ORDER_OPENSPACE -10
#define INIT_ORDER_XENOARCH -20
#define INIT_ORDER_CIRCUIT -21
@@ -84,6 +85,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
#define FIRE_PRIORITY_SHUTTLES 5
#define FIRE_PRIORITY_SUPPLY 5
+#define FIRE_PRIORITY_NIGHTSHIFT 5
#define FIRE_PRIORITY_ORBIT 8
#define FIRE_PRIORITY_VOTE 9
#define FIRE_PRIORITY_AI 10
diff --git a/code/__defines/turfs.dm b/code/__defines/turfs.dm
index bf4c3de6fe..64593f6e11 100644
--- a/code/__defines/turfs.dm
+++ b/code/__defines/turfs.dm
@@ -9,5 +9,12 @@
#define TURF_IS_FRAGILE 256
#define TURF_ACID_IMMUNE 512
+//Used for floor/wall smoothing
+#define SMOOTH_NONE 0 //Smooth only with itself
+#define SMOOTH_ALL 1 //Smooth with all of type
+#define SMOOTH_WHITELIST 2 //Smooth with a whitelist of subtypes
+#define SMOOTH_BLACKLIST 3 //Smooth with all but a blacklist of subtypes
+#define SMOOTH_GREYLIST 4 // Use a whitelist and a blacklist at the same time. atom smoothing only
+
#define isCardinal(x) (x == NORTH || x == SOUTH || x == EAST || x == WEST)
#define isDiagonal(x) (x == NORTHEAST || x == SOUTHEAST || x == NORTHWEST || x == SOUTHWEST)
\ No newline at end of file
diff --git a/code/_helpers/_lists.dm b/code/_helpers/_lists.dm
index d844d61b5c..124f69f45e 100644
--- a/code/_helpers/_lists.dm
+++ b/code/_helpers/_lists.dm
@@ -16,7 +16,7 @@
*/
//Returns a list in plain english as a string
-/proc/english_list(var/list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "")
+/proc/english_list(var/list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = ",")
// this proc cannot be merged with counting_english_list to maintain compatibility
// with shoddy use of this proc for code logic and for cases that require original order
switch(input.len)
@@ -26,7 +26,7 @@
else return "[jointext(input, comma_text, 1, -1)][final_comma_text][and_text][input[input.len]]"
//Returns a newline-separated list that counts equal-ish items, outputting count and item names, optionally with icons and specific determiners
-/proc/counting_english_list(var/list/input, output_icons = TRUE, determiners = DET_NONE, nothing_text = "nothing", line_prefix = "\t", first_item_prefix = "\n", last_item_suffix = "\n", and_text = "\n", comma_text = "\n", final_comma_text = "")
+/proc/counting_english_list(var/list/input, output_icons = TRUE, determiners = DET_NONE, nothing_text = "nothing", line_prefix = "\t", first_item_prefix = "\n", last_item_suffix = "\n", and_text = "\n", comma_text = "\n", final_comma_text = ",")
var/list/counts = list() // counted input items
var/list/items = list() // actual objects for later reference (for icons and formatting)
diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm
index 7be9093596..16fdec7bd0 100644
--- a/code/_helpers/game.dm
+++ b/code/_helpers/game.dm
@@ -231,35 +231,43 @@
. = list()
// Returns a list of mobs who can hear any of the radios given in @radios
var/list/speaker_coverage = list()
- for(var/obj/item/device/radio/R in radios)
- if(R)
- //Cyborg checks. Receiving message uses a bit of cyborg's charge.
- var/obj/item/device/radio/borg/BR = R
- if(istype(BR) && BR.myborg)
- var/mob/living/silicon/robot/borg = BR.myborg
- var/datum/robot_component/CO = borg.get_component("radio")
- if(!CO)
- continue //No radio component (Shouldn't happen)
- if(!borg.is_component_functioning("radio") || !borg.cell_use_power(CO.active_usage))
- continue //No power.
-
- var/turf/speaker = get_turf(R)
- if(speaker)
- for(var/turf/T in hear(R.canhear_range,speaker))
- speaker_coverage[T] = R
+ for(var/r in radios)
+ var/obj/item/device/radio/R = r // You better fucking be a radio.
+ var/turf/speaker = get_turf(R)
+ if(speaker)
+ for(var/turf/T in hear(R.canhear_range,speaker))
+ speaker_coverage[T] = R
// Try to find all the players who can hear the message
for(var/i = 1; i <= player_list.len; i++)
var/mob/M = player_list[i]
- if(M)
- var/turf/ear = get_turf(M)
- if(ear)
- // Ghostship is magic: Ghosts can hear radio chatter from anywhere
- if(speaker_coverage[ear] || (istype(M, /mob/observer/dead) && M.is_preference_enabled(/datum/client_preference/ghost_radio)))
- . |= M // Since we're already looping through mobs, why bother using |= ? This only slows things down.
+ if(M.can_hear_radio(speaker_coverage))
+ . += M
return .
+/mob/proc/can_hear_radio(var/list/hearturfs)
+ return FALSE
+
+/mob/living/can_hear_radio(var/list/hearturfs)
+ return get_turf(src) in hearturfs
+
+/mob/living/silicon/robot/can_hear_radio(var/list/hearturfs)
+ var/turf/T = get_turf(src)
+ var/obj/item/device/radio/borg/R = hearturfs[T] // this should be an assoc list of turf-to-radio
+
+ // We heard it on our own radio? We use power for that.
+ if(istype(R) && R.myborg == src)
+ var/datum/robot_component/CO = get_component("radio")
+ if(!CO || !is_component_functioning("radio") || !cell_use_power(CO.active_usage))
+ return FALSE // Sorry, couldn't hear
+
+ return R // radio, true, false, what's the difference
+
+/mob/observer/dead/can_hear_radio(var/list/hearturfs)
+ return is_preference_enabled(/datum/client_preference/ghost_radio)
+
+
//Uses dview to quickly return mobs and objects in view,
// then adds additional mobs or objects if they are in range 'smartly',
// based on their presence in lists of players or registered objects
@@ -272,17 +280,17 @@
var/list/hearturfs = list()
for(var/thing in hear)
- if(istype(thing,/obj))
+ if(istype(thing, /obj)) //Can't use isobj() because /atom/movable returns true in that, and so lighting overlays would be included
objs += thing
hearturfs |= get_turf(thing)
- else if(istype(thing,/mob))
+ if(ismob(thing))
mobs += thing
hearturfs |= get_turf(thing)
//A list of every mob with a client
for(var/mob in player_list)
- if(!istype(mob, /mob))
- crash_with("There is a null or non-mob reference inside player_list.")
+ if(!ismob(mob))
+ player_list -= mob
continue
if(get_turf(mob) in hearturfs)
mobs |= mob
diff --git a/code/_helpers/time.dm b/code/_helpers/time.dm
index c075925fdd..8648225d3a 100644
--- a/code/_helpers/time.dm
+++ b/code/_helpers/time.dm
@@ -18,6 +18,7 @@
#define DS2TICKS(DS) ((DS)/world.tick_lag) // Convert deciseconds to ticks
#define TICKS2DS(T) ((T) TICKS) // Convert ticks to deciseconds
+#define DS2NEARESTTICK(DS) TICKS2DS(-round(-(DS2TICKS(DS))))
/proc/get_game_time()
var/global/time_offset = 0
@@ -35,25 +36,25 @@
return wtime + (time_offset + wusage) * world.tick_lag
-var/roundstart_hour
+GLOBAL_VAR_INIT(roundstart_hour, pick(2,7,12,17))
var/station_date = ""
var/next_station_date_change = 1 DAY
-#define duration2stationtime(time) time2text(station_time_in_ticks + time, "hh:mm")
-#define worldtime2stationtime(time) time2text(roundstart_hour HOURS + time, "hh:mm")
-#define round_duration_in_ticks (round_start_time ? world.time - round_start_time : 0)
-#define station_time_in_ticks (roundstart_hour HOURS + round_duration_in_ticks)
+#define duration2stationtime(time) time2text(station_time_in_ds + time, "hh:mm")
+#define worldtime2stationtime(time) time2text(GLOB.roundstart_hour HOURS + time, "hh:mm")
+#define round_duration_in_ds (GLOB.round_start_time ? world.time - GLOB.round_start_time : 0)
+#define station_time_in_ds (GLOB.roundstart_hour HOURS + round_duration_in_ds)
/proc/stationtime2text()
- return time2text(station_time_in_ticks, "hh:mm")
+ return time2text(station_time_in_ds + GLOB.timezoneOffset, "hh:mm")
/proc/stationdate2text()
var/update_time = FALSE
- if(station_time_in_ticks > next_station_date_change)
+ if(station_time_in_ds > next_station_date_change)
next_station_date_change += 1 DAY
update_time = TRUE
if(!station_date || update_time)
- var/extra_days = round(station_time_in_ticks / (1 DAY)) DAYS
+ var/extra_days = round(station_time_in_ds / (1 DAY)) DAYS
var/timeofday = world.timeofday + extra_days
station_date = num2text((text2num(time2text(timeofday, "YYYY"))+544)) + "-" + time2text(timeofday, "MM-DD")
return station_date
@@ -64,6 +65,13 @@ var/next_station_date_change = 1 DAY
var/time_portion = time2text(world.timeofday, "hh:mm:ss")
return "[date_portion]T[time_portion]"
+/proc/get_timezone_offset()
+ var/midnight_gmt_here = text2num(time2text(0,"hh")) * 36000
+ if(midnight_gmt_here > 12 HOURS)
+ return 24 HOURS - midnight_gmt_here
+ else
+ return midnight_gmt_here
+
/proc/gameTimestamp(format = "hh:mm:ss", wtime=null)
if(!wtime)
wtime = world.time
@@ -83,19 +91,19 @@ proc/isDay(var/month, var/day)
var/next_duration_update = 0
var/last_round_duration = 0
-var/round_start_time = 0
+GLOBAL_VAR_INIT(round_start_time, 0)
/hook/roundstart/proc/start_timer()
- round_start_time = world.time
+ GLOB.round_start_time = world.time
return 1
/proc/roundduration2text()
- if(!round_start_time)
+ if(!GLOB.round_start_time)
return "00:00"
if(last_round_duration && world.time < next_duration_update)
return last_round_duration
- var/mills = round_duration_in_ticks // 1/10 of a second, not real milliseconds but whatever
+ var/mills = round_duration_in_ds // 1/10 of a second, not real milliseconds but whatever
//var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)
@@ -112,10 +120,6 @@ var/round_start_time = 0
var/datum/controller/process/process = processScheduler.getProcess(process_name)
return process.schedule_interval
-/hook/startup/proc/set_roundstart_hour()
- roundstart_hour = pick(2,7,12,17)
- return 1
-
/var/midnight_rollovers = 0
/var/rollovercheck_last_timeofday = 0
/proc/update_midnight_rollover()
diff --git a/code/_helpers/turfs.dm b/code/_helpers/turfs.dm
index a9cede52de..5a0a519743 100644
--- a/code/_helpers/turfs.dm
+++ b/code/_helpers/turfs.dm
@@ -169,3 +169,11 @@
T.ChangeTurf(get_base_turf_by_area(T))
return TRUE
+
+//Used for border objects. This returns true if this atom is on the border between the two specified turfs
+//This assumes that the atom is located inside the target turf
+/atom/proc/is_between_turfs(var/turf/origin, var/turf/target)
+ if (flags & ON_BORDER)
+ var/testdir = get_dir(target, origin)
+ return (dir & testdir)
+ return TRUE
diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index 15b65755c7..b431ac1298 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -23,9 +23,10 @@
/mob/living/silicon/ai/ClickOn(var/atom/A, params)
- if(world.time <= next_click)
+ if(!checkClickCooldown())
return
- next_click = world.time + 1
+
+ setClickCooldown(1)
if(client.buildmode) // comes after object.Click to allow buildmode gui objects to be clicked
build_click(src, client.buildmode, params, A)
@@ -42,6 +43,9 @@
if(stat)
return
+ if(control_disabled)
+ return
+
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
@@ -52,27 +56,18 @@
if(modifiers["shift"])
ShiftClickOn(A)
return
- if(modifiers["alt"]) // alt and alt-gr (rightalt)
+ if(modifiers["alt"])
AltClickOn(A)
return
if(modifiers["ctrl"])
CtrlClickOn(A)
return
- if(control_disabled || !canClick())
- return
-
if(aiCamera.in_camera_mode)
aiCamera.camera_mode_off()
aiCamera.captureimage(A, usr)
return
- /*
- AI restrained() currently does nothing
- if(restrained())
- RestrainedClickOn(A)
- else
- */
A.add_hiddenprint(src)
A.attack_ai(src)
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 8184c122e2..5b7a043569 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -38,10 +38,10 @@
* mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed
*/
/mob/proc/ClickOn(var/atom/A, var/params)
- if(world.time <= next_click) // Hard check, before anything else, to avoid crashing
+ if(!checkClickCooldown()) // Hard check, before anything else, to avoid crashing
return
- next_click = world.time + 1
+ setClickCooldown(1)
if(client && client.buildmode)
build_click(src, client.buildmode, params, A)
@@ -69,9 +69,6 @@
face_atom(A) // change direction to face what you clicked on
- if(!canClick()) // in the year 2000...
- return
-
if(istype(loc, /obj/mecha))
if(!locate(/turf) in list(A, A.loc)) // Prevents inventory from being drilled
return
@@ -143,12 +140,12 @@
return 1
/mob/proc/setClickCooldown(var/timeout)
- next_move = max(world.time + timeout, next_move)
+ next_click = max(world.time + timeout, next_click)
-/mob/proc/canClick()
- if(config.no_click_cooldown || next_move <= world.time)
- return 1
- return 0
+/mob/proc/checkClickCooldown()
+ if(next_click > world.time && !config.no_click_cooldown)
+ return FALSE
+ return TRUE
// Default behavior: ignore double clicks, the second click that makes the doubleclick call already calls for a normal click
/mob/proc/DblClickOn(var/atom/A, var/params)
@@ -295,7 +292,7 @@
var/obj/item/projectile/beam/LE = new (T)
LE.icon = 'icons/effects/genetics.dmi'
LE.icon_state = "eyelasers"
- playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1)
+ playsound(src, 'sound/weapons/taser2.ogg', 75, 1)
LE.firer = src
LE.preparePixelProjectile(A, src, params)
LE.fire()
diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index f8bce398a6..0c99425147 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -7,9 +7,10 @@
*/
/mob/living/silicon/robot/ClickOn(var/atom/A, var/params)
- if(world.time <= next_click)
+ if(!checkClickCooldown())
return
- next_click = world.time + 1
+
+ setClickCooldown(1)
if(client.buildmode) // comes after object.Click to allow buildmode gui objects to be clicked
build_click(src, client.buildmode, params, A)
@@ -35,9 +36,6 @@
if(stat || lockdown || weakened || stunned || paralysis)
return
- if(!canClick())
- return
-
face_atom(A) // change direction to face what you clicked on
if(aiCamera && aiCamera.in_camera_mode)
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index 4736d5d074..828a86fe2b 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -78,6 +78,13 @@
#define ui_ai_multicam "SOUTH+1:6,WEST+13"
#define ui_ai_add_multicam "SOUTH+1:6,WEST+14"
+//Upper-middle right (alerts)
+#define ui_alert1 "EAST-1:28,CENTER+5:27"
+#define ui_alert2 "EAST-1:28,CENTER+4:25"
+#define ui_alert3 "EAST-1:28,CENTER+3:23"
+#define ui_alert4 "EAST-1:28,CENTER+2:21"
+#define ui_alert5 "EAST-1:28,CENTER+1:19"
+
//Gun buttons
#define ui_gun1 "EAST-2:26,SOUTH+2:7"
#define ui_gun2 "EAST-1:28, SOUTH+3:7"
@@ -96,13 +103,12 @@
#define ui_alien_oxygen "EAST-1:28,NORTH-4:25"
//Middle right (status indicators)
-#define ui_nutrition "EAST-1:28,CENTER-2:11"
-#define ui_temp "EAST-1:28,CENTER-1:13"
-#define ui_health "EAST-1:28,CENTER:15"
-#define ui_internal "EAST-1:28,CENTER+1:17"
+#define ui_temp "EAST-1:28,CENTER-2:13"
+#define ui_health "EAST-1:28,CENTER-1:15"
+#define ui_internal "EAST-1:28,CENTER:17"
//borgs
-#define ui_borg_health "EAST-1:28,CENTER-1:13" //borgs have the health display where humans have the pressure damage indicator.
-#define ui_alien_health "EAST-1:28,CENTER-1:13" //aliens have the health display where humans have the pressure damage indicator.
+#define ui_borg_health "EAST-1:28,CENTER-2:13" //borgs have the health display where humans have the pressure damage indicator.
+#define ui_alien_health "EAST-1:28,CENTER-2:13" //aliens have the health display where humans have the pressure damage indicator.
#define ui_ling_chemical_display "EAST-1:28,CENTER-3:15"
#define ui_wiz_energy_display "EAST-1:28,CENTER-3:15"
diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm
index b5299cd77b..c123790b51 100644
--- a/code/_onclick/hud/action.dm
+++ b/code/_onclick/hud/action.dm
@@ -123,7 +123,7 @@
if(modifiers["shift"])
moved = 0
return 1
- if(usr.next_move >= world.time) // Is this needed ?
+ if(!usr.checkClickCooldown())
return
owner.Trigger()
return 1
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
new file mode 100644
index 0000000000..f45f8f3d3a
--- /dev/null
+++ b/code/_onclick/hud/alert.dm
@@ -0,0 +1,445 @@
+//A system to manage and display alerts on screen without needing you to do it yourself
+
+//PUBLIC - call these wherever you want
+
+
+/mob/proc/throw_alert(category, type, severity, obj/new_master)
+
+/* Proc to create or update an alert. Returns the alert if the alert is new or updated, 0 if it was thrown already
+ category is a text string. Each mob may only have one alert per category; the previous one will be replaced
+ path is a type path of the actual alert type to throw
+ severity is an optional number that will be placed at the end of the icon_state for this alert
+ For example, high pressure's icon_state is "highpressure" and can be serverity 1 or 2 to get "highpressure1" or "highpressure2"
+ new_master is optional and sets the alert's icon state to "template" in the ui_style icons with the master as an overlay.
+ Clicks are forwarded to master */
+
+ if(!category)
+ return
+
+ var/obj/screen/alert/alert
+ if(alerts[category])
+ alert = alerts[category]
+ if(new_master && new_master != alert.master)
+ WARNING("[src] threw alert [category] with new_master [new_master] while already having that alert with master [alert.master]")
+ clear_alert(category)
+ return .()
+ else if(alert.type != type)
+ clear_alert(category)
+ return .()
+ else if(!severity || severity == alert.severity)
+ if(alert.timeout)
+ clear_alert(category)
+ return .()
+ else //no need to update
+ return 0
+ else
+ alert = new type
+
+ if(new_master)
+ var/old_layer = new_master.layer
+ var/old_plane = new_master.plane
+ new_master.layer = LAYER_HUD_ABOVE
+ new_master.plane = PLANE_PLAYER_HUD_ABOVE
+ alert.overlays += new_master
+ new_master.layer = old_layer
+ new_master.plane = old_plane
+ alert.icon_state = "template" // We'll set the icon to the client's ui pref in reorganize_alerts()
+ alert.master = new_master
+ else
+ alert.icon_state = "[initial(alert.icon_state)][severity]"
+ alert.severity = severity
+
+ alerts[category] = alert
+ if(client && hud_used)
+ hud_used.reorganize_alerts()
+ alert.transform = matrix(32, 6, MATRIX_TRANSLATE)
+ animate(alert, transform = matrix(), time = 2.5, easing = CUBIC_EASING)
+
+ if(alert.timeout)
+ addtimer(CALLBACK(src, .proc/alert_timeout, alert, category), alert.timeout)
+ alert.timeout = world.time + alert.timeout - world.tick_lag
+ return alert
+
+/mob/proc/alert_timeout(obj/screen/alert/alert, category)
+ if(alert.timeout && alerts[category] == alert && world.time >= alert.timeout)
+ clear_alert(category)
+
+// Proc to clear an existing alert.
+/mob/proc/clear_alert(category)
+ var/obj/screen/alert/alert = alerts[category]
+ if(!alert)
+ return 0
+
+ alerts -= category
+ if(client && hud_used)
+ hud_used.reorganize_alerts()
+ client.screen -= alert
+ qdel(alert)
+
+/obj/screen/alert
+ icon = 'icons/mob/screen_alert.dmi'
+ icon_state = "default"
+ name = "Alert"
+ desc = "Something seems to have gone wrong with this alert, so report this bug please"
+ mouse_opacity = 1
+ var/timeout = 0 //If set to a number, this alert will clear itself after that many deciseconds
+ var/severity = 0
+ var/alerttooltipstyle = ""
+
+
+/obj/screen/alert/MouseEntered(location,control,params)
+ openToolTip(usr, src, params, title = name, content = desc, theme = alerttooltipstyle)
+
+
+/obj/screen/alert/MouseExited()
+ closeToolTip(usr)
+
+
+//Gas alerts
+/obj/screen/alert/not_enough_oxy
+ name = "Choking (No O2)"
+ desc = "You're not getting enough oxygen. Find some good air before you pass out! \
+The box in your backpack has an oxygen tank and breath mask in it."
+ icon_state = "not_enough_oxy"
+
+/obj/screen/alert/too_much_oxy
+ name = "Choking (O2)"
+ desc = "There's too much oxygen in the air, and you're breathing it in! Find some good air before you pass out!"
+ icon_state = "too_much_oxy"
+
+/obj/screen/alert/not_enough_nitro
+ name = "Choking (No N)"
+ desc = "You're not getting enough nitrogen. Find some good air before you pass out!"
+ icon_state = "not_enough_nitro"
+
+/obj/screen/alert/too_much_nitro
+ name = "Choking (N)"
+ desc = "There's too much nitrogen in the air, and you're breathing it in! Find some good air before you pass out!"
+ icon_state = "too_much_nitro"
+
+/obj/screen/alert/not_enough_co2
+ name = "Choking (No CO2)"
+ desc = "You're not getting enough carbon dioxide. Find some good air before you pass out!"
+ icon_state = "not_enough_co2"
+
+/obj/screen/alert/too_much_co2
+ name = "Choking (CO2)"
+ desc = "There's too much carbon dioxide in the air, and you're breathing it in! Find some good air before you pass out!"
+ icon_state = "too_much_co2"
+
+/obj/screen/alert/too_much_co2/plant
+ name = "Livin' the good life"
+ desc = "There's so much carbon dioxide in the air, you're in fucking heaven. Watch out for passed out fleshies, though."
+ icon_state = "too_much_co2"
+
+/obj/screen/alert/not_enough_tox
+ name = "Choking (No Phoron)"
+ desc = "You're not getting enough phoron. Find some good air before you pass out!"
+ icon_state = "not_enough_tox"
+
+/obj/screen/alert/tox_in_air
+ name = "Choking (Phoron)"
+ desc = "There's highly flammable, toxic phoron in the air and you're breathing it in. Find some fresh air. \
+The box in your backpack has an oxygen tank and gas mask in it."
+ icon_state = "too_much_tox"
+
+/obj/screen/alert/not_enough_fuel
+ name = "Choking (No Volatile fuel)"
+ desc = "You're not getting enough volatile fuel. Find some good air before you pass out!"
+ icon_state = "not_enough_tox"
+
+/obj/screen/alert/not_enough_n2o
+ name = "Choking (No Sleeping Gas)"
+ desc = "You're not getting enough sleeping gas. Find some good air before you pass out!"
+ icon_state = "not_enough_tox"
+//End gas alerts
+
+
+/obj/screen/alert/fat
+ name = "Fat"
+ desc = "You ate too much food, lardass. Run around the station and lose some weight."
+ icon_state = "fat"
+
+/obj/screen/alert/fat/vampire
+ desc = "You drank too much blood, lardass. Run around the station and lose some weight."
+ icon_state = "v_fat"
+
+/obj/screen/alert/fat/synth
+ desc = "Your battery is full! Don't overvolt it."
+ icon_state = "c_fat"
+
+/obj/screen/alert/hungry
+ name = "Hungry"
+ desc = "Some food would be good right about now."
+ icon_state = "hungry"
+
+/obj/screen/alert/hungry/vampire
+ desc = "You could use a bloodsnack or two."
+ icon_state = "v_hungry"
+
+/obj/screen/alert/hungry/synth
+ desc = "Battery's running a bit low, could use a topoff."
+ icon_state = "c_hungry"
+
+/obj/screen/alert/starving
+ name = "Starving"
+ desc = "You're severely malnourished. The hunger pains make moving around a chore."
+ icon_state = "starving"
+
+/obj/screen/alert/starving/vampire
+ desc = "You *need* blood; go rip out someone's throat already!"
+ icon_state = "v_starving"
+
+/obj/screen/alert/starving/synth
+ desc = "Your battery is about to die! Charge it ASAP!"
+ icon_state = "c_starving"
+
+/obj/screen/alert/hot
+ name = "Too Hot"
+ desc = "You're flaming hot! Get somewhere cooler and take off any insulating clothing like a fire suit."
+ icon_state = "hot"
+
+/obj/screen/alert/hot/robot
+ desc = "The air around you is too hot for a humanoid. Be careful to avoid exposing them to this enviroment."
+
+/obj/screen/alert/cold
+ name = "Too Cold"
+ desc = "You're freezing cold! Get somewhere warmer and take off any insulating clothing like a space suit."
+ icon_state = "cold"
+
+/obj/screen/alert/cold/robot
+ desc = "The air around you is too cold for a humanoid. Be careful to avoid exposing them to this enviroment."
+
+/obj/screen/alert/lowpressure
+ name = "Low Pressure"
+ desc = "The air around you is hazardously thin. A space suit would protect you."
+ icon_state = "lowpressure"
+
+/obj/screen/alert/highpressure
+ name = "High Pressure"
+ desc = "The air around you is hazardously thick. A fire suit would protect you."
+ icon_state = "highpressure"
+
+/obj/screen/alert/blind
+ name = "Blind"
+ desc = "You can't see! This may be caused by a genetic defect, eye trauma, being unconscious, \
+or something covering your eyes."
+ icon_state = "blind"
+
+/obj/screen/alert/high
+ name = "High"
+ desc = "Whoa man, you're tripping balls! Careful you don't get addicted... if you aren't already."
+ icon_state = "high"
+
+/obj/screen/alert/embeddedobject
+ name = "Embedded Object"
+ desc = "Something got lodged into your flesh and is causing major bleeding. It might fall out with time, but surgery is the safest way. \
+If you're feeling frisky, right click on yourself and select \"Remove embedded object\" to pull the object out."
+ icon_state = "embeddedobject"
+
+/obj/screen/alert/embeddedobject/Click()
+ if(isliving(usr))
+ var/mob/living/carbon/human/M = usr
+ return M.help_shake_act(M)
+
+/obj/screen/alert/asleep
+ name = "Asleep"
+ 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"
+
+/obj/screen/alert/weightless
+ name = "Weightless"
+ desc = "Gravity has ceased affecting you, and you're floating around aimlessly. You'll need something large and heavy, like a \
+wall or lattice, to push yourself off if you want to move. A jetpack would enable free range of motion. A pair of \
+magboots would let you walk around normally on the floor. Barring those, you can throw things, use a fire extinguisher, \
+or shoot a gun to move around via Newton's 3rd Law of Motion."
+ icon_state = "weightless"
+
+/obj/screen/alert/fire
+ name = "On Fire"
+ desc = "You're on fire. Stop, drop and roll to put the fire out or move to a vacuum area."
+ icon_state = "fire"
+
+/obj/screen/alert/fire/Click()
+ if(isliving(usr))
+ var/mob/living/L = usr
+ return L.resist()
+
+
+//ALIENS
+
+/obj/screen/alert/alien_tox
+ name = "Plasma"
+ desc = "There's flammable plasma in the air. If it lights up, you'll be toast."
+ icon_state = "alien_tox"
+ alerttooltipstyle = "alien"
+
+/obj/screen/alert/alien_fire
+// This alert is temporarily gonna be thrown for all hot air but one day it will be used for literally being on fire
+ name = "Too Hot"
+ desc = "It's too hot! Flee to space or at least away from the flames. Standing on weeds will heal you."
+ icon_state = "alien_fire"
+ alerttooltipstyle = "alien"
+
+/obj/screen/alert/alien_vulnerable
+ name = "Severed Matriarchy"
+ desc = "Your queen has been killed, you will suffer movement penalties and loss of hivemind. A new queen cannot be made until you recover."
+ icon_state = "alien_noqueen"
+ alerttooltipstyle = "alien"
+
+//BLOBS
+
+/obj/screen/alert/nofactory
+ name = "No Factory"
+ desc = "You have no factory, and are slowly dying!"
+ icon_state = "blobbernaut_nofactory"
+ alerttooltipstyle = "blob"
+
+//SILICONS
+
+/obj/screen/alert/nocell
+ name = "Missing Power Cell"
+ desc = "Unit has no power cell. No modules available until a power cell is reinstalled. Robotics may provide assistance."
+ icon_state = "nocell"
+
+/obj/screen/alert/emptycell
+ name = "Out of Power"
+ desc = "Unit's power cell has no charge remaining. No modules available until power cell is recharged. \
+Recharging stations are available in robotics, the dormitory bathrooms, and the AI satellite."
+ icon_state = "emptycell"
+
+/obj/screen/alert/lowcell
+ name = "Low Charge"
+ desc = "Unit's power cell is running low. Recharging stations are available in robotics, the dormitory bathrooms, and the AI satellite."
+ icon_state = "lowcell"
+
+//Need to cover all use cases - emag, illegal upgrade module, malf AI hack, traitor cyborg
+/obj/screen/alert/hacked
+ name = "Hacked"
+ desc = "Hazardous non-standard equipment detected. Please ensure any usage of this equipment is in line with unit's laws, if any."
+ icon_state = "hacked"
+
+/obj/screen/alert/locked
+ name = "Locked Down"
+ desc = "Unit has been remotely locked down. Usage of a Robotics Control Console like the one in the Research Director's \
+office by your AI master or any qualified human may resolve this matter. Robotics may provide further assistance if necessary."
+ icon_state = "locked"
+
+/obj/screen/alert/newlaw
+ name = "Law Update"
+ desc = "Laws have potentially been uploaded to or removed from this unit. Please be aware of any changes \
+so as to remain in compliance with the most up-to-date laws."
+ icon_state = "newlaw"
+ timeout = 300
+
+//MECHS
+
+/obj/screen/alert/low_mech_integrity
+ name = "Mech Damaged"
+ desc = "Mech integrity is low."
+ icon_state = "low_mech_integrity"
+
+
+//GHOSTS
+//TODO: expand this system to replace the pollCandidates/CheckAntagonist/"choose quickly"/etc Yes/No messages
+/obj/screen/alert/notify_cloning
+ name = "Revival"
+ desc = "Someone is trying to revive you. Re-enter your corpse if you want to be revived!"
+ icon_state = "template"
+ timeout = 300
+
+/obj/screen/alert/notify_cloning/Click()
+ if(!usr || !usr.client) return
+ var/mob/observer/dead/G = usr
+ G.reenter_corpse()
+
+// /obj/screen/alert/notify_jump
+// name = "Body created"
+// desc = "A body was created. You can enter it."
+// icon_state = "template"
+// timeout = 300
+// var/atom/jump_target = null
+// var/attack_not_jump = null
+
+// /obj/screen/alert/notify_jump/Click()
+// if(!usr || !usr.client) return
+// if(!jump_target) return
+// var/mob/dead/observer/G = usr
+// if(!istype(G)) return
+// if(attack_not_jump)
+// jump_target.attack_ghost(G)
+// else
+// var/turf/T = get_turf(jump_target)
+// if(T && isturf(T))
+// G.loc = T
+
+//OBJECT-BASED
+
+/obj/screen/alert/restrained/buckled
+ name = "Buckled"
+ desc = "You've been buckled to something. Click the alert to unbuckle unless you're handcuffed."
+
+/obj/screen/alert/restrained/handcuffed
+ name = "Handcuffed"
+ desc = "You're handcuffed and can't act. If anyone drags you, you won't be able to move. Click the alert to free yourself."
+
+/obj/screen/alert/restrained/legcuffed
+ name = "Legcuffed"
+ desc = "You're legcuffed, which slows you down considerably. Click the alert to free yourself."
+
+/obj/screen/alert/restrained/Click()
+ if(isliving(usr))
+ var/mob/living/L = usr
+ return L.resist()
+// PRIVATE = only edit, use, or override these if you're editing the system as a whole
+
+// Re-render all alerts - also called in /datum/hud/show_hud() because it's needed there
+/datum/hud/proc/reorganize_alerts()
+ var/list/alerts = mymob.alerts
+ var/icon_pref
+ if(!hud_shown)
+ for(var/i = 1, i <= alerts.len, i++)
+ mymob.client.screen -= alerts[alerts[i]]
+ return 1
+ for(var/i = 1, i <= alerts.len, i++)
+ var/obj/screen/alert/alert = alerts[alerts[i]]
+ if(alert.icon_state == "template")
+ if(!icon_pref)
+ icon_pref = ui_style2icon(mymob.client.prefs.UI_style)
+ alert.icon = icon_pref
+ switch(i)
+ if(1)
+ . = ui_alert1
+ if(2)
+ . = ui_alert2
+ if(3)
+ . = ui_alert3
+ if(4)
+ . = ui_alert4
+ if(5)
+ . = ui_alert5 // Right now there's 5 slots
+ else
+ . = ""
+ alert.screen_loc = .
+ mymob.client.screen |= alert
+ return 1
+
+/mob
+ var/list/alerts = list() // contains /obj/screen/alert only // On /mob so clientless mobs will throw alerts properly
+
+/obj/screen/alert/Click(location, control, params)
+ if(!usr || !usr.client)
+ return
+ var/paramslist = params2list(params)
+ if(paramslist["shift"]) // screen objects don't do the normal Click() stuff so we'll cheat
+ to_chat(usr,"[name] - [desc]")
+ return
+ if(master)
+ return usr.client.Click(master, location, control, params)
+
+/obj/screen/alert/Destroy()
+ ..()
+ severity = 0
+ master = null
+ screen_loc = ""
+ return QDEL_HINT_QUEUE
diff --git a/code/_onclick/hud/alien_larva.dm b/code/_onclick/hud/alien_larva.dm
index 2ec9da3b27..960582b4b1 100644
--- a/code/_onclick/hud/alien_larva.dm
+++ b/code/_onclick/hud/alien_larva.dm
@@ -21,13 +21,7 @@
mymob.healths.name = "health"
mymob.healths.screen_loc = ui_alien_health
- mymob.fire = new /obj/screen()
- mymob.fire.icon = 'icons/mob/screen1_alien.dmi'
- mymob.fire.icon_state = "fire0"
- mymob.fire.name = "fire"
- mymob.fire.screen_loc = ui_fire
-
mymob.client.screen = list()
- mymob.client.screen += list( mymob.healths, mymob.fire) //, mymob.rest, mymob.sleep, mymob.mach )
+ mymob.client.screen += list( mymob.healths) //, mymob.rest, mymob.sleep, mymob.mach )
mymob.client.screen += src.adding + src.other
mymob.client.screen += mymob.client.void
\ No newline at end of file
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 6bd7490411..0afb8acdfa 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -318,6 +318,11 @@ datum/hud/New(mob/owner)
else
mymob.instantiate_hud(src)
+ persistant_inventory_update()
+ mymob.reload_fullscreen() // Reload any fullscreen overlays this mob has.
+ mymob.update_action_buttons()
+ reorganize_alerts()
+
/mob/proc/instantiate_hud(var/datum/hud/HUD)
return
@@ -382,6 +387,7 @@ datum/hud/New(mob/owner)
hud_used.hidden_inventory_update()
hud_used.persistant_inventory_update()
update_action_buttons()
+ hud_used.reorganize_alerts()
//Similar to button_pressed_F12() but keeps zone_sel, gun_setting_icon, and healths.
/mob/proc/toggle_zoom_hud()
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index b372ec6882..fe32925cb9 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -28,6 +28,7 @@
inv_box.icon = ui_style
inv_box.color = ui_color
inv_box.alpha = ui_alpha
+ inv_box.hud = src
var/list/slot_data = hud_data.gear[gear_slot]
inv_box.name = gear_slot
@@ -192,6 +193,7 @@
using.screen_loc = ui_swaphand1
using.color = ui_color
using.alpha = ui_alpha
+ using.hud = src
src.adding += using
using = new /obj/screen/inventory()
@@ -201,6 +203,7 @@
using.screen_loc = ui_swaphand2
using.color = ui_color
using.alpha = ui_alpha
+ using.hud = src
src.adding += using
if(hud_data.has_resist)
@@ -243,27 +246,6 @@
hud_elements |= mymob.internals
if(hud_data.has_warnings)
- mymob.oxygen = new /obj/screen()
- mymob.oxygen.icon = ui_style
- mymob.oxygen.icon_state = "oxy0"
- mymob.oxygen.name = "oxygen"
- mymob.oxygen.screen_loc = ui_oxygen
- hud_elements |= mymob.oxygen
-
- mymob.toxin = new /obj/screen()
- mymob.toxin.icon = ui_style
- mymob.toxin.icon_state = "tox0"
- mymob.toxin.name = "toxin"
- mymob.toxin.screen_loc = ui_toxin
- hud_elements |= mymob.toxin
-
- mymob.fire = new /obj/screen()
- mymob.fire.icon = ui_style
- mymob.fire.icon_state = "fire0"
- mymob.fire.name = "fire"
- mymob.fire.screen_loc = ui_fire
- hud_elements |= mymob.fire
-
mymob.healths = new /obj/screen()
mymob.healths.icon = ui_style
mymob.healths.icon_state = "health0"
@@ -271,30 +253,6 @@
mymob.healths.screen_loc = ui_health
hud_elements |= mymob.healths
- if(hud_data.has_pressure)
- mymob.pressure = new /obj/screen()
- mymob.pressure.icon = ui_style
- mymob.pressure.icon_state = "pressure0"
- mymob.pressure.name = "pressure"
- mymob.pressure.screen_loc = ui_pressure
- hud_elements |= mymob.pressure
-
- if(hud_data.has_bodytemp)
- mymob.bodytemp = new /obj/screen()
- mymob.bodytemp.icon = ui_style
- mymob.bodytemp.icon_state = "temp1"
- mymob.bodytemp.name = "body temperature"
- mymob.bodytemp.screen_loc = ui_temp
- hud_elements |= mymob.bodytemp
-
- if(hud_data.has_nutrition)
- mymob.nutrition_icon = new /obj/screen()
- mymob.nutrition_icon.icon = ui_style
- mymob.nutrition_icon.icon_state = "nutrition0"
- mymob.nutrition_icon.name = "nutrition"
- mymob.nutrition_icon.screen_loc = ui_nutrition
- hud_elements |= mymob.nutrition_icon
-
mymob.ling_chem_display = new /obj/screen/ling/chems()
mymob.ling_chem_display.screen_loc = ui_ling_chemical_display
mymob.ling_chem_display.icon_state = "ling_chems"
diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm
index 392854742a..c71e0004c8 100644
--- a/code/_onclick/hud/robot.dm
+++ b/code/_onclick/hud/robot.dm
@@ -85,15 +85,6 @@ var/obj/screen/robot_inventory
src.adding += using
action_intent = using
-//Cell
- mymob:cells = new /obj/screen()
- mymob:cells.icon = ui_style
- mymob:cells.icon_state = "charge-empty"
- mymob:cells.alpha = ui_alpha
- mymob:cells.name = "cell"
- mymob:cells.screen_loc = ui_toxin
- src.other += mymob:cells
-
//Health
mymob.healths = new /obj/screen()
mymob.healths.icon = ui_style
@@ -142,28 +133,6 @@ var/obj/screen/robot_inventory
robot_inventory.screen_loc = ui_borg_inventory
src.other += robot_inventory
-//Temp
- mymob.bodytemp = new /obj/screen()
- mymob.bodytemp.icon_state = "temp0"
- mymob.bodytemp.name = "body temperature"
- mymob.bodytemp.screen_loc = ui_temp
-
- mymob.oxygen = new /obj/screen()
- mymob.oxygen.icon = ui_style
- mymob.oxygen.icon_state = "oxy0"
- mymob.oxygen.alpha = ui_alpha
- mymob.oxygen.name = "oxygen"
- mymob.oxygen.screen_loc = ui_oxygen
- src.other += mymob.oxygen
-
- mymob.fire = new /obj/screen()
- mymob.fire.icon = ui_style
- mymob.fire.icon_state = "fire0"
- mymob.fire.alpha = ui_alpha
- mymob.fire.name = "fire"
- mymob.fire.screen_loc = ui_fire
- src.other += mymob.fire
-
mymob.pullin = new /obj/screen()
mymob.pullin.icon = ui_style
mymob.pullin.icon_state = "pull0"
@@ -195,7 +164,7 @@ var/obj/screen/robot_inventory
mymob.client.screen = list()
- mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, robot_inventory, mymob.gun_setting_icon)
+ mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.hands, mymob.healths, mymob.pullin, robot_inventory, mymob.gun_setting_icon)
mymob.client.screen += src.adding + src.other
mymob.client.screen += mymob.client.void
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 4e0024e322..f930f4f462 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -34,7 +34,36 @@
/obj/screen/inventory
var/slot_id //The indentifier for the slot. It has nothing to do with ID cards.
+ var/list/object_overlays = list() // Required for inventory/screen overlays.
+/obj/screen/inventory/MouseEntered()
+ ..()
+ add_overlays()
+
+/obj/screen/inventory/MouseExited()
+ ..()
+ cut_overlay(object_overlays)
+ object_overlays.Cut()
+
+/obj/screen/inventory/proc/add_overlays()
+ var/mob/user = hud.mymob
+
+ if(hud && user && slot_id)
+ var/obj/item/holding = user.get_active_hand()
+
+ if(!holding || user.get_equipped_item(slot_id))
+ return
+
+ var/image/item_overlay = image(holding)
+ item_overlay.alpha = 92
+
+ if(!holding.mob_can_equip(user, slot_id, disable_warning = TRUE))
+ item_overlay.color = "#ff0000"
+ else
+ item_overlay.color = "#00ff00"
+
+ object_overlays += item_overlay
+ add_overlay(object_overlays)
/obj/screen/close
name = "close"
@@ -57,7 +86,7 @@
/obj/screen/item_action/Click()
if(!usr || !owner)
return 1
- if(!usr.canClick())
+ if(!usr.checkClickCooldown())
return
if(usr.stat || usr.restrained() || usr.stunned || usr.lying)
@@ -88,7 +117,7 @@
name = "storage"
/obj/screen/storage/Click()
- if(!usr.canClick())
+ if(!usr.checkClickCooldown())
return 1
if(usr.stat || usr.paralysis || usr.stunned || usr.weakened)
return 1
@@ -105,78 +134,116 @@
icon_state = "zone_sel"
screen_loc = ui_zonesel
var/selecting = BP_TORSO
+ var/static/list/hover_overlays_cache = list()
+ var/hovering_choice
+ var/mutable_appearance/selecting_appearance
/obj/screen/zone_sel/Click(location, control,params)
+ if(isobserver(usr))
+ return
+
var/list/PL = params2list(params)
var/icon_x = text2num(PL["icon-x"])
var/icon_y = text2num(PL["icon-y"])
- var/old_selecting = selecting //We're only going to update_icon() if there's been a change
+ var/choice = get_zone_at(icon_x, icon_y)
+ if(!choice)
+ return 1
+ return set_selected_zone(choice, usr)
+
+/obj/screen/zone_sel/MouseEntered(location, control, params)
+ MouseMove(location, control, params)
+
+/obj/screen/zone_sel/MouseMove(location, control, params)
+ if(isobserver(usr))
+ return
+
+ var/list/PL = params2list(params)
+ var/icon_x = text2num(PL["icon-x"])
+ var/icon_y = text2num(PL["icon-y"])
+ var/choice = get_zone_at(icon_x, icon_y)
+
+ if(hovering_choice == choice)
+ return
+ vis_contents -= hover_overlays_cache[hovering_choice]
+ hovering_choice = choice
+
+ var/obj/effect/overlay/zone_sel/overlay_object = hover_overlays_cache[choice]
+ if(!overlay_object)
+ overlay_object = new
+ overlay_object.icon_state = "[choice]"
+ hover_overlays_cache[choice] = overlay_object
+ vis_contents += overlay_object
+
+
+/obj/effect/overlay/zone_sel
+ icon = 'icons/mob/zone_sel.dmi'
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ alpha = 128
+ anchored = TRUE
+ layer = LAYER_HUD_ABOVE
+ plane = PLANE_PLAYER_HUD_ABOVE
+
+/obj/screen/zone_sel/MouseExited(location, control, params)
+ if(!isobserver(usr) && hovering_choice)
+ vis_contents -= hover_overlays_cache[hovering_choice]
+ hovering_choice = null
+
+/obj/screen/zone_sel/proc/get_zone_at(icon_x, icon_y)
switch(icon_y)
if(1 to 3) //Feet
switch(icon_x)
if(10 to 15)
- selecting = BP_R_FOOT
+ return BP_R_FOOT
if(17 to 22)
- selecting = BP_L_FOOT
- else
- return 1
+ return BP_L_FOOT
if(4 to 9) //Legs
switch(icon_x)
if(10 to 15)
- selecting = BP_R_LEG
+ return BP_R_LEG
if(17 to 22)
- selecting = BP_L_LEG
- else
- return 1
+ return BP_L_LEG
if(10 to 13) //Hands and groin
switch(icon_x)
if(8 to 11)
- selecting = BP_R_HAND
+ return BP_R_HAND
if(12 to 20)
- selecting = BP_GROIN
+ return BP_GROIN
if(21 to 24)
- selecting = BP_L_HAND
- else
- return 1
+ return BP_L_HAND
if(14 to 22) //Chest and arms to shoulders
switch(icon_x)
if(8 to 11)
- selecting = BP_R_ARM
+ return BP_R_ARM
if(12 to 20)
- selecting = BP_TORSO
+ return BP_TORSO
if(21 to 24)
- selecting = BP_L_ARM
- else
- return 1
+ return BP_L_ARM
if(23 to 30) //Head, but we need to check for eye or mouth
if(icon_x in 12 to 20)
- selecting = BP_HEAD
switch(icon_y)
if(23 to 24)
if(icon_x in 15 to 17)
- selecting = O_MOUTH
+ return O_MOUTH
if(26) //Eyeline, eyes are on 15 and 17
if(icon_x in 14 to 18)
- selecting = O_EYES
+ return O_EYES
if(25 to 27)
if(icon_x in 15 to 17)
- selecting = O_EYES
+ return O_EYES
+ return BP_HEAD
- if(old_selecting != selecting)
- update_icon()
- return 1
-
-/obj/screen/zone_sel/proc/set_selected_zone(bodypart)
- var/old_selecting = selecting
- selecting = bodypart
- if(old_selecting != selecting)
+/obj/screen/zone_sel/proc/set_selected_zone(choice, mob/user)
+ if(isobserver(user))
+ return
+ if(choice != selecting)
+ selecting = choice
update_icon()
/obj/screen/zone_sel/update_icon()
- overlays.Cut()
- overlays += image('icons/mob/zone_sel.dmi', "[selecting]")
-
+ cut_overlay(selecting_appearance)
+ selecting_appearance = mutable_appearance('icons/mob/zone_sel.dmi', "[selecting]")
+ add_overlay(selecting_appearance)
/obj/screen/Click(location, control, params)
if(!usr) return 1
@@ -495,7 +562,7 @@
/obj/screen/inventory/Click()
// At this point in client Click() code we have passed the 1/10 sec check and little else
// We don't even know if it's a middle click
- if(!usr.canClick())
+ if(!usr.checkClickCooldown())
return 1
if(usr.stat || usr.paralysis || usr.stunned || usr.weakened)
return 1
diff --git a/code/_onclick/hud/skybox.dm b/code/_onclick/hud/skybox.dm
index 492a11e588..8c1e3c10b5 100644
--- a/code/_onclick/hud/skybox.dm
+++ b/code/_onclick/hud/skybox.dm
@@ -50,11 +50,9 @@
if(. && client)
client.update_skybox(old_z != get_z(src))
-/mob/forceMove()
- var/old_z = get_z(src)
+/mob/Moved()
. = ..()
- if(. && client)
- client.update_skybox(old_z != get_z(src))
+ client?.update_skybox()
/mob/set_viewsize()
. = ..()
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index decc371475..54fc3239ac 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -97,7 +97,7 @@ avoid code duplication. This includes items that may sometimes act as a standard
/obj/item/proc/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone, var/attack_modifier)
user.break_cloak()
if(hitsound)
- playsound(loc, hitsound, 50, 1, -1)
+ playsound(src, hitsound, 50, 1, -1)
var/power = force
for(var/datum/modifier/M in user.modifiers)
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index a2d3f0c92b..485df1de41 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -31,7 +31,7 @@
if(client.buildmode)
build_click(src, client.buildmode, params, A)
return
- if(!canClick()) return
+ if(!checkClickCooldown()) return
setClickCooldown(4)
// You are responsible for checking config.ghost_interaction when you override this function
// Not all of them require checking, see below
@@ -50,8 +50,8 @@
/obj/machinery/teleport/hub/attack_ghost(mob/user as mob)
var/atom/l = loc
var/obj/machinery/computer/teleporter/com = locate(/obj/machinery/computer/teleporter, locate(l.x - 2, l.y, l.z))
- if(com.locked)
- user.loc = get_turf(com.locked)
+ if(com?.teleport_control.locked)
+ user.loc = get_turf(com.teleport_control.locked)
/obj/effect/portal/attack_ghost(mob/user as mob)
if(target)
diff --git a/code/_onclick/rig.dm b/code/_onclick/rig.dm
index ed7a1c7e2f..e281505dc2 100644
--- a/code/_onclick/rig.dm
+++ b/code/_onclick/rig.dm
@@ -63,7 +63,7 @@
return loc == card
/mob/living/proc/HardsuitClickOn(var/atom/A, var/alert_ai = 0)
- if(!can_use_rig() || !canClick())
+ if(!can_use_rig())
return 0
var/obj/item/weapon/rig/rig = get_rig()
if(istype(rig) && !rig.offline && rig.selected_module)
diff --git a/code/controllers/autotransfer.dm b/code/controllers/autotransfer.dm
index fb8cc8286a..776e2698ba 100644
--- a/code/controllers/autotransfer.dm
+++ b/code/controllers/autotransfer.dm
@@ -12,6 +12,6 @@ datum/controller/transfer_controller/Destroy()
datum/controller/transfer_controller/process()
currenttick = currenttick + 1
- if (round_duration_in_ticks >= timerbuffer - 1 MINUTE)
+ if (round_duration_in_ds >= timerbuffer - 1 MINUTE)
SSvote.autotransfer()
timerbuffer = timerbuffer + config.vote_autotransfer_interval
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index 450811a5fb..ec35af2752 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -232,6 +232,10 @@ var/list/gamemode_cache = list()
var/dooc_allowed = 1
var/dsay_allowed = 1
+ var/allow_byond_links = 0
+ var/allow_discord_links = 0
+ var/allow_url_links = 0 // honestly if I were you i'd leave this one off, only use in dire situations
+
var/starlight = 0 // Whether space turfs have ambient light or not
var/list/ert_species = list(SPECIES_HUMAN)
@@ -270,6 +274,9 @@ var/list/gamemode_cache = list()
// disables the annoying "You have already logged in this round, disconnect or be banned" popup for multikeying, because it annoys the shit out of me when testing.
var/disable_cid_warn_popup = FALSE
+ // whether or not to use the nightshift subsystem to perform lighting changes
+ var/static/enable_night_shifts = FALSE
+
/datum/configuration/New()
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
for (var/T in L)
@@ -420,6 +427,15 @@ var/list/gamemode_cache = list()
if ("allow_admin_spawning")
config.allow_admin_spawning = 1
+
+ if ("allow_byond_links")
+ allow_byond_links = 1
+
+ if ("allow_discord_links")
+ allow_discord_links = 1
+
+ if ("allow_url_links")
+ allow_url_links = 1
if ("no_dead_vote")
config.vote_no_dead = 1
@@ -888,6 +904,9 @@ var/list/gamemode_cache = list()
if("disable_cid_warn_popup")
config.disable_cid_warn_popup = TRUE
+ if("enable_night_shifts")
+ config.enable_night_shifts = TRUE
+
else
log_misc("Unknown setting in configuration: '[name]'")
diff --git a/code/controllers/subsystems/game_master.dm b/code/controllers/subsystems/game_master.dm
index d5326bfba6..ce7e8176c3 100644
--- a/code/controllers/subsystems/game_master.dm
+++ b/code/controllers/subsystems/game_master.dm
@@ -109,7 +109,7 @@ SUBSYSTEM_DEF(game_master)
return FALSE
// Last minute antagging is bad for humans to do, so the GM will respect the start and end of the round.
- var/mills = round_duration_in_ticks
+ var/mills = round_duration_in_ds
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)
diff --git a/code/controllers/subsystems/machines.dm b/code/controllers/subsystems/machines.dm
index 7f35bfd971..29d6ecce56 100644
--- a/code/controllers/subsystems/machines.dm
+++ b/code/controllers/subsystems/machines.dm
@@ -121,10 +121,8 @@ SUBSYSTEM_DEF(machines)
while(current_run.len)
var/obj/machinery/M = current_run[current_run.len]
current_run.len--
- if(istype(M) && !QDELETED(M) && !(M.process(wait) == PROCESS_KILL))
- if(M.use_power)
- M.auto_use_power()
- else
+
+ if(!istype(M) || QDELETED(M) || (M.process(wait) == PROCESS_KILL))
global.processing_machines.Remove(M)
if(!QDELETED(M))
DISABLE_BITFIELD(M.datum_flags, DF_ISPROCESSING)
diff --git a/code/controllers/subsystems/nightshift.dm b/code/controllers/subsystems/nightshift.dm
new file mode 100644
index 0000000000..3657a472c8
--- /dev/null
+++ b/code/controllers/subsystems/nightshift.dm
@@ -0,0 +1,62 @@
+SUBSYSTEM_DEF(nightshift)
+ name = "Night Shift"
+ init_order = INIT_ORDER_NIGHTSHIFT
+ priority = FIRE_PRIORITY_NIGHTSHIFT
+ wait = 60 SECONDS
+ flags = SS_NO_TICK_CHECK
+
+ var/nightshift_active = FALSE
+ var/nightshift_first_check = 30 SECONDS
+
+ var/high_security_mode = FALSE
+
+/datum/controller/subsystem/nightshift/Initialize()
+ if(!config.enable_night_shifts)
+ can_fire = FALSE
+ /*
+ if(config.randomize_shift_time)
+ GLOB.gametime_offset = rand(0, 23) HOURS
+ */
+ return ..()
+
+/datum/controller/subsystem/nightshift/fire(resumed = FALSE)
+ if(round_duration_in_ds < nightshift_first_check)
+ return
+ check_nightshift()
+
+/datum/controller/subsystem/nightshift/proc/announce(message)
+ var/announce_z
+ if(using_map.station_levels.len)
+ announce_z = pick(using_map.station_levels)
+ priority_announcement.Announce(message, new_title = "Automated Lighting System Announcement", new_sound = 'sound/misc/notice2.ogg', zlevel = announce_z)
+
+/datum/controller/subsystem/nightshift/proc/check_nightshift(check_canfire=FALSE) //This is called from elsewhere, like setting the alert levels
+ if(check_canfire && !can_fire)
+ return
+ var/emergency = security_level > SEC_LEVEL_GREEN
+ var/announcing = TRUE
+ var/night_time = using_map.get_nightshift()
+ if(high_security_mode != emergency)
+ high_security_mode = emergency
+ if(night_time)
+ announcing = FALSE
+ if(!emergency)
+ announce("Restoring night lighting configuration to normal operation.")
+ else
+ announce("Disabling night lighting: Station is in a state of emergency.")
+ if(emergency)
+ night_time = FALSE
+ if(nightshift_active != night_time)
+ update_nightshift(night_time, announcing)
+
+/datum/controller/subsystem/nightshift/proc/update_nightshift(active, announce = TRUE)
+ nightshift_active = active
+ if(announce)
+ if(active)
+ announce("Good evening, crew. To reduce power consumption and stimulate the circadian rhythms of some species, all of the lights aboard the station have been dimmed for the night.")
+ else
+ announce("Good morning, crew. As it is now day time, all of the lights aboard the station have been restored to their former brightness.")
+ for(var/obj/machinery/power/apc/apc in machines)
+ if(apc.z in using_map.station_levels)
+ apc.set_nightshift(active, TRUE)
+ CHECK_TICK
diff --git a/code/controllers/subsystems/open_space.dm b/code/controllers/subsystems/open_space.dm
index dfc1319009..4e96dbfda4 100644
--- a/code/controllers/subsystems/open_space.dm
+++ b/code/controllers/subsystems/open_space.dm
@@ -79,22 +79,6 @@ SUBSYSTEM_DEF(open_space)
/datum/controller/subsystem/open_space/stat_entry(msg_prefix)
return ..("T [turfs_to_process.len]")
-/turf/Entered(atom/movable/AM)
- . = ..()
- if(GLOB.open_space_initialised && !AM.invisibility && isobj(AM))
- var/turf/T = GetAbove(src)
- if(isopenspace(T))
- // log_debug("[T] ([T.x],[T.y],[T.z]) queued for update for [src].Entered([AM])")
- SSopen_space.add_turf(T, 1)
-
-/turf/Exited(atom/movable/AM)
- . = ..()
- if(GLOB.open_space_initialised && !AM.invisibility && isobj(AM))
- var/turf/T = GetAbove(src)
- if(isopenspace(T))
- // log_debug("[T] ([T.x],[T.y],[T.z]) queued for update for [src].Exited([AM])")
- SSopen_space.add_turf(T, 1)
-
/obj/update_icon()
. = ..()
if(GLOB.open_space_initialised && !invisibility && isturf(loc))
diff --git a/code/controllers/subsystems/planets.dm b/code/controllers/subsystems/planets.dm
index 9e823fc0db..5d1325bba5 100644
--- a/code/controllers/subsystems/planets.dm
+++ b/code/controllers/subsystems/planets.dm
@@ -6,16 +6,16 @@ SUBSYSTEM_DEF(planets)
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
- var/list/new_outdoor_turfs = list()
- var/list/new_outdoor_walls = list()
+ var/static/list/new_outdoor_turfs = list()
+ var/static/list/new_outdoor_walls = list()
- var/list/planets = list()
- var/list/z_to_planet = list()
+ var/static/list/planets = list()
+ var/static/list/z_to_planet = list()
- var/list/currentrun = list()
+ var/static/list/currentrun = list()
- var/list/needs_sun_update = list()
- var/list/needs_temp_update = list()
+ var/static/list/needs_sun_update = list()
+ var/static/list/needs_temp_update = list()
/datum/controller/subsystem/planets/Initialize(timeofday)
admin_notice("Initializing planetary weather.", R_DEBUG)
diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm
index b17640430b..62c8b79932 100644
--- a/code/controllers/subsystems/ticker.dm
+++ b/code/controllers/subsystems/ticker.dm
@@ -176,7 +176,7 @@ var/global/datum/controller/subsystem/ticker/ticker
create_characters() //Create player characters and transfer them.
collect_minds()
equip_characters()
- data_core.manifest()
+// data_core.manifest()
callHook("roundstart")
@@ -404,16 +404,25 @@ var/global/datum/controller/subsystem/ticker/ticker
/datum/controller/subsystem/ticker/proc/create_characters()
for(var/mob/new_player/player in player_list)
- if(player && player.ready && player.mind)
- if(player.mind.assigned_role=="AI")
+ if(player && player.ready && player.mind?.assigned_role)
+ var/datum/job/J = SSjob.get_job(player.mind.assigned_role)
+
+ // Snowflakey AI treatment
+ if(J?.mob_type & JOB_SILICON_AI)
player.close_spawn_windows()
- player.AIize()
- else if(!player.mind.assigned_role)
+ player.AIize(move = TRUE)
continue
- else
- player.create_character()
+
+ // Ask their new_player mob to spawn them
+ var/mob/living/carbon/human/new_char = player.create_character()
+
+ // Created their playable character, delete their /mob/new_player
+ if(new_char)
qdel(player)
+ // If they're a carbon, they can get manifested
+ if(J?.mob_type & JOB_CARBON)
+ data_core.manifest_inject(new_char)
/datum/controller/subsystem/ticker/proc/collect_minds()
for(var/mob/living/player in player_list)
diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm
index 3a22a1e86f..fc47258a82 100644
--- a/code/datums/helper_datums/teleport.dm
+++ b/code/datums/helper_datums/teleport.dm
@@ -96,7 +96,6 @@
var/turf/destturf
var/turf/curturf = get_turf(teleatom)
- var/area/destarea = get_area(destination)
if(precision)
var/list/posturfs = circlerangeturfs(destination,precision)
destturf = safepick(posturfs)
@@ -122,8 +121,6 @@
if(C)
C.forceMove(destturf)
- destarea.Entered(teleatom)
-
return 1
/datum/teleport/proc/teleport()
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index d5bd1058d1..a830efb9d2 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -480,6 +480,19 @@
else
return 0
+/datum/mind/proc/get_ghost(even_if_they_cant_reenter)
+ for(var/mob/observer/dead/G in player_list)
+ if(G.mind == src)
+ if(G.can_reenter_corpse || even_if_they_cant_reenter)
+ return G
+ break
+
+/datum/mind/proc/grab_ghost(force)
+ var/mob/observer/dead/G = get_ghost(even_if_they_cant_reenter = force)
+ . = G
+ if(G)
+ G.reenter_corpse()
+
//Initialisation procs
/mob/living/proc/mind_initialize()
if(mind)
diff --git a/code/datums/observation/power_change.dm b/code/datums/observation/power_change.dm
new file mode 100644
index 0000000000..4581dab84a
--- /dev/null
+++ b/code/datums/observation/power_change.dm
@@ -0,0 +1,21 @@
+// Observer Pattern Implementation: Area Power Change
+// Registration type: /area
+//
+// Raised when: An /area has a power change (the APC powers up/down or some channels are enabled/disabled)
+//
+// Arguments that the called proc should expect:
+// /area: The area experiencing the power change
+
+GLOBAL_DATUM_INIT(apc_event, /decl/observ/area_power_change, new)
+
+/decl/observ/area_power_change
+ name = "Area Power Change"
+ expected_type = /area
+
+/********************
+* Movement Handling *
+********************/
+
+/area/power_change()
+ . = ..()
+ GLOB.apc_event.raise_event(src)
diff --git a/code/datums/observation/turf_enterexit.dm b/code/datums/observation/turf_enterexit.dm
new file mode 100644
index 0000000000..30cec0c39d
--- /dev/null
+++ b/code/datums/observation/turf_enterexit.dm
@@ -0,0 +1,33 @@
+// Observer Pattern Implementation: Turf Entered/Exited
+// Registration type: /turf
+//
+// Raised when: A /turf has a new item in contents, or an item has left it's contents
+//
+// Arguments that the called proc should expect:
+// /turf: The turf that was entered/exited
+// /atom/movable/moving_instance: The instance that entered/exited
+// /atom/old_loc / /atom/new_loc: The previous/new loc of the mover
+
+
+GLOBAL_DATUM_INIT(turf_entered_event, /decl/observ/turf_entered, new)
+GLOBAL_DATUM_INIT(turf_exited_event, /decl/observ/turf_exited, new)
+
+/decl/observ/turf_entered
+ name = "Turf Entered"
+ expected_type = /turf
+
+/decl/observ/turf_exited
+ name = "Turf Exited"
+ expected_type = /turf
+
+/********************
+* Movement Handling *
+********************/
+
+/turf/Entered(var/atom/movable/am, var/atom/old_loc)
+ . = ..()
+ GLOB.turf_entered_event.raise_event(src, am, old_loc)
+
+/turf/Exited(var/atom/movable/am, var/atom/new_loc)
+ . = ..()
+ GLOB.turf_exited_event.raise_event(src, am, new_loc)
\ No newline at end of file
diff --git a/code/datums/orbit.dm b/code/datums/orbit.dm
index 5d457ff4ac..0176d7f23d 100644
--- a/code/datums/orbit.dm
+++ b/code/datums/orbit.dm
@@ -4,10 +4,12 @@
var/lock = TRUE
var/turf/lastloc
var/lastprocess
+ var/matrix/init_transform
-/datum/orbit/New(_orbiter, _orbiting, _lock)
+/datum/orbit/New(var/atom/movable/_orbiter, var/atom/_orbiting, _lock)
orbiter = _orbiter
orbiting = _orbiting
+ init_transform = _orbiter.transform
SSorbit.processing += src
if (!orbiting.orbiters)
orbiting.orbiters = list()
@@ -24,6 +26,7 @@
SSorbit.processing -= src
if (orbiter)
orbiter.orbiting = null
+ orbiter.transform = init_transform
orbiter = null
if (orbiting)
if (orbiting.orbiters)
@@ -84,7 +87,6 @@
new/datum/orbit(src, A, lockinorbit)
if (!orbiting) //something failed, and our orbit datum deleted itself
return
- var/matrix/initial_transform = matrix(transform)
//Head first!
if (pre_rotation)
@@ -101,9 +103,6 @@
SpinAnimation(rotation_speed, -1, clockwise, rotation_segments)
- //we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
- transform = initial_transform
-
/atom/movable/proc/stop_orbit()
SpinAnimation(0,0)
qdel(orbiting)
diff --git a/code/datums/outfits/military/marines.dm b/code/datums/outfits/military/marines.dm
index 719b36c690..a5a81b973d 100644
--- a/code/datums/outfits/military/marines.dm
+++ b/code/datums/outfits/military/marines.dm
@@ -1,23 +1,23 @@
/decl/hierarchy/outfit/military/marine/pt
name = OUTFIT_MILITARY("Marine PT")
- uniform = /obj/item/clothing/under/solgov/pt/marine
+ uniform = /obj/item/clothing/under/solgov/pt/army
shoes = /obj/item/clothing/shoes/black
/decl/hierarchy/outfit/military/marine/utility
name = OUTFIT_MILITARY("Marine Utility")
- uniform = /obj/item/clothing/under/solgov/utility/marine
+ uniform = /obj/item/clothing/under/solgov/utility/army
shoes = /obj/item/clothing/shoes/boots/jungle
/decl/hierarchy/outfit/military/marine/service
name = OUTFIT_MILITARY("Marine Service")
- uniform = /obj/item/clothing/under/solgov/service/marine
+ uniform = /obj/item/clothing/under/solgov/service/army
shoes = /obj/item/clothing/shoes/dress
- suit = /obj/item/clothing/suit/storage/service/marine
+ suit = /obj/item/clothing/suit/storage/solgov/service/army
/decl/hierarchy/outfit/military/marine/dress
name = OUTFIT_MILITARY("Marine Dress")
- uniform = /obj/item/clothing/under/solgov/mildress/marine
+ uniform = /obj/item/clothing/under/solgov/mildress/army
shoes = /obj/item/clothing/shoes/dress/white
- suit = /obj/item/clothing/suit/dress/marine
+ suit = /obj/item/clothing/suit/dress/solgov/army
gloves = /obj/item/clothing/gloves/white
- head = /obj/item/clothing/head/dress/marine
\ No newline at end of file
+ head = /obj/item/clothing/head/dress/army
\ No newline at end of file
diff --git a/code/datums/outfits/military/sifguard.dm b/code/datums/outfits/military/sifguard.dm
index 9348224a9e..fa44675b67 100644
--- a/code/datums/outfits/military/sifguard.dm
+++ b/code/datums/outfits/military/sifguard.dm
@@ -12,12 +12,12 @@
name = OUTFIT_MILITARY("SifGuard Service")
uniform = /obj/item/clothing/under/solgov/utility/sifguard
shoes = /obj/item/clothing/shoes/boots/tactical
- suit = /obj/item/clothing/suit/storage/service/sifguard
+ suit = /obj/item/clothing/suit/storage/solgov/service/sifguard
/decl/hierarchy/outfit/military/sifguard/dress
name = OUTFIT_MILITARY("SifGuard Dress")
- uniform = /obj/item/clothing/under/solgov/mildress/sifguard
+ uniform = /obj/item/clothing/under/solgov/service/sifguard
shoes = /obj/item/clothing/shoes/dress
- suit = /obj/item/clothing/suit/dress/expedition
+ suit = /obj/item/clothing/suit/storage/solgov/dress/sifguard
gloves = /obj/item/clothing/gloves/white
- head = /obj/item/clothing/head/dress/expedition
\ No newline at end of file
+ head = /obj/item/clothing/head/service/sifguard
\ No newline at end of file
diff --git a/code/datums/riding.dm b/code/datums/riding.dm
index 4f9513397a..ba96dbc405 100644
--- a/code/datums/riding.dm
+++ b/code/datums/riding.dm
@@ -2,7 +2,7 @@
/datum/riding
var/next_vehicle_move = 0 // Used for move delays
- var/vehicle_move_delay = 2 // Tick delay between movements, lower = faster, higher = slower
+ var/vehicle_move_delay = 2 // Decisecond delay between movements, lower = faster, higher = slower
var/keytype = null // Can give this a type to require the rider to hold the item type inhand to move the ridden atom.
var/nonhuman_key_exemption = FALSE // If true, nonhumans who can't hold keys don't need them, like borgs and simplemobs.
var/key_name = "the keys" // What the 'keys' for the thing being rided on would be called.
@@ -97,11 +97,13 @@
if(world.time < next_vehicle_move)
return
+
next_vehicle_move = world.time + vehicle_move_delay
+
if(keycheck(user))
if(!Process_Spacemove(direction) || !isturf(ridden.loc))
return
- ridden.Move(get_step(ridden, direction))
+ ridden.Move(get_step(ridden, direction), direction, vehicle_move_delay)
handle_vehicle_layer()
handle_vehicle_offsets()
diff --git a/code/defines/obj.dm b/code/defines/obj.dm
index 187b69e021..de7800acfb 100644
--- a/code/defines/obj.dm
+++ b/code/defines/obj.dm
@@ -29,7 +29,6 @@
density = 0
unacidable = 1//Just to be sure.
var/def_zone
- flags = PROXMOVE
pass_flags = PASSTABLE
@@ -59,22 +58,11 @@
var/damage = 0.0
var/range = 10.0
-
-/obj/effect/list_container
- name = "list container"
-
-/obj/effect/list_container/mobl
- name = "mobl"
- var/master = null
-
- var/list/container = list( )
-
/obj/effect/projection
name = "Projection"
desc = "This looks like a projection of something."
anchored = 1.0
-
/obj/effect/shut_controller
name = "shut controller"
var/moving = null
@@ -114,12 +102,5 @@
user.drop_item()
src.throw_at(target, throw_range, throw_speed, user)
-/obj/effect/stop
- var/victim = null
- icon_state = "empty"
- name = "Geas"
- desc = "You can't resist."
- // name = ""
-
/obj/effect/spawner
name = "object spawner"
diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm
index 962c91a621..e00a4a99df 100644
--- a/code/game/antagonist/antagonist.dm
+++ b/code/game/antagonist/antagonist.dm
@@ -4,6 +4,7 @@
var/list/restricted_jobs = list() // Jobs that cannot be this antagonist (depending on config)
var/list/protected_jobs = list() // As above.
var/list/roundstart_restricted = list() //Jobs that can be this antag, but not at roundstart
+ var/avoid_silicons = FALSE // If we won't hand this antag role to silicons (AI, borg, etc)
// Strings.
var/welcome_text = "Cry havoc and let slip the dogs of war!"
diff --git a/code/game/antagonist/antagonist_helpers.dm b/code/game/antagonist/antagonist_helpers.dm
index c8f2928ced..ebf212f065 100644
--- a/code/game/antagonist/antagonist_helpers.dm
+++ b/code/game/antagonist/antagonist_helpers.dm
@@ -10,6 +10,14 @@
return FALSE
if(config.protect_roles_from_antagonist && (player.assigned_role in protected_jobs))
return FALSE
+ if(avoid_silicons)
+ var/datum/job/J = SSjob.get_job(player.assigned_role)
+ if(J)
+ if(J.mob_type & JOB_SILICON)
+ return FALSE
+ else // If SSjob couldn't find a job, they don't have one yet, so the next best thing we can switch on are job preferences
+ if((player.current.client.prefs.job_engsec_high | player.current.client.prefs.job_engsec_med | player.current.client.prefs.job_engsec_low) & (AI | CYBORG)) // If they have ANY chance of being silicon
+ return FALSE
return TRUE
/datum/antagonist/proc/antags_are_dead()
diff --git a/code/game/antagonist/station/changeling.dm b/code/game/antagonist/station/changeling.dm
index 860e73a052..694c4a3634 100644
--- a/code/game/antagonist/station/changeling.dm
+++ b/code/game/antagonist/station/changeling.dm
@@ -5,7 +5,7 @@
role_text_plural = "Changelings"
bantype = "changeling"
feedback_tag = "changeling_objective"
- restricted_jobs = list("AI", "Cyborg")
+ avoid_silicons = TRUE
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Colony Director")
welcome_text = "Use say \"#g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them."
antag_sound = 'sound/effects/antag_notice/ling_alert.ogg'
diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm
index dc98622ba7..06aab654b4 100644
--- a/code/game/antagonist/station/cultist.dm
+++ b/code/game/antagonist/station/cultist.dm
@@ -11,7 +11,8 @@ var/datum/antagonist/cultist/cult
role_text = "Cultist"
role_text_plural = "Cultists"
bantype = "cultist"
- restricted_jobs = list("Chaplain","AI", "Cyborg")
+ restricted_jobs = list("Chaplain")
+ avoid_silicons = TRUE
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director")
roundstart_restricted = list("Internal Affairs Agent", "Head of Security", "Colony Director")
role_type = BE_CULTIST
diff --git a/code/game/antagonist/station/loyalist.dm b/code/game/antagonist/station/loyalist.dm
index 9b2333b491..ec27584426 100644
--- a/code/game/antagonist/station/loyalist.dm
+++ b/code/game/antagonist/station/loyalist.dm
@@ -29,7 +29,7 @@ var/datum/antagonist/loyalists/loyalists
faction_welcome = "Preserve NanoTrasen's interests against the traitorous recidivists amongst the crew. Protect the heads of staff with your life."
faction_indicator = "loyal"
faction_invisible = 1
- restricted_jobs = list("AI", "Cyborg")
+ avoid_silicons = TRUE
/datum/antagonist/loyalists/New()
..()
diff --git a/code/game/antagonist/station/renegade.dm b/code/game/antagonist/station/renegade.dm
index ed3c804506..cdd4efb8f3 100644
--- a/code/game/antagonist/station/renegade.dm
+++ b/code/game/antagonist/station/renegade.dm
@@ -6,7 +6,7 @@ var/datum/antagonist/renegade/renegades
role_text = "Renegade"
role_text_plural = "Renegades"
bantype = "renegade"
- restricted_jobs = list("AI", "Cyborg")
+ avoid_silicons = TRUE
welcome_text = "Something's going to go wrong today, you can just feel it. You're paranoid, you've got a gun, and you're going to survive."
antag_sound = 'sound/effects/antag_notice/general_goodie_alert.ogg'
antag_text = "You are a minor antagonist! Within the rules, \
diff --git a/code/game/antagonist/station/revolutionary.dm b/code/game/antagonist/station/revolutionary.dm
index 17c519b7a0..1db40f396a 100644
--- a/code/game/antagonist/station/revolutionary.dm
+++ b/code/game/antagonist/station/revolutionary.dm
@@ -29,7 +29,7 @@ var/datum/antagonist/revolutionary/revs
faction_indicator = "rev"
faction_invisible = 1
- restricted_jobs = list("AI", "Cyborg")
+ avoid_silicons = TRUE
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Colony Director", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
roundstart_restricted = list("Internal Affairs Agent", "Colony Director", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
diff --git a/code/game/antagonist/station/stowaway.dm b/code/game/antagonist/station/stowaway.dm
index dc3814b3b1..574fda0bca 100644
--- a/code/game/antagonist/station/stowaway.dm
+++ b/code/game/antagonist/station/stowaway.dm
@@ -6,7 +6,7 @@ var/datum/antagonist/stowaway/stowaways
role_text = "Stowaway"
role_text_plural = "Stowaways"
bantype = "renegade"
- restricted_jobs = list("AI")
+ avoid_silicons = TRUE // This was previously allowing cyborgs to be stowaways, but given that they would just connect to the AI, it didn't make much sense
welcome_text = "People are known to run from many things, or to many things, for many different reasons. You happen to be one of those people."
antag_text = "You are a minor antagonist! Within the server rules, do whatever it is \
that you came to the station to do. Espionage, thievery, or just running from the law are all examples. \
diff --git a/code/game/antagonist/station/thug.dm b/code/game/antagonist/station/thug.dm
index 61d92e1646..f26d6441a8 100644
--- a/code/game/antagonist/station/thug.dm
+++ b/code/game/antagonist/station/thug.dm
@@ -6,7 +6,7 @@ var/datum/antagonist/thug/thugs
role_text = "Thug"
role_text_plural = "Thugs"
bantype = "renegade"
- restricted_jobs = list("AI", "Cyborg")
+ avoid_silicons = TRUE
welcome_text = "Sometimes, people just need to get messed up. Luckily, that's what you're here to do."
antag_text = "You are a minor antagonist! Within the server rules, do whatever it is \
that you came to the station to do, be it violence, theft, or just extreme self-defense. \
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index 963530d671..b7d2c3f323 100644
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -25,6 +25,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
requires_power = 1
always_unpowered = 1
dynamic_lighting = 0
+ has_gravity = 0
power_light = 0
power_equip = 0
power_environ = 0
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index c93b6d78dc..80b7ec5b4f 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -21,14 +21,22 @@
var/requires_power = 1
var/always_unpowered = 0 //this gets overriden to 1 for space in area/New()
- var/power_equip = 1
- var/power_light = 1
- var/power_environ = 1
- var/music = null
- var/used_equip = 0
- var/used_light = 0
- var/used_environ = 0
+ // Power channel status - Is it currently energized?
+ var/power_equip = TRUE
+ var/power_light = TRUE
+ var/power_environ = TRUE
+ // Oneoff power usage - Used once and cleared each power cycle
+ var/oneoff_equip = 0
+ var/oneoff_light = 0
+ var/oneoff_environ = 0
+
+ // Continuous "static" power usage - Do not update these directly!
+ var/static_equip = 0
+ var/static_light = 0
+ var/static_environ = 0
+
+ var/music = null
var/has_gravity = 1
var/secret_name = FALSE // This tells certain things that display areas' names that they shouldn't display this area's name.
var/obj/machinery/power/apc/apc = null
@@ -81,7 +89,7 @@
for(var/atom/movable/AM in T)
A.Entered(AM, old_area)
for(var/obj/machinery/M in T)
- M.power_change()
+ M.area_changed(old_area, A)
/area/proc/get_contents()
return contents
@@ -239,33 +247,96 @@
if (fire || eject || party)
updateicon()
-/area/proc/usage(var/chan)
+/area/proc/usage(var/chan, var/include_static = TRUE)
var/used = 0
switch(chan)
if(LIGHT)
- used += used_light
+ used += oneoff_light + (include_static * static_light)
if(EQUIP)
- used += used_equip
+ used += oneoff_equip + (include_static * static_equip)
if(ENVIRON)
- used += used_environ
+ used += oneoff_environ + (include_static * static_environ)
if(TOTAL)
- used += used_light + used_equip + used_environ
+ used += oneoff_light + (include_static * static_light)
+ used += oneoff_equip + (include_static * static_equip)
+ used += oneoff_environ + (include_static * static_environ)
return used
+// Helper for APCs; will generally be called every tick.
/area/proc/clear_usage()
- used_equip = 0
- used_light = 0
- used_environ = 0
+ oneoff_equip = 0
+ oneoff_light = 0
+ oneoff_environ = 0
-/area/proc/use_power(var/amount, var/chan)
+// Use this for a one-time power draw from the area, typically for non-machines.
+/area/proc/use_power_oneoff(var/amount, var/chan)
switch(chan)
if(EQUIP)
- used_equip += amount
+ oneoff_equip += amount
if(LIGHT)
- used_light += amount
+ oneoff_light += amount
if(ENVIRON)
- used_environ += amount
+ oneoff_environ += amount
+ return amount
+// This is used by machines to properly update the area of power changes.
+/area/proc/power_use_change(old_amount, new_amount, chan)
+ use_power_static(new_amount - old_amount, chan) // Simultaneously subtract old_amount and add new_amount.
+
+// Not a proc you want to use directly unless you know what you are doing; see use_power_oneoff above instead.
+/area/proc/use_power_static(var/amount, var/chan)
+ switch(chan)
+ if(EQUIP)
+ static_equip += amount
+ if(LIGHT)
+ static_light += amount
+ if(ENVIRON)
+ static_environ += amount
+
+// This recomputes the continued power usage; can be used for testing or error recovery, but is not called every tick.
+/area/proc/retally_power()
+ static_equip = 0
+ static_light = 0
+ static_environ = 0
+ for(var/obj/machinery/M in src)
+ switch(M.power_channel)
+ if(EQUIP)
+ static_equip += M.get_power_usage()
+ if(LIGHT)
+ static_light += M.get_power_usage()
+ if(ENVIRON)
+ static_environ += M.get_power_usage()
+
+//////////////////////////////////////////////////////////////////
+
+/area/vv_get_dropdown()
+ . = ..()
+ VV_DROPDOWN_OPTION("check_static_power", "Check Static Power")
+
+/area/vv_do_topic(list/href_list)
+ . = ..()
+ IF_VV_OPTION("check_static_power")
+ if(!check_rights(R_DEBUG))
+ return
+ src.check_static_power(usr)
+ href_list["datumrefresh"] = "\ref[src]"
+
+// Debugging proc to report if static power is correct or not.
+/area/proc/check_static_power(var/user)
+ set name = "Check Static Power"
+ var/actual_static_equip = static_equip
+ var/actual_static_light = static_light
+ var/actual_static_environ = static_environ
+ retally_power()
+ if(user)
+ var/list/report = list("[src] ([type]) static power tally:")
+ report += "EQUIP: Actual: [actual_static_equip] Correct: [static_equip] Difference: [actual_static_equip - static_equip]"
+ report += "LIGHT: Actual: [actual_static_light] Correct: [static_light] Difference: [actual_static_light - static_light]"
+ report += "ENVIRON: Actual: [actual_static_environ] Correct: [static_environ] Difference: [actual_static_environ - static_environ]"
+ to_chat(user, report.Join("\n"))
+ return (actual_static_equip == static_equip && actual_static_light == static_light && actual_static_environ == static_environ)
+
+//////////////////////////////////////////////////////////////////
var/list/mob/living/forced_ambiance_list = new
@@ -317,6 +388,7 @@ var/list/mob/living/forced_ambiance_list = new
if(has_gravity)
thunk(M)
M.update_floating( M.Check_Dense_Object() )
+ M.update_gravity(has_gravity)
/area/proc/thunk(mob)
if(istype(get_turf(mob), /turf/space)) // Can't fall onto nothing.
@@ -336,7 +408,7 @@ var/list/mob/living/forced_ambiance_list = new
H.AdjustStunned(3)
H.AdjustWeakened(3)
to_chat(mob, "The sudden appearance of gravity makes you fall to the floor!")
- playsound(get_turf(src), "bodyfall", 50, 1)
+ playsound(mob, "bodyfall", 50, 1)
/area/proc/prison_break(break_lights = TRUE, open_doors = TRUE, open_blast_doors = TRUE)
var/obj/machinery/power/apc/theAPC = get_apc()
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 0bc5c14cf8..671bdf0b10 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -118,15 +118,33 @@
/atom/proc/CheckExit()
return 1
-// If you want to use this, the atom must have the PROXMOVE flag, and the moving
-// atom must also have the PROXMOVE flag currently to help with lag. ~ ComicIronic
-/atom/proc/HasProximity(atom/movable/AM as mob|obj)
+// Used to be for the PROXMOVE flag, but that was terrible, so instead it's just here as a stub for
+// all the atoms that still have the proc, but get events other ways.
+/atom/proc/HasProximity(turf/T, atom/movable/AM, old_loc)
return
+//Register listeners on turfs in a certain range
+/atom/proc/sense_proximity(var/range = 1, var/callback)
+ ASSERT(callback)
+ ASSERT(isturf(loc))
+ var/list/turfs = trange(range, src)
+ for(var/t in turfs)
+ var/turf/T = t
+ GLOB.turf_entered_event.register(T, src, callback)
+
+//Unregister from prox listening in a certain range. You should do this BEFORE you move, but if you
+// really can't, then you can set the center where you moved from.
+/atom/proc/unsense_proximity(var/range = 1, var/callback, var/center)
+ ASSERT(isturf(center) || isturf(loc))
+ var/list/turfs = trange(range, center ? center : src)
+ for(var/t in turfs)
+ var/turf/T = t
+ GLOB.turf_entered_event.unregister(T, src, callback)
+
+
/atom/proc/emp_act(var/severity)
return
-
/atom/proc/bullet_act(obj/item/projectile/P, def_zone)
P.on_hit(src, 0, def_zone)
. = 0
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 87445a4b38..ed8137d8a9 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -1,13 +1,13 @@
/atom/movable
layer = OBJ_LAYER
appearance_flags = TILE_BOUND|PIXEL_SCALE
- var/last_move = null
+ glide_size = 8
+ var/last_move = null //The direction the atom last moved
var/anchored = 0
// var/elevation = 2 - not used anywhere
var/moving_diagonally
var/move_speed = 10
var/l_move_time = 1
- var/m_flag = 1
var/throwing = 0
var/thrower
var/turf/throw_source = null
@@ -21,6 +21,7 @@
var/icon_rotation = 0 // Used to rotate icons in update_transform()
var/old_x = 0
var/old_y = 0
+ var/datum/riding/riding_datum = null
var/does_spin = TRUE // Does the atom spin when thrown (of course it does :P)
var/movement_type = NONE
@@ -52,77 +53,88 @@
return ..()
////////////////////////////////////////
-// Here's where we rewrite how byond handles movement except slightly different
-// To be removed on step_ conversion
-// All this work to prevent a second bump
-/atom/movable/Move(atom/newloc, direct=0)
- . = FALSE
- if(!newloc || newloc == loc)
- return
-
- if(!direct)
- direct = get_dir(src, newloc)
- set_dir(direct)
-
- if(!loc.Exit(src, newloc))
- return
-
- if(!newloc.Enter(src, src.loc))
- return
-
- if(!check_multi_tile_move_density_dir(direct, locs)) // We're big, and we can't move that way.
- return
-
- // Past this is the point of no return
- if(!locs || locs.len <= 1) // We're not a multi-tile object.
- var/atom/oldloc = loc
- var/area/oldarea = get_area(oldloc)
- var/area/newarea = get_area(newloc)
- loc = newloc
- . = TRUE
- oldloc.Exited(src, newloc)
- if(oldarea != newarea)
- oldarea.Exited(src, newloc)
-
- for(var/i in oldloc)
- if(i == src) // Multi tile objects
- continue
- var/atom/movable/thing = i
- thing.Uncrossed(src)
-
- newloc.Entered(src, oldloc)
- if(oldarea != newarea)
- newarea.Entered(src, oldloc)
-
- for(var/i in loc)
- if(i == src) // Multi tile objects
- continue
- var/atom/movable/thing = i
- thing.Crossed(src)
-
- else if(newloc) // We're a multi-tile object.
- . = doMove(newloc)
-
-//
-////////////////////////////////////////
-
-/atom/movable/Move(atom/newloc, direct = 0)
+/atom/movable/Move(atom/newloc, direct = 0, movetime)
+ // Didn't pass enough info
if(!loc || !newloc)
return FALSE
+
+ // Store this early before we might move, it's used several places
var/atom/oldloc = loc
+ // If we're not moving to the same spot (why? does that even happen?)
if(loc != newloc)
if(!direct)
direct = get_dir(oldloc, newloc)
- if (!(direct & (direct - 1))) //Cardinal move
- . = ..()
- else //Diagonal move, split it into cardinal moves
+ if (IS_CARDINAL(direct)) //Cardinal move
+ // Track our failure if any in this value
+ . = TRUE
+
+ // Face the direction of movement
+ set_dir(direct)
+
+ // Check to make sure we can leave
+ if(!loc.Exit(src, newloc))
+ . = FALSE
+
+ // Check to make sure we can enter, if we haven't already failed
+ if(. && !newloc.Enter(src, src.loc))
+ . = FALSE
+
+ // Check to make sure if we're multi-tile we can move, if we haven't already failed
+ if(. && !check_multi_tile_move_density_dir(direct, locs))
+ . = FALSE
+
+ // Definitely moving if you enter this, no failures so far
+ if(. && locs.len <= 1) // We're not a multi-tile object.
+ var/area/oldarea = get_area(oldloc)
+ var/area/newarea = get_area(newloc)
+ var/old_z = get_z(oldloc)
+ var/dest_z = get_z(newloc)
+
+ // Do The Move
+ glide_for(movetime)
+ loc = newloc
+ . = TRUE
+
+ // So objects can be informed of z-level changes
+ if (old_z != dest_z)
+ onTransitZ(old_z, dest_z)
+
+ // We don't call parent so we are calling this for byond
+ oldloc.Exited(src, newloc)
+ if(oldarea != newarea)
+ oldarea.Exited(src, newloc)
+
+ // Multi-tile objects can't reach here, otherwise you'd need to avoid uncrossing yourself
+ for(var/i in oldloc)
+ var/atom/movable/thing = i
+ // We don't call parent so we are calling this for byond
+ thing.Uncrossed(src)
+
+ // We don't call parent so we are calling this for byond
+ newloc.Entered(src, oldloc)
+ if(oldarea != newarea)
+ newarea.Entered(src, oldloc)
+
+ // Multi-tile objects can't reach here, otherwise you'd need to avoid uncrossing yourself
+ for(var/i in loc)
+ var/atom/movable/thing = i
+ // We don't call parent so we are calling this for byond
+ thing.Crossed(src)
+
+ // We're a multi-tile object (multiple locs)
+ else if(. && newloc)
+ . = doMove(newloc)
+
+ //Diagonal move, split it into cardinal moves
+ else
moving_diagonally = FIRST_DIAG_STEP
var/first_step_dir
// The `&& moving_diagonally` checks are so that a forceMove taking
// place due to a Crossed, Bumped, etc. call will interrupt
// the second half of the diagonal movement, or the second attempt
// at a first half if step() fails because we hit something.
+ glide_for(movetime)
if (direct & NORTH)
if (direct & EAST)
if (step(src, NORTH) && moving_diagonally)
@@ -161,47 +173,51 @@
first_step_dir = WEST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, SOUTH)
- if(moving_diagonally == SECOND_DIAG_STEP)
- if(!.)
- set_dir(first_step_dir)
- //else if (!inertia_moving)
- // inertia_next_move = world.time + inertia_move_delay
- // newtonian_move(direct)
+ // If we failed, turn to face the direction of the first step at least
+ if(!. && moving_diagonally == SECOND_DIAG_STEP)
+ set_dir(first_step_dir)
+ // Done, regardless!
moving_diagonally = 0
+ // We return because step above will call Move() and we don't want to do shenanigans back in here again
return
- if(!loc || (loc == oldloc && oldloc != newloc))
+ else if(!loc || (loc == oldloc))
last_move = 0
return
+ // If we moved, call Moved() on ourselves
if(.)
- Moved(oldloc, direct)
+ Moved(oldloc, direct, FALSE, movetime)
- //Polaris stuff
+ // Update timers/cooldown stuff
move_speed = world.time - l_move_time
l_move_time = world.time
- m_flag = 1
- //End
-
- last_move = direct
- set_dir(direct)
- if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob(s)
- return FALSE
+ last_move = direct // The direction you last moved
+ // set_dir(direct) //Don't think this is necessary
//Called after a successful Move(). By this point, we've already moved
-/atom/movable/proc/Moved(atom/OldLoc, Dir, Forced = FALSE)
- //if (!inertia_moving)
- // inertia_next_move = world.time + inertia_move_delay
- // newtonian_move(Dir)
- //if (length(client_mobs_in_contents))
- // update_parallax_contents()
-
+/atom/movable/proc/Moved(atom/old_loc, direction, forced = FALSE, movetime)
+ // Handle any buckled mobs on this movable
+ if(has_buckled_mobs())
+ handle_buckled_mob_movement(old_loc, direction, movetime)
+ if(riding_datum)
+ riding_datum.handle_vehicle_layer()
+ riding_datum.handle_vehicle_offsets()
return TRUE
+/atom/movable/set_dir(newdir)
+ . = ..(newdir)
+ if(riding_datum)
+ riding_datum.handle_vehicle_offsets()
+
+/atom/movable/relaymove(mob/user, direction)
+ . = ..()
+ if(riding_datum)
+ riding_datum.handle_ride(user, direction)
+
// Make sure you know what you're doing if you call this, this is intended to only be called by byond directly.
// You probably want CanPass()
/atom/movable/Cross(atom/movable/AM)
- . = TRUE
return CanPass(AM, loc)
/atom/movable/CanPass(atom/movable/mover, turf/target)
@@ -232,72 +248,113 @@
A.Bumped(src)
A.last_bumped = world.time
-/atom/movable/proc/forceMove(atom/destination)
+/atom/movable/proc/forceMove(atom/destination, direction, movetime)
. = FALSE
if(destination)
- . = doMove(destination)
+ . = doMove(destination, direction, movetime)
else
CRASH("No valid destination passed into forceMove")
/atom/movable/proc/moveToNullspace()
return doMove(null)
-/atom/movable/proc/doMove(atom/destination)
- . = FALSE
+/atom/movable/proc/doMove(atom/destination, direction, movetime)
+ var/atom/oldloc = loc
+ var/area/old_area = get_area(oldloc)
+ var/same_loc = oldloc == destination
+
if(destination)
- var/atom/oldloc = loc
- var/same_loc = oldloc == destination
- var/area/old_area = get_area(oldloc)
var/area/destarea = get_area(destination)
+ // Do The Move
+ glide_for(movetime)
+ last_move = isnull(direction) ? 0 : direction
loc = destination
+
+ // Unset this in case it was set in some other proc. We're no longer moving diagonally for sure.
moving_diagonally = 0
+ // We are moving to a different loc
if(!same_loc)
+ // Not moving out of nullspace
if(oldloc)
oldloc.Exited(src, destination)
+ // If it's not the same area, Exited() it
if(old_area && old_area != destarea)
old_area.Exited(src, destination)
- for(var/atom/movable/AM in oldloc)
+
+ // Uncross everything where we left
+ for(var/i in oldloc)
+ var/atom/movable/AM = i
+ if(AM == src)
+ continue
AM.Uncrossed(src)
+
+ // Information about turf and z-levels for source and dest collected
var/turf/oldturf = get_turf(oldloc)
var/turf/destturf = get_turf(destination)
var/old_z = (oldturf ? oldturf.z : null)
var/dest_z = (destturf ? destturf.z : null)
+
+ // So objects can be informed of z-level changes
if (old_z != dest_z)
onTransitZ(old_z, dest_z)
+
+ // Destination atom Entered
destination.Entered(src, oldloc)
+
+ // Entered() the new area if it's not the same area
if(destarea && old_area != destarea)
destarea.Entered(src, oldloc)
- for(var/atom/movable/AM in destination)
+ // We ignore ourselves because if we're multi-tile we might be in both old and new locs
+ for(var/i in destination)
+ var/atom/movable/AM = i
if(AM == src)
continue
AM.Crossed(src, oldloc)
+ // Call our thingy to inform everyone we moved
+ Moved(oldloc, NONE, TRUE)
+
// Break pulling if we are too far to pull now.
if(pulledby && (pulledby.z != src.z || get_dist(pulledby, src) > 1))
pulledby.stop_pulling()
- Moved(oldloc, NONE, TRUE)
- . = TRUE
+ // We moved
+ return TRUE
//If no destination, move the atom into nullspace (don't do this unless you know what you're doing)
- else
- . = TRUE
- if (loc)
- var/atom/oldloc = loc
- var/area/old_area = get_area(oldloc)
- oldloc.Exited(src, null)
- if(old_area)
- old_area.Exited(src, null)
+ else if(oldloc)
loc = null
+ // Uncross everything where we left (no multitile safety like above because we are definitely not still there)
+ for(var/i in oldloc)
+ var/atom/movable/AM = i
+ AM.Uncrossed(src)
+
+ // Exited() our loc and area
+ oldloc.Exited(src, null)
+ if(old_area)
+ old_area.Exited(src, null)
+
+ // We moved
+ return TRUE
+
/atom/movable/proc/onTransitZ(old_z,new_z)
GLOB.z_moved_event.raise_event(src, old_z, new_z)
for(var/item in src) // Notify contents of Z-transition. This can be overridden IF we know the items contents do not care.
var/atom/movable/AM = item
AM.onTransitZ(old_z,new_z)
+
+/atom/movable/proc/glide_for(movetime)
+ if(movetime)
+ glide_size = WORLD_ICON_SIZE/max(DS2TICKS(movetime), 1)
+ spawn(movetime)
+ glide_size = initial(glide_size)
+ else
+ glide_size = initial(glide_size)
+
/////////////////////////////////////////////////////////////////
//called when src is thrown into hit_atom
diff --git a/code/game/gamemodes/changeling/powers/armblade.dm b/code/game/gamemodes/changeling/powers/armblade.dm
index 664e6191ae..4a84fde371 100644
--- a/code/game/gamemodes/changeling/powers/armblade.dm
+++ b/code/game/gamemodes/changeling/powers/armblade.dm
@@ -113,11 +113,11 @@
/obj/item/weapon/melee/changeling/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(default_parry_check(user, attacker, damage_source) && prob(defend_chance))
user.visible_message("\The [user] parries [attack_text] with \the [src]!")
- playsound(user.loc, 'sound/weapons/slash.ogg', 50, 1)
+ playsound(src, 'sound/weapons/slash.ogg', 50, 1)
return 1
if(unique_parry_check(user, attacker, damage_source) && prob(projectile_parry_chance))
user.visible_message("\The [user] deflects [attack_text] with \the [src]!")
- playsound(user.loc, 'sound/weapons/slash.ogg', 50, 1)
+ playsound(src, 'sound/weapons/slash.ogg', 50, 1)
return 1
return 0
diff --git a/code/game/gamemodes/changeling/powers/escape_restraints.dm b/code/game/gamemodes/changeling/powers/escape_restraints.dm
index 08700b1e04..ced80d35bf 100644
--- a/code/game/gamemodes/changeling/powers/escape_restraints.dm
+++ b/code/game/gamemodes/changeling/powers/escape_restraints.dm
@@ -34,7 +34,7 @@
C.handcuffed = null
if(C.buckled && C.buckled.buckle_require_restraints)
C.buckled.unbuckle_mob()
- C.update_inv_handcuffed()
+ C.update_handcuffed()
if (C.client)
C.client.screen -= W
W.forceMove(C.loc)
diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm
index 420b1173c8..e483498155 100644
--- a/code/game/gamemodes/changeling/powers/revive.dm
+++ b/code/game/gamemodes/changeling/powers/revive.dm
@@ -50,7 +50,7 @@
H.handcuffed = null
if(H.buckled && H.buckled.buckle_require_restraints)
H.buckled.unbuckle_mob()
- H.update_inv_handcuffed()
+ H.update_handcuffed()
if (H.client)
H.client.screen -= W
W.forceMove(H.loc)
diff --git a/code/game/gamemodes/cult/construct_spells.dm b/code/game/gamemodes/cult/construct_spells.dm
index 64c97a30f4..954361fb9f 100644
--- a/code/game/gamemodes/cult/construct_spells.dm
+++ b/code/game/gamemodes/cult/construct_spells.dm
@@ -537,7 +537,7 @@ proc/findNullRod(var/atom/target)
new_projectile.fire()
log_and_message_admins("has casted [src] at \the [hit_atom].")
if(fire_sound)
- playsound(get_turf(src), fire_sound, 75, 1)
+ playsound(src, fire_sound, 75, 1)
return 1
return 0
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 8560582ee8..827e9730da 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -35,7 +35,7 @@
throw_at(get_edge_target_turf(src, pick(alldirs)), rand(1,3), throw_speed)
var/spooky = pick('sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg', 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/wail.ogg')
- playsound(loc, spooky, 50, 1)
+ playsound(src, spooky, 50, 1)
return 1
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index b9d434902e..bbf4bfb343 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -57,7 +57,7 @@
if(prob(1+ damage * 5))
visible_message("[shatter_message]")
STOP_PROCESSING(SSobj, src)
- playsound(get_turf(src),shatter_sound, 75, 1)
+ playsound(src,shatter_sound, 75, 1)
isbroken = 1
density = 0
icon_state = "[initial(icon_state)]-broken"
@@ -73,21 +73,21 @@
)
STOP_PROCESSING(SSobj, src)
user.do_attack_animation(src)
- playsound(get_turf(src),shatter_sound, 75, 1)
+ playsound(src,shatter_sound, 75, 1)
isbroken = 1
density = 0
icon_state = "[initial(icon_state)]-broken"
set_light(0)
else
to_chat(user, "You hit \the [src]!")
- playsound(get_turf(src),impact_sound, 75, 1)
+ playsound(src,impact_sound, 75, 1)
else
if(prob(damage * 2))
to_chat(user, "You pulverize what was left of \the [src]!")
qdel(src)
else
to_chat(user, "You hit \the [src]!")
- playsound(get_turf(src),impact_sound, 75, 1)
+ playsound(src,impact_sound, 75, 1)
/obj/structure/cult/pylon/proc/repair(mob/user as mob)
if(isbroken)
diff --git a/code/game/gamemodes/events/dust.dm b/code/game/gamemodes/events/dust.dm
index 400ae1058d..526164cd58 100644
--- a/code/game/gamemodes/events/dust.dm
+++ b/code/game/gamemodes/events/dust.dm
@@ -95,7 +95,7 @@ The "dust" will damage the hull of the station causin minor hull breaches.
if(!M.stat && !istype(M, /mob/living/silicon/ai))
shake_camera(M, 3, 1)
if (A)
- playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1)
+ playsound(src, 'sound/effects/meteorimpact.ogg', 40, 1)
if(ismob(A))
A.ex_act(strength)//This should work for now I guess
diff --git a/code/game/gamemodes/events/holidays/Christmas.dm b/code/game/gamemodes/events/holidays/Christmas.dm
index 66e329ac1a..c34f370a33 100644
--- a/code/game/gamemodes/events/holidays/Christmas.dm
+++ b/code/game/gamemodes/events/holidays/Christmas.dm
@@ -40,7 +40,7 @@
"What do you get from eating tree decorations?\n\nTinsilitis!",
"What do snowmen wear on their heads?\n\nIce caps!",
"Why is Christmas just like life on ss13?\n\nYou do all the work and the fat guy gets all the credit.",
- "Why doesn’t Santa have any children?\n\nBecause he only comes down the chimney.")
+ "Why doesn't Santa have any children?\n\nBecause he only comes down the chimney.")
new /obj/item/clothing/head/festive(target.loc)
user.update_icons()
cracked = 1
@@ -49,7 +49,7 @@
other_half.cracked = 1
other_half.icon_state = "cracker2"
target.put_in_active_hand(other_half)
- playsound(user, 'sound/effects/snap.ogg', 50, 1)
+ playsound(src, 'sound/effects/snap.ogg', 50, 1)
return 1
return ..()
diff --git a/code/game/gamemodes/game_mode_latespawn.dm b/code/game/gamemodes/game_mode_latespawn.dm
index 578c1a0d8c..9fcb4bd0ea 100644
--- a/code/game/gamemodes/game_mode_latespawn.dm
+++ b/code/game/gamemodes/game_mode_latespawn.dm
@@ -34,7 +34,7 @@
if(emergency_shuttle.shuttle && (emergency_shuttle.shuttle.moving_status == SHUTTLE_WARMUP || emergency_shuttle.shuttle.moving_status == SHUTTLE_INTRANSIT))
return // Don't do anything if the shuttle's coming.
- var/mills = round_duration_in_ticks
+ var/mills = round_duration_in_ds
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)
diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm
index 81b8a4e6b9..a07c42d69d 100644
--- a/code/game/gamemodes/meteor/meteors.dm
+++ b/code/game/gamemodes/meteor/meteors.dm
@@ -138,14 +138,13 @@
. = ..() //process movement...
- if(.)//.. if did move, ram the turf we get in
- var/turf/T = get_turf(loc)
- ram_turf(T)
+/obj/effect/meteor/Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
+ var/turf/T = get_turf(loc)
+ ram_turf(T)
- if(prob(10) && !istype(T, /turf/space))//randomly takes a 'hit' from ramming
- get_hit()
-
- return .
+ if(prob(10) && !istype(T, /turf/space)) //randomly takes a 'hit' from ramming
+ get_hit()
/obj/effect/meteor/Destroy()
walk(src,0) //this cancels the walk_towards() proc
diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm
index 5447431279..62406c3877 100644
--- a/code/game/gamemodes/nuclear/pinpointer.dm
+++ b/code/game/gamemodes/nuclear/pinpointer.dm
@@ -211,7 +211,7 @@
/obj/item/weapon/pinpointer/nukeop/proc/workdisk()
if(bomb_set) //If the bomb is set, lead to the shuttle
mode = 1 //Ensures worklocation() continues to work
- playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) //Plays a beep
+ playsound(src, 'sound/machines/twobeep.ogg', 50, 1) //Plays a beep
visible_message("Shuttle Locator active.") //Lets the mob holding it know that the mode has changed
return //Get outta here
@@ -236,7 +236,7 @@
/obj/item/weapon/pinpointer/nukeop/proc/worklocation()
if(!bomb_set)
mode = 0
- playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
+ playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
visible_message("Authentication Disk Locator active.")
return
diff --git a/code/game/gamemodes/technomancer/devices/shield_armor.dm b/code/game/gamemodes/technomancer/devices/shield_armor.dm
index c8e8130adc..7618708aad 100644
--- a/code/game/gamemodes/technomancer/devices/shield_armor.dm
+++ b/code/game/gamemodes/technomancer/devices/shield_armor.dm
@@ -70,7 +70,7 @@
to_chat(user, "Your shield has absorbed most of \the [damage_source].")
spark_system.start()
- playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
return 0 // This shield does not block all damage, so returning 0 is needed to tell the game to apply the new damage.
/obj/item/clothing/suit/armor/shield/attack_self(mob/user)
diff --git a/code/game/gamemodes/technomancer/devices/tesla_armor.dm b/code/game/gamemodes/technomancer/devices/tesla_armor.dm
index 86d6f82b08..124e1ed1f3 100644
--- a/code/game/gamemodes/technomancer/devices/tesla_armor.dm
+++ b/code/game/gamemodes/technomancer/devices/tesla_armor.dm
@@ -81,4 +81,4 @@
lightning.old_style_target(target)
lightning.fire()
visible_message("\The [src] strikes \the [target] with lightning!")
- playsound(get_turf(src), 'sound/weapons/gauss_shoot.ogg', 75, 1)
\ No newline at end of file
+ playsound(src, 'sound/weapons/gauss_shoot.ogg', 75, 1)
\ No newline at end of file
diff --git a/code/game/gamemodes/technomancer/spells/audible_deception.dm b/code/game/gamemodes/technomancer/spells/audible_deception.dm
index c8a66fac3c..1914b72f14 100644
--- a/code/game/gamemodes/technomancer/spells/audible_deception.dm
+++ b/code/game/gamemodes/technomancer/spells/audible_deception.dm
@@ -75,7 +75,7 @@
/obj/item/weapon/spell/audible_deception/on_ranged_cast(atom/hit_atom, mob/living/user)
var/turf/T = get_turf(hit_atom)
if(selected_sound && pay_energy(200))
- playsound(T, selected_sound, 80, 1, -1)
+ playsound(src, selected_sound, 80, 1, -1)
adjust_instability(1)
// Air Horn time.
if(selected_sound == 'sound/items/AirHorn.ogg' && pay_energy(3800))
diff --git a/code/game/gamemodes/technomancer/spells/instability_tap.dm b/code/game/gamemodes/technomancer/spells/instability_tap.dm
index 13a2b5e318..ad2c72518b 100644
--- a/code/game/gamemodes/technomancer/spells/instability_tap.dm
+++ b/code/game/gamemodes/technomancer/spells/instability_tap.dm
@@ -26,5 +26,5 @@
else
core.give_energy(amount)
adjust_instability(50)
- playsound(get_turf(src), 'sound/effects/supermatter.ogg', 75, 1)
+ playsound(src, 'sound/effects/supermatter.ogg', 75, 1)
qdel(src)
\ No newline at end of file
diff --git a/code/game/gamemodes/technomancer/spells/oxygenate.dm b/code/game/gamemodes/technomancer/spells/oxygenate.dm
index 61c6367260..b36f17c726 100644
--- a/code/game/gamemodes/technomancer/spells/oxygenate.dm
+++ b/code/game/gamemodes/technomancer/spells/oxygenate.dm
@@ -29,5 +29,5 @@
if(pay_energy(1500))
T.assume_gas("oxygen", 200)
T.assume_gas("nitrogen", 800)
- playsound(src.loc, 'sound/effects/spray.ogg', 50, 1, -3)
+ playsound(src, 'sound/effects/spray.ogg', 50, 1, -3)
adjust_instability(10)
\ No newline at end of file
diff --git a/code/game/gamemodes/technomancer/spells/projectile/projectile.dm b/code/game/gamemodes/technomancer/spells/projectile/projectile.dm
index a52bb2e584..62ae49b0f0 100644
--- a/code/game/gamemodes/technomancer/spells/projectile/projectile.dm
+++ b/code/game/gamemodes/technomancer/spells/projectile/projectile.dm
@@ -16,7 +16,7 @@
new_projectile.fire()
log_and_message_admins("has casted [src] at \the [hit_atom].")
if(fire_sound)
- playsound(get_turf(src), fire_sound, 75, 1)
+ playsound(src, fire_sound, 75, 1)
adjust_instability(instability_per_shot)
return 1
return 0
diff --git a/code/game/gamemodes/technomancer/spells/reflect.dm b/code/game/gamemodes/technomancer/spells/reflect.dm
index 47ed0663f2..756e9e27fc 100644
--- a/code/game/gamemodes/technomancer/spells/reflect.dm
+++ b/code/game/gamemodes/technomancer/spells/reflect.dm
@@ -60,7 +60,7 @@
P.damage = P.damage * 1.5
spark_system.start()
- playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
// now send a log so that admins don't think they're shooting themselves on purpose.
log_and_message_admins("[user] reflected [attacker]'s attack back at them.")
@@ -80,7 +80,7 @@
on the same side, and hits you!")
spark_system.start()
- playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
log_and_message_admins("[user] reflected [attacker]'s attack back at them.")
diff --git a/code/game/gamemodes/technomancer/spells/resurrect.dm b/code/game/gamemodes/technomancer/spells/resurrect.dm
index 02c072b90d..41dc9ce34f 100644
--- a/code/game/gamemodes/technomancer/spells/resurrect.dm
+++ b/code/game/gamemodes/technomancer/spells/resurrect.dm
@@ -44,7 +44,7 @@
for(var/mob/observer/dead/ghost in player_list)
if(ghost.mind == H.mind)
ghost.notify_revive("The Technomancer [user.real_name] is trying to revive you. \
- Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg')
+ Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg', source = user)
break
H.adjustBruteLoss(-40)
diff --git a/code/game/gamemodes/technomancer/spells/shield.dm b/code/game/gamemodes/technomancer/spells/shield.dm
index 6bcbda5ec4..b11d5590b0 100644
--- a/code/game/gamemodes/technomancer/spells/shield.dm
+++ b/code/game/gamemodes/technomancer/spells/shield.dm
@@ -55,7 +55,7 @@
if(check_shield_arc(user, bad_arc, damage_source, attacker))
user.visible_message("\The [user]'s [src] blocks [attack_text]!")
spark_system.start()
- playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
adjust_instability(2)
return 1
return 0
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index 2ded8a4cbe..b78fc5f74a 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -31,6 +31,7 @@
var/outfit_type // What outfit datum does this job use in its default title?
var/offmap_spawn = FALSE // Do we require weird and special spawning and datacore handling?
+ var/mob_type = JOB_CARBON // Bitflags representing mob type this job spawns
// Description of the job's role and minimum responsibilities.
var/job_description = "This Job doesn't have a description! Please report it!"
diff --git a/code/game/jobs/job/silicon.dm b/code/game/jobs/job/silicon.dm
index 6f89adcd07..1619569c9d 100644
--- a/code/game/jobs/job/silicon.dm
+++ b/code/game/jobs/job/silicon.dm
@@ -18,6 +18,7 @@
economic_modifier = 0
has_headset = FALSE
assignable = FALSE
+ mob_type = JOB_SILICON_AI
outfit_type = /decl/hierarchy/outfit/job/silicon/ai
job_description = "The AI oversees the operation of the station and its crew, but has no real authority over them. \
The AI is required to follow its Laws, and Lawbound Synthetics that are linked to it are expected to follow \
@@ -54,6 +55,7 @@
economic_modifier = 0
has_headset = FALSE
assignable = FALSE
+ mob_type = JOB_SILICON_ROBOT
outfit_type = /decl/hierarchy/outfit/job/silicon/cyborg
job_description = "A Cyborg is a mobile station synthetic, piloted by a cybernetically preserved brain. It is considered a person, but is still required \
to follow its Laws."
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index 806d0fe794..182382578a 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -360,54 +360,64 @@ var/global/datum/controller/occupations/job_master
//Equip custom gear loadout.
var/list/custom_equip_slots = list() //If more than one item takes the same slot, all after the first one spawn in storage.
var/list/custom_equip_leftovers = list()
- if(H.client.prefs.gear && H.client.prefs.gear.len && job.title != "Cyborg" && job.title != "AI")
+ if(H.client.prefs.gear && H.client.prefs.gear.len && !(job.mob_type & JOB_SILICON))
for(var/thing in H.client.prefs.gear)
var/datum/gear/G = gear_datums[thing]
- if(G)
- var/permitted
- if(G.allowed_roles)
- for(var/job_name in G.allowed_roles)
- if(job.title == job_name)
- permitted = 1
+ if(!G) //Not a real gear datum (maybe removed, as this is loaded from their savefile)
+ continue
+
+ var/permitted
+ // Check if it is restricted to certain roles
+ if(G.allowed_roles)
+ for(var/job_name in G.allowed_roles)
+ if(job.title == job_name)
+ permitted = 1
+ else
+ permitted = 1
+
+ // Check if they're whitelisted for this gear (in alien whitelist? seriously?)
+ if(G.whitelisted && !is_alien_whitelisted(H, GLOB.all_species[G.whitelisted]))
+ permitted = 0
+
+ // If they aren't, tell them
+ if(!permitted)
+ to_chat(H, "Your current species, job or whitelist status does not permit you to spawn with [thing]!")
+ continue
+
+ // Implants get special treatment
+ if(G.slot == "implant")
+ var/obj/item/weapon/implant/I = G.spawn_item(H)
+ I.invisibility = 100
+ I.implant_loadout(H)
+ continue
+
+ // Try desperately (and sorta poorly) to equip the item
+ if(G.slot && !(G.slot in custom_equip_slots))
+ var/metadata = H.client.prefs.gear[G.display_name]
+ if(G.slot == slot_wear_mask || G.slot == slot_wear_suit || G.slot == slot_head)
+ custom_equip_leftovers += thing
+ else if(H.equip_to_slot_or_del(G.spawn_item(H, metadata), G.slot))
+ to_chat(H, "Equipping you with \the [thing]!")
+ custom_equip_slots.Add(G.slot)
else
- permitted = 1
+ custom_equip_leftovers.Add(thing)
+ else
+ spawn_in_storage += thing
- if(G.whitelisted && !is_alien_whitelisted(H, GLOB.all_species[G.whitelisted]))
-
- //if(G.whitelisted && (G.whitelisted != H.species.name || !is_alien_whitelisted(H, G.whitelisted)))
- permitted = 0
-
- if(!permitted)
- to_chat(H, "Your current species, job or whitelist status does not permit you to spawn with [thing]!")
- continue
-
- if(G.slot == "implant")
- var/obj/item/weapon/implant/I = G.spawn_item(H)
- I.invisibility = 100
- I.implant_loadout(H)
- continue
-
- if(G.slot && !(G.slot in custom_equip_slots))
- // This is a miserable way to fix the loadout overwrite bug, but the alternative requires
- // adding an arg to a bunch of different procs. Will look into it after this merge. ~ Z
- var/metadata = H.client.prefs.gear[G.display_name]
- if(G.slot == slot_wear_mask || G.slot == slot_wear_suit || G.slot == slot_head)
- custom_equip_leftovers += thing
- else if(H.equip_to_slot_or_del(G.spawn_item(H, metadata), G.slot))
- to_chat(H, "Equipping you with \the [thing]!")
- custom_equip_slots.Add(G.slot)
- else
- custom_equip_leftovers.Add(thing)
- else
- spawn_in_storage += thing
- //Equip job items.
+ // Set up their account
job.setup_account(H)
+
+ // Equip job items.
job.equip(H, H.mind ? H.mind.role_alt_title : "")
+
+ // Stick their fingerprints on literally everything
job.apply_fingerprints(H)
- if(job.title != "Cyborg" && job.title != "AI")
+
+ // Only non-silicons get post-job-equip equipment
+ if(!(job.mob_type & JOB_SILICON))
H.equip_post_job()
- //If some custom items could not be equipped before, try again now.
+ // If some custom items could not be equipped before, try again now.
for(var/thing in custom_equip_leftovers)
var/datum/gear/G = gear_datums[thing]
if(G.slot in custom_equip_slots)
@@ -442,14 +452,16 @@ var/global/datum/controller/occupations/job_master
H.mind.assigned_role = rank
alt_title = H.mind.role_alt_title
- switch(rank)
- if("Cyborg")
- return H.Robotize()
- if("AI")
- return H
- if("Colony Director")
- var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP) ? null : sound('sound/misc/boatswain.ogg', volume=20)
- captain_announcement.Announce("All hands, [alt_title ? alt_title : "Colony Director"] [H.real_name] on deck!", new_sound = announce_sound, zlevel = H.z)
+ // If we're a silicon, we may be done at this point
+ if(job.mob_type & JOB_SILICON_ROBOT)
+ return H.Robotize()
+ if(job.mob_type & JOB_SILICON_AI)
+ return H
+
+ // TWEET PEEP
+ if(rank == "Colony Director")
+ var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP) ? null : sound('sound/misc/boatswain.ogg', volume=20)
+ captain_announcement.Announce("All hands, [alt_title ? alt_title : "Colony Director"] [H.real_name] on deck!", new_sound = announce_sound, zlevel = H.z)
//Deferred item spawning.
if(spawn_in_storage && spawn_in_storage.len)
@@ -559,7 +571,7 @@ var/global/datum/controller/occupations/job_master
if(!J) continue
J.total_positions = text2num(value)
J.spawn_positions = text2num(value)
- if(name == "AI" || name == "Cyborg")//I dont like this here but it will do for now
+ if(J.mob_type & JOB_SILICON)
J.total_positions = 0
return 1
diff --git a/code/game/machinery/CableLayer.dm b/code/game/machinery/CableLayer.dm
index 7bac2c4599..8edc131ac8 100644
--- a/code/game/machinery/CableLayer.dm
+++ b/code/game/machinery/CableLayer.dm
@@ -13,9 +13,9 @@
cable.amount = 100
..()
-/obj/machinery/cablelayer/Move(new_turf,M_Dir)
- ..()
- layCable(new_turf,M_Dir)
+/obj/machinery/cablelayer/Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
+ layCable(loc,direction)
/obj/machinery/cablelayer/attack_hand(mob/user as mob)
if(!cable&&!on)
@@ -41,7 +41,7 @@
m = min(m, cable.amount)
m = min(m, 30)
if(m)
- playsound(src.loc, O.usesound, 50, 1)
+ playsound(src, O.usesound, 50, 1)
use_cable(m)
var/obj/item/stack/cable_coil/CC = new (get_turf(src))
CC.amount = m
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index 5de1543426..0d67a00651 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -53,15 +53,6 @@
return TRUE
return FALSE
-/obj/machinery/optable/MouseDrop_T(obj/O as obj, mob/user as mob)
-
- if((!(istype(O, /obj/item/weapon)) || user.get_active_hand() != O))
- return
- user.drop_item()
- if(O.loc != src.loc)
- step(O, get_dir(O, src))
- return
-
/obj/machinery/optable/proc/check_victim()
if(locate(/mob/living/carbon/human, src.loc))
var/mob/living/carbon/human/M = locate(/mob/living/carbon/human, src.loc)
@@ -96,40 +87,43 @@
else
icon_state = "table2-idle"
-/obj/machinery/optable/MouseDrop_T(mob/target, mob/user)
-
- var/mob/living/M = user
- if(user.stat || user.restrained() || !check_table(user) || !iscarbon(target))
- return
- if(istype(M))
- take_victim(target,user)
- else
+/obj/machinery/optable/MouseDrop_T(mob/living/carbon/target, mob/living/user)
+ if(!istype(target) || !istype(user))
return ..()
+ if(!Adjacent(target) || !Adjacent(user))
+ return ..()
+
+ if(user.incapacitated() || !check_table(target, user))
+ return ..()
+
+ take_victim(target, user)
+
/obj/machinery/optable/verb/climb_on()
set name = "Climb On Table"
set category = "Object"
set src in oview(1)
- if(usr.stat || !ishuman(usr) || usr.restrained() || !check_table(usr))
+ var/mob/living/user = usr
+ if(!istype(user) || user.incapacitated() || !check_table(user, user))
return
- take_victim(usr,usr)
+ take_victim(user, user)
-/obj/machinery/optable/attackby(obj/item/weapon/W as obj, mob/living/carbon/user as mob)
+/obj/machinery/optable/attackby(obj/item/weapon/W, mob/living/carbon/user)
if(istype(W, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = W
- if(iscarbon(G.affecting) && check_table(G.affecting))
- take_victim(G.affecting,usr)
+ if(iscarbon(G.affecting) && check_table(G.affecting, user))
+ take_victim(G.affecting, user)
qdel(W)
return
-/obj/machinery/optable/proc/check_table(mob/living/carbon/patient as mob)
+/obj/machinery/optable/proc/check_table(mob/living/carbon/patient, mob/living/user)
check_victim()
if(victim && get_turf(victim) == get_turf(src) && victim.lying)
- to_chat(usr, "\The [src] is already occupied!")
+ to_chat(user, "\The [src] is already occupied!")
return 0
if(patient.buckled)
- to_chat(usr, "Unbuckle \the [patient] first!")
+ to_chat(user, "Unbuckle \the [patient] first!")
return 0
return 1
\ No newline at end of file
diff --git a/code/game/machinery/air_alarm.dm b/code/game/machinery/air_alarm.dm
index 3d76b02e0f..b45d00c3f7 100644
--- a/code/game/machinery/air_alarm.dm
+++ b/code/game/machinery/air_alarm.dm
@@ -116,7 +116,7 @@
/obj/machinery/alarm/proc/first_run()
alarm_area = get_area(src)
- area_uid = "\ref[alarm_area]"
+ area_uid = "\ref[alarm_area]"
if(name == "alarm")
name = "[alarm_area.name] Air Alarm"
@@ -188,7 +188,7 @@
regulating_temperature = 1
audible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
"You hear a click and a faint electronic hum.")
- playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
+ playsound(src, 'sound/machines/click.ogg', 50, 1)
else
//check for when we should stop adjusting temperature
if(get_danger_level(target_temperature, TLV["temperature"]) || abs(environment.temperature - target_temperature) <= 0.5)
@@ -196,7 +196,7 @@
regulating_temperature = 0
audible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
"You hear a click as a faint electronic humming stops.")
- playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
+ playsound(src, 'sound/machines/click.ogg', 50, 1)
if(regulating_temperature)
if(target_temperature > T0C + MAX_TEMPERATURE)
diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm
index 3833c72ee4..3a012a1ccd 100644
--- a/code/game/machinery/atmoalter/canister.dm
+++ b/code/game/machinery/atmoalter/canister.dm
@@ -171,7 +171,7 @@ update_flag
location.assume_air(air_contents)
src.destroyed = 1
- playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
+ playsound(src, 'sound/effects/spray.ogg', 10, 1, -3)
src.density = 0
update_icon()
diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm
index 3b6df894b5..879551493d 100644
--- a/code/game/machinery/atmoalter/scrubber.dm
+++ b/code/game/machinery/atmoalter/scrubber.dm
@@ -213,7 +213,7 @@
return
anchored = !anchored
- playsound(src.loc, I.usesound, 50, 1)
+ playsound(src, I.usesound, 50, 1)
to_chat(user, "You [anchored ? "wrench" : "unwrench"] \the [src].")
return
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 136c459cf7..0f468953a8 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -26,6 +26,8 @@
var/datum/wires/autolathe/wires = null
+ var/filtertext
+
/obj/machinery/autolathe/Initialize()
. = ..()
wires = new(src)
@@ -66,11 +68,14 @@
material_bottom += "
[stored_material[material]]/[storage_capacity[material]] | "
dat += "[material_top.Join()][material_bottom.Join()]
"
+ dat += "Filter: [filtertext ? filtertext : "None Set"]
"
dat += "Printable Designs
"
for(var/datum/category_item/autolathe/R in current_category.items)
if(R.hidden && !hacked)
continue
+ if(filtertext && findtext(R.name, filtertext) == 0)
+ continue
var/can_make = 1
var/list/material_string = list()
var/list/multiplier_string = list()
@@ -102,12 +107,14 @@
multiplier_string += "\[x[i]\]"
multiplier_string += "\[x[max_sheets]\]"
- dat += "| [R.hidden ? "*" : ""][can_make ? "" : ""][R.name][can_make ? "" : ""][R.hidden ? "*" : ""][multiplier_string.Join()] | [material_string.Join()] |
"
+ dat += "| [R.hidden ? "*" : ""][can_make ? "" : ""][R.name][can_make ? "" : ""][R.hidden ? "*" : ""][multiplier_string.Join()] | [material_string.Join()] |
"
dat += "
"
- user << browse(dat.Join(), "window=autolathe")
- onclose(user, "autolathe")
+ dat = jointext(dat, null)
+ var/datum/browser/popup = new(user, "autolathe", "Autolathe Production Menu", 550, 700)
+ popup.set_content(dat)
+ popup.open()
/obj/machinery/autolathe/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(busy)
@@ -196,7 +203,7 @@
else
to_chat(user, "You fill \the [src] with \the [eating].")
- flick("autolathe_o", src) // Plays metal insertion animation. Work out a good way to work out a fitting animation. ~Z
+ flick("autolathe_loading", src) // Plays metal insertion animation. Work out a good way to work out a fitting animation. ~Z
if(istype(eating,/obj/item/stack))
var/obj/item/stack/stack = eating
@@ -223,6 +230,16 @@
to_chat(usr, "The autolathe is busy. Please wait for completion of previous operation.")
return
+ else if(href_list["setfilter"])
+ var/filterstring = input(usr, "Input a filter string, or blank to not filter:", "Design Filter", filtertext) as null|text
+ if(!Adjacent(usr))
+ return
+ if(isnull(filterstring)) //Clicked Cancel
+ return
+ if(filterstring == "") //Cleared value
+ filtertext = null
+ filtertext = sanitize(filterstring, 25)
+
if(href_list["change_category"])
var/choice = input("Which category do you wish to display?") as null|anything in machine_recipes.categories
@@ -268,6 +285,7 @@
//Create the desired item.
var/obj/item/I = new making.path(src.loc)
+ flick("[initial(icon_state)]_finish", src)
if(multiplier > 1)
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
@@ -279,14 +297,16 @@
updateUsrDialog()
/obj/machinery/autolathe/update_icon()
+ overlays.Cut()
+
+ icon_state = initial(icon_state)
+
if(panel_open)
- icon_state = "autolathe_t"
- else if(busy)
- icon_state = "autolathe_n"
- else
- if(icon_state == "autolathe_n")
- flick("autolathe_u", src) // If lid WAS closed, show opening animation
- icon_state = "autolathe"
+ overlays.Add(image(icon, "[icon_state]_panel"))
+ if(stat & NOPOWER)
+ return
+ if(busy)
+ icon_state = "[icon_state]_work"
//Updates overall lathe storage size.
/obj/machinery/autolathe/RefreshParts()
diff --git a/code/game/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm
index 0865a3ec55..d8bd9ba1d1 100644
--- a/code/game/machinery/biogenerator.dm
+++ b/code/game/machinery/biogenerator.dm
@@ -163,11 +163,11 @@
processing = 1
update_icon()
updateUsrDialog()
- playsound(src.loc, 'sound/machines/blender.ogg', 40, 1)
+ playsound(src, 'sound/machines/blender.ogg', 40, 1)
use_power(S * 30)
sleep((S + 15) / eat_eff)
processing = 0
- playsound(src.loc, 'sound/machines/biogenerator_end.ogg', 40, 1)
+ playsound(src, 'sound/machines/biogenerator_end.ogg', 40, 1)
update_icon()
else
menustat = "void"
diff --git a/code/game/machinery/bioprinter.dm b/code/game/machinery/bioprinter.dm
index 853029b217..034a7fe243 100644
--- a/code/game/machinery/bioprinter.dm
+++ b/code/game/machinery/bioprinter.dm
@@ -283,7 +283,7 @@
/obj/machinery/organ_printer/flesh/print_organ(var/choice)
var/obj/item/organ/O = ..()
- playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
+ playsound(src, 'sound/machines/ding.ogg', 50, 1)
visible_message("\The [src] dings, then spits out \a [O].")
return O
@@ -348,7 +348,7 @@
var/obj/item/organ/O = ..()
O.robotize()
O.status |= ORGAN_CUT_AWAY // robotize() resets status to 0
- playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
+ playsound(src, 'sound/machines/ding.ogg', 50, 1)
audible_message("\The [src] dings, then spits out \a [O].")
return O
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 8be097fa2f..8fd7c44c7c 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -82,6 +82,8 @@
..()
/obj/machinery/camera/Destroy()
+ if(isMotion())
+ unsense_proximity(callback = .HasProximity)
deactivate(null, 0) //kick anyone viewing out
if(assembly)
qdel(assembly)
@@ -151,7 +153,7 @@
user.do_attack_animation(src)
user.setClickCooldown(user.get_attack_speed())
visible_message("\The [user] slashes at [src]!")
- playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
+ playsound(src, 'sound/weapons/slash.ogg', 100, 1)
add_hiddenprint(user)
destroy()
@@ -162,7 +164,7 @@
S.do_attack_animation(src)
S.setClickCooldown(user.get_attack_speed())
visible_message("\The [user] [pick(S.attacktext)] \the [src]!")
- playsound(src.loc, S.attack_sound, 100, 1)
+ playsound(src, S.attack_sound, 100, 1)
add_hiddenprint(user)
destroy()
..()
@@ -176,7 +178,7 @@
panel_open = !panel_open
user.visible_message("[user] screws the camera's panel [panel_open ? "open" : "closed"]!",
"You screw the camera's panel [panel_open ? "open" : "closed"].")
- playsound(src.loc, W.usesound, 50, 1)
+ playsound(src, W.usesound, 50, 1)
else if((W.is_wirecutter() || istype(W, /obj/item/device/multitool)) && panel_open)
interact(user)
@@ -251,7 +253,7 @@
if (istype(W, /obj/item)) //is it even possible to get into attackby() with non-items?
var/obj/item/I = W
if (I.hitsound)
- playsound(loc, I.hitsound, 50, 1, -1)
+ playsound(src, I.hitsound, 50, 1, -1)
take_damage(W.force)
else
@@ -271,7 +273,7 @@
visible_message(" [user] has deactivated [src]!")
else
visible_message(" [src] clicks and shuts down. ")
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
+ playsound(src, 'sound/items/Wirecutter.ogg', 100, 1)
icon_state = "[initial(icon_state)]1"
add_hiddenprint(user)
else
@@ -279,7 +281,7 @@
visible_message(" [user] has reactivated [src]!")
else
visible_message(" [src] clicks and reactivates itself. ")
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
+ playsound(src, 'sound/items/Wirecutter.ogg', 100, 1)
icon_state = initial(icon_state)
add_hiddenprint(user)
@@ -301,7 +303,7 @@
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, loc)
spark_system.start()
- playsound(loc, "sparks", 50, 1)
+ playsound(src, "sparks", 50, 1)
/obj/machinery/camera/proc/set_status(var/newstatus)
if (status != newstatus)
@@ -397,7 +399,7 @@
// Do after stuff here
to_chat(user, "You start to weld [src]..")
- playsound(src.loc, WT.usesound, 50, 1)
+ playsound(src, WT.usesound, 50, 1)
WT.eyecheck(user)
busy = 1
if(do_after(user, 100 * WT.toolspeed))
diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm
index 31877f868e..69fb773c6d 100644
--- a/code/game/machinery/camera/camera_assembly.dm
+++ b/code/game/machinery/camera/camera_assembly.dm
@@ -78,7 +78,7 @@
if(3)
// State 3
if(W.is_screwdriver())
- playsound(src.loc, W.usesound, 50, 1)
+ playsound(src, W.usesound, 50, 1)
var/input = sanitize(input(usr, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: "+using_map.station_short+",Security,Secret ", "Set Network", camera_network ? camera_network : NETWORK_DEFAULT))
if(!input)
@@ -118,7 +118,7 @@
else if(W.is_wirecutter())
new/obj/item/stack/cable_coil(get_turf(src), 2)
- playsound(src.loc, W.usesound, 50, 1)
+ playsound(src, W.usesound, 50, 1)
to_chat(user, "You cut the wires from the circuits.")
state = 2
return
@@ -161,7 +161,7 @@
return 0
to_chat(user, "You start to weld the [src]..")
- playsound(src.loc, WT.usesound, 50, 1)
+ playsound(src, WT.usesound, 50, 1)
WT.eyecheck(user)
busy = 1
if(do_after(user, 20 * WT.toolspeed))
diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm
index eac1f89386..ad183a7be8 100644
--- a/code/game/machinery/camera/motion.dm
+++ b/code/game/machinery/camera/motion.dm
@@ -3,15 +3,13 @@
var/detectTime = 0
var/area/ai_monitored/area_motion = null
var/alarm_delay = 100 // Don't forget, there's another 10 seconds in queueAlarm()
- flags = PROXMOVE
/obj/machinery/camera/internal_process()
// motion camera event loop
if (stat & (EMPED|NOPOWER))
return
if(!isMotion())
- . = PROCESS_KILL
- return
+ return PROCESS_KILL
if (detectTime > 0)
var/elapsed = world.time - detectTime
if (elapsed > alarm_delay)
@@ -56,7 +54,7 @@
detectTime = -1
return 1
-/obj/machinery/camera/HasProximity(atom/movable/AM as mob|obj)
+/obj/machinery/camera/HasProximity(turf/T, atom/movable/AM, old_loc)
// Motion cameras outside of an "ai monitored" area will use this to detect stuff.
if (!area_motion)
if(isliving(AM))
diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm
index 15b5f7abca..f625fb9546 100644
--- a/code/game/machinery/camera/presets.dm
+++ b/code/game/machinery/camera/presets.dm
@@ -212,9 +212,12 @@ var/global/list/engineering_networks = list(
update_coverage()
/obj/machinery/camera/proc/upgradeMotion()
+ if(!isturf(loc))
+ return //nooooo
assembly.upgrades.Add(new /obj/item/device/assembly/prox_sensor(assembly))
setPowerUsage()
START_MACHINE_PROCESSING(src)
+ sense_proximity(callback = .HasProximity)
update_coverage()
/obj/machinery/camera/proc/setPowerUsage()
diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm
index f7fd84eca7..60541e0fe3 100644
--- a/code/game/machinery/camera/tracking.dm
+++ b/code/game/machinery/camera/tracking.dm
@@ -152,11 +152,11 @@
cameraFollow = null
/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target as mob)
- if(!istype(target)) return
+ if(!istype(target)) return FALSE
var/mob/living/silicon/ai/U = usr
if(target == U.cameraFollow)
- return
+ return TRUE
if(U.cameraFollow)
U.ai_cancel_tracking()
@@ -185,6 +185,8 @@
return
sleep(10)
+ return TRUE
+
/obj/machinery/camera/attack_ai(var/mob/living/silicon/ai/user as mob)
if (!istype(user))
return
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 0e184bfc90..019ed86bea 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -201,7 +201,7 @@
return
else if((occupant.health >= heal_level || occupant.health == occupant.getMaxHealth()) && (!eject_wait))
- playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
+ playsound(src, 'sound/machines/ding.ogg', 50, 1)
audible_message("\The [src] signals that the cloning process is complete.")
connected_message("Cloning Process Complete.")
locked = 0
diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm
index 8a88948ee0..397366c6c2 100644
--- a/code/game/machinery/computer/ai_core.dm
+++ b/code/game/machinery/computer/ai_core.dm
@@ -15,7 +15,7 @@
switch(state)
if(0)
if(P.is_wrench())
- playsound(loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
if(do_after(user, 20 * P.toolspeed))
to_chat(user, "You wrench the frame into place.")
anchored = 1
@@ -25,7 +25,7 @@
if(!WT.isOn())
to_chat(user, "The welder must be on for this task.")
return
- playsound(loc, WT.usesound, 50, 1)
+ playsound(src, WT.usesound, 50, 1)
if(do_after(user, 20 * WT.toolspeed))
if(!src || !WT.remove_fuel(0, user)) return
to_chat(user, "You deconstruct the frame.")
@@ -33,25 +33,25 @@
qdel(src)
if(1)
if(P.is_wrench())
- playsound(loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
if(do_after(user, 20 * P.toolspeed))
to_chat(user, "You unfasten the frame.")
anchored = 0
state = 0
if(istype(P, /obj/item/weapon/circuitboard/aicore) && !circuit)
- playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "You place the circuit board inside the frame.")
icon_state = "1"
circuit = P
user.drop_item()
P.loc = src
if(P.is_screwdriver() && circuit)
- playsound(loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You screw the circuit board into place.")
state = 2
icon_state = "2"
if(P.is_crowbar() && circuit)
- playsound(loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You remove the circuit board.")
state = 1
icon_state = "0"
@@ -59,7 +59,7 @@
circuit = null
if(2)
if(P.is_screwdriver() && circuit)
- playsound(loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You unfasten the circuit board.")
state = 1
icon_state = "1"
@@ -69,7 +69,7 @@
to_chat(user, "You need five coils of wire to add them to the frame.")
return
to_chat(user, "You start to add cables to the frame.")
- playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if (do_after(user, 20) && state == 2)
if (C.use(5))
state = 3
@@ -81,7 +81,7 @@
if (brain)
to_chat(user, "Get that brain out of there first")
else
- playsound(loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You remove the cables.")
state = 2
icon_state = "2"
@@ -94,7 +94,7 @@
to_chat(user, "You need two sheets of glass to put in the glass panel.")
return
to_chat(user, "You start to put in the glass panel.")
- playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if (do_after(user, 20) && state == 3)
if(RG.use(2))
to_chat(user, "You put in the glass panel.")
@@ -146,7 +146,7 @@
icon_state = "3b"
if(P.is_crowbar() && brain)
- playsound(loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You remove the brain.")
brain.loc = loc
brain = null
@@ -154,7 +154,7 @@
if(4)
if(P.is_crowbar())
- playsound(loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You remove the glass panel.")
state = 3
if (brain)
@@ -165,7 +165,7 @@
return
if(P.is_screwdriver())
- playsound(loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You connect the monitor.")
if(!brain)
var/open_for_latejoin = alert(user, "Would you like this core to be open for latejoining AIs?", "Latejoin", "Yes", "Yes", "No") == "Yes"
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 86f3fe93da..0ce27d99bb 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -672,10 +672,10 @@
src.visible_message("The machine states, 'YOU ARE UNDER ARREST, RAIDER!' and shoots handcuffs onto [usr]!", "You hear something say 'YOU ARE UNDER ARREST, RAIDER!' and a clinking sound")
var/obj/item/weapon/handcuffs/C = new(src.loc)
var/mob/living/carbon/human/H = usr
- if(istype(usr))
+ if(istype(H))
C.forceMove(H)
H.handcuffed = C
- H.update_inv_handcuffed()
+ H.update_handcuffed()
else
C.throw_at(usr,16,3,src)
diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm
index c69cca31b5..48f899ed0d 100644
--- a/code/game/machinery/computer/atmos_control.dm
+++ b/code/game/machinery/computer/atmos_control.dm
@@ -21,7 +21,7 @@
/obj/machinery/computer/atmoscontrol/laptop
name = "Atmospherics Laptop"
desc = "A cheap laptop."
- icon_screen = "atmoslaptop"
+ icon_screen = "medlaptop"
icon_state = "laptop"
icon_keyboard = "laptop_key"
density = 0
diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm
index 960ce3dc35..054c9c2cc3 100644
--- a/code/game/machinery/computer/buildandrepair.dm
+++ b/code/game/machinery/computer/buildandrepair.dm
@@ -14,7 +14,7 @@
switch(state)
if(0)
if(P.is_wrench())
- playsound(src.loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
if(do_after(user, 20 * P.toolspeed))
to_chat(user, "You wrench the frame into place.")
src.anchored = 1
@@ -24,7 +24,7 @@
if(!WT.remove_fuel(0, user))
to_chat(user, "The welding tool must be on to complete this task.")
return
- playsound(src.loc, WT.usesound, 50, 1)
+ playsound(src, WT.usesound, 50, 1)
if(do_after(user, 20 * WT.toolspeed))
if(!src || !WT.isOn()) return
to_chat(user, "You deconstruct the frame.")
@@ -32,7 +32,7 @@
qdel(src)
if(1)
if(P.is_wrench())
- playsound(src.loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
if(do_after(user, 20 * P.toolspeed))
to_chat(user, "You unfasten the frame.")
src.anchored = 0
@@ -40,7 +40,7 @@
if(istype(P, /obj/item/weapon/circuitboard) && !circuit)
var/obj/item/weapon/circuitboard/B = P
if(B.board_type == "computer")
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "You place the circuit board inside the frame.")
src.icon_state = "1"
src.circuit = P
@@ -49,12 +49,12 @@
else
to_chat(user, "This frame does not accept circuit boards of this type!")
if(P.is_screwdriver() && circuit)
- playsound(src.loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You screw the circuit board into place.")
src.state = 2
src.icon_state = "2"
if(P.is_crowbar()) && circuit)
- playsound(src.loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You remove the circuit board.")
src.state = 1
src.icon_state = "0"
@@ -62,7 +62,7 @@
src.circuit = null
if(2)
if(P.is_screwdriver() && circuit)
- playsound(src.loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You unfasten the circuit board.")
src.state = 1
src.icon_state = "1"
@@ -72,7 +72,7 @@
to_chat(user, "You need five coils of wire to add them to the frame.")
return
to_chat(user, "You start to add cables to the frame.")
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, 20) && state == 2)
if (C.use(5))
to_chat(user, "You add cables to the frame.")
@@ -80,7 +80,7 @@
icon_state = "3"
if(3)
if(P.is_wirecutter())
- playsound(src.loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You remove the cables.")
src.state = 2
src.icon_state = "2"
@@ -92,7 +92,7 @@
if (G.get_amount() < 2)
to_chat(user, "You need two sheets of glass to put in the glass panel.")
return
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "You start to put in the glass panel.")
if(do_after(user, 20) && state == 3)
if (G.use(2))
@@ -101,13 +101,13 @@
src.icon_state = "4"
if(4)
if(P.is_crowbar())
- playsound(src.loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You remove the glass panel.")
src.state = 3
src.icon_state = "3"
new /obj/item/stack/material/glass( src.loc, 2 )
if(P.is_screwdriver())
- playsound(src.loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You connect the monitor.")
var/B = new src.circuit.build_path ( src.loc )
src.circuit.construct(B)
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index 11d1660746..6b8006836c 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -119,6 +119,12 @@
check_eye(user)
return 1
+/obj/machinery/computer/security/relaymove(mob/user,direct)
+ var/turf/T = get_turf(current_camera)
+ for(var/i; i < 10; i++)
+ T = get_step(T, direct)
+ jump_on_click(user, T)
+
//Camera control: moving.
/obj/machinery/computer/security/proc/jump_on_click(var/mob/user,var/A)
if(user.machine != src)
@@ -185,22 +191,15 @@
update_use_power(USE_POWER_IDLE)
//Camera control: mouse.
+/* Oh my god
/atom/DblClick()
..()
if(istype(usr.machine,/obj/machinery/computer/security))
var/obj/machinery/computer/security/console = usr.machine
console.jump_on_click(usr,src)
-//Camera control: arrow keys.
-/mob/Move(n,direct)
- if(istype(machine,/obj/machinery/computer/security))
- var/obj/machinery/computer/security/console = machine
- var/turf/T = get_turf(console.current_camera)
- for(var/i;i<10;i++)
- T = get_step(T,direct)
- console.jump_on_click(src,T)
- return
- return ..(n,direct)
+*/
+//Camera control: arrow keys.
/obj/machinery/computer/security/telescreen
name = "Telescreen"
desc = "Used for watching an empty arena."
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 90c09acb44..30c15f6d04 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -323,10 +323,9 @@
if ((!subject.ckey) || (!subject.client))
scantemp = "Error: Mental interface failure."
if(subject.stat == DEAD && subject.mind && subject.mind.key) // If they're dead and not in their body, tell them to get in it.
- for(var/mob/observer/dead/ghost in player_list)
- if(ghost.ckey == ckey(subject.mind.key))
- ghost.notify_revive("Someone is trying to scan your body in the cloner. Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg')
- break
+ var/mob/observer/dead/ghost = subject.get_ghost()
+ if(ghost)
+ ghost.notify_revive("Someone is trying to scan your body in the cloner. Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg', source = src)
return
if (!isnull(find_record(subject.ckey)))
scantemp = "Subject already in database."
diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm
index 441970a8cb..dbd5ba8383 100644
--- a/code/game/machinery/computer/pod.dm
+++ b/code/game/machinery/computer/pod.dm
@@ -51,7 +51,7 @@
/*
/obj/machinery/computer/pod/attackby(I as obj, user as mob)
if(I.is_screwdriver())
- playsound(src.loc, W.usesound, 50, 1)
+ playsound(src, W.usesound, 50, 1)
if(do_after(user, 20))
if(stat & BROKEN)
to_chat(user, "The broken glass falls out.")
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index aa9c230e22..3717da58c5 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -33,7 +33,7 @@
if (C.get_amount() < 5)
to_chat(user, "You need five lengths of cable to add them to the frame.")
return
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "You start to add cables to the frame.")
if(do_after(user, 20) && state == 1)
if(C.use(5))
@@ -50,7 +50,7 @@
if(istype(P, /obj/item/weapon/circuitboard))
var/obj/item/weapon/circuitboard/B = P
if(B.board_type == "machine")
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "You add the circuit board to the frame.")
circuit = P
user.drop_item()
@@ -72,7 +72,7 @@
to_chat(user, "This frame does not accept circuit boards of this type!")
else
if(P.is_wirecutter())
- playsound(src.loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
to_chat(user, "You remove the cables.")
state = 1
icon_state = "box_0"
@@ -103,7 +103,7 @@
component_check = 0
break
if(component_check)
- playsound(src.loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
var/obj/machinery/new_machine = new src.circuit.build_path(src.loc, src.dir)
if(new_machine.component_parts)
@@ -131,7 +131,7 @@
if(istype(P, /obj/item))
for(var/I in req_components)
if(istype(P, text2path(I)) && (req_components[I] > 0))
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(P.is_cable_coil))
var/obj/item/stack/cable_coil/CP = P
if(CP.get_amount() > 1)
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 42725bbe28..05eb9c322c 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -57,7 +57,7 @@ Barricades
if("brute")
health -= W.force * 0.75
if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD)))
- playsound(loc, 'sound/effects/woodcutting.ogg', 100, 1)
+ playsound(src, 'sound/effects/woodcutting.ogg', 100, 1)
else
playsound(src, 'sound/weapons/smash.ogg', 50, 1)
CheckHealth()
@@ -76,9 +76,9 @@ Barricades
/obj/structure/barricade/attack_generic(var/mob/user, var/damage, var/attack_verb)
visible_message("[user] [attack_verb] the [src]!")
if(material == get_material_by_name("resin"))
- playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
+ playsound(src, 'sound/effects/attackblob.ogg', 100, 1)
else if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD)))
- playsound(loc, 'sound/effects/woodcutting.ogg', 100, 1)
+ playsound(src, 'sound/effects/woodcutting.ogg', 100, 1)
else
playsound(src, 'sound/weapons/smash.ogg', 50, 1)
user.do_attack_animation(src)
diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm
index e4a81d675c..b8f7acd5bf 100644
--- a/code/game/machinery/door_control.dm
+++ b/code/game/machinery/door_control.dm
@@ -31,7 +31,7 @@
if(req_access.len || req_one_access.len)
req_access = list()
req_one_access = list()
- playsound(src.loc, "sparks", 100, 1)
+ playsound(src, "sparks", 100, 1)
return 1
/obj/machinery/button/remote/attack_hand(mob/user as mob)
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 172f51e908..f5c42b8bb6 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -73,7 +73,7 @@
if(do_after(user,5 SECONDS,src))
visible_message("\The [user] forces \the [src] open, sparks flying from its electronics!")
src.do_animate("spark")
- playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1)
src.locked = 0
src.welded = 0
update_icon()
@@ -82,7 +82,7 @@
else if(src.density)
visible_message("\The [user] begins forcing \the [src] open!")
if(do_after(user, 5 SECONDS,src))
- playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1)
visible_message("\The [user] forces \the [src] open!")
open(1)
else
@@ -637,13 +637,10 @@ About the new airlock wires panel:
return 0
if(hasShocked)
return 0 //Already shocked someone recently?
- if(..())
- hasShocked = 1
- sleep(10)
+ . = ..()
+ hasShocked = 1
+ spawn(10)
hasShocked = 0
- return 1
- else
- return 0
/obj/machinery/door/airlock/update_icon()
@@ -903,7 +900,7 @@ About the new airlock wires panel:
src.welded = 1
else
src.welded = null
- playsound(src.loc, C.usesound, 75, 1)
+ playsound(src, C.usesound, 75, 1)
src.update_icon()
return
else
@@ -1023,9 +1020,9 @@ About the new airlock wires panel:
//if the door is unpowered then it doesn't make sense to hear the woosh of a pneumatic actuator
if(arePowerSystemsOn())
- playsound(src.loc, open_sound_powered, 50, 1)
+ playsound(src, open_sound_powered, 50, 1)
else
- playsound(src.loc, open_sound_unpowered, 75, 1)
+ playsound(src, open_sound_unpowered, 75, 1)
if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density)
src.closeOther.close()
@@ -1107,7 +1104,7 @@ About the new airlock wires panel:
for(var/atom/movable/AM in turf)
if(AM.blocks_airlock())
if(!has_beeped)
- playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0)
+ playsound(src, 'sound/machines/buzz-two.ogg', 50, 0)
has_beeped = 1
close_door_at = world.time + 6
return
@@ -1120,9 +1117,9 @@ About the new airlock wires panel:
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
has_beeped = 0
if(arePowerSystemsOn())
- playsound(src.loc, close_sound_powered, 50, 1)
+ playsound(src, close_sound_powered, 50, 1)
else
- playsound(src.loc, open_sound_unpowered, 75, 1)
+ playsound(src, open_sound_unpowered, 75, 1)
for(var/turf/turf in locs)
var/obj/structure/window/killthis = (locate(/obj/structure/window) in turf)
if(killthis)
diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm
index 5ff587a7d9..136b793f10 100644
--- a/code/game/machinery/doors/blast_door.dm
+++ b/code/game/machinery/doors/blast_door.dm
@@ -100,7 +100,7 @@
// Description: Opens or closes the door, depending on current state. No checks are done inside this proc.
/obj/machinery/door/blast/proc/force_toggle(var/forced = 0, mob/user as mob)
if (forced)
- playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1)
if(src.density)
src.force_open()
@@ -150,7 +150,7 @@
user.visible_message("\The [user] hits \the [src] with \the [W] with no visible effect.")
else
user.visible_message("\The [user] forcefully strikes \the [src] with \the [W]!")
- playsound(src.loc, hitsound, 100, 1)
+ playsound(src, hitsound, 100, 1)
take_damage(W.force*0.35) //it's a blast door, it should take a while. -Luke
return
@@ -180,7 +180,7 @@
user.visible_message("\The [user] hits \the [src] with \the [W] with no visible effect.")
else
user.visible_message("\The [user] forcefully strikes \the [src] with \the [W]!")
- playsound(src.loc, hitsound, 100, 1)
+ playsound(src, hitsound, 100, 1)
take_damage(W.force*0.15) //If the item isn't a weapon, let's make this take longer than usual to break it down.
return
@@ -194,13 +194,13 @@
if(src.density)
visible_message("\The [user] begins forcing \the [src] open!")
if(do_after(user, 15 SECONDS,src))
- playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1)
visible_message("\The [user] forces \the [src] open!")
force_open(1)
else
visible_message("\The [user] begins forcing \the [src] closed!")
if(do_after(user, 5 SECONDS,src))
- playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1)
visible_message("\The [user] forces \the [src] closed!")
force_close(1)
else
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 271dd6f829..8b8fa2da51 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -112,6 +112,11 @@
else
bumpopen(M)
+ if(istype(AM, /obj/item/device/uav))
+ if(check_access(null))
+ open()
+ else
+ do_animate("deny")
if(istype(AM, /mob/living/bot))
var/mob/living/bot/bot = AM
@@ -189,7 +194,7 @@
tforce = 15 * (speed/5)
else
tforce = AM:throwforce * (speed/5)
- playsound(src.loc, hitsound, 100, 1)
+ playsound(src, hitsound, 100, 1)
take_damage(tforce)
return
@@ -275,7 +280,7 @@
user.visible_message("\The [user] hits \the [src] with \the [W] with no visible effect.")
else
user.visible_message("\The [user] forcefully strikes \the [src] with \the [W]!")
- playsound(src.loc, hitsound, 100, 1)
+ playsound(src, hitsound, 100, 1)
take_damage(W.force)
return
@@ -400,7 +405,7 @@
if("deny")
if(density && !(stat & (NOPOWER|BROKEN)))
flick("door_deny", src)
- playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0)
+ playsound(src, 'sound/machines/buzz-two.ogg', 50, 0)
return
@@ -479,8 +484,7 @@
else
source.thermal_conductivity = initial(source.thermal_conductivity)
-/obj/machinery/door/Move(new_loc, new_dir)
- //update_nearby_tiles()
+/obj/machinery/door/Moved(atom/old_loc, direction, forced = FALSE)
. = ..()
if(width > 1)
if(dir in list(EAST, WEST))
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index e4c83ef1bf..52ea077669 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -200,14 +200,14 @@
if(src.blocked)
visible_message("\The [user] begins digging into \the [src] internals!")
if(do_after(user,5 SECONDS,src))
- playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1)
src.blocked = 0
update_icon()
open(1)
else if(src.density)
visible_message("\The [user] begins forcing \the [src] open!")
if(do_after(user, 2 SECONDS,src))
- playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1)
visible_message("\The [user] forces \the [src] open!")
open(1)
else
diff --git a/code/game/machinery/doors/firedoor_assembly.dm b/code/game/machinery/doors/firedoor_assembly.dm
index 4eeec7c5ff..aa857d5065 100644
--- a/code/game/machinery/doors/firedoor_assembly.dm
+++ b/code/game/machinery/doors/firedoor_assembly.dm
@@ -32,7 +32,7 @@ obj/structure/firedoor_assembly/attackby(obj/item/C, mob/user as mob)
to_chat(user, "You wire \the [src].")
else if(C.is_wirecutter() && wired )
- playsound(src.loc, C.usesound, 100, 1)
+ playsound(src, C.usesound, 100, 1)
user.visible_message("[user] cuts the wires from \the [src].", "You start to cut the wires from \the [src].")
if(do_after(user, 40))
@@ -43,7 +43,7 @@ obj/structure/firedoor_assembly/attackby(obj/item/C, mob/user as mob)
else if(istype(C, /obj/item/weapon/circuitboard/airalarm) && wired)
if(anchored)
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
user.visible_message("[user] has inserted a circuit into \the [src]!",
"You have inserted the circuit into \the [src]!")
if(glass)
@@ -56,7 +56,7 @@ obj/structure/firedoor_assembly/attackby(obj/item/C, mob/user as mob)
to_chat(user, "You must secure \the [src] first!")
else if(C.is_wrench())
anchored = !anchored
- playsound(src.loc, C.usesound, 50, 1)
+ playsound(src, C.usesound, 50, 1)
user.visible_message("[user] has [anchored ? "" : "un" ]secured \the [src]!",
"You have [anchored ? "" : "un" ]secured \the [src]!")
update_icon()
@@ -86,7 +86,7 @@ obj/structure/firedoor_assembly/attackby(obj/item/C, mob/user as mob)
else if(istype(C, /obj/item/stack/material) && C.get_material_name() == "rglass" && !glass)
var/obj/item/stack/S = C
if (S.get_amount() >= 1)
- playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 100, 1)
user.visible_message("[user] adds [S.name] to \the [src].",
"You start to install [S.name] into \the [src].")
if(do_after(user, 40, src) && !glass && S.use(1))
diff --git a/code/game/machinery/doors/multi_tile.dm b/code/game/machinery/doors/multi_tile.dm
index 5ead377f0c..ec561032a1 100644
--- a/code/game/machinery/doors/multi_tile.dm
+++ b/code/game/machinery/doors/multi_tile.dm
@@ -16,7 +16,7 @@
QDEL_NULL(filler2)
return ..()
-/obj/machinery/door/airlock/multi_tile/Move()
+/obj/machinery/door/airlock/multi_tile/Moved(atom/old_loc, direction, forced = FALSE)
. = ..()
SetBounds()
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index f7b8a1222d..98fb1c75d8 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -115,7 +115,7 @@
if (!operating) //in case of emag
operating = 1
flick(text("[src.base_state]opening"), src)
- playsound(src.loc, 'sound/machines/windowdoor.ogg', 100, 1)
+ playsound(src, 'sound/machines/windowdoor.ogg', 100, 1)
sleep(10)
explosion_resistance = 0
@@ -132,7 +132,7 @@
return FALSE
operating = TRUE
flick(text("[]closing", src.base_state), src)
- playsound(src.loc, 'sound/machines/windowdoor.ogg', 100, 1)
+ playsound(src, 'sound/machines/windowdoor.ogg', 100, 1)
density = TRUE
update_icon()
@@ -158,7 +158,7 @@
if(istype(user,/mob/living/carbon/human))
var/mob/living/carbon/human/H = user
if(H.species.can_shred(H))
- playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
visible_message("[user] smashes against the [src.name].", 1)
user.do_attack_animation(src)
user.setClickCooldown(user.get_attack_speed())
@@ -212,8 +212,8 @@
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src.loc)
spark_system.start()
- playsound(src.loc, "sparks", 50, 1)
- playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, "sparks", 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
visible_message("The glass door was sliced open by [user]!")
return 1
@@ -259,7 +259,7 @@
if(src.density && istype(I, /obj/item/weapon) && !istype(I, /obj/item/weapon/card))
user.setClickCooldown(user.get_attack_speed(I))
var/aforce = I.force
- playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
visible_message("[src] was hit by [I].")
if(I.damtype == BRUTE || I.damtype == BURN)
take_damage(aforce)
diff --git a/code/game/machinery/exonet_node.dm b/code/game/machinery/exonet_node.dm
index a1ca480d26..cb54a0c857 100644
--- a/code/game/machinery/exonet_node.dm
+++ b/code/game/machinery/exonet_node.dm
@@ -173,7 +173,7 @@
// Description: This writes to the logs list, so that people can see what people are doing on the Exonet ingame. Note that this is not an admin logging function.
// Communicators are already logged seperately.
/obj/machinery/exonet_node/proc/write_log(var/origin_address, var/target_address, var/data_type, var/content)
- //var/timestamp = time2text(station_time_in_ticks, "hh:mm:ss")
+ //var/timestamp = time2text(station_time_in_ds, "hh:mm:ss")
var/timestamp = "[stationdate2text()] [stationtime2text()]"
var/msg = "[timestamp] | FROM [origin_address] TO [target_address] | TYPE: [data_type] | CONTENT: [content]"
logs.Add(msg)
diff --git a/code/game/machinery/fire_alarm.dm b/code/game/machinery/fire_alarm.dm
index a9b4a0705e..fa95fed959 100644
--- a/code/game/machinery/fire_alarm.dm
+++ b/code/game/machinery/fire_alarm.dm
@@ -208,7 +208,7 @@ FIRE ALARM
for(var/obj/machinery/firealarm/FA in area)
fire_alarm.triggerAlarm(loc, FA, duration, hidden = alarms_hidden)
update_icon()
- playsound(src.loc, 'sound/machines/airalarm.ogg', 25, 0, 4)
+ playsound(src, 'sound/machines/airalarm.ogg', 25, 0, 4)
return
/obj/machinery/firealarm/proc/set_security_level(var/newlevel)
diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm
index 572977ceb4..ad82ffd656 100644
--- a/code/game/machinery/flasher.dm
+++ b/code/game/machinery/flasher.dm
@@ -13,7 +13,6 @@
anchored = 1
use_power = USE_POWER_IDLE
idle_power_usage = 2
- flags = PROXMOVE
/obj/machinery/flasher/portable //Portable version of the flasher. Only flashes when anchored
name = "portable flasher"
@@ -57,7 +56,7 @@
if((disable) || (last_flash && world.time < last_flash + 150))
return
- playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
+ playsound(src, 'sound/weapons/flash.ogg', 100, 1)
flick("[base_state]_flash", src)
last_flash = world.time
use_power(1500)
@@ -92,13 +91,13 @@
flash()
..(severity)
-/obj/machinery/flasher/portable/HasProximity(atom/movable/AM as mob|obj)
- if((disable) || (last_flash && world.time < last_flash + 150))
+/obj/machinery/flasher/portable/HasProximity(turf/T, atom/movable/AM, oldloc)
+ if(disable || !anchored || (last_flash && world.time < last_flash + 150))
return
- if(istype(AM, /mob/living/carbon))
+ if(iscarbon(AM))
var/mob/living/carbon/M = AM
- if((M.m_intent != "walk") && (anchored))
+ if(M.m_intent != "walk")
flash()
/obj/machinery/flasher/portable/attackby(obj/item/weapon/W as obj, mob/user as mob)
@@ -108,11 +107,13 @@
if(!anchored)
user.show_message(text("[src] can now be moved."))
- overlays.Cut()
-
+ cut_overlays()
+ unsense_proximity(callback = .HasProximity)
+
else if(anchored)
user.show_message(text("[src] is now secured."))
- overlays += "[base_state]-s"
+ add_overlay("[base_state]-s")
+ sense_proximity(callback = .HasProximity)
/obj/machinery/button/flasher
name = "flasher button"
diff --git a/code/game/machinery/floor_light.dm b/code/game/machinery/floor_light.dm
index de51359855..09296ac302 100644
--- a/code/game/machinery/floor_light.dm
+++ b/code/game/machinery/floor_light.dm
@@ -31,7 +31,7 @@ var/list/floor_light_cache = list()
if(!WT.remove_fuel(0, user))
to_chat(user, "\The [src] must be on to complete this task.")
return
- playsound(src.loc, WT.usesound, 50, 1)
+ playsound(src, WT.usesound, 50, 1)
if(!do_after(user, 20 * WT.toolspeed))
return
if(!src || !WT.isOn())
@@ -53,7 +53,7 @@ var/list/floor_light_cache = list()
stat |= BROKEN
else
visible_message("\The [user] attacks \the [src]!")
- playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
if(isnull(damaged)) damaged = 0
update_brightness()
return
diff --git a/code/game/machinery/floorlayer.dm b/code/game/machinery/floorlayer.dm
index c4af8fb3a8..d8a2b463e2 100644
--- a/code/game/machinery/floorlayer.dm
+++ b/code/game/machinery/floorlayer.dm
@@ -12,8 +12,8 @@
T = new/obj/item/stack/tile/floor(src)
..()
-/obj/machinery/floorlayer/Move(new_turf,M_Dir)
- ..()
+/obj/machinery/floorlayer/Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
if(on)
if(mode["dismantle"])
@@ -26,7 +26,7 @@
CollectTiles(old_turf)
- old_turf = new_turf
+ old_turf = loc
/obj/machinery/floorlayer/attack_hand(mob/user as mob)
on=!on
diff --git a/code/game/machinery/frame.dm b/code/game/machinery/frame.dm
index 789773e8c3..209a06edab 100644
--- a/code/game/machinery/frame.dm
+++ b/code/game/machinery/frame.dm
@@ -274,7 +274,7 @@
if(P.is_wrench())
if(state == FRAME_PLACED && !anchored)
to_chat(user, "You start to wrench the frame into place.")
- playsound(src.loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
if(do_after(user, 20 * P.toolspeed))
anchored = TRUE
if(!need_circuit && circuit)
@@ -295,7 +295,7 @@
if(state == FRAME_PLACED)
var/obj/item/weapon/weldingtool/WT = P
if(WT.remove_fuel(0, user))
- playsound(src.loc, P.usesound, 50, 1)
+ playsound(src, P.usesound, 50, 1)
if(do_after(user, 20 * P.toolspeed))
if(src && WT.isOn())
to_chat(user, "You deconstruct the frame.")
@@ -311,7 +311,7 @@
var/obj/item/weapon/circuitboard/B = P
var/datum/frame/frame_types/board_type = B.board_type
if(board_type.name == frame_type.name)
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "You place the circuit board inside the frame.")
circuit = P
user.drop_item()
@@ -464,7 +464,7 @@
to_chat(user, "You need five coils of wire to add them to the frame.")
return
to_chat(user, "You start to add cables to the frame.")
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, 20) && state == FRAME_FASTENED)
if(C.use(5))
to_chat(user, "You add cables to the frame.")
@@ -475,7 +475,7 @@
if(frame_type.frame_class == FRAME_CLASS_MACHINE)
for(var/I in req_components)
if(istype(P, I) && (req_components[I] > 0))
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(istype(P, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/CP = P
if(CP.get_amount() > 1)
@@ -524,7 +524,7 @@
if(G.get_amount() < 2)
to_chat(user, "You need two sheets of glass to put in the glass panel.")
return
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "You start to put in the glass panel.")
if(do_after(user, 20) && state == FRAME_WIRED)
if(G.use(2))
@@ -536,7 +536,7 @@
if(G.get_amount() < 2)
to_chat(user, "You need two sheets of glass to put in the glass panel.")
return
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "You start to put in the glass panel.")
if(do_after(user, 20) && state == FRAME_WIRED)
if(G.use(2))
@@ -548,7 +548,7 @@
if(frame_type.frame_class == FRAME_CLASS_MACHINE)
for(var/I in req_components)
if(istype(P, I) && (req_components[I] > 0))
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(istype(P, /obj/item/stack))
var/obj/item/stack/ST = P
if(ST.get_amount() > 1)
diff --git a/code/game/machinery/jukebox.dm b/code/game/machinery/jukebox.dm
index 344a800acf..b2bacc13d9 100644
--- a/code/game/machinery/jukebox.dm
+++ b/code/game/machinery/jukebox.dm
@@ -142,7 +142,7 @@ datum/track/New(var/title_name, var/audio)
StopPlaying()
else if(href_list["play"])
if(emagged)
- playsound(src.loc, 'sound/items/AirHorn.ogg', 100, 1)
+ playsound(src, 'sound/items/AirHorn.ogg', 100, 1)
for(var/mob/living/carbon/M in ohearers(6, src))
if(M.get_ear_protection() >= 2)
continue
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index b72cab14f0..e61076587b 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -5,12 +5,16 @@ Overview:
of 'Del' removes reference to src machine in global 'machines list'.
Class Variables:
+
+ power_init_complete (boolean)
+ Indicates that we have have registered our static power usage with the area.
+
use_power (num)
current state of auto power use.
Possible Values:
- 0 -- no auto power use
- 1 -- machine is using power at its idle power level
- 2 -- machine is using power at its active power level
+ USE_POWER_OFF:0 -- no auto power use
+ USE_POWER_IDLE:1 -- machine is using power at its idle power level
+ USE_POWER_ACTIVE:2 -- machine is using power at its active power level
active_power_usage (num)
Value for the amount of power to use when in active power mode
@@ -51,28 +55,18 @@ Class Procs:
Destroy() 'game/machinery/machine.dm'
- auto_use_power() 'game/machinery/machine.dm'
- This proc determines how power mode power is deducted by the machine.
- 'auto_use_power()' is called by the 'master_controller' game_controller every
- tick.
+ get_power_usage() 'game/machinery/machinery_power.dm'
+ Returns the amount of power this machine uses every SSmachines cycle.
+ Default definition uses 'use_power', 'active_power_usage', 'idle_power_usage'
- Return Value:
- return:1 -- if object is powered
- return:0 -- if object is not powered.
-
- Default definition uses 'use_power', 'power_channel', 'active_power_usage',
- 'idle_power_usage', 'powered()', and 'use_power()' implement behavior.
-
- powered(chan = EQUIP) 'modules/power/power.dm'
+ powered(chan = CURRENT_CHANNEL) 'game/machinery/machinery_power.dm'
Checks to see if area that contains the object has power available for power
channel given in 'chan'.
- use_power(amount, chan=EQUIP, autocalled) 'modules/power/power.dm'
+ use_power_oneoff(amount, chan=CURRENT_CHANNEL) 'game/machinery/machinery_power.dm'
Deducts 'amount' from the power channel 'chan' of the area that contains the object.
- If it's autocalled then everything is normal, if something else calls use_power we are going to
- need to recalculate the power two ticks in a row.
- power_change() 'modules/power/power.dm'
+ power_change() 'game/machinery/machinery_power.dm'
Called by the area that contains the object when ever that area under goes a
power state change (area runs out of power, or area channel is turned off).
@@ -108,6 +102,7 @@ Class Procs:
var/idle_power_usage = 0
var/active_power_usage = 0
var/power_channel = EQUIP //EQUIP, ENVIRON or LIGHT
+ var/power_init_complete = FALSE
var/list/component_parts = null //list of all the parts used to build it, if made from certain kinds of frames.
var/uid
var/panel_open = 0
@@ -126,7 +121,7 @@ Class Procs:
if(ispath(circuit))
circuit = new circuit(src)
-/obj/machinery/Initialize()
+/obj/machinery/Initialize(var/mapload)
. = ..()
global.machines += src
if(ispath(circuit))
@@ -135,6 +130,8 @@ Class Procs:
START_MACHINE_PROCESSING(src)
else
START_PROCESSING(SSfastprocess, src)
+ if(!mapload)
+ power_change()
/obj/machinery/Destroy()
if(!speed_process)
@@ -147,7 +144,9 @@ Class Procs:
if(A.loc == src) // If the components are inside the machine, delete them.
qdel(A)
else // Otherwise we assume they were dropped to the ground during deconstruction, and were not removed from the component_parts list by deconstruction code.
- component_parts -= A
+ warning("[A] was still in [src]'s component_parts when it was Destroy()'d")
+ component_parts.Cut()
+ component_parts = null
if(contents) // The same for contents.
for(var/atom/A in contents)
if(ishuman(A))
@@ -159,9 +158,8 @@ Class Procs:
qdel(A)
return ..()
-/obj/machinery/process()//If you dont use process or power why are you here
- if(!(use_power || idle_power_usage || active_power_usage))
- return PROCESS_KILL
+/obj/machinery/process() // Steady power usage is handled separately. If you dont use process why are you here?
+ return PROCESS_KILL
/obj/machinery/emp_act(severity)
if(use_power && stat == 0)
@@ -194,31 +192,6 @@ Class Procs:
else
return
-//sets the use_power var and then forces an area power update
-/obj/machinery/proc/update_use_power(var/new_use_power)
- use_power = new_use_power
-
-// Sets the power_channel var
-/obj/machinery/proc/update_power_channel(var/new_channel)
- power_channel = new_channel
-
-// Sets the idle_power_usage var
-/obj/machinery/proc/update_idle_power_usage(var/new_power_usage)
- idle_power_usage = new_power_usage
-
-// Sets the active_power_usage var
-/obj/machinery/proc/update_active_power_usage(var/new_power_usage)
- active_power_usage = new_power_usage
-
-/obj/machinery/proc/auto_use_power()
- if(!powered(power_channel))
- return 0
- if(use_power == USE_POWER_IDLE)
- use_power(idle_power_usage, power_channel, 1)
- else if(use_power >= USE_POWER_ACTIVE)
- use_power(active_power_usage, power_channel, 1)
- return 1
-
/obj/machinery/vv_edit_var(var/var_name, var/new_value)
if(var_name == NAMEOF(src, use_power))
update_use_power(new_value)
@@ -304,7 +277,7 @@ Class Procs:
text = "\The [src] pings."
state(text, "blue")
- playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
+ playsound(src, 'sound/machines/ping.ogg', 50, 0)
/obj/machinery/proc/shock(mob/user, prb)
if(inoperable())
@@ -369,7 +342,7 @@ Class Procs:
return FALSE
if(panel_open)
return FALSE // Close panel first!
- playsound(loc, W.usesound, 50, 1)
+ playsound(src, W.usesound, 50, 1)
var/actual_time = W.toolspeed * time
if(actual_time != 0)
user.visible_message( \
@@ -430,12 +403,12 @@ Class Procs:
if(!panel_open)
return 0
user.visible_message("[user] has cut the wires inside \the [src]!", "You have cut the wires inside \the [src].")
- playsound(src.loc, W.usesound, 50, 1)
+ playsound(src, W.usesound, 50, 1)
new/obj/item/stack/cable_coil(get_turf(src), 5)
. = dismantle()
/obj/machinery/proc/dismantle()
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
//TFF 3/6/19 - port Cit RP fix of infinite frames. If it doesn't have a circuit board, don't create a frame. Return a smack instead. BONK!
if(!circuit)
return 0
@@ -483,6 +456,7 @@ Class Procs:
return 1
/datum/proc/apply_visual(mob/M)
+ M.sight = 0 //Just reset their mesons and stuff so they can't use them, by default.
return
/datum/proc/remove_visual(mob/M)
diff --git a/code/game/machinery/machinery_power.dm b/code/game/machinery/machinery_power.dm
new file mode 100644
index 0000000000..be648d0f80
--- /dev/null
+++ b/code/game/machinery/machinery_power.dm
@@ -0,0 +1,167 @@
+//
+// /obj/machinery POWER USAGE CODE HERE! GO GO GADGET STATIC POWER!
+// Note: You can find /obj/machinery/power power usage code in power.dm
+//
+// The following four machinery variables determine the "static" amount of power used every power cycle:
+// - use_power, idle_power_usage, active_power_usage, power_channel
+//
+// Please never change any of these variables! Use the procs that update them instead!
+//
+
+// Note that we update the area even if the area is unpowered.
+#define REPORT_POWER_CONSUMPTION_CHANGE(old_power, new_power)\
+ if(old_power != new_power){\
+ var/area/A = get_area(src);\
+ if(A) A.power_use_change(old_power, new_power, power_channel)}
+
+// Current power consumption right now.
+#define POWER_CONSUMPTION (use_power == USE_POWER_IDLE ? idle_power_usage : (use_power >= USE_POWER_ACTIVE ? active_power_usage : 0))
+
+// returns true if the area has power on given channel (or doesn't require power).
+// defaults to power_channel
+/obj/machinery/proc/powered(var/chan = CURRENT_CHANNEL) // defaults to power_channel
+ //Don't do this. It allows machines that set use_power to 0 when off (many machines) to
+ //be turned on again and used after a power failure because they never gain the NOPOWER flag.
+ //if(!use_power)
+ // return 1
+
+ var/area/A = get_area(src) // make sure it's in an area
+ if(!A)
+ return 0 // if not, then not powered
+ if(chan == CURRENT_CHANNEL)
+ chan = power_channel
+ return A.powered(chan) // return power status of the area
+
+// called whenever the power settings of the containing area change
+// by default, check equipment channel & set/clear NOPOWER flag
+// Returns TRUE if NOPOWER stat flag changed.
+// can override if needed
+/obj/machinery/proc/power_change()
+ var/oldstat = stat
+ if(powered(power_channel))
+ stat &= ~NOPOWER
+ else
+ stat |= NOPOWER
+ return (stat != oldstat)
+
+// Get the amount of power this machine will consume each cycle. Override by experts only!
+/obj/machinery/proc/get_power_usage()
+ return POWER_CONSUMPTION
+
+// DEPRECATED! - USE use_power_oneoff() instead!
+/obj/machinery/proc/use_power(var/amount, var/chan = -1) // defaults to power_channel
+ return src.use_power_oneoff(amount, chan);
+
+// This will have this machine have its area eat this much power next tick, and not afterwards. Do not use for continued power draw.
+// Returns actual amount drawn (In theory this could be less than the amount asked for. In pratice it won't be FOR NOW)
+/obj/machinery/proc/use_power_oneoff(var/amount, var/chan = CURRENT_CHANNEL)
+ var/area/A = get_area(src) // make sure it's in an area
+ if(!A)
+ return
+ if(chan == CURRENT_CHANNEL)
+ chan = power_channel
+ return A.use_power_oneoff(amount, chan)
+
+// Check if we CAN use a given amount of extra power as a one off. Returns amount we could use without actually using it.
+// For backwards compatibilty this returns true if the channel is powered. This is consistant with pre-static-power
+// behavior of APC powerd machines, but at some point we might want to make this a bit cooler.
+/obj/machinery/proc/can_use_power_oneoff(var/amount, var/chan = CURRENT_CHANNEL)
+ if(powered(chan))
+ return amount // If channel is powered then you can do it.
+ return 0
+
+// Do not do power stuff in New/Initialize until after ..()
+/obj/machinery/Initialize()
+ . = ..()
+ var/power = POWER_CONSUMPTION
+ REPORT_POWER_CONSUMPTION_CHANGE(0, power)
+ power_init_complete = TRUE
+
+// Or in Destroy at all, but especially after the ..().
+/obj/machinery/Destroy()
+ if(ismovable(loc))
+ GLOB.moved_event.unregister(loc, src, .proc/update_power_on_move) // Unregister just in case
+ var/power = POWER_CONSUMPTION
+ REPORT_POWER_CONSUMPTION_CHANGE(power, 0)
+ . = ..()
+
+// Registering moved_event observers for all machines is too expensive. Instead we do it ourselves.
+// 99% of machines are always on a turf anyway, very few need recursive move handling.
+/obj/machinery/Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
+ update_power_on_move(src, old_loc, loc)
+ if(ismovable(loc)) // Register for recursive movement (if the thing we're inside moves)
+ GLOB.moved_event.register(loc, src, .proc/update_power_on_move)
+ if(ismovable(old_loc)) // Unregister recursive movement.
+ GLOB.moved_event.unregister(old_loc, src, .proc/update_power_on_move)
+
+/obj/machinery/proc/update_power_on_move(atom/movable/mover, atom/old_loc, atom/new_loc)
+ var/area/old_area = get_area(old_loc)
+ var/area/new_area = get_area(new_loc)
+ if(old_area != new_area)
+ area_changed(old_area, new_area)
+
+/obj/machinery/proc/area_changed(area/old_area, area/new_area)
+ if(old_area == new_area || !power_init_complete)
+ return
+ var/power = POWER_CONSUMPTION
+ if(!power)
+ return // This is the most likely case anyway.
+
+ if(old_area)
+ old_area.power_use_change(power, 0, power_channel) // Remove our usage from old area
+ if(new_area)
+ new_area.power_use_change(0, power, power_channel) // Add our usage to new area
+ power_change() // Force check in case the old area was powered and the new one isn't or vice versa.
+
+//
+// Usage Update Procs - These procs are the only allowed way to modify these four variables:
+// - use_power, idle_power_usage, active_power_usage, power_channel
+//
+
+// Sets the use_power var and then forces an area power update
+/obj/machinery/proc/update_use_power(var/new_use_power)
+ if(use_power == new_use_power)
+ return
+ if(!power_init_complete)
+ use_power = new_use_power
+ return TRUE // We'll be retallying anyway.
+ var/old_power = POWER_CONSUMPTION
+ use_power = new_use_power
+ var/new_power = POWER_CONSUMPTION
+ REPORT_POWER_CONSUMPTION_CHANGE(old_power, new_power)
+ return TRUE
+
+// Sets the power_channel var and then forces an area power update.
+/obj/machinery/proc/update_power_channel(var/new_channel)
+ if(power_channel == new_channel)
+ return
+ if(!power_init_complete)
+ power_channel = new_channel
+ return TRUE // We'll be retallying anyway.
+ var/power = POWER_CONSUMPTION
+ REPORT_POWER_CONSUMPTION_CHANGE(power, 0) // Subtract from old channel
+ power_channel = new_channel
+ REPORT_POWER_CONSUMPTION_CHANGE(0, power) // Add to new channel
+ return TRUE
+
+// Sets the idle_power_usage var and then forces an area power update if use_power was USE_POWER_IDLE
+/obj/machinery/proc/update_idle_power_usage(var/new_power_usage)
+ if(idle_power_usage == new_power_usage)
+ return
+ var/old_power = idle_power_usage
+ idle_power_usage = new_power_usage
+ if(power_init_complete && use_power == USE_POWER_IDLE) // If this is the channel in use
+ REPORT_POWER_CONSUMPTION_CHANGE(old_power, new_power_usage)
+
+// Sets the active_power_usage var and then forces an area power update if use_power was USE_POWER_ACTIVE
+/obj/machinery/proc/update_active_power_usage(var/new_power_usage)
+ if(active_power_usage == new_power_usage)
+ return
+ var/old_power = active_power_usage
+ active_power_usage = new_power_usage
+ if(power_init_complete && use_power == USE_POWER_ACTIVE) // If this is the channel in use
+ REPORT_POWER_CONSUMPTION_CHANGE(old_power, new_power_usage)
+
+#undef REPORT_POWER_CONSUMPTION_CHANGE
+#undef POWER_CONSUMPTION
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index 6d7b24e5cf..ff16c8d044 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -79,7 +79,7 @@
newMsg.body = msg
newMsg.time_stamp = "[stationtime2text()]"
newMsg.is_admin_message = adminMessage
- newMsg.post_time = round_duration_in_ticks // Should be almost universally unique
+ newMsg.post_time = round_duration_in_ds // Should be almost universally unique
if(message_type)
newMsg.message_type = message_type
if(photo)
@@ -904,7 +904,7 @@ obj/item/weapon/newspaper/Topic(href, href_list)
if(curr_page == 0) //We're at the start, get to the middle
screen = 1
curr_page++
- playsound(loc, "pageturn", 50, 1)
+ playsound(src, "pageturn", 50, 1)
else if(href_list["prev_page"])
if(curr_page == 0)
@@ -916,7 +916,7 @@ obj/item/weapon/newspaper/Topic(href, href_list)
if(curr_page == pages+1) //we're at the end, let's go back to the middle.
screen = 1
curr_page--
- playsound(src.loc, "pageturn", 50, 1)
+ playsound(src, "pageturn", 50, 1)
if(istype(src.loc, /mob))
attack_self(src.loc)
@@ -974,9 +974,9 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob)
spawn(300)
alert = 0
update_icon()
- playsound(src.loc, 'sound/machines/twobeep.ogg', 75, 1)
+ playsound(src, 'sound/machines/twobeep.ogg', 75, 1)
else
for(var/mob/O in hearers(world.view-1, T))
O.show_message("[name] beeps, \"Attention! Wanted issue distributed!\"",2)
- playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 75, 1)
+ playsound(src, 'sound/machines/warning-buzzer.ogg', 75, 1)
return
diff --git a/code/game/machinery/oxygen_pump.dm b/code/game/machinery/oxygen_pump.dm
index b40314d2c2..37c75957be 100644
--- a/code/game/machinery/oxygen_pump.dm
+++ b/code/game/machinery/oxygen_pump.dm
@@ -41,8 +41,11 @@
return ..()
/obj/machinery/oxygen_pump/MouseDrop(var/mob/living/carbon/human/target, src_location, over_location)
- ..()
- if(istype(target) && CanMouseDrop(target))
+ var/mob/living/user = usr
+ if(!istype(user) || !istype(target))
+ return ..()
+
+ if(CanMouseDrop(target, user))
if(!can_apply_to_target(target, usr)) // There is no point in attempting to apply a mask if it's impossible.
return
usr.visible_message("\The [usr] begins placing \the [contained] onto [target].")
diff --git a/code/game/machinery/pda_multicaster.dm b/code/game/machinery/pda_multicaster.dm
index 94d46058ce..b82760ac21 100644
--- a/code/game/machinery/pda_multicaster.dm
+++ b/code/game/machinery/pda_multicaster.dm
@@ -2,7 +2,7 @@
name = "\improper PDA multicaster"
desc = "This machine mirrors messages sent to it to specific departments."
icon = 'icons/obj/stationobjs.dmi'
- icon_state = "controller"
+ icon_state = "pdamulti"
density = 1
anchored = 1
circuit = /obj/item/weapon/circuitboard/telecomms/pda_multicaster
@@ -35,7 +35,7 @@
if(on)
icon_state = initial(icon_state)
else
- icon_state = "[initial(icon_state)]-p"
+ icon_state = "[initial(icon_state)]_off"
/obj/machinery/pda_multicaster/attackby(obj/item/I, mob/user)
if(I.is_screwdriver())
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index 13b1dc1bb7..f5f2532080 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -132,12 +132,6 @@ Buildable meters
src.set_dir(turn(src.dir, 270))
fixdir()
-// If you want to disable pipe dir changing when pulled, uncomment this
-// /obj/item/pipe/Move()
-// var/old_dir = dir
-// . = ..()
-// set_dir(old_dir) //pipes changing direction when moved is just annoying and buggy
-
// Don't let pulling a pipe straighten it out.
/obj/item/pipe/binary/bendable/Move()
var/old_bent = !IS_CARDINAL(dir)
diff --git a/code/game/machinery/pipe/pipelayer.dm b/code/game/machinery/pipe/pipelayer.dm
index f0219a8a2c..8b49989e61 100644
--- a/code/game/machinery/pipe/pipelayer.dm
+++ b/code/game/machinery/pipe/pipelayer.dm
@@ -42,15 +42,15 @@
..()
// Whenever we move, if enabled try and lay pipe
-/obj/machinery/pipelayer/Move(new_turf,M_Dir)
- ..()
+/obj/machinery/pipelayer/Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
if(on && a_dis)
dismantleFloor(old_turf)
- layPipe(old_turf, M_Dir, old_dir)
+ layPipe(old_turf, direction, old_dir)
- old_turf = new_turf
- old_dir = turn(M_Dir, 180)
+ old_turf = loc
+ old_dir = turn(direction, 180)
/obj/machinery/pipelayer/attack_hand(mob/user as mob)
if(..())
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index b67f3738bd..436f738efc 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -549,12 +549,12 @@
if(do_after(user, 50 * I.toolspeed))
//This code handles moving the turret around. After all, it's a portable turret!
if(!anchored)
- playsound(loc, I.usesound, 100, 1)
+ playsound(src, I.usesound, 100, 1)
anchored = TRUE
update_icon()
to_chat(user, "You secure the exterior bolts on the turret.")
else if(anchored)
- playsound(loc, I.usesound, 100, 1)
+ playsound(src, I.usesound, 100, 1)
anchored = FALSE
to_chat(user, "You unsecure the exterior bolts on the turret.")
update_icon()
@@ -890,10 +890,10 @@
var/obj/item/projectile/A
if(emagged || lethal)
A = new lethal_projectile(loc)
- playsound(loc, lethal_shot_sound, 75, 1)
+ playsound(src, lethal_shot_sound, 75, 1)
else
A = new projectile(loc)
- playsound(loc, shot_sound, 75, 1)
+ playsound(src, shot_sound, 75, 1)
// Lethal/emagged turrets use twice the power due to higher energy beams
// Emagged turrets again use twice as much power due to higher firing rates
@@ -966,14 +966,14 @@
switch(build_step)
if(0) //first step
if(I.is_wrench() && !anchored)
- playsound(loc, I.usesound, 100, 1)
+ playsound(src, I.usesound, 100, 1)
to_chat(user, "You secure the external bolts.")
anchored = TRUE
build_step = 1
return
else if(I.is_crowbar() && !anchored)
- playsound(loc, I.usesound, 75, 1)
+ playsound(src, I.usesound, 75, 1)
to_chat(user, "You dismantle the turret construction.")
new /obj/item/stack/material/steel(loc, 5)
qdel(src)
@@ -991,7 +991,7 @@
return
else if(I.is_wrench())
- playsound(loc, I.usesound, 75, 1)
+ playsound(src, I.usesound, 75, 1)
to_chat(user, "You unfasten the external bolts.")
anchored = FALSE
build_step = 0
@@ -999,7 +999,7 @@
if(2)
if(I.is_wrench())
- playsound(loc, I.usesound, 100, 1)
+ playsound(src, I.usesound, 100, 1)
to_chat(user, "You bolt the metal armor into place.")
build_step = 3
return
@@ -1012,7 +1012,7 @@
to_chat(user, "You need more fuel to complete this task.")
return
- playsound(loc, I.usesound, 50, 1)
+ playsound(src, I.usesound, 50, 1)
if(do_after(user, 20 * I.toolspeed))
if(!src || !WT.remove_fuel(5, user)) return
build_step = 1
@@ -1039,7 +1039,7 @@
return
else if(I.is_wrench())
- playsound(loc, I.usesound, 100, 1)
+ playsound(src, I.usesound, 100, 1)
to_chat(user, "You remove the turret's metal armor bolts.")
build_step = 2
return
@@ -1058,7 +1058,7 @@
if(5)
if(I.is_screwdriver())
- playsound(loc, I.usesound, 100, 1)
+ playsound(src, I.usesound, 100, 1)
build_step = 6
to_chat(user, "You close the internal access hatch.")
return
@@ -1076,7 +1076,7 @@
return
else if(I.is_screwdriver())
- playsound(loc, I.usesound, 100, 1)
+ playsound(src, I.usesound, 100, 1)
build_step = 5
to_chat(user, "You open the internal access hatch.")
return
@@ -1088,7 +1088,7 @@
if(WT.get_fuel() < 5)
to_chat(user, "You need more fuel to complete this task.")
- playsound(loc, WT.usesound, 50, 1)
+ playsound(src, WT.usesound, 50, 1)
if(do_after(user, 30 * WT.toolspeed))
if(!src || !WT.remove_fuel(5, user))
return
@@ -1106,7 +1106,7 @@
qdel(src) // qdel
else if(I.is_crowbar())
- playsound(loc, I.usesound, 75, 1)
+ playsound(src, I.usesound, 75, 1)
to_chat(user, "You pry off the turret's exterior armor.")
new /obj/item/stack/material/steel(loc, 2)
build_step = 6
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index 9a50c34aad..ab78094832 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -84,7 +84,7 @@
return
anchored = !anchored
to_chat(user, "You [anchored ? "attached" : "detached"] [src].")
- playsound(loc, G.usesound, 75, 1)
+ playsound(src, G.usesound, 75, 1)
else if(default_deconstruction_screwdriver(user, G))
return
else if(default_deconstruction_crowbar(user, G))
diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm
index 7f659920d3..cdc3d4621a 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -54,6 +54,9 @@
recharge_amount = cell.give(recharge_amount)
use_power(recharge_amount / CELLRATE)
+ else
+ // Since external power is offline, draw operating current from the internal cell
+ cell.use(get_power_usage() * CELLRATE)
if(icon_update_tick >= 10)
icon_update_tick = 0
@@ -63,19 +66,6 @@
if(occupant || recharge_amount)
update_icon()
-//since the recharge station can still be on even with NOPOWER. Instead it draws from the internal cell.
-/obj/machinery/recharge_station/auto_use_power()
- if(!(stat & NOPOWER))
- return ..()
-
- if(!has_cell_power())
- return 0
- if(use_power == USE_POWER_IDLE)
- cell.use(idle_power_usage * CELLRATE)
- else if(use_power >= USE_POWER_ACTIVE)
- cell.use(active_power_usage * CELLRATE)
- return 1
-
//Processes the occupant, drawing from the internal power cell if needed.
/obj/machinery/recharge_station/proc/process_occupant()
if(isrobot(occupant))
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index ec3ab2f692..664d1c686f 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -206,7 +206,7 @@
protected = 1
if(!protected)
- playsound(src.loc, "sparks", 75, 1, -1)
+ playsound(src, "sparks", 75, 1, -1)
to_chat(user, "You try to touch the controls but you get zapped. There must be a short circuit somewhere.")
return*/
else //welp, the guy is protected, we can continue
@@ -232,7 +232,7 @@
protected = 1
if(!protected)
- playsound(src.loc, "sparks", 75, 1, -1)
+ playsound(src, "sparks", 75, 1, -1)
to_chat(user, "You try to touch the controls but you get zapped. There must be a short circuit somewhere.")
return*/
else
@@ -657,6 +657,15 @@
model_text = "Pilot"
departments = list("Pilot Blue","Pilot")
+/obj/machinery/suit_cycler/vintage
+ name = "Vintage suit cycler"
+ model_text = "Vintage"
+ departments = list("Vintage Crew","Vintage Engineering","Vintage Marine","Vintage Medical","Vintage Officer")
+
+/obj/machinery/suit_cycler/vintage/Initialize()
+ species -= SPECIES_TESHARI
+ return ..()
+
/obj/machinery/suit_cycler/attack_ai(mob/user as mob)
return attack_hand(user)
@@ -766,7 +775,7 @@
//Clear the access reqs, disable the safeties, and open up all paintjobs.
to_chat(user, "You run the sequencer across the interface, corrupting the operating protocols.")
- departments = list("Engineering","Mining","Medical","Security","Atmospherics","HAZMAT","Construction","Biohazard","Crowd Control","Security EVA","Emergency Medical Response","^%###^%$", "Charring")
+ departments = list("Engineering","Mining","Medical","Security","Atmospherics","HAZMAT","Construction","Biohazard","Crowd Control","Security EVA","Emergency Medical Response","^%###^%$", "Charring","Vintage Crew","Vintage Engineering","Vintage Marine","Vintage Medical","Vintage Officer")
species = list(SPECIES_HUMAN,SPECIES_TAJ,SPECIES_SKRELL,SPECIES_UNATHI, SPECIES_TESHARI)
emagged = 1
@@ -1068,6 +1077,22 @@
if("Gem-Encrusted" || "Wizard")
parent_helmet = /obj/item/clothing/head/helmet/space/void/wizard
parent_suit = /obj/item/clothing/suit/space/void/wizard
+ //Special or Event suits
+ if("Vintage Crew")
+ parent_helmet = /obj/item/clothing/head/helmet/space/void/refurb
+ parent_suit = /obj/item/clothing/suit/space/void/refurb
+ if("Vintage Engineering")
+ parent_helmet = /obj/item/clothing/head/helmet/space/void/refurb/engineering
+ parent_suit = /obj/item/clothing/suit/space/void/refurb/engineering
+ if("Vintage Medical")
+ parent_helmet = /obj/item/clothing/head/helmet/space/void/refurb/medical
+ parent_suit = /obj/item/clothing/suit/space/void/refurb/medical
+ if("Vintage Marine")
+ parent_helmet = /obj/item/clothing/head/helmet/space/void/refurb/marine
+ parent_suit = /obj/item/clothing/suit/space/void/refurb/marine
+ if("Vintage Officer")
+ parent_helmet = /obj/item/clothing/head/helmet/space/void/refurb/officer
+ parent_suit = /obj/item/clothing/suit/space/void/refurb/officer
//BEGIN: Space for additional downstream variants
//END: downstream variant space
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm
index a5e7a40f8e..3a6f4e589b 100644
--- a/code/game/machinery/telecomms/broadcaster.dm
+++ b/code/game/machinery/telecomms/broadcaster.dm
@@ -133,7 +133,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/obj/machinery/telecomms/allinone
name = "Telecommunications Mainframe"
icon = 'icons/obj/stationobjs.dmi'
- icon_state = "comm_server"
+ icon_state = "allinone"
desc = "A compact machine used for portable subspace telecommuniations processing."
density = 1
use_power = USE_POWER_IDLE
diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm
index f04cf7076a..8cd1d8811e 100644
--- a/code/game/machinery/telecomms/logbrowser.dm
+++ b/code/game/machinery/telecomms/logbrowser.dm
@@ -192,7 +192,7 @@
/obj/machinery/computer/telecomms/server/emag_act(var/remaining_charges, var/mob/user)
if(!emagged)
- playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1)
+ playsound(src, 'sound/effects/sparks4.ogg', 75, 1)
emagged = 1
to_chat(user, "You you disable the security protocols")
src.updateUsrDialog()
diff --git a/code/game/machinery/telecomms/telemonitor.dm b/code/game/machinery/telecomms/telemonitor.dm
index 819108b2ce..51a6ebf991 100644
--- a/code/game/machinery/telecomms/telemonitor.dm
+++ b/code/game/machinery/telecomms/telemonitor.dm
@@ -127,7 +127,7 @@
/obj/machinery/computer/telecomms/monitor/emag_act(var/remaining_charges, var/mob/user)
if(!emagged)
- playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1)
+ playsound(src, 'sound/effects/sparks4.ogg', 75, 1)
emagged = 1
to_chat(user, "You you disable the security protocols")
src.updateUsrDialog()
diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm
index 686a764ada..51c09d95e3 100644
--- a/code/game/machinery/telecomms/traffic_control.dm
+++ b/code/game/machinery/telecomms/traffic_control.dm
@@ -210,7 +210,7 @@
/obj/machinery/computer/telecomms/traffic/emag_act(var/remaining_charges, var/mob/user)
if(!emagged)
- playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1)
+ playsound(src, 'sound/effects/sparks4.ogg', 75, 1)
emagged = 1
to_chat(user, "You you disable the security protocols")
src.updateUsrDialog()
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index c792639f1b..7b95e738d4 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -1,3 +1,6 @@
+//////
+////// Teleporter computer
+//////
/obj/machinery/computer/teleporter
name = "teleporter control console"
desc = "Used to control a linked teleportation Hub and Station."
@@ -5,23 +8,23 @@
icon_screen = "teleport"
circuit = /obj/item/weapon/circuitboard/teleporter
dir = 4
- var/obj/item/locked = null
var/id = null
var/one_time_use = 0 //Used for one-time-use teleport cards (such as clown planet coordinates.)
//Setting this to 1 will set locked to null after a player enters the portal and will not allow hand-teles to open portals to that location.
+ var/datum/nano_module/program/teleport_control/teleport_control
/obj/machinery/computer/teleporter/New()
id = "[rand(1000, 9999)]"
..()
underlays.Cut()
underlays += image('icons/obj/stationobjs.dmi', icon_state = "telecomp-wires")
- return
+ teleport_control = new(src)
/obj/machinery/computer/teleporter/Initialize()
. = ..()
- var/obj/machinery/teleport/station/station
- var/obj/machinery/teleport/hub/hub
-
+ var/obj/machinery/teleport/station/station = null
+ var/obj/machinery/teleport/hub/hub = null
+
// Search surrounding turfs for the station, and then search the station's surrounding turfs for the hub.
for(var/direction in cardinal)
station = locate(/obj/machinery/teleport/station, get_step(src, direction))
@@ -34,9 +37,15 @@
if(istype(station))
station.com = hub
+ teleport_control.hub = hub
if(istype(hub))
hub.com = src
+ teleport_control.station = station
+
+/obj/machinery/computer/teleporter/Destroy()
+ qdel_null(teleport_control)
+ return ..()
/obj/machinery/computer/teleporter/attackby(I as obj, mob/living/user as mob)
if(istype(I, /obj/item/weapon/card/data/))
@@ -74,7 +83,7 @@
else
for(var/mob/O in hearers(src, null))
O.show_message("Locked In", 2)
- locked = L
+ teleport_control.locked = L
one_time_use = 1
add_fingerprint(usr)
@@ -86,57 +95,109 @@
/obj/machinery/teleport/station/attack_ai()
attack_hand()
-/obj/machinery/computer/teleporter/attack_hand(user as mob)
- if(..()) return
+/obj/machinery/computer/teleporter/attack_ai(mob/user)
+ ui_interact(user)
- /* Ghosts can't use this one because it's a direct selection */
- if(istype(user, /mob/observer/dead)) return
+/obj/machinery/computer/teleporter/attack_hand(mob/user)
+ add_fingerprint(user)
+ if(stat & (BROKEN|NOPOWER))
+ return
+ ui_interact(user)
- var/list/L = list()
- var/list/areaindex = list()
+/obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ teleport_control.ui_interact(user, ui_key, ui, force_open)
- for(var/obj/item/device/radio/beacon/R in all_beacons)
- var/turf/T = get_turf(R)
- if(!T)
- continue
- if(!(T.z in using_map.player_levels))
- continue
- var/tmpname = T.loc.name
- if(areaindex[tmpname])
- tmpname = "[tmpname] ([++areaindex[tmpname]])"
- else
- areaindex[tmpname] = 1
- L[tmpname] = R
+/obj/machinery/computer/teleporter/interact(mob/user)
+ teleport_control.ui_interact(user)
- for (var/obj/item/weapon/implant/tracking/I in all_tracking_implants)
- if(!I.implanted || !ismob(I.loc))
- continue
- else
- var/mob/M = I.loc
- if(M.stat == 2)
- if(M.timeofdeath + 6000 < world.time)
- continue
- var/turf/T = get_turf(M)
- if(T) continue
- if(T.z == 2) continue
- var/tmpname = M.real_name
+//////
+////// Nano-module for teleporter
+//////
+/datum/nano_module/program/teleport_control
+ name = "Teleporter Control"
+ var/locked_name = "Not Locked"
+ var/obj/item/locked = null
+ var/obj/machinery/teleport/station/station = null
+ var/obj/machinery/teleport/hub/hub = null
+
+/datum/nano_module/program/teleport_control/Topic(href, href_list)
+ if(..()) return 1
+
+ if(href_list["select_target"])
+ var/list/L = list()
+ var/list/areaindex = list()
+
+ for(var/obj/item/device/radio/beacon/R in all_beacons)
+ var/turf/T = get_turf(R)
+ if(!T)
+ continue
+ if(!(T.z in using_map.player_levels))
+ continue
+ var/tmpname = T.loc.name
if(areaindex[tmpname])
tmpname = "[tmpname] ([++areaindex[tmpname]])"
else
areaindex[tmpname] = 1
- L[tmpname] = I
+ L[tmpname] = R
- var/desc = input("Please select a location to lock in.", "Locking Computer") in L|null
- if(!desc)
- return
- if(get_dist(src, usr) > 1 && !issilicon(usr))
- return
+ for (var/obj/item/weapon/implant/tracking/I in all_tracking_implants)
+ if(!I.implanted || !ismob(I.loc))
+ continue
+ else
+ var/mob/M = I.loc
+ if(M.stat == 2)
+ if(M.timeofdeath + 6000 < world.time)
+ continue
+ var/turf/T = get_turf(M)
+ if(T) continue
+ if(T.z == 2) continue
+ var/tmpname = M.real_name
+ if(areaindex[tmpname])
+ tmpname = "[tmpname] ([++areaindex[tmpname]])"
+ else
+ areaindex[tmpname] = 1
+ L[tmpname] = I
- locked = L[desc]
- for(var/mob/O in hearers(src, null))
- O.show_message("Locked In", 2)
- add_fingerprint(usr)
- return
+ var/desc = input("Please select a location to lock in.", "Locking Menu") in L|null
+ if(!desc)
+ return 0
+ if(get_dist(host, usr) > 1 && !issilicon(usr))
+ return 0
+
+ locked = L[desc]
+ locked_name = desc
+ return 1
+
+ if(href_list["test_fire"])
+ station?.testfire()
+ return 1
+
+ if(href_list["toggle_on"])
+ if(!station)
+ return 0
+
+ if(station.engaged)
+ station.disengage()
+ else
+ station.engage()
+
+ return 1
+
+/datum/nano_module/program/teleport_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
+ var/list/data = host.initial_data()
+
+ data["locked_name"] = locked_name ? locked_name : "No Target"
+ data["station_connected"] = station ? 1 : 0
+ data["hub_connected"] = hub ? 1 : 0
+ data["calibrated"] = hub ? hub.accurate : 0
+ data["teleporter_on"] = station ? station.engaged : 0
+
+ ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "teleport_control.tmpl", "Teleport Control Console", 400, 500, state = state)
+ ui.set_initial_data(data)
+ ui.open()
+ ui.set_auto_update(1)
/obj/machinery/computer/teleporter/verb/set_id(t as text)
set category = "Object"
@@ -158,6 +219,9 @@
if(!T || istype(T, /area)) return null
return T
+//////
+////// Root of all the machinery
+//////
/obj/machinery/teleport
name = "teleport"
icon = 'icons/obj/stationobjs.dmi'
@@ -165,6 +229,9 @@
anchored = 1.0
var/lockeddown = 0
+//////
+////// The part you step into
+//////
/obj/machinery/teleport/hub
name = "teleporter hub"
desc = "It's the hub of a teleporting machine."
@@ -182,6 +249,11 @@
underlays += image('icons/obj/stationobjs.dmi', icon_state = "tele-wires")
default_apply_parts()
+/obj/machinery/teleport/hub/Destroy()
+ com?.teleport_control.hub = null
+ com = null
+ return ..()
+
/obj/machinery/teleport/hub/Bumped(M as mob|obj)
spawn()
if(icon_state == "tele1")
@@ -192,7 +264,7 @@
/obj/machinery/teleport/hub/proc/teleport(atom/movable/M as mob|obj)
if(!com)
return
- if(!com.locked)
+ if(!com.teleport_control.locked)
for(var/mob/O in hearers(src, null))
O.show_message("Failure: Cannot authenticate locked on coordinates. Please reinstate coordinate matrix.")
return
@@ -200,11 +272,11 @@
if(prob(5) && !accurate) //oh dear a problem, put em in deep space
do_teleport(M, locate(rand((2*TRANSITIONEDGE), world.maxx - (2*TRANSITIONEDGE)), rand((2*TRANSITIONEDGE), world.maxy - (2*TRANSITIONEDGE)), 3), 2)
else
- do_teleport(M, com.locked) //dead-on precision
+ do_teleport(M, com.teleport_control.locked) //dead-on precision
if(com.one_time_use) //Make one-time-use cards only usable one time!
com.one_time_use = 0
- com.locked = null
+ com.teleport_control.locked = null
else
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
@@ -214,92 +286,10 @@
for(var/mob/B in hearers(src, null))
B.show_message("Test fire completed.")
return
-/*
-/proc/do_teleport(atom/movable/M as mob|obj, atom/destination, precision)
- if(istype(M, /obj/effect))
- qdel(M)
- return
- if(istype(M, /obj/item/weapon/disk/nuclear)) // Don't let nuke disks get teleported --NeoFite
- for(var/mob/O in viewers(M, null))
- O.show_message(text("The [] bounces off of the portal!", M.name), 1)
- return
- if(istype(M, /mob/living))
- var/mob/living/MM = M
- if(MM.check_contents_for(/obj/item/weapon/disk/nuclear))
- to_chat(MM, "Something you are carrying seems to be unable to pass through the portal. Better drop it if you want to go through.")
- return
- var/disky = 0
- for (var/atom/O in M.contents) //I'm pretty sure this accounts for the maximum amount of container in container stacking. --NeoFite
- if(istype(O, /obj/item/weapon/storage) || istype(O, /obj/item/weapon/gift))
- for (var/obj/OO in O.contents)
- if(istype(OO, /obj/item/weapon/storage) || istype(OO, /obj/item/weapon/gift))
- for (var/obj/OOO in OO.contents)
- if(istype(OOO, /obj/item/weapon/disk/nuclear))
- disky = 1
- if(istype(OO, /obj/item/weapon/disk/nuclear))
- disky = 1
- if(istype(O, /obj/item/weapon/disk/nuclear))
- disky = 1
- if(istype(O, /mob/living))
- var/mob/living/MM = O
- if(MM.check_contents_for(/obj/item/weapon/disk/nuclear))
- disky = 1
- if(disky)
- for(var/mob/P in viewers(M, null))
- P.show_message(text("The [] bounces off of the portal!", M.name), 1)
- return
-
-//Bags of Holding cause bluespace teleportation to go funky. --NeoFite
- if(istype(M, /mob/living))
- var/mob/living/MM = M
- if(MM.check_contents_for(/obj/item/weapon/storage/backpack/holding))
- to_chat(MM, "The Bluespace interface on your Bag of Holding interferes with the teleport!")
- precision = rand(1,100)
- if(istype(M, /obj/item/weapon/storage/backpack/holding))
- precision = rand(1,100)
- for (var/atom/O in M.contents) //I'm pretty sure this accounts for the maximum amount of container in container stacking. --NeoFite
- if(istype(O, /obj/item/weapon/storage) || istype(O, /obj/item/weapon/gift))
- for (var/obj/OO in O.contents)
- if(istype(OO, /obj/item/weapon/storage) || istype(OO, /obj/item/weapon/gift))
- for (var/obj/OOO in OO.contents)
- if(istype(OOO, /obj/item/weapon/storage/backpack/holding))
- precision = rand(1,100)
- if(istype(OO, /obj/item/weapon/storage/backpack/holding))
- precision = rand(1,100)
- if(istype(O, /obj/item/weapon/storage/backpack/holding))
- precision = rand(1,100)
- if(istype(O, /mob/living))
- var/mob/living/MM = O
- if(MM.check_contents_for(/obj/item/weapon/storage/backpack/holding))
- precision = rand(1,100)
-
- var/turf/destturf = get_turf(destination)
-
- var/tx = destturf.x + rand(precision * -1, precision)
- var/ty = destturf.y + rand(precision * -1, precision)
-
- var/tmploc
-
- if(ismob(destination.loc)) //If this is an implant.
- tmploc = locate(tx, ty, destturf.z)
- else
- tmploc = locate(tx, ty, destination.z)
-
- if(tx == destturf.x && ty == destturf.y && (istype(destination.loc, /obj/structure/closet) || istype(destination.loc, /obj/structure/closet/secure_closet)))
- tmploc = destination.loc
-
- if(tmploc==null)
- return
-
- M.loc = tmploc
- sleep(2)
-
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, M)
- s.start()
- return
-*/
+//////
+////// The middle part
+//////
/obj/machinery/teleport/station
name = "station"
desc = "It's the station thingy of a teleport thingy." //seriously, wtf.
@@ -317,18 +307,11 @@
. = ..()
add_overlay("controller-wires")
default_apply_parts()
-
-/obj/machinery/teleport/station/attackby(var/obj/item/weapon/W)
- attack_hand()
-/obj/machinery/teleport/station/attack_ai()
- attack_hand()
-
-/obj/machinery/teleport/station/attack_hand()
- if(engaged)
- disengage()
- else
- engage()
+/obj/machinery/teleport/station/Destroy()
+ com?.com?.teleport_control.station = null
+ com = null
+ return ..()
/obj/machinery/teleport/station/proc/engage()
if(stat & (BROKEN|NOPOWER))
@@ -360,26 +343,16 @@
engaged = 0
return
-/obj/machinery/teleport/station/verb/testfire()
- set name = "Test Fire Teleporter"
- set category = "Object"
- set src in oview(1)
-
- if(stat & (BROKEN|NOPOWER) || !istype(usr,/mob/living))
+/obj/machinery/teleport/station/proc/testfire()
+ if(!com || active)
return
- if(com && !active)
- active = 1
- for(var/mob/O in hearers(src, null))
- O.show_message("Test firing!", 2)
- com.teleport()
- use_power(5000)
+ active = TRUE
+ visible_message("Test firing!")
+ com.teleport()
+ use_power(5000)
- spawn(30)
- active=0
-
- add_fingerprint(usr)
- return
+ VARSET_IN(src, active, FALSE, 3 SECONDS)
/obj/machinery/teleport/station/power_change()
..()
diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm
index c9c8ba20ae..621feae713 100644
--- a/code/game/machinery/transformer.dm
+++ b/code/game/machinery/transformer.dm
@@ -28,14 +28,14 @@
if(stat & (BROKEN|NOPOWER))
return
if(!transform_dead && H.stat == DEAD)
- playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
return
- playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
use_power(5000) // Use a lot of power.
var/mob/living/silicon/robot = H.Robotize()
robot.SetLockDown()
spawn(50) // So he can't jump out the gate right away.
- playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
+ playsound(src, 'sound/machines/ping.ogg', 50, 0)
if(robot)
robot.SetLockDown(0)
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 2730c2dd86..868313258b 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -65,6 +65,7 @@
var/list/log = list()
var/req_log_access = access_cargo //default access for checking logs is cargo
var/has_logs = 0 //defaults to 0, set to anything else for vendor to have logs
+ var/can_rotate = 1 //Defaults to yes, can be set to 0 for vendors without or with unwanted directionals.
/obj/machinery/vending/Initialize()
@@ -252,7 +253,7 @@
*/
/obj/machinery/vending/proc/pay_with_ewallet(var/obj/item/weapon/spacecash/ewallet/wallet)
visible_message("\The [usr] swipes \the [wallet] through \the [src].")
- playsound(src.loc, 'sound/machines/id_swipe.ogg', 50, 1)
+ playsound(src, 'sound/machines/id_swipe.ogg', 50, 1)
if(currently_vending.price > wallet.worth)
status_message = "Insufficient funds on chargecard."
status_error = 1
@@ -273,7 +274,7 @@
visible_message("\The [usr] swipes \the [I] through \the [src].")
else
visible_message("\The [usr] swipes \the [ID_container] through \the [src].")
- playsound(src.loc, 'sound/machines/id_swipe.ogg', 50, 1)
+ playsound(src, 'sound/machines/id_swipe.ogg', 50, 1)
var/datum/money_account/customer_account = get_account(I.associated_account_number)
if(!customer_account)
status_message = "Error: Unable to access account. Please contact technical support if problem persists."
@@ -429,7 +430,7 @@
if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
to_chat(usr, "Access denied.") //Unless emagged of course
flick("[icon_state]-deny",src)
- playsound(src.loc, 'sound/machines/deniedbeep.ogg', 50, 0)
+ playsound(src, 'sound/machines/deniedbeep.ogg', 50, 0)
return
var/key = text2num(href_list["vend"])
@@ -466,7 +467,7 @@
if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
to_chat(usr, "Access denied.") //Unless emagged of course
flick("[icon_state]-deny",src)
- playsound(src.loc, 'sound/machines/deniedbeep.ogg', 50, 0)
+ playsound(src, 'sound/machines/deniedbeep.ogg', 50, 0)
return
vend_ready = 0 //One thing at a time!!
status_message = "Vending..."
@@ -505,7 +506,7 @@
sleep(3)
if(R.get_product(get_turf(src)))
visible_message("\The [src] clunks as it vends an additional item.")
- playsound(src.loc, "sound/[vending_sound]", 100, 1, 1)
+ playsound(src, "sound/[vending_sound]", 100, 1, 1)
status_message = ""
status_error = 0
@@ -545,6 +546,22 @@
else
to_chat(user,"You do not have the required access to view the vending logs for this machine.")
+
+/obj/machinery/vending/verb/rotate_clockwise()
+ set name = "Rotate Vending Machine Clockwise"
+ set category = "Object"
+ set src in oview(1)
+
+ if (src.can_rotate == 0)
+ to_chat(usr, "\The [src] cannot be rotated.")
+ return 0
+
+ if (src.anchored || usr:stat)
+ to_chat(usr, "It is bolted down!")
+ return 0
+ src.set_dir(turn(src.dir, 270))
+ return 1
+
/obj/machinery/vending/verb/check_logs()
set name = "Check Vending Logs"
set category = "Object"
@@ -761,10 +778,10 @@
product_slogans = "Try our new nougat bar!;Twice the calories for half the price!"
product_ads = "The healthiest!;Award-winning chocolate bars!;Mmm! So good!;Oh my god it's so juicy!;Have a snack.;Snacks are good for you!;Have some more Getmore!;Best quality snacks straight from mars.;We love chocolate!;Try our new jerky!"
icon_state = "snack"
- products = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 6,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 6,/obj/item/weapon/reagent_containers/food/snacks/chips =6,
- /obj/item/weapon/reagent_containers/food/snacks/sosjerky = 6,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 6,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 6,
- /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 6, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 6, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 3)
- contraband = list(/obj/item/weapon/reagent_containers/food/snacks/syndicake = 6,/obj/item/weapon/reagent_containers/food/snacks/unajerky = 6,)
+ products = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 12,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 12,/obj/item/weapon/reagent_containers/food/snacks/chips =12,
+ /obj/item/weapon/reagent_containers/food/snacks/sosjerky = 12,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 12,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 12,
+ /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 12, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 12, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 6)
+ contraband = list(/obj/item/weapon/reagent_containers/food/snacks/syndicake = 6,/obj/item/weapon/reagent_containers/food/snacks/unajerky = 12,)
prices = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 1,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 5,/obj/item/weapon/reagent_containers/food/snacks/chips = 1,
/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 2,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 1,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 1,
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 1, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 2, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 4)
@@ -793,11 +810,11 @@
name = "SweatMAX"
desc = "Fueled by your inner inadequacy!"
icon_state = "fitness"
- products = list(/obj/item/weapon/reagent_containers/food/drinks/smallmilk = 8,
- /obj/item/weapon/reagent_containers/food/drinks/smallchocmilk = 8,
+ products = list(/obj/item/weapon/reagent_containers/food/drinks/smallmilk = 16,
+ /obj/item/weapon/reagent_containers/food/drinks/smallchocmilk = 16,
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask/proteinshake = 8,
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask = 8,
- /obj/item/weapon/reagent_containers/food/snacks/candy/proteinbar = 8,
+ /obj/item/weapon/reagent_containers/food/snacks/candy/proteinbar = 16,
/obj/item/weapon/reagent_containers/food/snacks/liquidfood = 8,
/obj/item/weapon/reagent_containers/pill/diet = 8,
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose = 5,
@@ -834,13 +851,13 @@
product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs.;Feeling temperamental? Try a Temperamento!;Carcinoma Angels - go fuck yerself!;Don't be so hard on yourself, kid. Smoke a Lucky Star!"
vend_delay = 34
icon_state = "cigs"
- products = list(/obj/item/weapon/storage/fancy/cigarettes = 5,
- /obj/item/weapon/storage/fancy/cigarettes/dromedaryco = 5,
- /obj/item/weapon/storage/fancy/cigarettes/killthroat = 5,
- /obj/item/weapon/storage/fancy/cigarettes/luckystars = 5,
- /obj/item/weapon/storage/fancy/cigarettes/jerichos = 5,
- /obj/item/weapon/storage/fancy/cigarettes/menthols = 5,
- /obj/item/weapon/storage/rollingpapers = 5,
+ products = list(/obj/item/weapon/storage/fancy/cigarettes = 10,
+ /obj/item/weapon/storage/fancy/cigarettes/dromedaryco = 10,
+ /obj/item/weapon/storage/fancy/cigarettes/killthroat = 10,
+ /obj/item/weapon/storage/fancy/cigarettes/luckystars = 10,
+ /obj/item/weapon/storage/fancy/cigarettes/jerichos = 10,
+ /obj/item/weapon/storage/fancy/cigarettes/menthols = 10,
+ /obj/item/weapon/storage/rollingpapers = 10,
/obj/item/weapon/storage/box/matches = 10,
/obj/item/weapon/flame/lighter/random = 4,
/obj/item/clothing/mask/smokable/ecig/util = 2,
@@ -918,6 +935,7 @@
contraband = list(/obj/item/weapon/reagent_containers/syringe/antitoxin = 4,/obj/item/weapon/reagent_containers/syringe/antiviral = 4,/obj/item/weapon/reagent_containers/pill/tox = 1)
req_log_access = access_cmo
has_logs = 1
+ can_rotate = 0
/obj/machinery/vending/wallmed2
name = "NanoMed"
@@ -929,6 +947,7 @@
contraband = list(/obj/item/weapon/reagent_containers/pill/tox = 3)
req_log_access = access_cmo
has_logs = 1
+ can_rotate = 0
/obj/machinery/vending/security
name = "SecTech"
@@ -953,6 +972,7 @@
premium = list(/obj/item/weapon/reagent_containers/glass/bottle/ammonia = 10,/obj/item/weapon/reagent_containers/glass/bottle/diethylamine = 5)
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
+
/obj/machinery/vending/hydroseeds
name = "MegaSeed Servitor"
desc = "When you need seeds fast!"
@@ -1174,6 +1194,7 @@
/obj/item/toy/plushie/tabby_cat = 50,
/obj/item/device/threadneedle = 2)
+
/obj/machinery/vending/fishing
name = "Loot Trawler"
desc = "A special vendor for fishing equipment."
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index 2026c1dc2b..b975d00d8b 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -59,8 +59,8 @@
I.decontaminate()
//Tanning!
- for(var/obj/item/stack/material/hairlesshide/HH in washing)
- var/obj/item/stack/material/wetleather/WL = new(src)
+ for(var/obj/item/stack/hairlesshide/HH in washing)
+ var/obj/item/stack/wetleather/WL = new(src)
WL.amount = HH.amount
qdel(HH)
diff --git a/code/game/mecha/combat/fighter.dm b/code/game/mecha/combat/fighter.dm
index 171c96395e..c87af14617 100644
--- a/code/game/mecha/combat/fighter.dm
+++ b/code/game/mecha/combat/fighter.dm
@@ -164,7 +164,7 @@
else if(moved && gravity && !ground_capable)
occupant_message("Collision alert! Vehicle not rated for use in gravity!")
take_damage(NOGRAV_FIGHTER_DAMAGE, "brute")
- playsound(loc, 'sound/effects/grillehit.ogg', 50, 1)
+ playsound(src, 'sound/effects/grillehit.ogg', 50, 1)
/obj/mecha/combat/fighter/handle_equipment_movement()
. = ..()
diff --git a/code/game/mecha/combat/gorilla.dm b/code/game/mecha/combat/gorilla.dm
index e413fc892a..2f75de4a15 100644
--- a/code/game/mecha/combat/gorilla.dm
+++ b/code/game/mecha/combat/gorilla.dm
@@ -179,7 +179,7 @@
src.occupant_message("Zoom mode [zoom?"en":"dis"]abled.")
if(zoom)
src.occupant.set_viewsize(12)
- playsound(src.occupant, 'sound/mecha/imag_enh.ogg',50)
+ playsound(src, 'sound/mecha/imag_enh.ogg',50)
else
src.occupant.set_viewsize() // Reset to default
return
diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm
index 30ea5ea738..87a107f2c0 100644
--- a/code/game/mecha/equipment/mecha_equipment.dm
+++ b/code/game/mecha/equipment/mecha_equipment.dm
@@ -28,7 +28,7 @@
sleep(equip_cooldown)
set_ready_state(1)
if(ready_sound) //Kind of like the kinetic accelerator.
- playsound(loc, ready_sound, 50, 1, -1)
+ playsound(src, ready_sound, 50, 1, -1)
if(target && chassis)
return 1
return 0
diff --git a/code/game/mecha/equipment/tools/clamp.dm b/code/game/mecha/equipment/tools/clamp.dm
index a587d89568..6091764c2b 100644
--- a/code/game/mecha/equipment/tools/clamp.dm
+++ b/code/game/mecha/equipment/tools/clamp.dm
@@ -33,7 +33,7 @@
if(FD.blocked)
FD.visible_message("\The [chassis] begins prying on \the [FD]!")
if(do_after(chassis.occupant,10 SECONDS,FD))
- playsound(FD.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ playsound(FD, 'sound/machines/airlock_creaking.ogg', 100, 1)
FD.blocked = 0
FD.update_icon()
FD.open(1)
@@ -41,7 +41,7 @@
else if(FD.density)
FD.visible_message("\The [chassis] begins forcing \the [FD] open!")
if(do_after(chassis.occupant, 5 SECONDS,FD))
- playsound(FD.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ playsound(FD, 'sound/machines/airlock_creaking.ogg', 100, 1)
FD.visible_message("\The [chassis] forces \the [FD] open!")
FD.open(1)
else
@@ -57,7 +57,7 @@
if(do_after(chassis.occupant, 15 SECONDS,AD) && chassis.Adjacent(AD))
AD.welded = FALSE
AD.update_icon()
- playsound(AD.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ playsound(AD, 'sound/machines/airlock_creaking.ogg', 100, 1)
AD.visible_message("\The [chassis] tears \the [AD] open!")
if(!AD.welded)
if(density)
@@ -100,15 +100,15 @@
M.adjustOxyLoss(round(dam_force/2))
M.updatehealth()
occupant_message("You squeeze [target] with [src.name]. Something cracks.")
- playsound(src.loc, "fracture", 5, 1, -2) //CRACK
+ playsound(src, "fracture", 5, 1, -2) //CRACK
chassis.visible_message("[chassis] squeezes [target].")
else if(chassis.occupant.a_intent == I_DISARM && enable_special)
- playsound(src.loc, 'sound/mecha/hydraulic.ogg', 10, 1, -2)
+ playsound(src, 'sound/mecha/hydraulic.ogg', 10, 1, -2)
M.take_overall_damage(dam_force/2)
M.adjustOxyLoss(round(dam_force/3))
M.updatehealth()
occupant_message("You slam [target] with [src.name]. Something cracks.")
- playsound(src.loc, "fracture", 3, 1, -2) //CRACK 2
+ playsound(src, "fracture", 3, 1, -2) //CRACK 2
chassis.visible_message("[chassis] slams [target].")
M.throw_at(get_step(M,get_dir(src, M)), 14, 1.5, chassis)
else
diff --git a/code/game/mecha/equipment/tools/cloak.dm b/code/game/mecha/equipment/tools/cloak.dm
index 6f6ddd1c8f..e78a4f7395 100644
--- a/code/game/mecha/equipment/tools/cloak.dm
+++ b/code/game/mecha/equipment/tools/cloak.dm
@@ -46,7 +46,7 @@
log_message("Activated.")
cloak_iterator.start()
set_ready_state(0)
- playsound(get_turf(src), 'sound/effects/EMPulse.ogg', 100, 1)
+ playsound(src, 'sound/effects/EMPulse.ogg', 100, 1)
/obj/item/mecha_parts/mecha_equipment/cloak/proc/stop_cloak()
if(chassis)
@@ -54,7 +54,7 @@
log_message("Deactivated.")
cloak_iterator.stop()
set_ready_state(1)
- playsound(get_turf(src), 'sound/effects/EMPulse.ogg', 100, 1)
+ playsound(src, 'sound/effects/EMPulse.ogg', 100, 1)
// These things are so silly
/datum/global_iterator/mecha_cloak/process(var/obj/item/mecha_parts/mecha_equipment/cloak/cloak)
diff --git a/code/game/mecha/equipment/tools/energy_relay.dm b/code/game/mecha/equipment/tools/energy_relay.dm
index d6917a0de1..0e02f927e4 100644
--- a/code/game/mecha/equipment/tools/energy_relay.dm
+++ b/code/game/mecha/equipment/tools/energy_relay.dm
@@ -111,5 +111,5 @@
if(pow_chan)
var/delta = min(12, ER.chassis.cell.maxcharge-cur_charge)
ER.chassis.give_power(delta)
- A.use_power(delta*ER.coeff, pow_chan)
+ A.use_power_oneoff(delta*ER.coeff, pow_chan)
return
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/extinguisher.dm b/code/game/mecha/equipment/tools/extinguisher.dm
index d383573017..5bb6cd147c 100644
--- a/code/game/mecha/equipment/tools/extinguisher.dm
+++ b/code/game/mecha/equipment/tools/extinguisher.dm
@@ -25,14 +25,14 @@
var/obj/o = target
var/amount = o.reagents.trans_to_obj(src, 200)
occupant_message("[amount] units transferred into internal tank.")
- playsound(chassis, 'sound/effects/refill.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 50, 1, -6)
return
if (src.reagents.total_volume < 1)
occupant_message("\The [src] is empty.")
return
- playsound(chassis, 'sound/effects/extinguish.ogg', 75, 1, -3)
+ playsound(src, 'sound/effects/extinguish.ogg', 75, 1, -3)
var/direction = get_dir(chassis,target)
diff --git a/code/game/mecha/equipment/tools/syringe_gun.dm b/code/game/mecha/equipment/tools/syringe_gun.dm
index 36763c7f12..95c87b6253 100644
--- a/code/game/mecha/equipment/tools/syringe_gun.dm
+++ b/code/game/mecha/equipment/tools/syringe_gun.dm
@@ -67,7 +67,7 @@
syringes -= S
S.icon = 'icons/obj/chemical.dmi'
S.icon_state = "syringeproj"
- playsound(chassis, 'sound/items/syringeproj.ogg', 50, 1)
+ playsound(src, 'sound/items/syringeproj.ogg', 50, 1)
log_message("Launched [S] from [src], targeting [target].")
spawn(-1)
src = null //if src is deleted, still process the syringe
diff --git a/code/game/mecha/equipment/weapons/honk.dm b/code/game/mecha/equipment/weapons/honk.dm
index 921111a6cd..427d53295c 100644
--- a/code/game/mecha/equipment/weapons/honk.dm
+++ b/code/game/mecha/equipment/weapons/honk.dm
@@ -16,7 +16,7 @@
if(!equip_ready)
return 0
- playsound(chassis, 'sound/effects/bang.ogg', 30, 1, 30)
+ playsound(src, 'sound/effects/bang.ogg', 30, 1, 30)
chassis.occupant_message("You emit a high-pitched noise from the mech.")
for(var/mob/living/carbon/M in ohearers(6, chassis))
if(istype(M, /mob/living/carbon/human))
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index 5d01416785..355ce629ac 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -36,7 +36,7 @@
aimloc = locate(targloc.x+GaussRandRound(deviation,1),targloc.y+GaussRandRound(deviation,1),targloc.z)
if(!aimloc || aimloc == curloc || (locs && aimloc in locs))
break
- playsound(chassis, fire_sound, fire_volume, 1)
+ playsound(src, fire_sound, fire_volume, 1)
projectiles--
var/turf/projectile_turf
if(chassis.locs && chassis.locs.len) // Multi tile.
diff --git a/code/game/mecha/mech_prosthetics.dm b/code/game/mecha/mech_prosthetics.dm
index 17c715e9a4..1615be1ff4 100644
--- a/code/game/mecha/mech_prosthetics.dm
+++ b/code/game/mecha/mech_prosthetics.dm
@@ -1,6 +1,6 @@
/obj/machinery/pros_fabricator
icon = 'icons/obj/robotics.dmi'
- icon_state = "fab-idle"
+ icon_state = "prosfab"
name = "Prosthetics Fabricator"
desc = "A machine used for construction of prosthetics."
density = 1
@@ -32,7 +32,7 @@
/obj/machinery/pros_fabricator/Initialize()
. = ..()
default_apply_parts()
-
+
files = new /datum/research(src) //Setup the research data holder.
/obj/machinery/pros_fabricator/Initialize()
@@ -54,12 +54,14 @@
/obj/machinery/pros_fabricator/update_icon()
overlays.Cut()
+ icon_state = initial(icon_state)
+
if(panel_open)
- icon_state = "fab-o"
- else
- icon_state = "fab-idle"
+ overlays.Add(image(icon, "[icon_state]_panel"))
+ if(stat & NOPOWER)
+ return
if(busy)
- overlays += "fab-active"
+ icon_state = "[icon_state]_work"
/obj/machinery/pros_fabricator/dismantle()
for(var/f in materials)
@@ -198,9 +200,7 @@
if(materials[S.material.name] + amnt <= res_max_amount)
if(S && S.get_amount() >= 1)
var/count = 0
- overlays += "fab-load-metal"
- spawn(10)
- overlays -= "fab-load-metal"
+ flick("[initial(icon_state)]_loading", src)
while(materials[S.material.name] + amnt <= res_max_amount && S.get_amount() >= 1)
materials[S.material.name] += amnt
S.use(1)
@@ -273,6 +273,7 @@
materials[M] = max(0, materials[M] - D.materials[M] * mat_efficiency)
if(D.build_path)
var/obj/new_item = D.Fabricate(get_step(get_turf(src), src.dir), src) // Sometimes returns a mob. Beware!
+ flick("[initial(icon_state)]_finish", src)
visible_message("\The [src] pings, indicating that \the [D] is complete.", "You hear a ping.")
if(mat_efficiency != 1)
if(istype(new_item, /obj/) && new_item.matter && new_item.matter.len > 0)
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index bcf9459be2..4aa82bad7a 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -95,9 +95,9 @@
var/list/cargo = list()
var/cargo_capacity = 3
- var/static/image/radial_image_eject = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject"),
- var/static/image/radial_image_airtoggle = image(icon= 'icons/mob/radial.dmi', icon_state = "radial_airtank"),
- var/static/image/radial_image_lighttoggle = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_light"),
+ var/static/image/radial_image_eject = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject")
+ var/static/image/radial_image_airtoggle = image(icon= 'icons/mob/radial.dmi', icon_state = "radial_airtank")
+ var/static/image/radial_image_lighttoggle = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_light")
var/static/image/radial_image_statpanel = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine2")
@@ -433,11 +433,9 @@
//////// Movement procs ////////
//////////////////////////////////
-/obj/mecha/Move()
+/obj/mecha/Moved(atom/old_loc, direction, forced = FALSE)
. = ..()
- if(.)
- MoveAction()
- return
+ MoveAction()
/obj/mecha/proc/MoveAction() //Allows mech equipment to do an action once the mech moves
if(!equipment.len)
@@ -631,6 +629,7 @@
////////////////////////////////////////
/obj/mecha/take_damage(amount, type="brute")
+ update_damage_alerts()
if(amount)
var/damage = absorbDamage(amount,type)
health -= damage
@@ -671,12 +670,12 @@
if(!prob(src.deflect_chance))
src.take_damage(15)
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1)
to_chat(user, "You slash at the armored suit!")
visible_message("\The [user] slashes at [src.name]'s armor!")
else
src.log_append_to_last("Armor saved.")
- playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1)
to_chat(user, "Your claws had no effect!")
src.occupant_message("\The [user]'s claws are stopped by the armor.")
visible_message("\The [user] rebounds off [src.name]'s armor!")
@@ -805,14 +804,14 @@
if(!prob(src.deflect_chance))
src.take_damage(6)
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- playsound(src.loc, 'sound/effects/blobattack.ogg', 50, 1, -1)
+ playsound(src, 'sound/effects/blobattack.ogg', 50, 1, -1)
to_chat(user, "You smash at the armored suit!")
for (var/mob/V in viewers(src))
if(V.client && !(V.blinded))
V.show_message("\The [user] smashes against [src.name]'s armor!", 1)
else
src.log_append_to_last("Armor saved.")
- playsound(src.loc, 'sound/effects/blobattack.ogg', 50, 1, -1)
+ playsound(src, 'sound/effects/blobattack.ogg', 50, 1, -1)
to_chat(user, "Your attack had no effect!")
src.occupant_message("\The [user]'s attack is stopped by the armor.")
for (var/mob/V in viewers(src))
@@ -971,6 +970,7 @@
if(src.healthYou repair some damage to [src.name].")
src.health += min(10, initial(src.health)-src.health)
+ update_damage_alerts()
else
to_chat(user, "The [src.name] is at full integrity")
return
@@ -1321,6 +1321,8 @@
src.verbs += /obj/mecha/verb/eject
src.log_append_to_last("[H] moved in as pilot.")
src.icon_state = src.reset_icon()
+ update_cell_alerts()
+ update_damage_alerts()
set_dir(dir_in)
playsound(src, 'sound/machines/windowdoor.ogg', 50, 1)
if(occupant.client && cloaked_selfimage)
@@ -1403,6 +1405,8 @@
occupant.loc = mmi
mmi.mecha = null
occupant.canmove = 0
+ occupant.clear_alert("charge")
+ occupant.clear_alert("mech damage")
occupant = null
icon_state = src.reset_icon()+"-open"
set_dir(dir_in)
@@ -1971,12 +1975,14 @@
return call((proc_res["dynusepower"]||src), "dynusepower")(amount)
/obj/mecha/proc/dynusepower(amount)
+ update_cell_alerts()
if(get_charge())
cell.use(amount)
return 1
return 0
/obj/mecha/proc/give_power(amount)
+ update_cell_alerts()
if(!isnull(get_charge()))
cell.give(amount)
return 1
@@ -2005,7 +2011,7 @@
user.attack_log += text("\[[time_stamp()]\] attacked [src.name]")
else
src.log_append_to_last("Armor saved.")
- playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1)
src.occupant_message("\The [user]'s attack is stopped by the armor.")
visible_message("\The [user] rebounds off [src.name]'s armor!")
user.attack_log += text("\[[time_stamp()]\] attacked [src.name]")
@@ -2154,3 +2160,31 @@
//src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
return
*/
+
+/obj/mecha/proc/update_cell_alerts()
+ if(occupant && cell)
+ var/cellcharge = cell.charge/cell.maxcharge
+ switch(cellcharge)
+ if(0.75 to INFINITY)
+ occupant.clear_alert("charge")
+ if(0.5 to 0.75)
+ occupant.throw_alert("charge", /obj/screen/alert/lowcell, 1)
+ if(0.25 to 0.5)
+ occupant.throw_alert("charge", /obj/screen/alert/lowcell, 2)
+ if(0.01 to 0.25)
+ occupant.throw_alert("charge", /obj/screen/alert/lowcell, 3)
+ else
+ occupant.throw_alert("charge", /obj/screen/alert/emptycell)
+
+/obj/mecha/proc/update_damage_alerts()
+ if(occupant)
+ var/integrity = health/initial(health)*100
+ switch(integrity)
+ if(30 to 45)
+ occupant.throw_alert("mech damage", /obj/screen/alert/low_mech_integrity, 1)
+ if(15 to 35)
+ occupant.throw_alert("mech damage", /obj/screen/alert/low_mech_integrity, 2)
+ if(-INFINITY to 15)
+ occupant.throw_alert("mech damage", /obj/screen/alert/low_mech_integrity, 3)
+ else
+ occupant.clear_alert("mech damage")
\ No newline at end of file
diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm
index b4723a4be3..890a27b100 100644
--- a/code/game/objects/buckling.dm
+++ b/code/game/objects/buckling.dm
@@ -66,6 +66,7 @@
buckled_mobs |= M
post_buckle_mob(M)
+ M.throw_alert("buckled", /obj/screen/alert/restrained/buckled, new_master = src)
return TRUE
/atom/movable/proc/unbuckle_mob(mob/living/buckled_mob, force = FALSE)
@@ -81,6 +82,7 @@
buckled_mob.anchored = initial(buckled_mob.anchored)
buckled_mob.update_canmove()
buckled_mob.update_floating( buckled_mob.Check_Dense_Object() )
+ buckled_mob.clear_alert("buckled")
// buckled_mob = null
buckled_mobs -= buckled_mob
@@ -120,7 +122,7 @@
// step_towards(M, src)
. = buckle_mob(M, forced)
- playsound(src.loc, 'sound/effects/seatbelt.ogg', 50, 1)
+ playsound(src, 'sound/effects/seatbelt.ogg', 50, 1)
if(.)
if(!silent)
if(M == user)
@@ -136,7 +138,7 @@
/atom/movable/proc/user_unbuckle_mob(mob/living/buckled_mob, mob/user)
var/mob/living/M = unbuckle_mob(buckled_mob)
- playsound(src.loc, 'sound/effects/seatbelt.ogg', 50, 1)
+ playsound(src, 'sound/effects/seatbelt.ogg', 50, 1)
if(M)
if(M != user)
M.visible_message(\
@@ -151,19 +153,18 @@
add_fingerprint(user)
return M
-/atom/movable/proc/handle_buckled_mob_movement(newloc,direct)
- if(has_buckled_mobs())
- for(var/A in buckled_mobs)
- var/mob/living/L = A
-// if(!L.Move(newloc, direct))
- if(!L.forceMove(newloc, direct))
- loc = L.loc
- last_move = L.last_move
- L.inertia_dir = last_move
- return FALSE
- else
- L.set_dir(dir)
- return TRUE
+/atom/movable/proc/handle_buckled_mob_movement(atom/old_loc, direct, movetime)
+ for(var/A in buckled_mobs)
+ var/mob/living/L = A
+ if(!L.Move(loc, direct, movetime))
+ L.forceMove(loc, direct, movetime)
+ L.last_move = last_move
+ L.inertia_dir = last_move
+
+ if(!buckle_dir)
+ L.set_dir(dir)
+ else
+ L.set_dir(buckle_dir)
/atom/movable/proc/can_buckle_check(mob/living/M, forced = FALSE)
if(!buckled_mobs)
diff --git a/code/game/objects/effects/alien/aliens.dm b/code/game/objects/effects/alien/aliens.dm
index 203b768d75..836e277872 100644
--- a/code/game/objects/effects/alien/aliens.dm
+++ b/code/game/objects/effects/alien/aliens.dm
@@ -66,7 +66,7 @@
/obj/effect/alien/resin/attack_generic(var/mob/user, var/damage, var/attack_verb)
visible_message("[user] [attack_verb] the [src]!")
- playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
+ playsound(src, 'sound/effects/attackblob.ogg', 100, 1)
user.do_attack_animation(src)
health -= damage
healthcheck()
@@ -100,7 +100,7 @@
tforce = 10
else
tforce = AM:throwforce
- playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
+ playsound(src, 'sound/effects/attackblob.ogg', 100, 1)
health = max(0, health - tforce)
healthcheck()
..()
@@ -137,7 +137,7 @@
user.setClickCooldown(user.get_attack_speed(W))
var/aforce = W.force
health = max(0, health - aforce)
- playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
+ playsound(src, 'sound/effects/attackblob.ogg', 100, 1)
healthcheck()
..()
return
@@ -176,11 +176,11 @@
. = ..()
if(isspace(loc))
return INITIALIZE_HINT_QDEL
-
+
linked_node = node
if(newcolor)
color = newcolor
-
+
if(icon_state == "weeds")
icon_state = pick("weeds", "weeds1", "weeds2")
@@ -203,7 +203,7 @@
desc = "Weird glowing organic growth."
layer = ABOVE_TURF_LAYER+0.01
light_range = NODERANGE
-
+
var/node_range = NODERANGE
var/set_color = "#321D37"
@@ -216,6 +216,8 @@
else
qdel(existing)
+ linked_node = src
+
if(newcolor)
set_color = newcolor
if(set_color)
@@ -299,7 +301,7 @@
W.color = W.linked_node.set_color
- if(prob(max(10, 40 - (5 * nearby_weeds.len))))
+ if(prob(max(10, 60 - (5 * nearby_weeds.len))))
W.process()
/obj/effect/alien/weeds/ex_act(severity)
@@ -328,7 +330,7 @@
if(WT.remove_fuel(0, user))
damage = 15
- playsound(loc, 'sound/items/Welder.ogg', 100, 1)
+ playsound(src, 'sound/items/Welder.ogg', 100, 1)
health -= damage
healthcheck()
@@ -441,7 +443,6 @@
var/health = 100
var/status = BURST //can be GROWING, GROWN or BURST; all mutually exclusive
- flags = PROXMOVE
/obj/effect/alien/egg/New()
/*
@@ -532,7 +533,7 @@
if(WT.remove_fuel(0, user))
damage = 15
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
+ playsound(src, 'sound/items/Welder.ogg', 100, 1)
src.health -= damage
src.healthcheck()
@@ -545,16 +546,4 @@
/obj/effect/alien/egg/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > 500 + T0C)
health -= 5
- healthcheck()
-/*
-/obj/effect/alien/egg/HasProximity(atom/movable/AM as mob|obj)
- if(status == GROWN)
- if(!CanHug(AM))
- return
-
- var/mob/living/carbon/C = AM
- if(C.stat == CONSCIOUS && C.status_flags & XENO_HOST)
- return
-
- Burst(0)
-*/
\ No newline at end of file
+ healthcheck()
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/contraband.dm b/code/game/objects/effects/decals/contraband.dm
index 6ac967fc00..f533a2da60 100644
--- a/code/game/objects/effects/decals/contraband.dm
+++ b/code/game/objects/effects/decals/contraband.dm
@@ -146,7 +146,7 @@
/obj/structure/sign/poster/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(W.is_wirecutter())
- playsound(src.loc, W.usesound, 100, 1)
+ playsound(src, W.usesound, 100, 1)
if(ruined)
to_chat(user, "You remove the remnants of the poster.")
qdel(src)
@@ -166,7 +166,7 @@
return
visible_message("[user] rips [src] in a single, decisive motion!" )
- playsound(src.loc, 'sound/items/poster_ripped.ogg', 100, 1)
+ playsound(src, 'sound/items/poster_ripped.ogg', 100, 1)
ruined = 1
icon_state = "poster_ripped"
name = "ripped poster"
diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm
index 00896e7107..15931b5868 100644
--- a/code/game/objects/effects/effect_system.dm
+++ b/code/game/objects/effects/effect_system.dm
@@ -98,7 +98,7 @@ steam.start() -- spawns the effect
/obj/effect/effect/sparks/New()
..()
- playsound(src.loc, "sparks", 100, 1)
+ playsound(src, "sparks", 100, 1)
var/turf/T = src.loc
if (istype(T, /turf))
T.hotspot_expose(1000,100)
@@ -113,12 +113,11 @@ steam.start() -- spawns the effect
T.hotspot_expose(1000,100)
return ..()
-/obj/effect/effect/sparks/Move()
- ..()
- var/turf/T = src.loc
- if (istype(T, /turf))
+/obj/effect/effect/sparks/Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
+ if(isturf(loc))
+ var/turf/T = loc
T.hotspot_expose(1000,100)
- return
/datum/effect/effect/system/spark_spread
var/total_sparks = 0 // To stop it being spammed and lagging!
@@ -225,8 +224,8 @@ steam.start() -- spawns the effect
time_to_live = 600
//var/list/projectiles
-/obj/effect/effect/smoke/bad/Move()
- ..()
+/obj/effect/effect/smoke/bad/Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
for(var/mob/living/L in get_turf(src))
affect(L)
@@ -281,8 +280,8 @@ steam.start() -- spawns the effect
STOP_PROCESSING(SSobj, src)
return ..()
-/obj/effect/effect/smoke/elemental/Move()
- ..()
+/obj/effect/effect/smoke/elemental/Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
for(var/mob/living/L in range(1, src))
affect(L)
diff --git a/code/game/objects/effects/explosion_particles.dm b/code/game/objects/effects/explosion_particles.dm
index 63b2a09c24..12a1e92020 100644
--- a/code/game/objects/effects/explosion_particles.dm
+++ b/code/game/objects/effects/explosion_particles.dm
@@ -12,10 +12,6 @@
qdel(src)
return
-/obj/effect/expl_particles/Move()
- ..()
- return
-
/datum/effect/system/expl_particles
var/number = 10
var/turf/location
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index f2a15be551..1497e4e7a0 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -61,7 +61,7 @@
panel_open = !panel_open
user.visible_message("[user] very carefully screws the mine's panel [panel_open ? "open" : "closed"].",
"You very carefully screw the mine's panel [panel_open ? "open" : "closed"].")
- playsound(src.loc, W.usesound, 50, 1)
+ playsound(src, W.usesound, 50, 1)
else if((W.is_wirecutter() || istype(W, /obj/item/device/multitool)) && panel_open)
interact(user)
@@ -224,7 +224,7 @@
msg_admin_attack("[key_name_admin(user)] primed \a [src]")
user.visible_message("[user] starts priming \the [src.name].", "You start priming \the [src.name]. Hold still!")
if(do_after(user, 10 SECONDS))
- playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3)
+ playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
prime(user)
else
visible_message("[user] triggers \the [src.name]!", "You accidentally trigger \the [src.name]!")
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 2254696e4a..dc3a151686 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -94,6 +94,8 @@
var/drop_sound = 'sound/items/drop/device.ogg' // drop sound - this is the default
+ var/tip_timer // reference to timer id for a tooltip we might open soon
+
/obj/item/New()
..()
if(embed_chance < 0)
@@ -339,7 +341,7 @@ var/list/global/slot_flags_enumeration = list(
//If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen.
//Set disable_warning to 1 if you wish it to not give you outputs.
//Should probably move the bulk of this into mob code some time, as most of it is related to the definition of slots and not item-specific
-/obj/item/proc/mob_can_equip(M as mob, slot, disable_warning = 0)
+/obj/item/proc/mob_can_equip(M as mob, slot, disable_warning = FALSE)
if(!slot) return 0
if(!M) return 0
@@ -506,7 +508,7 @@ var/list/global/slot_flags_enumeration = list(
var/hit_zone = get_zone_with_miss_chance(U.zone_sel.selecting, M, U.get_accuracy_penalty(U))
if(!hit_zone)
U.do_attack_animation(M)
- playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
+ playsound(src, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
//visible_message("[U] attempts to stab [M] in the eyes, but misses!")
for(var/mob/V in viewers(M))
V.show_message("[U] attempts to stab [M] in the eyes, but misses!")
@@ -602,19 +604,24 @@ var/list/global/slot_flags_enumeration = list(
blood_DNA[M.dna.unique_enzymes] = M.dna.b_type
return 1 //we applied blood to the item
-
+GLOBAL_LIST_EMPTY(blood_overlays_by_type)
/obj/item/proc/generate_blood_overlay()
+ // Already got one
if(blood_overlay)
return
+
+ // Already cached
+ if(GLOB.blood_overlays_by_type[type])
+ blood_overlay = GLOB.blood_overlays_by_type[type]
+ return
- var/icon/I = new /icon(icon, icon_state)
- I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD) //fills the icon_state with white (except where it's transparent)
- I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY) //adds blood and the remaining white areas become transparant
-
- //not sure if this is worth it. It attaches the blood_overlay to every item of the same type if they don't have one already made.
- for(var/obj/item/A in world)
- if(A.type == type && !A.blood_overlay)
- A.blood_overlay = image(I)
+ // Firsties!
+ var/image/blood = image(icon = 'icons/effects/blood.dmi', icon_state = "itemblood") // Needs to be a new one each time since we're slicing it up with filters.
+ blood.filters += filter(type = "alpha", icon = icon(icon, icon_state)) // Same, this filter is unique for each blood overlay per type
+ GLOB.blood_overlays_by_type[type] = blood
+
+ // And finally
+ blood_overlay = blood
/obj/item/proc/showoff(mob/user)
for (var/mob/M in view(user))
@@ -665,6 +672,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
H.toggle_zoom_hud() // If the user has already limited their HUD this avoids them having a HUD when they zoom in
H.set_viewsize(viewsize)
zoom = 1
+ GLOB.moved_event.register(H, src, .proc/zoom)
var/tilesize = 32
var/viewoffset = tilesize * tileoffset
@@ -693,6 +701,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
if(!H.hud_used.hud_shown)
H.toggle_zoom_hud()
zoom = 0
+ GLOB.moved_event.unregister(H, src, .proc/zoom)
H.client.pixel_x = 0
H.client.pixel_y = 0
@@ -875,4 +884,18 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
return FALSE
/obj/item/proc/is_welder()
- return FALSE
\ No newline at end of file
+ return FALSE
+
+/obj/item/MouseEntered(location,control,params)
+ . = ..()
+ if(usr.is_preference_enabled(/datum/client_preference/inv_tooltips) && ((src in usr) || isstorage(loc))) // If in inventory or in storage we're looking at
+ var/user = usr
+ tip_timer = addtimer(CALLBACK(src, .proc/openTip, location, control, params, user), 5, TIMER_STOPPABLE)
+
+/obj/item/MouseExited()
+ . = ..()
+ deltimer(tip_timer)
+ closeToolTip(usr)
+
+/obj/item/proc/openTip(location, control, params, user)
+ openToolTip(user, src, params, title = name, content = desc)
diff --git a/code/game/objects/items/bells.dm b/code/game/objects/items/bells.dm
index af9d7ce0f8..c05c7d2686 100644
--- a/code/game/objects/items/bells.dm
+++ b/code/game/objects/items/bells.dm
@@ -19,7 +19,7 @@
/obj/item/weapon/deskbell/attack(mob/target as mob, mob/living/user as mob)
if(!broken)
- playsound(user.loc, 'sound/effects/deskbell.ogg', 50, 1)
+ playsound(src, 'sound/effects/deskbell.ogg', 50, 1)
..()
/obj/item/weapon/deskbell/attack_hand(mob/user)
@@ -61,12 +61,12 @@
/obj/item/weapon/deskbell/proc/ring(mob/user)
if(user.a_intent == "harm")
- playsound(user.loc, 'sound/effects/deskbell_rude.ogg', 50, 1)
+ playsound(src, 'sound/effects/deskbell_rude.ogg', 50, 1)
to_chat(user,"You hammer [src] rudely!")
if (prob(2))
break_bell(user)
else
- playsound(user.loc, 'sound/effects/deskbell.ogg', 50, 1)
+ playsound(src, 'sound/effects/deskbell.ogg', 50, 1)
to_chat(user,"You gracefully ring [src].")
/obj/item/weapon/deskbell/proc/check_ability(mob/user)
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index 8f89c2c074..cf32e30c90 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -330,7 +330,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/ai/attack_self(mob/user as mob)
if ((honkamt > 0) && (prob(60)))//For clown virus.
honkamt--
- playsound(loc, 'sound/items/bikehorn.ogg', 30, 1)
+ playsound(src, 'sound/items/bikehorn.ogg', 30, 1)
return
@@ -774,7 +774,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
scanmode = 4
if("Honk")
if ( !(last_honk && world.time < last_honk + 20) )
- playsound(loc, 'sound/items/bikehorn.ogg', 50, 1)
+ playsound(src, 'sound/items/bikehorn.ogg', 50, 1)
last_honk = world.time
if("Gas Scan")
if(scanmode == 5)
@@ -983,7 +983,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
if ((honkamt > 0) && (prob(60)))//For clown virus.
honkamt--
- playsound(loc, 'sound/items/bikehorn.ogg', 30, 1)
+ playsound(src, 'sound/items/bikehorn.ogg', 30, 1)
return 1 // return 1 tells it to refresh the UI in NanoUI
@@ -1020,14 +1020,14 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/datum/effect/effect/system/smoke_spread/chem/S = new /datum/effect/effect/system/smoke_spread/chem
S.attach(P.loc)
S.set_up(P, 10, 0, P.loc)
- playsound(P.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
+ playsound(P, 'sound/effects/smoke.ogg', 50, 1, -3)
S.start()
message += "Large clouds of smoke billow forth from your [P]!"
if(i>=40 && i<=45) //Bad smoke
var/datum/effect/effect/system/smoke_spread/bad/B = new /datum/effect/effect/system/smoke_spread/bad
B.attach(P.loc)
B.set_up(P, 10, 0, P.loc)
- playsound(P.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
+ playsound(P, 'sound/effects/smoke.ogg', 50, 1, -3)
B.start()
message += "Large clouds of noxious smoke billow forth from your [P]!"
if(i>=65 && i<=75) //Weaken
@@ -1064,7 +1064,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/mob/M = loc
M.put_in_hands(id)
to_chat(usr, "You remove the ID from the [name].")
- playsound(loc, 'sound/machines/id_swipe.ogg', 100, 1)
+ playsound(src, 'sound/machines/id_swipe.ogg', 100, 1)
else
id.loc = get_turf(src)
id = null
@@ -1133,7 +1133,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
conversations.Add("\ref[P]")
if(!P.conversations.Find("\ref[src]"))
P.conversations.Add("\ref[src]")
-
+ to_chat(U, "[bicon(src)] Sent message to [P.owner] ([P.ownjob]), \"[t]\"")
if (prob(15)) //Give the AI a chance of intercepting the message
var/who = src.owner
@@ -1151,7 +1151,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/proc/new_info(var/beep_silent, var/message_tone, var/reception_message)
if (!beep_silent)
- playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
+ playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
for (var/mob/O in hearers(2, loc))
O.show_message(text("[bicon(src)] *[message_tone]*"))
//Search for holder of the PDA.
@@ -1280,7 +1280,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
if (cartridge.radio)
cartridge.radio.hostpda = null
to_chat(usr, "You remove \the [cartridge] from the [name].")
- playsound(loc, 'sound/machines/id_swipe.ogg', 100, 1)
+ playsound(src, 'sound/machines/id_swipe.ogg', 100, 1)
cartridge = null
/obj/item/device/pda/proc/id_check(mob/user as mob, choice as num)//To check for IDs; 1 for in-pda use, 2 for out of pda use.
diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm
index 627145a38f..d6f42bee8f 100644
--- a/code/game/objects/items/devices/chameleonproj.dm
+++ b/code/game/objects/items/devices/chameleonproj.dm
@@ -31,7 +31,7 @@
if(!proximity) return
if(!active_dummy)
if(istype(target,/obj/item) && !istype(target, /obj/item/weapon/disk/nuclear))
- playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1, -6)
+ playsound(src, 'sound/weapons/flash.ogg', 100, 1, -6)
to_chat(user, "Scanned [target].")
saved_item = target.type
saved_icon = target.icon
@@ -42,7 +42,7 @@
if(!can_use || !saved_item) return
if(active_dummy)
eject_all()
- playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6)
+ playsound(src, 'sound/effects/pop.ogg', 100, 1, -6)
qdel(active_dummy)
active_dummy = null
to_chat(usr, "You deactivate the [src].")
@@ -51,7 +51,7 @@
flick("emppulse",T)
spawn(8) qdel(T)
else
- playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6)
+ playsound(src, 'sound/effects/pop.ogg', 100, 1, -6)
var/obj/O = new saved_item(src)
if(!O) return
var/obj/effect/dummy/chameleon/C = new /obj/effect/dummy/chameleon(usr.loc)
diff --git a/code/game/objects/items/devices/communicator/messaging.dm b/code/game/objects/items/devices/communicator/messaging.dm
index c6191ab21e..2b4e0bcdd4 100644
--- a/code/game/objects/items/devices/communicator/messaging.dm
+++ b/code/game/objects/items/devices/communicator/messaging.dm
@@ -76,7 +76,7 @@
return
if(ringer)
- playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
+ playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
for (var/mob/O in hearers(2, loc))
O.show_message(text("[bicon(src)] *beep*"))
diff --git a/code/game/objects/items/devices/communicator/phone.dm b/code/game/objects/items/devices/communicator/phone.dm
index 492cd84179..3f13df8825 100644
--- a/code/game/objects/items/devices/communicator/phone.dm
+++ b/code/game/objects/items/devices/communicator/phone.dm
@@ -161,7 +161,7 @@
voice_requests |= candidate
if(ringer)
- playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
+ playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
for (var/mob/O in hearers(2, loc))
O.show_message(text("[bicon(src)] *beep*"))
diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm
index dbb1410ef9..a53a6e00c7 100644
--- a/code/game/objects/items/devices/defib.dm
+++ b/code/game/objects/items/devices/defib.dm
@@ -380,23 +380,21 @@
// This proc is used so that we can return out of the revive process while ensuring that busy and update_icon() are handled
/obj/item/weapon/shockpaddles/proc/do_revive(mob/living/carbon/human/H, mob/user)
- if(!H.client && !H.teleop)
- for(var/mob/observer/dead/ghost in player_list)
- if(ghost.mind == H.mind)
- ghost.notify_revive("Someone is trying to resuscitate you. Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg')
- break
+ var/mob/observer/dead/ghost = H.get_ghost()
+ if(ghost)
+ ghost.notify_revive("Someone is trying to resuscitate you. Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg', source = src)
//beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
user.visible_message("\The [user] begins to place [src] on [H]'s chest.", "You begin to place [src] on [H]'s chest...")
if(!do_after(user, 30, H))
return
user.visible_message("\The [user] places [src] on [H]'s chest.", "You place [src] on [H]'s chest.")
- playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
+ playsound(src, 'sound/machines/defib_charge.ogg', 50, 0)
var/error = can_defib(H)
if(error)
make_announcement(error, "warning")
- playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
+ playsound(src, 'sound/machines/defib_failed.ogg', 50, 0)
return
if(check_blood_level(H))
@@ -409,18 +407,18 @@
//deduct charge here, in case the base unit was EMPed or something during the delay time
if(!checked_use(chargecost))
make_announcement("buzzes, \"Insufficient charge.\"", "warning")
- playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
+ playsound(src, 'sound/machines/defib_failed.ogg', 50, 0)
return
H.visible_message("\The [H]'s body convulses a bit.")
- playsound(get_turf(src), "bodyfall", 50, 1)
- playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
+ playsound(src, "bodyfall", 50, 1)
+ playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1)
set_cooldown(cooldowntime)
error = can_revive(H)
if(error)
make_announcement(error, "warning")
- playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
+ playsound(src, 'sound/machines/defib_failed.ogg', 50, 0)
return
H.apply_damage(burn_damage_amt, BURN, BP_TORSO)
@@ -434,7 +432,7 @@
H.adjustToxLoss(-H.getToxLoss())
make_announcement("pings, \"Resuscitation successful.\"", "notice")
- playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0)
+ playsound(src, 'sound/machines/defib_success.ogg', 50, 0)
make_alive(H)
@@ -455,7 +453,7 @@
to_chat(user, "You can't do that while the safety is enabled.")
return
- playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
+ playsound(src, 'sound/machines/defib_charge.ogg', 50, 0)
audible_message("\The [src] lets out a steadily rising hum...")
if(!do_after(user, chargetime, H))
@@ -464,12 +462,12 @@
//deduct charge here, in case the base unit was EMPed or something during the delay time
if(!checked_use(chargecost))
make_announcement("buzzes, \"Insufficient charge.\"", "warning")
- playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
+ playsound(src, 'sound/machines/defib_failed.ogg', 50, 0)
return
user.visible_message("\The [user] shocks [H] with \the [src]!", "You shock [H] with \the [src]!")
- playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 100, 1, -1)
- playsound(loc, 'sound/weapons/Egloves.ogg', 100, 1, -1)
+ playsound(src, 'sound/machines/defib_zap.ogg', 100, 1, -1)
+ playsound(src, 'sound/weapons/Egloves.ogg', 100, 1, -1)
set_cooldown(cooldowntime)
H.stun_effect_act(2, 120, target_zone)
@@ -543,10 +541,10 @@
safety = new_safety
if(safety)
make_announcement("beeps, \"Safety protocols enabled!\"", "notice")
- playsound(get_turf(src), 'sound/machines/defib_safetyon.ogg', 50, 0)
+ playsound(src, 'sound/machines/defib_safetyon.ogg', 50, 0)
else
make_announcement("beeps, \"Safety protocols disabled!\"", "warning")
- playsound(get_turf(src), 'sound/machines/defib_safetyoff.ogg', 50, 0)
+ playsound(src, 'sound/machines/defib_safetyoff.ogg', 50, 0)
update_icon()
..()
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index 6c512650b6..91915c8c07 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -48,7 +48,7 @@
user.visible_message("\The [user] successfully repairs \the [src]!")
broken = FALSE
update_icon()
- playsound(src.loc, W.usesound, 50, 1)
+ playsound(src, W.usesound, 50, 1)
else
user.visible_message("\The [user] fails to repair \the [src].")
repairing = FALSE
@@ -138,7 +138,7 @@
if(user)
update_icon()
to_chat(user, "click")
- playsound(src.loc, 'sound/weapons/empty.ogg', 80, 1)
+ playsound(src, 'sound/weapons/empty.ogg', 80, 1)
return FALSE
else if(battery && battery.checked_use(charge_cost + (round(charge_cost / 4) * max(0, times_used - max_flashes)))) // Using over your maximum flashes starts taking more charge per added flash.
times_used++
@@ -164,7 +164,7 @@
if(!check_capacitor(user))
return
- playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
+ playsound(src, 'sound/weapons/flash.ogg', 100, 1)
var/flashfail = 0
if(iscarbon(M))
@@ -245,7 +245,7 @@
if(!check_capacitor(user))
return
- playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
+ playsound(src, 'sound/weapons/flash.ogg', 100, 1)
flick("flash2", src)
if(user && isrobot(user))
spawn(0)
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 5246e6f3c3..c908f30e17 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -20,24 +20,19 @@
/obj/item/device/flashlight/Initialize()
. = ..()
- update_icon()
-
-/obj/item/device/flashlight/New()
- if(power_use)
- START_PROCESSING(SSobj, src)
-
- if(cell_type)
- cell = new cell_type(src)
- brightness_levels = list("low" = 0.25, "medium" = 0.5, "high" = 1)
- power_usage = brightness_levels[brightness_level]
+ if(power_use && cell_type)
+ cell = new cell_type(src)
+ brightness_levels = list("low" = 0.25, "medium" = 0.5, "high" = 1)
+ power_usage = brightness_levels[brightness_level]
else
verbs -= /obj/item/device/flashlight/verb/toggle
- ..()
+
+ update_icon()
/obj/item/device/flashlight/Destroy()
- if(power_use)
- STOP_PROCESSING(SSobj, src)
+ STOP_PROCESSING(SSobj, src)
+ qdel_null(cell)
return ..()
/obj/item/device/flashlight/get_cell()
@@ -58,18 +53,17 @@
update_icon()
/obj/item/device/flashlight/process()
- if(on)
- if(cell)
- if(brightness_level && power_usage)
- if(power_usage < cell.charge)
- cell.charge -= power_usage
- else
- cell.charge = 0
- visible_message("\The [src] flickers before going dull.")
- set_light(0)
- playsound(src.loc, 'sound/effects/sparks3.ogg', 10, 1, -3) //Small cue that your light went dull in your pocket.
- on = 0
- update_icon()
+ if(!on || !cell)
+ return PROCESS_KILL
+
+ if(brightness_level && power_usage)
+ if(cell.use(power_usage) != power_usage) // we weren't able to use our full power_usage amount!
+ visible_message("\The [src] flickers before going dull.")
+ set_light(0)
+ playsound(src.loc, 'sound/effects/sparks3.ogg', 10, 1, -3) //Small cue that your light went dull in your pocket.
+ on = 0
+ update_icon()
+ return PROCESS_KILL
/obj/item/device/flashlight/update_icon()
if(on)
@@ -111,6 +105,10 @@
to_chat(user, "You flick the switch on [src], but nothing happens.")
return 0
on = !on
+ if(on && power_use)
+ START_PROCESSING(SSobj, src)
+ else if(power_use)
+ STOP_PROCESSING(SSobj, src)
playsound(src.loc, 'sound/weapons/empty.ogg', 15, 1, -3)
update_icon()
user.update_action_buttons()
diff --git a/code/game/objects/items/devices/geiger.dm b/code/game/objects/items/devices/geiger.dm
index b9b177e683..62c1f7d1ed 100644
--- a/code/game/objects/items/devices/geiger.dm
+++ b/code/game/objects/items/devices/geiger.dm
@@ -13,7 +13,6 @@
var/datum/looping_sound/geiger/soundloop
/obj/item/device/geiger/Initialize()
- START_PROCESSING(SSobj, src)
soundloop = new(list(src), FALSE)
return ..()
@@ -60,6 +59,10 @@
/obj/item/device/geiger/attack_self(var/mob/user)
scanning = !scanning
+ if(scanning)
+ START_PROCESSING(SSobj, src)
+ else
+ STOP_PROCESSING(SSobj, src)
update_icon()
update_sound()
to_chat(user, "[bicon(src)] You switch [scanning ? "on" : "off"] \the [src].")
diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm
index 562ed56990..095f565bd4 100644
--- a/code/game/objects/items/devices/gps.dm
+++ b/code/game/objects/items/devices/gps.dm
@@ -59,11 +59,11 @@ var/list/GPS_list = list()
visible_message("\The [src] appears to be functional again.")
/obj/item/device/gps/update_icon()
- overlays.Cut()
+ cut_overlays()
if(emped)
- overlays += image(icon, src, "emp")
+ add_overlay("emp")
else if(tracking)
- overlays += image(icon, src, "working")
+ add_overlay("working")
/obj/item/device/gps/attack_self(mob/user)
display(user)
@@ -89,6 +89,8 @@ var/list/GPS_list = list()
continue
var/turf/T = get_turf(G)
+ if(!T)
+ continue
if(local_mode && curr.z != T.z)
continue
if(!(T.z in dat["z_level_detection"]))
@@ -183,6 +185,13 @@ var/list/GPS_list = list()
/obj/item/device/gps/security/on
tracking = TRUE
+/obj/item/device/gps/security/hos
+ icon_state = "gps-sec-hos"
+ gps_tag = "HOS0"
+
+/obj/item/device/gps/security/hos/on
+ tracking = TRUE
+
/obj/item/device/gps/medical
icon_state = "gps-med"
gps_tag = "MED0"
@@ -190,6 +199,13 @@ var/list/GPS_list = list()
/obj/item/device/gps/medical/on
tracking = TRUE
+/obj/item/device/gps/medical/cmo
+ icon_state = "gps-med-cmo"
+ gps_tag = "CMO0"
+
+/obj/item/device/gps/medical/cmo/on
+ tracking = TRUE
+
/obj/item/device/gps/science
icon_state = "gps-sci"
gps_tag = "SCI0"
@@ -197,6 +213,13 @@ var/list/GPS_list = list()
/obj/item/device/gps/science/on
tracking = TRUE
+/obj/item/device/gps/science/rd
+ icon_state = "gps-sci-rd"
+ gps_tag = "RD0"
+
+/obj/item/device/gps/science/rd/on
+ tracking = TRUE
+
/obj/item/device/gps/engineering
icon_state = "gps-eng"
gps_tag = "ENG0"
@@ -204,6 +227,20 @@ var/list/GPS_list = list()
/obj/item/device/gps/engineering/on
tracking = TRUE
+/obj/item/device/gps/engineering/atmos
+ icon_state = "gps-eng-atm"
+ gps_tag = "ATM0"
+
+/obj/item/device/gps/engineering/atmos/on
+ tracking = TRUE
+
+/obj/item/device/gps/engineering/ce
+ icon_state = "gps-eng-ce"
+ gps_tag = "CE0"
+
+/obj/item/device/gps/engineering/ce/on
+ tracking = TRUE
+
/obj/item/device/gps/mining
icon_state = "gps-mine"
gps_tag = "MINE0"
diff --git a/code/game/objects/items/devices/hacktool.dm b/code/game/objects/items/devices/hacktool.dm
index 0b6d25f0c9..a48a3da024 100644
--- a/code/game/objects/items/devices/hacktool.dm
+++ b/code/game/objects/items/devices/hacktool.dm
@@ -26,7 +26,7 @@
/obj/item/device/multitool/hacktool/attackby(var/obj/item/W, var/mob/user)
if(W.is_screwdriver())
in_hack_mode = !in_hack_mode
- playsound(src.loc, W.usesound, 50, 1)
+ playsound(src, W.usesound, 50, 1)
else
..()
diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm
index 3ce7a0b236..6ae95bcf8a 100644
--- a/code/game/objects/items/devices/lightreplacer.dm
+++ b/code/game/objects/items/devices/lightreplacer.dm
@@ -96,7 +96,7 @@
new_bulbs += AddShards(1)
qdel(L)
if(new_bulbs != 0)
- playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
+ playsound(src, 'sound/machines/ding.ogg', 50, 1)
to_chat(user, "You insert \the [L.name] into \the [src.name]. You have [uses] light\s remaining.")
return
@@ -148,7 +148,7 @@
/obj/item/device/lightreplacer/proc/Use(var/mob/user)
- playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
+ playsound(src, 'sound/machines/click.ogg', 50, 1)
add_uses(-1)
return 1
@@ -182,7 +182,7 @@
var/new_bulbs = AddShards(1)
if(new_bulbs != 0)
to_chat(U, "\The [src] has fabricated a new bulb from the broken bulbs it has stored. It now has [uses] uses.")
- playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
+ playsound(src, 'sound/machines/ding.ogg', 50, 1)
target.status = LIGHT_EMPTY
target.update()
@@ -211,7 +211,7 @@
/obj/item/device/lightreplacer/emag_act(var/remaining_charges, var/mob/user)
emagged = !emagged
- playsound(src.loc, "sparks", 100, 1)
+ playsound(src, "sparks", 100, 1)
update_icon()
return 1
diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm
index 7e7bbdb629..5516ccb099 100644
--- a/code/game/objects/items/devices/megaphone.dm
+++ b/code/game/objects/items/devices/megaphone.dm
@@ -134,7 +134,7 @@
user.audible_message("[user.GetVoice()][user.GetAltName()] broadcasts, \"[pick(insultmsg)]\"")
if(broadcast_size >= 11)
var/turf/T = get_turf(user)
- playsound(T, 'sound/items/AirHorn.ogg', 100, 1)
+ playsound(src, 'sound/items/AirHorn.ogg', 100, 1)
for(var/mob/living/carbon/M in oviewers(4, T))
if(M.get_ear_protection() >= 2)
continue
diff --git a/code/game/objects/items/devices/modkit.dm b/code/game/objects/items/devices/modkit.dm
index 6847bb6fb0..820229fd83 100644
--- a/code/game/objects/items/devices/modkit.dm
+++ b/code/game/objects/items/devices/modkit.dm
@@ -47,7 +47,7 @@
to_chat(user, "[O] must be safely placed on the ground for modification.")
return
- playsound(src.loc, O.usesound, 100, 1)
+ playsound(src, O.usesound, 100, 1)
user.visible_message("\The [user] opens \the [src] and modifies \the [O].","You open \the [src] and modify \the [O].")
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 06a7314f32..5303113441 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -10,9 +10,20 @@
flags = NOBLOODY
var/circuit = /obj/item/weapon/circuitboard/intercom
var/number = 0
- var/last_tick //used to delay the powercheck
var/wiresexposed = 0
+/obj/item/device/radio/intercom/Initialize()
+ . = ..()
+ var/area/A = get_area(src)
+ if(A)
+ GLOB.apc_event.register(A, src, /obj/update_icon)
+
+/obj/item/device/radio/intercom/Destroy()
+ var/area/A = get_area(src)
+ if(A)
+ GLOB.apc_event.unregister(A, src, /obj/update_icon)
+ return ..()
+
/obj/item/device/radio/intercom/custom
name = "station intercom (Custom)"
broadcasting = 0
@@ -59,7 +70,6 @@
/obj/item/device/radio/intercom/New()
..()
- START_PROCESSING(SSobj, src)
circuit = new circuit(src)
/obj/item/device/radio/intercom/department/medbay/New()
@@ -102,10 +112,6 @@
..()
internal_channels[num2text(RAID_FREQ)] = list(access_syndicate)
-/obj/item/device/radio/intercom/Destroy()
- STOP_PROCESSING(SSobj, src)
- return ..()
-
/obj/item/device/radio/intercom/attack_ai(mob/user as mob)
src.add_fingerprint(user)
spawn (0)
@@ -122,15 +128,8 @@
wiresexposed = !wiresexposed
to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]")
playsound(src, W.usesound, 50, 1)
- if(wiresexposed)
- if(!on)
- icon_state = "intercom-p_open"
- else
- icon_state = "intercom_open"
- else
- icon_state = "intercom"
- return
- if(wiresexposed && W.is_wirecutter())
+ update_icon()
+ else if(wiresexposed && W.is_wirecutter())
user.visible_message("[user] has cut the wires inside \the [src]!", "You have cut the wires inside \the [src].")
playsound(src, W.usesound, 50, 1)
new/obj/item/stack/cable_coil(get_turf(src), 5)
@@ -148,7 +147,6 @@
qdel(src)
else
src.attack_hand(user)
- return
/obj/item/device/radio/intercom/receive_range(freq, level)
if (!on)
@@ -165,29 +163,20 @@
return canhear_range
-/obj/item/device/radio/intercom/process()
- if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0))
- last_tick = world.timeofday
+/obj/item/device/radio/intercom/update_icon()
+ var/area/A = get_area(src)
+ on = A?.powered(EQUIP)
- if(!src.loc)
- on = 0
+ if(!on)
+ if(wiresexposed)
+ icon_state = "intercom-p_open"
else
- var/area/A = get_area(src)
- if(!A)
- on = 0
- else
- on = A.powered(EQUIP) // set "on" to the power status
-
- if(!on)
- if(wiresexposed)
- icon_state = "intercom-p_open"
- else
- icon_state = "intercom-p"
+ icon_state = "intercom-p"
+ else
+ if(wiresexposed)
+ icon_state = "intercom_open"
else
- if(wiresexposed)
- icon_state = "intercom_open"
- else
- icon_state = initial(icon_state)
+ icon_state = initial(icon_state)
/obj/item/device/radio/intercom/locked
var/locked_frequency
diff --git a/code/game/objects/items/devices/suit_cooling.dm b/code/game/objects/items/devices/suit_cooling.dm
index 8c8a208db8..0c097295bb 100644
--- a/code/game/objects/items/devices/suit_cooling.dm
+++ b/code/game/objects/items/devices/suit_cooling.dm
@@ -28,14 +28,17 @@
/obj/item/device/suit_cooling_unit/ui_action_click()
toggle(usr)
-/obj/item/device/suit_cooling_unit/New()
- START_PROCESSING(SSobj, src)
- cell = new/obj/item/weapon/cell/high() //comes not with the crappy default power cell - because this is dedicated EVA equipment
- cell.loc = src
+/obj/item/device/suit_cooling_unit/Initialize()
+ . = ..()
+ cell = new/obj/item/weapon/cell/high(src) //comes not with the crappy default power cell - because this is dedicated EVA equipment
+
+/obj/item/device/suit_cooling_unit/Destroy()
+ qdel_null(cell)
+ return ..()
/obj/item/device/suit_cooling_unit/process()
if (!on || !cell)
- return
+ return PROCESS_KILL
if (!ismob(loc))
return
@@ -106,11 +109,13 @@
return
on = 1
+ START_PROCESSING(SSobj, src)
updateicon()
/obj/item/device/suit_cooling_unit/proc/turn_off(var/failed)
if(failed) visible_message("\The [src] clicks and whines as it powers down.")
on = 0
+ STOP_PROCESSING(SSobj, src)
updateicon()
/obj/item/device/suit_cooling_unit/attack_self(var/mob/user)
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index 7a9b07b999..3ddc35a209 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -50,7 +50,7 @@ effective or pretty fucking useless.
add_attack_logs(user,affected,"Used a [name]")
- playsound(src.loc, 'sound/misc/interference.ogg', 50, 1)
+ playsound(src, 'sound/misc/interference.ogg', 50, 1)
to_chat(user, "You trigger [src].")
times_used += 1
if(times_used >= max_uses)
diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm
index 4169dfc947..406919f96a 100644
--- a/code/game/objects/items/devices/transfer_valve.dm
+++ b/code/game/objects/items/devices/transfer_valve.dm
@@ -9,7 +9,6 @@
var/mob/attacher = null
var/valve_open = 0
var/toggle = 1
- flags = PROXMOVE
/obj/item/device/transfer_valve/attackby(obj/item/item, mob/user)
var/turf/location = get_turf(src) // For admin logs
@@ -57,11 +56,15 @@
return
-/obj/item/device/transfer_valve/HasProximity(atom/movable/AM as mob|obj)
- if(!attached_device) return
- attached_device.HasProximity(AM)
- return
+/obj/item/device/transfer_valve/HasProximity(turf/T, atom/movable/AM, old_loc)
+ attached_device?.HasProximity(T, AM, old_loc)
+/obj/item/device/transfer_valve/Moved(old_loc, direction, forced)
+ . = ..()
+ if(isturf(old_loc))
+ unsense_proximity(callback = .HasProximity, center = old_loc)
+ if(isturf(loc))
+ sense_proximity(callback = .HasProximity)
/obj/item/device/transfer_valve/attack_self(mob/user as mob)
ui_interact(user)
diff --git a/code/game/objects/items/devices/whistle.dm b/code/game/objects/items/devices/whistle.dm
index c26d3f80aa..cf8cebeec1 100644
--- a/code/game/objects/items/devices/whistle.dm
+++ b/code/game/objects/items/devices/whistle.dm
@@ -32,11 +32,11 @@
return
if(isnull(insults))
- playsound(get_turf(src), 'sound/voice/halt.ogg', 100, 1, vary = 0)
+ playsound(src, 'sound/voice/halt.ogg', 100, 1, vary = 0)
user.audible_message("[user]'s [name] rasps, \"[use_message]\"", "\The [user] holds up \the [name].")
else
if(insults > 0)
- playsound(get_turf(src), 'sound/voice/binsult.ogg', 100, 1, vary = 0)
+ playsound(src, 'sound/voice/binsult.ogg', 100, 1, vary = 0)
// Yes, it used to show the transcription of the sound clip. That was a) inaccurate b) immature as shit.
user.audible_message("[user]'s [name] gurgles something indecipherable and deeply offensive.", "\The [user] holds up \the [name].")
insults--
diff --git a/code/game/objects/items/paintkit.dm b/code/game/objects/items/paintkit.dm
index a0bebc699f..223c9a2018 100644
--- a/code/game/objects/items/paintkit.dm
+++ b/code/game/objects/items/paintkit.dm
@@ -16,7 +16,7 @@
/obj/item/device/kit/proc/use(var/amt, var/mob/user)
uses -= amt
- playsound(get_turf(user), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
if(uses<1)
user.drop_item()
qdel(src)
@@ -157,6 +157,7 @@
/obj/item/device/kit/suit/rig/customize(var/obj/item/I, var/mob/user)
var/obj/item/weapon/rig/RIG = I
RIG.suit_state = new_icon
+ RIG.item_state = new_icon
RIG.suit_type = "customized [initial(RIG.suit_type)]"
RIG.name = "[new_name]"
RIG.desc = new_desc
@@ -170,17 +171,17 @@
piece.desc = "It seems to be part of a [RIG.name]."
piece.icon_state = "[RIG.suit_state]"
if(istype(piece, /obj/item/clothing/shoes))
- icon = 'icons/mob/custom_items_rig_boots.dmi'
- icon_override = 'icons/mob/custom_items_rig_boots.dmi'
+ piece.icon = 'icons/mob/custom_items_rig_boots.dmi'
+ piece.icon_override = 'icons/mob/custom_items_rig_boots.dmi'
if(istype(piece, /obj/item/clothing/suit))
- icon = 'icons/mob/custom_items_rig_suit.dmi'
- icon_override = 'icons/mob/custom_items_rig_suit.dmi'
+ piece.icon = 'icons/mob/custom_items_rig_suit.dmi'
+ piece.icon_override = 'icons/mob/custom_items_rig_suit.dmi'
if(istype(piece, /obj/item/clothing/head))
- icon = 'icons/mob/custom_items_rig_helmet.dmi'
- icon_override = 'icons/mob/custom_items_rig_helmet.dmi'
+ piece.icon = 'icons/mob/custom_items_rig_helmet.dmi'
+ piece.icon_override = 'icons/mob/custom_items_rig_helmet.dmi'
if(istype(piece, /obj/item/clothing/gloves))
- icon = 'icons/mob/custom_items_rig_gloves.dmi'
- icon_override = 'icons/mob/custom_items_rig_gloves.dmi'
+ piece.icon = 'icons/mob/custom_items_rig_gloves.dmi'
+ piece.icon_override = 'icons/mob/custom_items_rig_gloves.dmi'
if(RIG.helmet && istype(RIG.helmet, /obj/item/clothing/head/helmet) && new_light_overlay)
var/obj/item/clothing/head/helmet/H = RIG.helmet
H.light_overlay = new_light_overlay
@@ -196,6 +197,9 @@
return
return ..()
+/obj/item/device/kit/suit/rig/debug/Initialize()
+ set_info("debug suit", "This is a test", "debug", CUSTOM_ITEM_OBJ, CUSTOM_ITEM_MOB)
+
/obj/item/device/kit/paint
name = "mecha customisation kit"
desc = "A kit containing all the needed tools and parts to repaint a mech."
diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm
index c3bc83d3b9..982236f43c 100644
--- a/code/game/objects/items/shooting_range.dm
+++ b/code/game/objects/items/shooting_range.dm
@@ -18,12 +18,12 @@
break
..() // delete target
- Move()
- ..()
+ Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
// After target moves, check for nearby stakes. If associated, move to target
for(var/obj/structure/target_stake/M in view(3,src))
if(M.density == 0 && M.pinned_target == src)
- M.loc = loc
+ M.forceMove(loc)
// This may seem a little counter-intuitive but I assure you that's for a purpose.
// Stakes are the ones that carry targets, yes, but in the stake code we set
diff --git a/code/game/objects/items/stacks/marker_beacons.dm b/code/game/objects/items/stacks/marker_beacons.dm
index 88eb8e6271..5c7ed3aa04 100644
--- a/code/game/objects/items/stacks/marker_beacons.dm
+++ b/code/game/objects/items/stacks/marker_beacons.dm
@@ -58,7 +58,7 @@ var/list/marker_beacon_colors = list(
return
if(use(1))
to_chat(user, "You activate and anchor [amount ? "a":"the"] [singular_name] in place.")
- playsound(user, 'sound/machines/click.ogg', 50, 1)
+ playsound(src, 'sound/machines/click.ogg', 50, 1)
var/obj/structure/marker_beacon/M = new(user.loc, picked_color)
transfer_fingerprints_to(M)
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 80f7f5ba41..2cb4e1863b 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -24,6 +24,11 @@
to_chat(user, "You don't have the dexterity to do this!")
return 1
+ var/available = get_amount()
+ if(!available)
+ to_chat(user, "There's not enough [uses_charge ? "charge" : "items"] left to use that!")
+ return 1
+
if (istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
@@ -101,11 +106,12 @@
to_chat(user, "The wounds on [M]'s [affecting.name] have already been bandaged.")
return 1
else
+ var/available = get_amount()
user.visible_message("\The [user] starts bandaging [M]'s [affecting.name].", \
"You start bandaging [M]'s [affecting.name]." )
var/used = 0
for (var/datum/wound/W in affecting.wounds)
- if (W.internal)
+ if(W.internal)
continue
if(W.bandaged)
continue
@@ -119,6 +125,10 @@
to_chat(user, "The wounds on [M]'s [affecting.name] have already been bandaged.")
return 1
+ if(used >= available)
+ to_chat(user, "You run out of [src]!")
+ break
+
if (W.current_stage <= W.max_bleeding_stage)
user.visible_message("\The [user] bandages \a [W.desc] on [M]'s [affecting.name].", \
"You bandage \a [W.desc] on [M]'s [affecting.name]." )
@@ -164,6 +174,7 @@
to_chat(user, "The wounds on [M]'s [affecting.name] have already been bandaged.")
return 1
else
+ var/available = get_amount()
user.visible_message("\The [user] starts treating [M]'s [affecting.name].", \
"You start treating [M]'s [affecting.name]." )
var/used = 0
@@ -182,6 +193,10 @@
to_chat(user, "The wounds on [M]'s [affecting.name] have already been bandaged.")
return 1
+ if(used >= available)
+ to_chat(user, "You run out of [src]!")
+ break
+
if (W.current_stage <= W.max_bleeding_stage)
user.visible_message("\The [user] bandages \a [W.desc] on [M]'s [affecting.name].", \
"You bandage \a [W.desc] on [M]'s [affecting.name]." )
@@ -271,6 +286,7 @@
to_chat(user, "The wounds on [M]'s [affecting.name] have already been treated.")
return 1
else
+ var/available = get_amount()
user.visible_message("\The [user] starts treating [M]'s [affecting.name].", \
"You start treating [M]'s [affecting.name]." )
var/used = 0
@@ -287,6 +303,11 @@
if(affecting.is_bandaged() && affecting.is_disinfected()) // We do a second check after the delay, in case it was bandaged after the first check.
to_chat(user, "The wounds on [M]'s [affecting.name] have already been bandaged.")
return 1
+
+ if(used >= available)
+ to_chat(user, "You run out of [src]!")
+ break
+
if (W.current_stage <= W.max_bleeding_stage)
user.visible_message("\The [user] cleans \a [W.desc] on [M]'s [affecting.name] and seals the edges with bioglue.", \
"You clean and seal \a [W.desc] on [M]'s [affecting.name]." )
diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm
index 255a739d84..ad3e349ba7 100644
--- a/code/game/objects/items/stacks/sheets/leather.dm
+++ b/code/game/objects/items/stacks/sheets/leather.dm
@@ -1,4 +1,4 @@
-/obj/item/stack/material/animalhide/human
+/obj/item/stack/animalhide/human
name = "human skin"
desc = "The by-product of human farming."
singular_name = "human skin piece"
@@ -6,63 +6,63 @@
no_variants = FALSE
drop_sound = 'sound/items/drop/clothing.ogg'
-/obj/item/stack/material/animalhide/human
+/obj/item/stack/animalhide/human
amount = 50
-/obj/item/stack/material/animalhide/corgi
+/obj/item/stack/animalhide/corgi
name = "corgi hide"
desc = "The by-product of corgi farming."
singular_name = "corgi hide piece"
icon_state = "sheet-corgi"
-/obj/item/stack/material/animalhide/corgi
+/obj/item/stack/animalhide/corgi
amount = 50
-/obj/item/stack/material/animalhide/cat
+/obj/item/stack/animalhide/cat
name = "cat hide"
desc = "The by-product of cat farming."
singular_name = "cat hide piece"
icon_state = "sheet-cat"
-/obj/item/stack/material/animalhide/cat
+/obj/item/stack/animalhide/cat
amount = 50
-/obj/item/stack/material/animalhide/monkey
+/obj/item/stack/animalhide/monkey
name = "monkey hide"
desc = "The by-product of monkey farming."
singular_name = "monkey hide piece"
icon_state = "sheet-monkey"
-/obj/item/stack/material/animalhide/monkey
+/obj/item/stack/animalhide/monkey
amount = 50
-/obj/item/stack/material/animalhide/lizard
+/obj/item/stack/animalhide/lizard
name = "lizard skin"
desc = "Sssssss..."
singular_name = "lizard skin piece"
icon_state = "sheet-lizard"
-/obj/item/stack/material/animalhide/lizard
+/obj/item/stack/animalhide/lizard
amount = 50
-/obj/item/stack/material/animalhide/xeno
+/obj/item/stack/animalhide/xeno
name = "alien hide"
desc = "The skin of a terrible creature."
singular_name = "alien hide piece"
icon_state = "sheet-xeno"
-/obj/item/stack/material/animalhide/xeno
+/obj/item/stack/animalhide/xeno
amount = 50
//don't see anywhere else to put these, maybe together they could be used to make the xenos suit?
-/obj/item/stack/material/xenochitin
+/obj/item/stack/xenochitin
name = "alien chitin"
desc = "A piece of the hide of a terrible creature."
singular_name = "alien hide piece"
icon = 'icons/mob/alien.dmi'
icon_state = "chitin"
-/obj/item/stack/material/xenochitin
+/obj/item/stack/xenochitin
amount = 50
/obj/item/xenos_claw
@@ -77,17 +77,17 @@
icon = 'icons/mob/alien.dmi'
icon_state = "weed_extract"
-/obj/item/stack/material/hairlesshide
+/obj/item/stack/hairlesshide
name = "hairless hide"
desc = "This hide was stripped of it's hair, but still needs tanning."
singular_name = "hairless hide piece"
icon_state = "sheet-hairlesshide"
no_variants = FALSE
-/obj/item/stack/material/hairlesshide
+/obj/item/stack/hairlesshide
amount = 50
-/obj/item/stack/material/wetleather
+/obj/item/stack/wetleather
name = "wet leather"
desc = "This leather has been cleaned but still needs to be dried."
singular_name = "wet leather piece"
@@ -96,11 +96,11 @@
var/drying_threshold_temperature = 500 //Kelvin to start drying
no_variants = FALSE
-/obj/item/stack/material/wetleather
+/obj/item/stack/wetleather
amount = 50
//Step one - dehairing.
-/obj/item/stack/material/animalhide/attackby(obj/item/weapon/W as obj, mob/user as mob)
+/obj/item/stack/animalhide/attackby(obj/item/weapon/W as obj, mob/user as mob)
if( istype(W, /obj/item/weapon/material/knife) || \
istype(W, /obj/item/weapon/material/twohanded/fireaxe) || \
istype(W, /obj/item/weapon/material/knife/machete/hatchet) )
@@ -110,13 +110,13 @@
if(do_after(user,50))
to_chat(usr, "You cut the hair from this [src.singular_name]")
//Try locating an exisitng stack on the tile and add to there if possible
- for(var/obj/item/stack/material/hairlesshide/HS in usr.loc)
+ for(var/obj/item/stack/hairlesshide/HS in usr.loc)
if(HS.amount < 50)
HS.amount++
src.use(1)
break
//If it gets to here it means it did not find a suitable stack on the tile.
- var/obj/item/stack/material/hairlesshide/HS = new(usr.loc)
+ var/obj/item/stack/hairlesshide/HS = new(usr.loc)
HS.amount = 1
src.use(1)
else
@@ -126,7 +126,7 @@
//Step two - washing..... it's actually in washing machine code.
//Step three - drying
-/obj/item/stack/material/wetleather/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+/obj/item/stack/wetleather/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
if(exposed_temperature >= drying_threshold_temperature)
wetness--
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 7e89f96807..eb432d63c1 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -181,7 +181,7 @@
bullets--
D.icon_state = "foamdart"
D.name = "foam dart"
- playsound(user.loc, 'sound/items/syringeproj.ogg', 50, 1)
+ playsound(src, 'sound/items/syringeproj.ogg', 50, 1)
for(var/i=0, i<6, i++)
if (D)
@@ -229,7 +229,7 @@
O.show_message(text("\The [] casually lines up a shot with []'s head and pulls the trigger!", user, M), 1, "You hear the sound of foam against skull", 2)
O.show_message(text("\The [] was hit in the head by the foam dart!", M), 1)
- playsound(user.loc, 'sound/items/syringeproj.ogg', 50, 1)
+ playsound(src, 'sound/items/syringeproj.ogg', 50, 1)
new /obj/item/toy/ammo/crossbow(M.loc)
src.bullets--
else if (M.lying && src.bullets == 0)
@@ -278,12 +278,12 @@
src.active = !( src.active )
if (src.active)
to_chat(user, "You extend the plastic blade with a quick flick of your wrist.")
- playsound(user, 'sound/weapons/saberon.ogg', 50, 1)
+ playsound(src, 'sound/weapons/saberon.ogg', 50, 1)
src.item_state = "[icon_state]_blade"
src.w_class = ITEMSIZE_LARGE
else
to_chat(user, "You push the plastic blade back down into the handle.")
- playsound(user, 'sound/weapons/saberoff.ogg', 50, 1)
+ playsound(src, 'sound/weapons/saberoff.ogg', 50, 1)
src.item_state = "[icon_state]"
src.w_class = ITEMSIZE_SMALL
update_icon()
@@ -397,7 +397,7 @@
/obj/item/toy/bosunwhistle/attack_self(mob/user as mob)
if(cooldown < world.time - 35)
to_chat(user, "You blow on [src], creating an ear-splitting noise!")
- playsound(user, 'sound/misc/boatswain.ogg', 20, 1)
+ playsound(src, 'sound/misc/boatswain.ogg', 20, 1)
cooldown = world.time
/*
@@ -413,14 +413,14 @@
/obj/item/toy/prize/attack_self(mob/user as mob)
if(cooldown < world.time - 8)
to_chat(user, "You play with [src].")
- playsound(user, 'sound/mecha/mechstep.ogg', 20, 1)
+ playsound(src, 'sound/mecha/mechstep.ogg', 20, 1)
cooldown = world.time
/obj/item/toy/prize/attack_hand(mob/user as mob)
if(loc == user)
if(cooldown < world.time - 8)
to_chat(user, "You play with [src].")
- playsound(user, 'sound/mecha/mechturn.ogg', 20, 1)
+ playsound(src, 'sound/mecha/mechturn.ogg', 20, 1)
cooldown = world.time
return
..()
@@ -499,7 +499,7 @@
if(cooldown < world.time)
cooldown = (world.time + 30) //3 second cooldown
user.visible_message("The [src] says \"[toysay]\".")
- playsound(user, 'sound/machines/click.ogg', 20, 1)
+ playsound(src, 'sound/machines/click.ogg', 20, 1)
/obj/item/toy/figure/cmo
name = "Chief Medical Officer action figure"
@@ -753,12 +753,12 @@
// Attack mob
/obj/item/toy/plushie/carp/attack(mob/M as mob, mob/user as mob)
- playsound(loc, bitesound, 20, 1) // Play bite sound in local area
+ playsound(src, bitesound, 20, 1) // Play bite sound in local area
return ..()
// Attack self
/obj/item/toy/plushie/carp/attack_self(mob/user as mob)
- playsound(src.loc, bitesound, 20, 1)
+ playsound(src, bitesound, 20, 1)
return ..()
@@ -1371,7 +1371,7 @@
if(!cooldown) //for the sanity of everyone
var/message = generate_ion_law()
to_chat(user, "You press the button on [src].")
- playsound(user, 'sound/machines/click.ogg', 20, 1)
+ playsound(src, 'sound/machines/click.ogg', 20, 1)
visible_message("[message]")
cooldown = 1
spawn(30) cooldown = 0
@@ -1390,7 +1390,7 @@
if(!cooldown) //for the sanity of everyone
var/message = pick("You won't get away this time, Griffin!", "Stop right there, criminal!", "Hoot! Hoot!", "I am the night!")
to_chat(user, "You pull the string on the [src].")
- //playsound(user, 'sound/misc/hoot.ogg', 25, 1)
+ //playsound(src, 'sound/misc/hoot.ogg', 25, 1)
visible_message("[message]")
cooldown = 1
spawn(30) cooldown = 0
@@ -1409,7 +1409,7 @@
if(!cooldown) //for the sanity of everyone
var/message = pick("You can't stop me, Owl!", "My plan is flawless! The vault is mine!", "Caaaawwww!", "You will never catch me!")
to_chat(user, "You pull the string on the [src].")
- //playsound(user, 'sound/misc/caw.ogg', 25, 1)
+ //playsound(src, 'sound/misc/caw.ogg', 25, 1)
visible_message("[message]")
cooldown = 1
spawn(30) cooldown = 0
diff --git a/code/game/objects/items/uav.dm b/code/game/objects/items/uav.dm
new file mode 100644
index 0000000000..2b323e4898
--- /dev/null
+++ b/code/game/objects/items/uav.dm
@@ -0,0 +1,348 @@
+#define UAV_OFF 0
+#define UAV_ON 1
+#define UAV_PAIRING 2
+#define UAV_PACKED 3
+
+/obj/item/device/uav
+ name = "recon skimmer"
+ desc = "A semi-portable reconnaissance drone that folds into a backpack-sized carrying case."
+ icon = 'icons/obj/uav.dmi'
+ icon_state = "uav"
+
+ var/obj/item/weapon/cell/cell
+ var/cell_type = null //Can put a starting cell here
+
+ density = 1 //Is dense, but not anchored, so you can swap with it
+ slowdown = 3 //Heevvee.
+
+ health = 100
+ var/power_per_process = 50 // About 6.5 minutes of use on a high-cell (10,000)
+ var/state = UAV_OFF
+
+ var/datum/effect/effect/system/ion_trail_follow/ion_trail
+
+ var/list/mob/living/masters
+
+ // So you know which is which
+ var/nickname = "Generic Droan"
+
+ // Radial menu
+ var/static/image/radial_pickup = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_pickup")
+ var/static/image/radial_wrench = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_wrench")
+ var/static/image/radial_power = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_power")
+ var/static/image/radial_pair = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_pair")
+
+ // Movement cooldown
+ var/next_move = 0
+
+ // Idle shutdown time
+ var/no_masters_time = 0
+
+/obj/item/device/uav/loaded
+ cell_type = /obj/item/weapon/cell/high
+
+/obj/item/device/uav/Initialize()
+ . = ..()
+
+ if(!cell && cell_type)
+ cell = new cell_type
+
+ ion_trail = new /datum/effect/effect/system/ion_trail_follow()
+ ion_trail.set_up(src)
+ ion_trail.stop()
+
+/obj/item/device/uav/Destroy()
+ qdel_null(cell)
+ qdel_null(ion_trail)
+ LAZYCLEARLIST(masters)
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/obj/item/device/uav/attack_hand(var/mob/user)
+ //Has to be on the ground to work with it properly
+ if(!isturf(loc))
+ return ..()
+
+ var/list/options = list(
+ "Pick Up" = radial_pickup,
+ "(Dis)Assemble" = radial_wrench,
+ "Toggle Power" = radial_power,
+ "Pairing Mode" = radial_pair)
+ var/choice = show_radial_menu(user, src, options, require_near = !issilicon(user))
+
+ switch(choice)
+ // Can pick up when off or packed
+ if("Pick Up")
+ if(state == UAV_OFF || state == UAV_PACKED)
+ return ..()
+ else
+ to_chat(user,"Turn [nickname] off or pack it first!")
+ return
+ // Can disasemble or reassemble from packed or off (and this one takes time)
+ if("(Dis)Assemble")
+ if(can_transition_to(state == UAV_PACKED ? UAV_OFF : UAV_PACKED, user) && do_after(user, 10 SECONDS, src))
+ return toggle_packed(user)
+ // Can toggle power from on and off
+ if("Toggle Power")
+ if(can_transition_to(state == UAV_ON ? UAV_OFF : UAV_ON, user))
+ return toggle_power(user)
+ // Can pair when off
+ if("Pairing Mode")
+ if(can_transition_to(state == UAV_PAIRING ? UAV_OFF : UAV_PAIRING, user))
+ return toggle_pairing(user)
+
+/obj/item/device/uav/attackby(var/obj/item/I, var/mob/user)
+ if(istype(I, /obj/item/modular_computer) && state == UAV_PAIRING)
+ var/obj/item/modular_computer/MC = I
+ LAZYDISTINCTADD(MC.paired_uavs, weakref(src))
+ playsound(src, 'sound/machines/buttonbeep.ogg', 50, 1)
+ visible_message("[user] pairs [I] to [nickname]")
+ toggle_pairing()
+
+ else if(I.is_screwdriver() && cell)
+ if(do_after(user, 3 SECONDS, src))
+ to_chat(user, "You remove [cell] into [nickname].")
+ playsound(src, I.usesound, 50, 1)
+ power_down()
+ cell.forceMove(get_turf(src))
+ cell = null
+
+ else if(istype(I, /obj/item/weapon/cell) && !cell)
+ if(do_after(user, 3 SECONDS, src))
+ to_chat(user, "You insert [I] into [nickname].")
+ playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
+ power_down()
+ user.remove_from_mob(I)
+ I.forceMove(src)
+ cell = I
+
+ else if(istype(I, /obj/item/weapon/pen) || istype(I, /obj/item/device/flashlight/pen))
+ var/tmp_label = sanitizeSafe(input(user, "Enter a nickname for [src]", "Nickname", nickname), MAX_NAME_LEN)
+ if(length(tmp_label) > 50 || length(tmp_label) < 3)
+ to_chat(user, "The nickname must be between 3 and 50 characters.")
+ else
+ to_chat(user, "You scribble your new nickname on the side of [src].")
+ nickname = tmp_label
+ desc = initial(desc) + " This one has '[nickname]' scribbled on the side."
+ else
+ return ..()
+
+/obj/item/device/uav/proc/can_transition_to(var/new_state, var/mob/user)
+ switch(state) //Current one
+ if(UAV_ON)
+ if(new_state == UAV_OFF || new_state == UAV_PACKED)
+ . = TRUE
+ if(UAV_OFF)
+ if(new_state == UAV_ON || new_state == UAV_PACKED || new_state == UAV_PAIRING)
+ . = TRUE
+ if(UAV_PAIRING)
+ if(new_state == UAV_OFF)
+ . = TRUE
+ if(UAV_PACKED)
+ if(new_state == UAV_OFF)
+ . = TRUE
+
+ if(!.)
+ if(user)
+ to_chat(user, "You can't do that while [nickname] is in this state.")
+ return FALSE
+
+/obj/item/device/uav/update_icon()
+ cut_overlays()
+ switch(state)
+ if(UAV_PAIRING)
+ add_overlay("[initial(icon_state)]_pairing")
+ icon_state = "[initial(icon_state)]"
+ if(UAV_ON)
+ icon_state = "[initial(icon_state)]_on"
+ if(UAV_OFF)
+ icon_state = "[initial(icon_state)]"
+ if(UAV_PACKED)
+ icon_state = "[initial(icon_state)]_packed"
+
+/obj/item/device/uav/process()
+ if(cell?.use(power_per_process) != power_per_process)
+ visible_message("[src] sputters and thuds to the ground, inert.")
+ playsound(src, 'sound/items/drop/metalboots.ogg', 75, 1)
+ power_down()
+ health -= initial(health)*0.25 //Lose 25% of your original health
+
+ if(LAZYLEN(masters))
+ no_masters_time = 0
+ else if(no_masters_time++ > 50)
+ power_down()
+
+/obj/item/device/uav/proc/toggle_pairing()
+ switch(state)
+ if(UAV_PAIRING)
+ state = UAV_OFF
+ update_icon()
+ return TRUE
+ if(UAV_OFF)
+ state = UAV_PAIRING
+ update_icon()
+ return TRUE
+ return FALSE
+
+/obj/item/device/uav/proc/toggle_power()
+ switch(state)
+ if(UAV_OFF)
+ power_up()
+ return TRUE
+ if(UAV_ON)
+ power_down()
+ return TRUE
+ return FALSE
+
+/obj/item/device/uav/proc/toggle_packed()
+ if(UAV_ON)
+ power_down()
+ switch(state)
+ if(UAV_OFF) //Packing
+ state = UAV_PACKED
+ w_class = ITEMSIZE_LARGE
+ slowdown = 1
+ density = FALSE
+ update_icon()
+ return TRUE
+ if(UAV_PACKED) //Unpacking
+ state = UAV_OFF
+ w_class = ITEMSIZE_HUGE
+ slowdown = 3
+ density = TRUE
+ update_icon()
+ return TRUE
+ return FALSE
+
+/obj/item/device/uav/proc/power_up()
+ if(state != UAV_OFF || !isturf(loc))
+ return
+ if(cell?.use(power_per_process) != power_per_process)
+ visible_message("[src] sputters and chugs as it tries, and fails, to power up.")
+ return
+
+ state = UAV_ON
+ update_icon()
+ start_hover()
+ set_light(4, 4, "#FFFFFF")
+ START_PROCESSING(SSobj, src)
+ no_masters_time = 0
+ visible_message("[nickname] buzzes and lifts into the air.")
+
+/obj/item/device/uav/proc/power_down()
+ if(state != UAV_ON)
+ return
+
+ state = UAV_OFF
+ update_icon()
+ stop_hover()
+ set_light(0)
+ LAZYCLEARLIST(masters)
+ STOP_PROCESSING(SSobj, src)
+ visible_message("[nickname] gracefully settles onto the ground.")
+
+//////////////// Helpers
+/obj/item/device/uav/get_cell()
+ return cell
+
+/obj/item/device/uav/relaymove(var/mob/user, direction, signal = 1)
+ if(signal && state == UAV_ON && (weakref(user) in masters))
+ if(next_move <= world.time)
+ next_move = world.time + (1 SECOND/signal)
+ step(src, direction)
+ return TRUE // Even if we couldn't step, we're taking credit for absorbing the move
+ return FALSE
+
+/obj/item/device/uav/proc/get_status_string()
+ return "[nickname] - [get_x(src)],[get_y(src)],[get_z(src)] - I:[health]/[initial(health)] - C:[cell ? "[cell.charge]/[cell.maxcharge]" : "Not Installed"]"
+
+/obj/item/device/uav/proc/add_master(var/mob/living/M)
+ LAZYDISTINCTADD(masters, weakref(M))
+
+/obj/item/device/uav/proc/remove_master(var/mob/living/M)
+ LAZYREMOVE(masters, weakref(M))
+
+/obj/item/device/uav/check_eye()
+ if(state == UAV_ON)
+ return 0
+ else
+ return -1
+
+/obj/item/device/uav/proc/start_hover()
+ if(!ion_trail.on) //We'll just use this to store if we're floating or not
+ ion_trail.start()
+ var/amplitude = 2 //maximum displacement from original position
+ var/period = 36 //time taken for the mob to go up >> down >> original position, in deciseconds. Should be multiple of 4
+
+ var/top = old_y + amplitude
+ var/bottom = old_y - amplitude
+ var/half_period = period / 2
+ var/quarter_period = period / 4
+
+ animate(src, pixel_y = top, time = quarter_period, easing = SINE_EASING | EASE_OUT, loop = -1) //up
+ animate(pixel_y = bottom, time = half_period, easing = SINE_EASING, loop = -1) //down
+ animate(pixel_y = old_y, time = quarter_period, easing = SINE_EASING | EASE_IN, loop = -1) //back
+
+/obj/item/device/uav/proc/stop_hover()
+ if(ion_trail.on)
+ ion_trail.stop()
+ animate(src, pixel_y = old_y, time = 5, easing = SINE_EASING | EASE_IN) //halt animation
+
+/obj/item/device/uav/hear_talk(var/mob/M, list/message_pieces, verb)
+ var/name_used = M.GetVoice()
+ for(var/wr_master in masters)
+ var/weakref/wr = wr_master
+ var/mob/master = wr.resolve()
+ var/message = master.combine_message(message_pieces, verb, M)
+ var/rendered = "UAV received: [name_used] [message]"
+ master.show_message(rendered, 2)
+
+/obj/item/device/uav/see_emote(var/mob/living/M, text)
+ for(var/wr_master in masters)
+ var/weakref/wr = wr_master
+ var/mob/master = wr.resolve()
+ var/rendered = "UAV received, [text]"
+ master.show_message(rendered, 2)
+
+/obj/item/device/uav/show_message(msg, type, alt, alt_type)
+ for(var/wr_master in masters)
+ var/weakref/wr = wr_master
+ var/mob/master = wr.resolve()
+ var/rendered = "UAV received, [msg]"
+ master.show_message(rendered, type)
+
+/obj/item/device/uav/take_damage(var/damage)
+ health -= damage
+ CheckHealth()
+ return
+
+/obj/item/device/uav/attack_generic(var/mob/user, var/damage, var/attack_verb)
+ visible_message("[user] [attack_verb] the [src]!")
+ playsound(src, 'sound/weapons/smash.ogg', 50, 1)
+ user.do_attack_animation(src)
+ health -= damage
+ CheckHealth()
+ return
+
+/obj/item/device/uav/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ die()
+ if(2.0)
+ health -= 25
+ CheckHealth()
+
+/obj/item/device/uav/proc/CheckHealth()
+ if(health <= 0)
+ die()
+
+/obj/item/device/uav/proc/die()
+ visible_message("[src] shorts out and explodes!")
+ power_down()
+ var/turf/T = get_turf(src)
+ qdel(src)
+ explosion(T, -1, 0, 1, 2) //Not very large
+
+#undef UAV_OFF
+#undef UAV_ON
+#undef UAV_PACKED
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm
index bafe4878f9..2dbd4aa082 100644
--- a/code/game/objects/items/weapons/RCD.dm
+++ b/code/game/objects/items/weapons/RCD.dm
@@ -57,7 +57,7 @@
stored_matter += cartridge.remaining
user.drop_from_inventory(W)
qdel(W)
- playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
+ playsound(src, 'sound/machines/click.ogg', 50, 1)
to_chat(user, span("notice", "The RCD now holds [stored_matter]/[max_stored_matter] matter-units."))
return TRUE
return ..()
@@ -70,7 +70,7 @@
mode_index++
to_chat(user, span("notice", "Changed mode to '[modes[mode_index]]'."))
- playsound(src.loc, 'sound/effects/pop.ogg', 50, 0)
+ playsound(src, 'sound/effects/pop.ogg', 50, 0)
if(prob(20))
src.spark_system.start()
@@ -106,7 +106,7 @@
to_chat(user, span("warning", "\The [src] lacks the required material to start."))
return FALSE
- playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
+ playsound(src, 'sound/machines/click.ogg', 50, 1)
var/true_delay = rcd_results[RCD_VALUE_DELAY] * toolspeed
@@ -126,7 +126,7 @@
return FALSE
if(A.rcd_act(user, src, rcd_results[RCD_VALUE_MODE]))
consume_resources(rcd_results[RCD_VALUE_COST])
- playsound(get_turf(A), 'sound/items/deconstruct.ogg', 50, 1)
+ playsound(A, 'sound/items/deconstruct.ogg', 50, 1)
return TRUE
// If they moved, kill the beam immediately.
diff --git a/code/game/objects/items/weapons/RSF.dm b/code/game/objects/items/weapons/RSF.dm
index 724e85e1f6..3059e5af7f 100644
--- a/code/game/objects/items/weapons/RSF.dm
+++ b/code/game/objects/items/weapons/RSF.dm
@@ -48,7 +48,7 @@ RSF
qdel(W)
stored_matter += 10
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
+ playsound(src, 'sound/machines/click.ogg', 10, 1)
to_chat(user,"The RSF now holds [stored_matter]/30 fabrication-units.")
return
@@ -64,7 +64,7 @@ RSF
glasstype = /obj/item/weapon/reagent_containers/food/drinks/metaglass
/obj/item/weapon/rsf/attack_self(mob/user as mob)
- playsound(src.loc, 'sound/effects/pop.ogg', 50, 0)
+ playsound(src, 'sound/effects/pop.ogg', 50, 0)
if (mode == 1)
mode = 2
to_chat(user,"Changed dispensing mode to 'Container'.")
@@ -101,7 +101,7 @@ RSF
if(!istype(A, /obj/structure/table) && !istype(A, /turf/simulated/floor))
return
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
+ playsound(src, 'sound/machines/click.ogg', 10, 1)
var/used_energy = 0
var/obj/product
diff --git a/code/game/objects/items/weapons/canes.dm b/code/game/objects/items/weapons/canes.dm
index f7688fb2d1..5b7f346684 100644
--- a/code/game/objects/items/weapons/canes.dm
+++ b/code/game/objects/items/weapons/canes.dm
@@ -33,7 +33,7 @@
if(concealed_blade)
user.visible_message("[user] has unsheathed \a [concealed_blade] from [T.his] [src]!", "You unsheathe \the [concealed_blade] from \the [src].")
// Calling drop/put in hands to properly call item drop/pickup procs
- playsound(user.loc, 'sound/weapons/holster/sheathout.ogg', 50, 1)
+ playsound(src, 'sound/weapons/holster/sheathout.ogg', 50, 1)
user.drop_from_inventory(src)
user.put_in_hands(concealed_blade)
user.put_in_hands(src)
@@ -47,7 +47,7 @@
if(!src.concealed_blade && istype(W))
var/datum/gender/T = gender_datums[user.get_visible_gender()]
user.visible_message("[user] has sheathed \a [W] into [T.his] [src]!", "You sheathe \the [W] into \the [src].")
- playsound(user.loc, 'sound/weapons/holster/sheathin.ogg', 50, 1)
+ playsound(src, 'sound/weapons/holster/sheathin.ogg', 50, 1)
user.drop_from_inventory(W)
W.loc = src
src.concealed_blade = W
@@ -119,6 +119,6 @@
H.update_inv_l_hand()
H.update_inv_r_hand()
- playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1)
+ playsound(src, 'sound/weapons/empty.ogg', 50, 1)
add_fingerprint(user)
return TRUE
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm
index b6952198bd..46f9a34f4d 100644
--- a/code/game/objects/items/weapons/cigs_lighters.dm
+++ b/code/game/objects/items/weapons/cigs_lighters.dm
@@ -193,7 +193,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/clothing/mask/smokable/proc/die(var/nomessage = 0)
var/turf/T = get_turf(src)
set_light(0)
- playsound(src.loc, 'sound/items/cigs_lighters/cig_snuff.ogg', 50, 1)
+ playsound(src, 'sound/items/cigs_lighters/cig_snuff.ogg', 50, 1)
STOP_PROCESSING(SSobj, src)
if (type_butt)
var/obj/item/butt = new type_butt(T)
@@ -215,7 +215,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
var/mob/living/M = loc
if (!nomessage)
to_chat(M, "Your [name] goes out, and you empty the ash.")
- playsound(src.loc, 'sound/items/cigs_lighters/cig_snuff.ogg', 50, 1)
+ playsound(src, 'sound/items/cigs_lighters/cig_snuff.ogg', 50, 1)
lit = 0
icon_state = initial(icon_state)
item_state = initial(item_state)
@@ -333,7 +333,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(lit == 1)
if(user.a_intent == I_HURT)
user.visible_message("[user] drops and treads on the lit [src], putting it out instantly.")
- playsound(src.loc, 'sound/items/cigs_lighters/cig_snuff.ogg', 50, 1)
+ playsound(src, 'sound/items/cigs_lighters/cig_snuff.ogg', 50, 1)
die(1)
else
user.visible_message("[user] puts out \the [src].")
@@ -427,7 +427,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(lit == 1)
if(user.a_intent == I_HURT)
user.visible_message("[user] empties the lit [src] on the floor!.")
- playsound(src.loc, 'sound/items/cigs_lighters/cig_snuff.ogg', 50, 1)
+ playsound(src, 'sound/items/cigs_lighters/cig_snuff.ogg', 50, 1)
die(1)
else
user.visible_message("[user] puts out \the [src].")
@@ -552,7 +552,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
lit = 1
icon_state = "[base_state]on"
item_state = "[base_state]on"
- playsound(src.loc, activation_sound, 75, 1)
+ playsound(src, activation_sound, 75, 1)
if(istype(src, /obj/item/weapon/flame/lighter/zippo) )
user.visible_message("Without even breaking stride, [user] flips open and lights [src] in one smooth movement.")
else
@@ -572,7 +572,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
lit = 0
icon_state = "[base_state]"
item_state = "[base_state]"
- playsound(src.loc, deactivation_sound, 75, 1)
+ playsound(src, deactivation_sound, 75, 1)
if(istype(src, /obj/item/weapon/flame/lighter/zippo) )
user.visible_message("You hear a quiet click, as [user] shuts off [src] without even looking at what they're doing.")
else
diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm
index 1f53e64e77..73604b49f9 100644
--- a/code/game/objects/items/weapons/clown_items.dm
+++ b/code/game/objects/items/weapons/clown_items.dm
@@ -71,7 +71,7 @@
/obj/item/weapon/bikehorn/attack_self(mob/user as mob)
if (spam_flag == 0)
spam_flag = 1
- playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1)
+ playsound(src, 'sound/items/bikehorn.ogg', 50, 1)
src.add_fingerprint(user)
spawn(20)
spam_flag = 0
diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm
index 5e7b54c9eb..e9951c83d4 100644
--- a/code/game/objects/items/weapons/extinguisher.dm
+++ b/code/game/objects/items/weapons/extinguisher.dm
@@ -75,7 +75,7 @@
var/obj/o = target
var/amount = o.reagents.trans_to_obj(src, 50)
to_chat(user, "You fill [src] with [amount] units of the contents of [target].")
- playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 50, 1, -6)
return
if (!safety)
@@ -88,7 +88,7 @@
src.last_use = world.time
- playsound(src.loc, 'sound/effects/extinguish.ogg', 75, 1, -3)
+ playsound(src, 'sound/effects/extinguish.ogg', 75, 1, -3)
var/direction = get_dir(src,target)
diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm
index 94ca8b7cd2..88d9b0ff5d 100644
--- a/code/game/objects/items/weapons/gift_wrappaper.dm
+++ b/code/game/objects/items/weapons/gift_wrappaper.dm
@@ -27,7 +27,7 @@
/obj/item/weapon/gift/attack_self(mob/user as mob)
user.drop_item()
- playsound(src.loc, 'sound/items/package_unwrap.ogg', 50,1)
+ playsound(src, 'sound/items/package_unwrap.ogg', 50,1)
if(src.gift)
user.put_in_active_hand(gift)
src.gift.add_fingerprint(user)
diff --git a/code/game/objects/items/weapons/grenades/anti_photon_grenade.dm b/code/game/objects/items/weapons/grenades/anti_photon_grenade.dm
index 6646e698f9..fe4d80418d 100644
--- a/code/game/objects/items/weapons/grenades/anti_photon_grenade.dm
+++ b/code/game/objects/items/weapons/grenades/anti_photon_grenade.dm
@@ -7,7 +7,7 @@
origin_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 4)
/obj/item/weapon/grenade/anti_photon/detonate()
- playsound(src.loc, 'sound/effects/phasein.ogg', 50, 1, 5)
+ playsound(src, 'sound/effects/phasein.ogg', 50, 1, 5)
set_light(10, -10, "#FFFFFF")
var/extra_delay = rand(0,90)
@@ -18,5 +18,5 @@
set_light(10, 10, "#[num2hex(rand(64,255))][num2hex(rand(64,255))][num2hex(rand(64,255))]")
spawn(210)
..()
- playsound(src.loc, 'sound/effects/bang.ogg', 50, 1, 5)
+ playsound(src, 'sound/effects/bang.ogg', 50, 1, 5)
qdel(src)
diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm
index 157c64f09f..cb3184a7f6 100644
--- a/code/game/objects/items/weapons/grenades/chem_grenade.dm
+++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm
@@ -63,7 +63,7 @@
return
path = 1
to_chat(user, "You add [W] to the metal casing.")
- playsound(src.loc, 'sound/items/Screwdriver2.ogg', 25, -3)
+ playsound(src, 'sound/items/Screwdriver2.ogg', 25, -3)
user.remove_from_mob(det)
det.loc = src
detonator = det
@@ -96,7 +96,7 @@
return
else
to_chat(user, "You unlock the assembly.")
- playsound(src.loc, W.usesound, 50, -3)
+ playsound(src, W.usesound, 50, -3)
name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
icon_state = initial(icon_state) + (detonator?"_ass":"")
stage = 1
@@ -154,7 +154,7 @@
active = 0
if(!has_reagents)
icon_state = initial(icon_state) +"_locked"
- playsound(src.loc, 'sound/items/Screwdriver2.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver2.ogg', 50, 1)
spawn(0) //Otherwise det_time is erroneously set to 0 after this
if(istimer(detonator.a_left)) //Make sure description reflects that the timer has been reset
var/obj/item/device/assembly/timer/T = detonator.a_left
@@ -164,7 +164,7 @@
det_time = 10*T.time
return
- playsound(src.loc, 'sound/effects/bamf.ogg', 50, 1)
+ playsound(src, 'sound/effects/bamf.ogg', 50, 1)
for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
G.reagents.trans_to_obj(src, G.reagents.total_volume)
diff --git a/code/game/objects/items/weapons/grenades/concussion.dm b/code/game/objects/items/weapons/grenades/concussion.dm
index 073b5ed9d1..fb821ab6f8 100644
--- a/code/game/objects/items/weapons/grenades/concussion.dm
+++ b/code/game/objects/items/weapons/grenades/concussion.dm
@@ -19,7 +19,7 @@
if(is_below_sound_pressure(T))
visible_message("Whump.")
return
- playsound(src.loc, 'sound/effects/bang.ogg', 75, 1, -3)
+ playsound(src, 'sound/effects/bang.ogg', 75, 1, -3)
if(istype(T))
for(var/mob/living/L in orange(T, radius))
if(ishuman(L))
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm
index 087265ca5b..e2d095e0e1 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/weapons/grenades/flashbang.dm
@@ -29,7 +29,7 @@
/obj/item/weapon/grenade/flashbang/proc/bang(var/turf/T , var/mob/living/carbon/M) // Added a new proc called 'bang' that takes a location and a person to be banged.
to_chat(M, "BANG") // Called during the loop that bangs people in lockers/containers and when banging
- playsound(src.loc, 'sound/effects/bang.ogg', 50, 1, 30) // people in normal view. Could theroetically be called during other explosions.
+ playsound(src, 'sound/effects/bang.ogg', 50, 1, 30) // people in normal view. Could theroetically be called during other explosions.
// -- Polymorph
//Checking for protections
@@ -119,11 +119,11 @@
for(var/do_spawn = numspawned, do_spawn > 0, do_spawn--)
new /obj/item/weapon/grenade/flashbang/cluster(src.loc)//Launches flashbangs
- playsound(src.loc, 'sound/weapons/armbomb.ogg', 75, 1, -3)
+ playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
for(var/do_again = again, do_again > 0, do_again--)
new /obj/item/weapon/grenade/flashbang/clusterbang/segment(src.loc)//Creates a 'segment' that launches a few more flashbangs
- playsound(src.loc, 'sound/weapons/armbomb.ogg', 75, 1, -3)
+ playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
qdel(src)
return
diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm
index fdab7aaf39..7ac049a774 100644
--- a/code/game/objects/items/weapons/grenades/grenade.dm
+++ b/code/game/objects/items/weapons/grenades/grenade.dm
@@ -33,7 +33,7 @@
to_chat(user, "You prime the [name]! [det_time/10] seconds!")
active = 1
icon_state = initial(icon_state) + "_active"
- playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3)
+ playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
spawn(det_time)
detonate()
return
@@ -75,7 +75,7 @@
icon_state = initial(icon_state) + "_active"
active = 1
- playsound(loc, arm_sound, 75, 1, -3)
+ playsound(src, arm_sound, 75, 1, -3)
spawn(det_time)
detonate()
@@ -83,7 +83,7 @@
/obj/item/weapon/grenade/proc/detonate()
-// playsound(loc, 'sound/items/Welder2.ogg', 25, 1)
+// playsound(src, 'sound/items/Welder2.ogg', 25, 1)
var/turf/T = get_turf(src)
if(T)
T.hotspot_expose(700,125)
diff --git a/code/game/objects/items/weapons/grenades/smokebomb.dm b/code/game/objects/items/weapons/grenades/smokebomb.dm
index 28540b981f..75c0e6a299 100644
--- a/code/game/objects/items/weapons/grenades/smokebomb.dm
+++ b/code/game/objects/items/weapons/grenades/smokebomb.dm
@@ -21,7 +21,7 @@
return ..()
/obj/item/weapon/grenade/smokebomb/detonate()
- playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
+ playsound(src, 'sound/effects/smoke.ogg', 50, 1, -3)
src.smoke.set_up(10, 0, usr.loc)
spawn(0)
for(var/i = 1 to smoke_strength)
diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm
index 5cab658098..5f1bd4503b 100644
--- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm
+++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm
@@ -15,7 +15,7 @@
if(spawner_type && deliveryamt)
// Make a quick flash
var/turf/T = get_turf(src)
- playsound(T, 'sound/effects/phasein.ogg', 100, 1)
+ playsound(src, 'sound/effects/phasein.ogg', 100, 1)
for(var/mob/living/carbon/human/M in viewers(T, null))
if(M:eyecheck() <= 0)
M.flash_eyes()
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index 753f72a809..d50e42981e 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -60,7 +60,7 @@
return 0
/obj/item/weapon/handcuffs/proc/place_handcuffs(var/mob/living/carbon/target, var/mob/user)
- playsound(src.loc, cuff_sound, 30, 1, -2)
+ playsound(src, cuff_sound, 30, 1, -2)
var/mob/living/carbon/human/H = target
if(!istype(H))
@@ -98,7 +98,7 @@
user.drop_from_inventory(cuffs)
cuffs.loc = target
target.handcuffed = cuffs
- target.update_inv_handcuffed()
+ target.update_handcuffed()
target.drop_r_hand()
target.drop_l_hand()
target.stop_pulling()
@@ -244,7 +244,7 @@ var/last_chew = 0
to_chat(user, "You need to have a firm grip on [C] before you can put \the [src] on!")
/obj/item/weapon/handcuffs/legcuffs/proc/place_legcuffs(var/mob/living/carbon/target, var/mob/user)
- playsound(src.loc, cuff_sound, 30, 1, -2)
+ playsound(src, cuff_sound, 30, 1, -2)
var/mob/living/carbon/human/H = target
if(!istype(H))
@@ -315,7 +315,7 @@ var/last_chew = 0
qdel(src)
/obj/item/weapon/handcuffs/legcuffs/bola/place_legcuffs(var/mob/living/carbon/target, var/mob/user)
- playsound(src.loc, cuff_sound, 30, 1, -2)
+ playsound(src, cuff_sound, 30, 1, -2)
var/mob/living/carbon/human/H = target
if(!istype(H))
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 34f44ffc8d..81d5bb8f04 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -252,7 +252,7 @@ Implant Specifics:
"}
if (elevel == "Localized Limb")
if(part) //For some reason, small_boom() didn't work. So have this bit of working copypaste.
imp_in.visible_message("Something beeps inside [imp_in][part ? "'s [part.name]" : ""]!")
- playsound(loc, 'sound/items/countdown.ogg', 75, 1, -3)
+ playsound(src, 'sound/items/countdown.ogg', 75, 1, -3)
sleep(25)
if (istype(part,/obj/item/organ/external/chest) || \
istype(part,/obj/item/organ/external/groin) || \
@@ -325,7 +325,7 @@ Implant Specifics:
"}
/obj/item/weapon/implant/explosive/proc/small_boom()
if (ishuman(imp_in) && part)
imp_in.visible_message("Something beeps inside [imp_in][part ? "'s [part.name]" : ""]!")
- playsound(loc, 'sound/items/countdown.ogg', 75, 1, -3)
+ playsound(src, 'sound/items/countdown.ogg', 75, 1, -3)
spawn(25)
if (ishuman(imp_in) && part)
//No tearing off these parts since it's pretty much killing
diff --git a/code/game/objects/items/weapons/implants/implantfreedom.dm b/code/game/objects/items/weapons/implants/implantfreedom.dm
index b55274cc92..6e4f5f7a16 100644
--- a/code/game/objects/items/weapons/implants/implantfreedom.dm
+++ b/code/game/objects/items/weapons/implants/implantfreedom.dm
@@ -27,7 +27,7 @@
source.handcuffed = null
if(source.buckled && source.buckled.buckle_require_restraints)
source.buckled.unbuckle_mob()
- source.update_inv_handcuffed()
+ source.update_handcuffed()
if (source.client)
source.client.screen -= W
if (W)
diff --git a/code/game/objects/items/weapons/material/chainsaw.dm b/code/game/objects/items/weapons/material/chainsaw.dm
index fe99fad674..8ba5f20695 100644
--- a/code/game/objects/items/weapons/material/chainsaw.dm
+++ b/code/game/objects/items/weapons/material/chainsaw.dm
@@ -53,7 +53,7 @@ obj/item/weapon/chainsaw/proc/turnOff(mob/user as mob)
if(!on) return
to_chat(user, "You switch the gas nozzle on the chainsaw, turning it off.")
attack_verb = list("bluntly hit", "beat", "knocked")
- playsound(user, 'sound/weapons/chainsaw_turnoff.ogg',40,1)
+ playsound(src, 'sound/weapons/chainsaw_turnoff.ogg',40,1)
force = inactive_force
edge = 0
sharp = 0
@@ -93,7 +93,7 @@ obj/item/weapon/chainsaw/afterattack(atom/A as mob|obj|turf|area, mob/user as mo
to_chat(user, "You begin filling the tank on the chainsaw.")
if(do_after(usr, 15))
A.reagents.trans_to_obj(src, max_fuel)
- playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 50, 1, -6)
to_chat(user, "Chainsaw succesfully refueled.")
else
to_chat(user, "Don't move while you're refilling the chainsaw.")
diff --git a/code/game/objects/items/weapons/material/kitchen.dm b/code/game/objects/items/weapons/material/kitchen.dm
index b2369f995d..4464084f85 100644
--- a/code/game/objects/items/weapons/material/kitchen.dm
+++ b/code/game/objects/items/weapons/material/kitchen.dm
@@ -46,7 +46,7 @@
if(!(M.can_force_feed(user, loaded) && do_mob(user, M, 5 SECONDS)))
return
M.visible_message("\The [user] feeds some [loaded] to \the [M] with \the [src].")
- playsound(M.loc,'sound/items/eatfood.ogg', rand(10,40), 1)
+ playsound(src,'sound/items/eatfood.ogg', rand(10,40), 1)
overlays.Cut()
return
else
diff --git a/code/game/objects/items/weapons/material/knives.dm b/code/game/objects/items/weapons/material/knives.dm
index 099edd65c4..c06e80becf 100644
--- a/code/game/objects/items/weapons/material/knives.dm
+++ b/code/game/objects/items/weapons/material/knives.dm
@@ -46,7 +46,7 @@
active = !active
if(active)
to_chat(user, "You flip out \the [src].")
- playsound(user, 'sound/weapons/flipblade.ogg', 15, 1)
+ playsound(src, 'sound/weapons/flipblade.ogg', 15, 1)
else
to_chat(user, "\The [src] can now be concealed.")
update_force()
diff --git a/code/game/objects/items/weapons/material/material_armor.dm b/code/game/objects/items/weapons/material/material_armor.dm
index d981cafc07..91aca12dc1 100644
--- a/code/game/objects/items/weapons/material/material_armor.dm
+++ b/code/game/objects/items/weapons/material/material_armor.dm
@@ -125,7 +125,7 @@ Protectiveness | Armor %
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, user.loc)
spark_system.start()
- playsound(user.loc, 'sound/effects/teleport.ogg', 50, 1)
+ playsound(src, 'sound/effects/teleport.ogg', 50, 1)
user.loc = picked
return PROJECTILE_FORCE_MISS
diff --git a/code/game/objects/items/weapons/material/shards.dm b/code/game/objects/items/weapons/material/shards.dm
index e2394537f3..19eaf7f776 100644
--- a/code/game/objects/items/weapons/material/shards.dm
+++ b/code/game/objects/items/weapons/material/shards.dm
@@ -102,7 +102,7 @@
if(will_break && src.loc == user) // If it's not in our hand anymore
user.visible_message("[user] hit \the [target] with \the [src], shattering it!", "You shatter \the [src] in your hand!")
- playsound(user, pick('sound/effects/Glassbr1.ogg', 'sound/effects/Glassbr2.ogg', 'sound/effects/Glassbr3.ogg'), 30, 1)
+ playsound(src, pick('sound/effects/Glassbr1.ogg', 'sound/effects/Glassbr2.ogg', 'sound/effects/Glassbr3.ogg'), 30, 1)
qdel(src)
return
@@ -116,7 +116,7 @@
if(M.buckled) //wheelchairs, office chairs, rollerbeds
return
- playsound(src.loc, 'sound/effects/glass_step.ogg', 50, 1) // not sure how to handle metal shards with sounds
+ playsound(src, 'sound/effects/glass_step.ogg', 50, 1) // not sure how to handle metal shards with sounds
if(ishuman(M))
var/mob/living/carbon/human/H = M
diff --git a/code/game/objects/items/weapons/material/swords.dm b/code/game/objects/items/weapons/material/swords.dm
index 3affd40887..ba0fe4ddfe 100644
--- a/code/game/objects/items/weapons/material/swords.dm
+++ b/code/game/objects/items/weapons/material/swords.dm
@@ -14,7 +14,7 @@
/obj/item/weapon/material/sword/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(unique_parry_check(user, attacker, damage_source) && prob(50))
user.visible_message("\The [user] parries [attack_text] with \the [src]!")
- playsound(user.loc, 'sound/weapons/punchmiss.ogg', 50, 1)
+ playsound(src, 'sound/weapons/punchmiss.ogg', 50, 1)
return 1
return 0
diff --git a/code/game/objects/items/weapons/material/twohanded.dm b/code/game/objects/items/weapons/material/twohanded.dm
index 244b2c6001..e2d5e94118 100644
--- a/code/game/objects/items/weapons/material/twohanded.dm
+++ b/code/game/objects/items/weapons/material/twohanded.dm
@@ -61,7 +61,7 @@
/obj/item/weapon/material/twohanded/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(wielded && default_parry_check(user, attacker, damage_source) && prob(15))
user.visible_message("\The [user] parries [attack_text] with \the [src]!")
- playsound(user.loc, 'sound/weapons/punchmiss.ogg', 50, 1)
+ playsound(src, 'sound/weapons/punchmiss.ogg', 50, 1)
return 1
return 0
diff --git a/code/game/objects/items/weapons/material/twohanded.dm.orig b/code/game/objects/items/weapons/material/twohanded.dm.orig
index 01f4ee7e55..47d4f230c6 100644
--- a/code/game/objects/items/weapons/material/twohanded.dm.orig
+++ b/code/game/objects/items/weapons/material/twohanded.dm.orig
@@ -159,18 +159,8 @@
if(istype(A,/obj/structure/window))
var/obj/structure/window/W = A
W.shatter()
-<<<<<<< HEAD:code/game/objects/items/weapons/material/twohanded.dm
/*
-=======
- else if(istype(A,/obj/structure/grille))
- qdel(A)
- else if(istype(A,/obj/effect/plant))
- var/obj/effect/plant/P = A
- P.die_off()
-
- qdel(A)
->>>>>>> 284d1cc1f5c67503fe0da89ce01985d73bb02038:code/game/objects/items/weapons/twohanded.dm
/*
* Double-Bladed Energy Swords - Cheridan
*/
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 21d4d53a5c..7153ebfa60 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -57,14 +57,14 @@
sharp = 1
edge = 1
w_class = active_w_class
- playsound(user, 'sound/weapons/saberon.ogg', 50, 1)
+ playsound(src, 'sound/weapons/saberon.ogg', 50, 1)
update_icon()
set_light(lrange, lpower, lcolor)
/obj/item/weapon/melee/energy/proc/deactivate(mob/living/user)
if(!active)
return
- playsound(user, 'sound/weapons/saberoff.ogg', 50, 1)
+ playsound(src, 'sound/weapons/saberoff.ogg', 50, 1)
item_state = "[icon_state]"
active = 0
embed_chance = initial(embed_chance)
@@ -310,7 +310,7 @@
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, user.loc)
spark_system.start()
- playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
return 1
if(active && unique_parry_check(user, attacker, damage_source) && prob(projectile_parry_chance))
user.visible_message("\The [user] deflects [attack_text] with \the [src]!")
@@ -318,7 +318,7 @@
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, user.loc)
spark_system.start()
- playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
return 1
return 0
@@ -370,7 +370,7 @@
// EMP stuff.
var/obj/O = AM
O.emp_act(3) // A weaker severity is used because this has infinite uses.
- playsound(get_turf(O), 'sound/effects/EMPulse.ogg', 100, 1)
+ playsound(O, 'sound/effects/EMPulse.ogg', 100, 1)
user.setClickCooldown(user.get_attack_speed(src)) // A lot of objects don't set click delay.
return ..()
@@ -379,9 +379,9 @@
if(target.isSynthetic() && active)
// Do some extra damage. Not a whole lot more since emp_act() is pretty nasty on FBPs already.
target.emp_act(3) // A weaker severity is used because this has infinite uses.
- playsound(get_turf(target), 'sound/effects/EMPulse.ogg', 100, 1)
+ playsound(target, 'sound/effects/EMPulse.ogg', 100, 1)
target.adjustFireLoss(force * 3) // 15 Burn, for 20 total.
- playsound(get_turf(target), 'sound/weapons/blade1.ogg', 100, 1)
+ playsound(target, 'sound/weapons/blade1.ogg', 100, 1)
// Make lesser robots really mad at us.
if(target.mob_class & MOB_CLASS_SYNTHETIC)
@@ -481,7 +481,7 @@
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, user.loc)
spark_system.start()
- playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
return 1
if(unique_parry_check(user, attacker, damage_source) && prob(projectile_parry_chance))
user.visible_message("\The [user] deflects [attack_text] with \the [src]!")
@@ -489,7 +489,7 @@
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, user.loc)
spark_system.start()
- playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
return 1
return 0
@@ -547,6 +547,6 @@
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, user.loc)
spark_system.start()
- playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
return 1
return 0
diff --git a/code/game/objects/items/weapons/melee/misc.dm b/code/game/objects/items/weapons/melee/misc.dm
index 7d390d613f..4185cf92c2 100644
--- a/code/game/objects/items/weapons/melee/misc.dm
+++ b/code/game/objects/items/weapons/melee/misc.dm
@@ -69,7 +69,7 @@
/obj/item/weapon/melee/cursedblade/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(default_parry_check(user, attacker, damage_source) && prob(50))
user.visible_message("\The [user] parries [attack_text] with \the [src]!")
- playsound(user.loc, 'sound/weapons/punchmiss.ogg', 50, 1)
+ playsound(src, 'sound/weapons/punchmiss.ogg', 50, 1)
return 1
return 0
diff --git a/code/game/objects/items/weapons/paiwire.dm b/code/game/objects/items/weapons/paiwire.dm
index 638d8f51cb..b654c24e67 100644
--- a/code/game/objects/items/weapons/paiwire.dm
+++ b/code/game/objects/items/weapons/paiwire.dm
@@ -1,7 +1,7 @@
/obj/item/weapon/pai_cable/proc/plugin(obj/machinery/M as obj, mob/user as mob)
if(istype(M, /obj/machinery/door) || istype(M, /obj/machinery/camera))
user.visible_message("[user] inserts [src] into a data port on [M].", "You insert [src] into a data port on [M].", "You hear the satisfying click of a wire jack fastening into place.")
- playsound(user, 'sound/machines/click.ogg', 50, 1)
+ playsound(src, 'sound/machines/click.ogg', 50, 1)
user.drop_item()
src.loc = M
src.machine = M
diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm
index 4d78a09bc5..e4a518e8db 100644
--- a/code/game/objects/items/weapons/shields.dm
+++ b/code/game/objects/items/weapons/shields.dm
@@ -94,7 +94,7 @@
return 0
//Otherwise, if we're here, we're gonna stop the attack entirely.
user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
- playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1)
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
return 1
return 0
@@ -102,7 +102,7 @@
if(istype(W, /obj/item/weapon/melee/baton))
if(cooldown < world.time - 25)
user.visible_message("[user] bashes [src] with [W]!")
- playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1)
+ playsound(src, 'sound/effects/shieldbash.ogg', 50, 1)
cooldown = world.time
else
..()
@@ -144,7 +144,7 @@
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, user.loc)
spark_system.start()
- playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
/obj/item/weapon/shield/energy/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null)
if(istype(damage_source, /obj/item/projectile))
@@ -163,7 +163,7 @@
update_icon()
w_class = ITEMSIZE_LARGE
slot_flags = null
- playsound(user, 'sound/weapons/saberon.ogg', 50, 1)
+ playsound(src, 'sound/weapons/saberon.ogg', 50, 1)
to_chat(user, "\The [src] is now active.")
else
@@ -171,7 +171,7 @@
update_icon()
w_class = ITEMSIZE_TINY
slot_flags = SLOT_EARS
- playsound(user, 'sound/weapons/saberoff.ogg', 50, 1)
+ playsound(src, 'sound/weapons/saberoff.ogg', 50, 1)
to_chat(user, "\The [src] can now be concealed.")
if(istype(user,/mob/living/carbon/human))
@@ -240,7 +240,7 @@
/obj/item/weapon/shield/riot/tele/attack_self(mob/living/user)
active = !active
icon_state = "teleriot[active]"
- playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1)
+ playsound(src, 'sound/weapons/empty.ogg', 50, 1)
if(active)
force = 8
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index 88f6caeb74..2cdc341523 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -21,13 +21,13 @@
/obj/item/weapon/storage/backpack/equipped(var/mob/user, var/slot)
if (slot == slot_back && src.use_sound)
- playsound(src.loc, src.use_sound, 50, 1, -5)
+ playsound(src, src.use_sound, 50, 1, -5)
..(user, slot)
/*
/obj/item/weapon/storage/backpack/dropped(mob/user as mob)
if (loc == user && src.use_sound)
- playsound(src.loc, src.use_sound, 50, 1, -5)
+ playsound(src, src.use_sound, 50, 1, -5)
..(user)
*/
diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm
index 0d97b4f878..75cbc2297e 100644
--- a/code/game/objects/items/weapons/storage/bible.dm
+++ b/code/game/objects/items/weapons/storage/bible.dm
@@ -35,5 +35,5 @@
/obj/item/weapon/storage/bible/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (src.use_sound)
- playsound(src.loc, src.use_sound, 50, 1, -5)
+ playsound(src, src.use_sound, 50, 1, -5)
..()
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index a1cad988d7..1655cb28a6 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -52,7 +52,7 @@
return
// Now make the cardboard
to_chat(user, "You fold [src] flat.")
- playsound(src.loc, 'sound/items/storage/boxfold.ogg', 30, 1)
+ playsound(src, 'sound/items/storage/boxfold.ogg', 30, 1)
new foldable(get_turf(src))
qdel(src)
diff --git a/code/game/objects/items/weapons/storage/internal.dm b/code/game/objects/items/weapons/storage/internal.dm
index 6fbbedf069..63afc51b4e 100644
--- a/code/game/objects/items/weapons/storage/internal.dm
+++ b/code/game/objects/items/weapons/storage/internal.dm
@@ -18,7 +18,7 @@
/obj/item/weapon/storage/internal/attack_hand()
return //make sure this is never picked up
-/obj/item/weapon/storage/internal/mob_can_equip()
+/obj/item/weapon/storage/internal/mob_can_equip(M as mob, slot, disable_warning = FALSE)
return 0 //make sure this is never picked up
//Helper procs to cleanly implement internal storages - storage items that provide inventory slots for other items.
diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm
index 2fa8e54e87..b10caa3610 100644
--- a/code/game/objects/items/weapons/storage/lockbox.dm
+++ b/code/game/objects/items/weapons/storage/lockbox.dm
@@ -40,8 +40,8 @@
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src.loc)
spark_system.start()
- playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1)
- playsound(src.loc, "sparks", 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, "sparks", 50, 1)
if(!locked)
..()
else
diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm
index c8bc129e3d..034e37ff8e 100644
--- a/code/game/objects/items/weapons/storage/secure.dm
+++ b/code/game/objects/items/weapons/storage/secure.dm
@@ -39,8 +39,8 @@
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src.loc)
spark_system.start()
- playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1)
- playsound(src.loc, "sparks", 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, "sparks", 50, 1)
return
if (W.is_screwdriver())
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index d14a4ab29b..bfcbd695e5 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -142,7 +142,7 @@
/obj/item/weapon/storage/proc/open(mob/user as mob)
if (use_sound)
- playsound(src.loc, src.use_sound, 50, 0, -5)
+ playsound(src, src.use_sound, 50, 0, -5)
orient2hud(user)
if (user.s_active)
@@ -729,3 +729,12 @@
/obj/item/weapon/storage/AllowDrop()
return TRUE
+
+//Useful for spilling the contents of containers all over the floor
+/obj/item/weapon/storage/proc/spill(var/dist = 2, var/turf/T = null)
+ if (!istype(T))//If its not on the floor this might cause issues
+ T = get_turf(src)
+
+ for (var/obj/O in contents)
+ remove_from_storage(O, T)
+ O.tumble(2)
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index 183366a4c7..87ce75a233 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -148,7 +148,7 @@
if(bcell && bcell.charge > hitcost)
status = !status
to_chat(user, "[src] is now [status ? "on" : "off"].")
- playsound(loc, "sparks", 75, 1, -1)
+ playsound(src, "sparks", 75, 1, -1)
update_icon()
else
status = 0
@@ -193,7 +193,7 @@
target.visible_message("[target] has been prodded in the [affecting.name] with [src] by [user]!")
else
target.visible_message("[target] has been prodded with [src] by [user]!")
- playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/Egloves.ogg', 50, 1, -1)
//stun effects
if(status)
diff --git a/code/game/objects/items/weapons/swords_axes_etc.dm b/code/game/objects/items/weapons/swords_axes_etc.dm
index 204ebb6f89..a4a7992872 100644
--- a/code/game/objects/items/weapons/swords_axes_etc.dm
+++ b/code/game/objects/items/weapons/swords_axes_etc.dm
@@ -77,7 +77,7 @@
H.update_inv_l_hand()
H.update_inv_r_hand()
- playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1)
+ playsound(src, 'sound/weapons/empty.ogg', 50, 1)
add_fingerprint(user)
if(blood_overlay && blood_DNA && (blood_DNA.len >= 1)) //updates blood overlay, if any
@@ -104,7 +104,7 @@
user.take_organ_damage(2*force)
return
if(..())
- //playsound(src.loc, "swing_hit", 50, 1, -1)
+ //playsound(src, "swing_hit", 50, 1, -1)
return
else
return ..()
diff --git a/code/game/objects/items/weapons/syndie.dm b/code/game/objects/items/weapons/syndie.dm
index c4e273deea..b97f5303df 100644
--- a/code/game/objects/items/weapons/syndie.dm
+++ b/code/game/objects/items/weapons/syndie.dm
@@ -48,7 +48,7 @@
/obj/item/weapon/syndie/c4explosive/proc/detonate()
icon_state = "c-4[size]_1"
- playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1)
+ playsound(src, 'sound/weapons/armbomb.ogg', 75, 1)
for(var/mob/O in hearers(src, null))
O.show_message("[bicon(src)] The [src.name] beeps! ")
sleep(50)
diff --git a/code/game/objects/items/weapons/tanks/jetpack.dm b/code/game/objects/items/weapons/tanks/jetpack.dm
index eec15d1e94..32f6f99b27 100644
--- a/code/game/objects/items/weapons/tanks/jetpack.dm
+++ b/code/game/objects/items/weapons/tanks/jetpack.dm
@@ -31,7 +31,7 @@
. = ..()
if(air_contents.total_moles < 5)
. += "The meter on \the [src] indicates you are almost out of gas!"
- playsound(user, 'sound/effects/alert.ogg', 50, 1)
+ playsound(src, 'sound/effects/alert.ogg', 50, 1)
/obj/item/weapon/tank/jetpack/verb/toggle_rockets()
set name = "Toggle Jetpack Stabilization"
@@ -84,9 +84,8 @@
item_state_slots = list(slot_r_hand_str = "jetpack-void", slot_l_hand_str = "jetpack-void")
/obj/item/weapon/tank/jetpack/void/Initialize()
- ..()
+ . = ..()
air_contents.adjust_gas("oxygen", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
- return
/obj/item/weapon/tank/jetpack/oxygen
name = "jetpack (oxygen)"
@@ -95,9 +94,8 @@
item_state_slots = list(slot_r_hand_str = "jetpack", slot_l_hand_str = "jetpack")
/obj/item/weapon/tank/jetpack/oxygen/Initialize()
- ..()
+ . = ..()
air_contents.adjust_gas("oxygen", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
- return
/obj/item/weapon/tank/jetpack/carbondioxide
name = "jetpack (carbon dioxide)"
@@ -107,9 +105,8 @@
item_state_slots = list(slot_r_hand_str = "jetpack-black", slot_l_hand_str = "jetpack-black")
/obj/item/weapon/tank/jetpack/carbondioxide/Initialize()
- ..()
+ . = ..()
air_contents.adjust_gas("carbon_dioxide", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
- return
/obj/item/weapon/tank/jetpack/rig
name = "jetpack"
diff --git a/code/game/objects/items/weapons/tanks/tank_types.dm b/code/game/objects/items/weapons/tanks/tank_types.dm
index c2a342b618..a838bf6c03 100644
--- a/code/game/objects/items/weapons/tanks/tank_types.dm
+++ b/code/game/objects/items/weapons/tanks/tank_types.dm
@@ -17,9 +17,8 @@
distribute_pressure = ONE_ATMOSPHERE*O2STANDARD
/obj/item/weapon/tank/oxygen/Initialize()
- ..()
+ . = ..()
air_contents.adjust_gas("oxygen", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
- return
/obj/item/weapon/tank/oxygen/examine(mob/user)
. = ..()
@@ -43,14 +42,12 @@
icon_state = "anesthetic"
/obj/item/weapon/tank/anesthetic/Initialize()
- ..()
+ . = ..()
air_contents.gas["oxygen"] = (3*ONE_ATMOSPHERE)*70/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD
air_contents.gas["sleeping_agent"] = (3*ONE_ATMOSPHERE)*70/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD
air_contents.update_values()
- return
-
/*
* Air
*/
@@ -66,12 +63,9 @@
user << sound('sound/effects/alert.ogg')
/obj/item/weapon/tank/air/Initialize()
- ..()
-
+ . = ..()
src.air_contents.adjust_multi("oxygen", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD, "nitrogen", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD)
- return
-
/*
* Phoron
*/
@@ -83,10 +77,8 @@
slot_flags = null //they have no straps!
/obj/item/weapon/tank/phoron/Initialize()
- ..()
-
+ . = ..()
src.air_contents.adjust_gas("phoron", (3*ONE_ATMOSPHERE)*70/(R_IDEAL_GAS_EQUATION*T20C))
- return
/obj/item/weapon/tank/phoron/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
@@ -109,10 +101,8 @@
slot_flags = SLOT_BACK //these ones have straps!
/obj/item/weapon/tank/vox/Initialize()
- ..()
-
+ . = ..()
air_contents.adjust_gas("phoron", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
- return
/obj/item/weapon/tank/phoron/pressurized
name = "fuel can"
@@ -120,12 +110,9 @@
w_class = ITEMSIZE_NORMAL
/obj/item/weapon/tank/phoron/pressurized/Initialize()
- ..()
-
+ . = ..()
adjust_scale(0.8)
-
air_contents.adjust_gas("phoron", (7*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
- return
/*
* Emergency Oxygen
@@ -149,9 +136,8 @@
gauge_icon = "indicator_emergency"
/obj/item/weapon/tank/emergency/oxygen/Initialize()
- ..()
+ . = ..()
src.air_contents.adjust_gas("oxygen", (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
- return
/obj/item/weapon/tank/emergency/oxygen/examine(mob/user)
. = ..()
@@ -178,9 +164,8 @@
volume = 10
/obj/item/weapon/tank/stasis/oxygen/Initialize()
- ..()
+ . = ..()
src.air_contents.adjust_gas("oxygen", (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
- return
/obj/item/weapon/tank/emergency/nitrogen
name = "emergency nitrogen tank"
@@ -205,7 +190,7 @@
gauge_icon = "indicator_emergency"
/obj/item/weapon/tank/emergency/phoron/Initialize()
- ..()
+ . = ..()
src.air_contents.adjust_gas("phoron", (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/weapon/tank/emergency/phoron/double
@@ -224,10 +209,8 @@
distribute_pressure = ONE_ATMOSPHERE*O2STANDARD
/obj/item/weapon/tank/nitrogen/Initialize()
- ..()
-
+ . = ..()
src.air_contents.adjust_gas("nitrogen", (3*ONE_ATMOSPHERE)*70/(R_IDEAL_GAS_EQUATION*T20C))
- return
/obj/item/weapon/tank/nitrogen/examine(mob/user)
. = ..()
@@ -243,6 +226,5 @@
volume = 10
/obj/item/weapon/tank/stasis/nitro_cryo/Initialize()
- ..()
+ . = ..()
src.air_contents.adjust_gas_temp("nitrogen", (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*TN60C), TN60C)
- return
diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm
index b9eeef5629..9957e09f55 100644
--- a/code/game/objects/items/weapons/tanks/tanks.dm
+++ b/code/game/objects/items/weapons/tanks/tanks.dm
@@ -59,15 +59,13 @@ var/list/global/tank_gauge_cache = list()
/obj/item/weapon/tank/Initialize()
- ..()
+ . = ..()
src.init_proxy()
src.air_contents = new /datum/gas_mixture()
src.air_contents.volume = volume //liters
src.air_contents.temperature = T20C
- START_PROCESSING(SSobj, src)
update_gauge()
- return
/obj/item/weapon/tank/Destroy()
QDEL_NULL(air_contents)
@@ -81,6 +79,13 @@ var/list/global/tank_gauge_cache = list()
. = ..()
+/obj/item/weapon/tank/equipped() // Note that even grabbing into a hand calls this, so it should be fine as a 'has a player touched this'
+ . = ..()
+ // An attempt at optimization. There are MANY tanks during rounds that will never get touched.
+ // Don't see why any of those would explode spontaneously. So only tanks that players touch get processed.
+ // This could be optimized more, but it's a start!
+ START_PROCESSING(SSobj, src) // This has a built in safety to avoid multi-processing
+
/obj/item/weapon/tank/examine(mob/user)
. = ..()
if(loc == user)
@@ -466,7 +471,7 @@ var/list/global/tank_gauge_cache = list()
if(!T)
return
T.assume_air(air_contents)
- playsound(get_turf(src), 'sound/weapons/Gunshot_shotgun.ogg', 20, 1)
+ playsound(src, 'sound/weapons/Gunshot_shotgun.ogg', 20, 1)
visible_message("[bicon(src)] \The [src] flies apart!", "You hear a bang!")
T.hotspot_expose(air_contents.temperature, 70, 1)
@@ -513,7 +518,7 @@ var/list/global/tank_gauge_cache = list()
T.assume_air(leaked_gas)
if(!leaking)
visible_message("[bicon(src)] \The [src] relief valve flips open with a hiss!", "You hear hissing.")
- playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
+ playsound(src, 'sound/effects/spray.ogg', 10, 1, -3)
leaking = 1
#ifdef FIREDBG
log_debug("[x],[y] tank is leaking: [pressure] kPa, integrity [integrity]")
@@ -673,6 +678,11 @@ var/list/global/tank_gauge_cache = list()
tank.update_icon()
tank.overlays -= "bomb_assembly"
-/obj/item/device/tankassemblyproxy/HasProximity(atom/movable/AM as mob|obj)
- if(src.assembly)
- src.assembly.HasProximity(AM)
+/obj/item/device/tankassemblyproxy/HasProximity(turf/T, atom/movable/AM, old_loc)
+ assembly?.HasProximity(T, AM, old_loc)
+
+/obj/item/device/tankassemblyproxy/Moved(old_loc, direction, forced)
+ if(isturf(old_loc))
+ unsense_proximity(callback = .HasProximity, center = old_loc)
+ if(isturf(loc))
+ sense_proximity(callback = .HasProximity)
diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm
index 03436bafb5..c219c89eb7 100644
--- a/code/game/objects/items/weapons/teleportation.dm
+++ b/code/game/objects/items/weapons/teleportation.dm
@@ -147,11 +147,11 @@ Frequency:
if(com)
break
break
- if (istype(com, /obj/machinery/computer/teleporter) && com.locked && !com.one_time_use)
+ if (istype(com, /obj/machinery/computer/teleporter) && com.teleport_control.locked && !com.one_time_use)
if(R.icon_state == "tele1")
- L["[com.id] (Active)"] = com.locked
+ L["[com.id] (Active)"] = com.teleport_control.locked
else
- L["[com.id] (Inactive)"] = com.locked
+ L["[com.id] (Inactive)"] = com.teleport_control.locked
var/list/turfs = list( )
for(var/turf/T in orange(10))
if(T.x>world.maxx-8 || T.x<8) continue //putting them at the edge is dumb
diff --git a/code/game/objects/items/weapons/tools/crowbar.dm b/code/game/objects/items/weapons/tools/crowbar.dm
index 56afaf8219..a139efe9f6 100644
--- a/code/game/objects/items/weapons/tools/crowbar.dm
+++ b/code/game/objects/items/weapons/tools/crowbar.dm
@@ -102,7 +102,7 @@
return ..()
/obj/item/weapon/tool/crowbar/power/attack_self(mob/user)
- playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1)
+ playsound(src, 'sound/items/change_jaws.ogg', 50, 1)
user.drop_item(src)
counterpart.forceMove(get_turf(src))
src.forceMove(counterpart)
diff --git a/code/game/objects/items/weapons/tools/screwdriver.dm b/code/game/objects/items/weapons/tools/screwdriver.dm
index 8045445ca3..aea17ebf2b 100644
--- a/code/game/objects/items/weapons/tools/screwdriver.dm
+++ b/code/game/objects/items/weapons/tools/screwdriver.dm
@@ -107,14 +107,6 @@
random_color = FALSE
reach = 2
-/obj/item/weapon/tool/screwdriver/hybrid/is_screwdriver()
- if(prob(10))
- var/turf/T = get_turf(src)
- SSradiation.radiate(get_turf(src), 5)
- T.visible_message("\The [src] shudders!")
- return FALSE
- return TRUE
-
/obj/item/weapon/tool/screwdriver/cyborg
name = "powered screwdriver"
desc = "An electrical screwdriver, designed to be both precise and quick."
@@ -154,7 +146,7 @@
return ..()
/obj/item/weapon/tool/screwdriver/power/attack_self(mob/user)
- playsound(get_turf(user),'sound/items/change_drill.ogg',50,1)
+ playsound(src,'sound/items/change_drill.ogg',50,1)
user.drop_item(src)
counterpart.forceMove(get_turf(src))
src.forceMove(counterpart)
diff --git a/code/game/objects/items/weapons/tools/weldingtool.dm b/code/game/objects/items/weapons/tools/weldingtool.dm
index a6e7646022..0c0add9e24 100644
--- a/code/game/objects/items/weapons/tools/weldingtool.dm
+++ b/code/game/objects/items/weapons/tools/weldingtool.dm
@@ -146,7 +146,7 @@
if(!welding && max_fuel)
O.reagents.trans_to_obj(src, max_fuel)
to_chat(user, "Welder refueled")
- playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 50, 1, -6)
return
else if(!welding)
to_chat(user, "[src] doesn't use fuel.")
@@ -273,7 +273,7 @@
to_chat(M, "You switch the [src] on.")
else if(T)
T.visible_message("\The [src] turns on.")
- playsound(loc, acti_sound, 50, 1)
+ playsound(src, acti_sound, 50, 1)
src.force = 15
src.damtype = "fire"
src.w_class = ITEMSIZE_LARGE
@@ -295,7 +295,7 @@
to_chat(M, "You switch \the [src] off.")
else if(T)
T.visible_message("\The [src] turns off.")
- playsound(loc, deac_sound, 50, 1)
+ playsound(src, deac_sound, 50, 1)
src.force = 3
src.damtype = "brute"
src.w_class = initial(src.w_class)
@@ -449,11 +449,11 @@
name = "strange welding tool"
desc = "An experimental welder capable of synthesizing its own fuel from spatial waveforms. It's like welding with a star!"
icon_state = "hybwelder"
- max_fuel = 20
+ max_fuel = 80 //more max fuel is better! Even if it doesn't actually use fuel.
eye_safety_modifier = -2 // Brighter than the sun. Literally, you can look at the sun with a welding mask of proper grade, this will burn through that.
slowdown = 0.1
toolspeed = 0.25
- w_class = ITEMSIZE_LARGE
+ w_class = ITEMSIZE_NORMAL
flame_intensity = 5
origin_tech = list(TECH_ENGINEERING = 5, TECH_PHORON = 4, TECH_PRECURSOR = 1)
reach = 2
diff --git a/code/game/objects/items/weapons/tools/wirecutters.dm b/code/game/objects/items/weapons/tools/wirecutters.dm
index 28e9e8f6cf..3b8c83c1f9 100644
--- a/code/game/objects/items/weapons/tools/wirecutters.dm
+++ b/code/game/objects/items/weapons/tools/wirecutters.dm
@@ -37,7 +37,7 @@
C.handcuffed = null
if(C.buckled && C.buckled.buckle_require_restraints)
C.buckled.unbuckle_mob()
- C.update_inv_handcuffed()
+ C.update_handcuffed()
return
else
..()
@@ -87,14 +87,6 @@
toolspeed = 0.4
reach = 2
-/obj/item/weapon/tool/wirecutters/hybrid/is_wirecutter()
- if(prob(10))
- var/turf/T = get_turf(src)
- SSradiation.radiate(get_turf(src), 5)
- T.visible_message("\The [src] shudders!")
- return FALSE
- return TRUE
-
/obj/item/weapon/tool/wirecutters/power
name = "jaws of life"
desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a cutting head."
@@ -121,9 +113,9 @@
return ..()
/obj/item/weapon/tool/wirecutters/power/attack_self(mob/user)
- playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1)
+ playsound(src, 'sound/items/change_jaws.ogg', 50, 1)
user.drop_item(src)
counterpart.forceMove(get_turf(src))
src.forceMove(counterpart)
user.put_in_active_hand(counterpart)
- to_chat(user, "You attach the pry jaws to [src].")
\ No newline at end of file
+ to_chat(user, "You attach the pry jaws to [src].")
diff --git a/code/game/objects/items/weapons/tools/wrench.dm b/code/game/objects/items/weapons/tools/wrench.dm
index 89a51cf217..d96a244282 100644
--- a/code/game/objects/items/weapons/tools/wrench.dm
+++ b/code/game/objects/items/weapons/tools/wrench.dm
@@ -26,7 +26,7 @@
usesound = 'sound/items/drill_use.ogg'
toolspeed = 0.5
-/obj/item/weapon/tool/wrench/hybrid // Slower and bulkier than normal power tools, but it has the power of reach.
+/obj/item/weapon/tool/wrench/hybrid // Slower and bulkier than normal power tools, but it has the power of reach. If reach even worked half the time.
name = "strange wrench"
desc = "A wrench with many common uses. Can be usually found in your hand."
icon = 'icons/obj/tools.dmi'
@@ -42,13 +42,6 @@
toolspeed = 0.5
reach = 2
-/obj/item/weapon/tool/wrench/hybrid/is_wrench()
- if(prob(10))
- var/turf/T = get_turf(src)
- SSradiation.radiate(get_turf(src), 5)
- T.visible_message("\The [src] shudders!")
- return FALSE
- return TRUE
/datum/category_item/catalogue/anomalous/precursor_a/alien_wrench
name = "Precursor Alpha Object - Fastener Torque Tool"
@@ -103,7 +96,7 @@
return ..()
/obj/item/weapon/tool/wrench/power/attack_self(mob/user)
- playsound(get_turf(user),'sound/items/change_drill.ogg',50,1)
+ playsound(src,'sound/items/change_drill.ogg',50,1)
user.drop_item(src)
counterpart.forceMove(get_turf(src))
src.forceMove(counterpart)
diff --git a/code/game/objects/items/weapons/towels.dm b/code/game/objects/items/weapons/towels.dm
index ba1b662ebb..b9566c399b 100644
--- a/code/game/objects/items/weapons/towels.dm
+++ b/code/game/objects/items/weapons/towels.dm
@@ -12,7 +12,7 @@
/obj/item/weapon/towel/attack_self(mob/living/user as mob)
user.visible_message(text("[] uses [] to towel themselves off.", user, src))
- playsound(user, 'sound/weapons/towelwipe.ogg', 25, 1)
+ playsound(src, 'sound/weapons/towelwipe.ogg', 25, 1)
if(user.fire_stacks > 0)
user.fire_stacks = (max(0, user.fire_stacks - 1.5))
else if(user.fire_stacks < 0)
diff --git a/code/game/objects/items/weapons/traps.dm b/code/game/objects/items/weapons/traps.dm
index 8e6667c759..0ec9bc7af3 100644
--- a/code/game/objects/items/weapons/traps.dm
+++ b/code/game/objects/items/weapons/traps.dm
@@ -39,7 +39,7 @@
"You have deployed \the [src]!",
"You hear a latch click loudly."
)
- playsound(src.loc, 'sound/machines/click.ogg',70, 1)
+ playsound(src, 'sound/machines/click.ogg',70, 1)
deployed = 1
user.drop_from_inventory(src)
@@ -64,7 +64,7 @@
"You begin disarming \the [src]!",
"You hear a latch click followed by the slow creaking of a spring."
)
- playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
+ playsound(src, 'sound/machines/click.ogg', 50, 1)
if(do_after(user, 60))
user.visible_message(
@@ -98,6 +98,16 @@
if(!L.apply_damage(30, BRUTE, target_zone, blocked, soaked, used_weapon=src))
return 0
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ var/obj/item/organ/external/affected = H.get_organ(check_zone(target_zone))
+ if(!affected) // took it clean off!
+ to_chat(H, "The steel jaws of \the [src] take your limb clean off!")
+ L.Stun(stun_length*2)
+ deployed = 0
+ anchored = FALSE
+ return
+
//trap the victim in place
set_dir(L.dir)
can_buckle = 1
diff --git a/code/game/objects/items/weapons/trays.dm b/code/game/objects/items/weapons/trays.dm
index 48d65ffb16..6809ae4547 100644
--- a/code/game/objects/items/weapons/trays.dm
+++ b/code/game/objects/items/weapons/trays.dm
@@ -36,10 +36,10 @@
M.Weaken(1)
user.take_organ_damage(2)
if(prob(50))
- playsound(M, 'sound/items/trayhit1.ogg', 50, 1)
+ playsound(src, 'sound/items/trayhit1.ogg', 50, 1)
return
else
- playsound(M, 'sound/items/trayhit2.ogg', 50, 1) //sound playin'
+ playsound(src, 'sound/items/trayhit2.ogg', 50, 1) //sound playin'
return //it always returns, but I feel like adding an extra return just for safety's sakes. EDIT; Oh well I won't :3
var/mob/living/carbon/human/H = M ///////////////////////////////////// /Let's have this ready for later.
@@ -60,12 +60,12 @@
else
M.take_organ_damage(5)
if(prob(50))
- playsound(M, 'sound/items/trayhit1.ogg', 50, 1)
+ playsound(src, 'sound/items/trayhit1.ogg', 50, 1)
for(var/mob/O in viewers(M, null))
O.show_message(text("[] slams [] with the tray!", user, M), 1)
return
else
- playsound(M, 'sound/items/trayhit2.ogg', 50, 1) //we applied the damage, we played the sound, we showed the appropriate messages. Time to return and stop the proc
+ playsound(src, 'sound/items/trayhit2.ogg', 50, 1) //we applied the damage, we played the sound, we showed the appropriate messages. Time to return and stop the proc
for(var/mob/O in viewers(M, null))
O.show_message(text("[] slams [] with the tray!", user, M), 1)
return
@@ -93,11 +93,11 @@
location.add_blood(H)
if(prob(50))
- playsound(M, 'sound/items/trayhit1.ogg', 50, 1)
+ playsound(src, 'sound/items/trayhit1.ogg', 50, 1)
for(var/mob/O in viewers(M, null))
O.show_message(text("[] slams [] with the tray!", user, M), 1)
else
- playsound(M, 'sound/items/trayhit2.ogg', 50, 1) //sound playin'
+ playsound(src, 'sound/items/trayhit2.ogg', 50, 1) //sound playin'
for(var/mob/O in viewers(M, null))
O.show_message(text("[] slams [] with the tray!", user, M), 1)
if(prob(10))
@@ -117,11 +117,11 @@
location.add_blood(H)
if(prob(50))
- playsound(M, 'sound/items/trayhit1.ogg', 50, 1)
+ playsound(src, 'sound/items/trayhit1.ogg', 50, 1)
for(var/mob/O in viewers(M, null))
O.show_message(text("[] slams [] in the face with the tray!", user, M), 1)
else
- playsound(M, 'sound/items/trayhit2.ogg', 50, 1) //sound playin' again
+ playsound(src, 'sound/items/trayhit2.ogg', 50, 1) //sound playin' again
for(var/mob/O in viewers(M, null))
O.show_message(text("[] slams [] in the face with the tray!", user, M), 1)
if(prob(30))
@@ -141,7 +141,7 @@
if(istype(W, /obj/item/weapon/material/kitchen/rollingpin))
if(cooldown < world.time - 25)
user.visible_message("[user] bashes [src] with [W]!")
- playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1)
+ playsound(src, 'sound/effects/shieldbash.ogg', 50, 1)
cooldown = world.time
else
..()
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index ff982da257..82e6ff7699 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -99,7 +99,6 @@
anchored = 0
can_buckle = 1
- buckle_movable = 1
buckle_lying = 0
buckle_dir = SOUTH
@@ -122,18 +121,6 @@
if(!has_buckled_mobs())
qdel(src)
-/obj/effect/energy_net/Move()
- ..()
- if(has_buckled_mobs())
- for(var/A in buckled_mobs)
- var/mob/living/occupant = A
- occupant.buckled = null
- occupant.forceMove(src.loc)
- occupant.buckled = src
- if (occupant && (src.loc != occupant.loc))
- unbuckle_mob(occupant)
- qdel(src)
-
/obj/effect/energy_net/user_unbuckle_mob(mob/living/buckled_mob, mob/user)
user.setClickCooldown(user.get_attack_speed())
visible_message("[user] begins to tear at \the [src]!")
diff --git a/code/game/objects/items/weapons/weldbackpack.dm b/code/game/objects/items/weapons/weldbackpack.dm
index f603aa6498..e839bba3b3 100644
--- a/code/game/objects/items/weapons/weldbackpack.dm
+++ b/code/game/objects/items/weapons/weldbackpack.dm
@@ -68,7 +68,7 @@
to_chat(user, "That was close!")
src.reagents.trans_to_obj(W, T.max_fuel)
to_chat(user, "Welder refilled!")
- playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 50, 1, -6)
return
else if(nozzle)
if(nozzle == W)
@@ -105,7 +105,7 @@
if (istype(O, /obj/structure/reagent_dispensers/fueltank) && src.reagents.total_volume < max_fuel)
O.reagents.trans_to_obj(src, max_fuel)
to_chat(user, "You crack the cap off the top of the pack and fill it back up again from the tank.")
- playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 50, 1, -6)
return
else if (istype(O, /obj/structure/reagent_dispensers/fueltank) && src.reagents.total_volume == max_fuel)
to_chat(user, "The pack is already full!")
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index a14a62eaa8..02ee4265b3 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -142,6 +142,7 @@
return
/mob/proc/unset_machine()
+ machine?.remove_visual(src)
src.machine = null
/mob/proc/set_machine(var/obj/O)
@@ -198,4 +199,19 @@
// Test for if stepping on a tile containing this obj is safe to do, used for things like landmines and cliffs.
/obj/proc/is_safe_to_step(mob/living/L)
- return TRUE
\ No newline at end of file
+ return TRUE
+
+/obj/proc/container_resist(var/mob/living)
+ return
+
+
+//To be called from things that spill objects on the floor.
+//Makes an object move around randomly for a couple of tiles
+/obj/proc/tumble(var/dist = 2)
+ set waitfor = FALSE
+ if (dist >= 1)
+ dist += rand(0,1)
+ for(var/i = 1, i <= dist, i++)
+ if(src)
+ step(src, pick(NORTH,SOUTH,EAST,WEST))
+ sleep(rand(2,4))
diff --git a/code/game/objects/random/_random.dm b/code/game/objects/random/_random.dm
index b559495eb5..8b616c83f5 100644
--- a/code/game/objects/random/_random.dm
+++ b/code/game/objects/random/_random.dm
@@ -11,15 +11,7 @@
. = ..()
if (!prob(spawn_nothing_percentage))
spawn_item()
- Random_SafeDestroy(0)
-
-// This function should, theoretically, guarantee the deletion of the random object. Not all of them destroy themselves for some reason, especially if created through non-standard means.
-/obj/random/proc/Random_SafeDestroy(var/recursion_level)
- set waitfor = FALSE
- sleep(30)
- qdel(src)
- if(src && recursion_level < 5)
- Random_SafeDestroy(recursion_level + 1)
+ return INITIALIZE_HINT_QDEL
// this function should return a specific item to spawn
/obj/random/proc/item_to_spawn()
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index 3e571009d2..f81419be75 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -8,11 +8,21 @@
var/parts
var/list/climbers = list()
var/block_turf_edges = FALSE // If true, turf edge icons will not be made on the turf this occupies.
+
+ var/list/connections = list("0", "0", "0", "0")
+ var/list/other_connections = list("0", "0", "0", "0")
+ var/list/blend_objects = newlist() // Objects which to blend with
+ var/list/noblend_objects = newlist() //Objects to avoid blending with (such as children of listed blend objects.
+
+/obj/structure/Initialize()
+ . = ..()
+ if(climbable)
+ verbs += /obj/structure/proc/climb_on
/obj/structure/Destroy()
if(parts)
new parts(loc)
- . = ..()
+ return ..()
/obj/structure/attack_hand(mob/user)
if(breakable)
@@ -46,13 +56,7 @@
if(3.0)
return
-/obj/structure/New()
- ..()
- if(climbable)
- verbs += /obj/structure/proc/climb_on
-
/obj/structure/proc/climb_on()
-
set name = "Climb structure"
set desc = "Climbs onto a structure."
set category = "Object"
@@ -61,7 +65,6 @@
do_climb(usr)
/obj/structure/MouseDrop_T(mob/target, mob/user)
-
var/mob/living/H = user
if(istype(H) && can_climb(H) && target == user)
do_climb(target)
@@ -185,3 +188,69 @@
user.do_attack_animation(src)
spawn(1) qdel(src)
return 1
+
+/obj/structure/proc/can_visually_connect()
+ return anchored
+
+/obj/structure/proc/can_visually_connect_to(var/obj/structure/S)
+ return istype(S, src)
+
+/obj/structure/proc/update_connections(propagate = 0)
+ var/list/dirs = list()
+ var/list/other_dirs = list()
+
+ for(var/obj/structure/S in orange(src, 1))
+ if(can_visually_connect_to(S))
+ if(S.can_visually_connect())
+ if(propagate)
+ //S.update_connections() //Not here
+ S.update_icon()
+ dirs += get_dir(src, S)
+
+ if(!can_visually_connect())
+ connections = list("0", "0", "0", "0")
+ other_connections = list("0", "0", "0", "0")
+ return FALSE
+
+ for(var/direction in cardinal)
+ var/turf/T = get_step(src, direction)
+ var/success = 0
+ for(var/b_type in blend_objects)
+ if(istype(T, b_type))
+ success = 1
+ if(propagate)
+ var/turf/simulated/wall/W = T
+ if(istype(W))
+ W.update_connections(1)
+ if(success)
+ break // breaks inner loop
+ if(!success)
+ blend_obj_loop:
+ for(var/obj/O in T)
+ for(var/b_type in blend_objects)
+ if(istype(O, b_type))
+ success = 1
+ for(var/obj/structure/S in T)
+ if(istype(S, src))
+ success = 0
+ for(var/nb_type in noblend_objects)
+ if(istype(O, nb_type))
+ success = 0
+
+ if(success)
+ break blend_obj_loop // breaks outer loop
+
+ if(success)
+ dirs += get_dir(src, T)
+ other_dirs += get_dir(src, T)
+
+ refresh_neighbors()
+
+ connections = dirs_to_corner_states(dirs)
+ other_connections = dirs_to_corner_states(other_dirs)
+ return TRUE
+
+/obj/structure/proc/refresh_neighbors()
+ for(var/thing in RANGE_TURFS(1, src))
+ var/turf/T = thing
+ T.update_icon()
diff --git a/code/game/objects/structures/catwalk.dm b/code/game/objects/structures/catwalk.dm
index 26e040c7e9..147a5dc38f 100644
--- a/code/game/objects/structures/catwalk.dm
+++ b/code/game/objects/structures/catwalk.dm
@@ -1,107 +1,183 @@
-// Based on catwalk.dm from https://github.com/Endless-Horizon/CEV-Eris
/obj/structure/catwalk
name = "catwalk"
desc = "Cats really don't like these things."
- plane = DECAL_PLANE
- layer = ABOVE_UTILITY
icon = 'icons/turf/catwalks.dmi'
icon_state = "catwalk"
+ plane = DECAL_PLANE
+ layer = ABOVE_UTILITY
density = 0
+ anchored = 1.0
+ var/hatch_open = FALSE
+ var/plating_color = null
+ var/obj/item/stack/tile/plated_tile = null
+ var/static/plating_colors = list(
+ /obj/item/stack/tile/floor = "#858a8f",
+ /obj/item/stack/tile/floor/dark = "#4f4f4f",
+ /obj/item/stack/tile/floor/white = "#e8e8e8")
var/health = 100
var/maxhealth = 100
- anchored = 1.0
/obj/structure/catwalk/Initialize()
. = ..()
- for(var/obj/structure/catwalk/O in range(1))
- O.update_icon()
for(var/obj/structure/catwalk/C in get_turf(src))
if(C != src)
- warning("Duplicate [type] in [loc] ([x], [y], [z])")
- return INITIALIZE_HINT_QDEL
+ qdel(C)
+ update_connections(1)
update_icon()
+
/obj/structure/catwalk/Destroy()
- var/turf/location = loc
- . = ..()
- location.alpha = initial(location.alpha)
- for(var/obj/structure/catwalk/L in orange(location, 1))
- L.update_icon()
+ redraw_nearby_catwalks()
+ return ..()
+
+/obj/structure/catwalk/proc/redraw_nearby_catwalks()
+ for(var/direction in alldirs)
+ var/obj/structure/catwalk/L = locate() in get_step(src, direction)
+ if(L)
+ L.update_connections()
+ L.update_icon() //so siding get updated properly
+
/obj/structure/catwalk/update_icon()
- var/connectdir = 0
- for(var/direction in cardinal)
- if(locate(/obj/structure/catwalk, get_step(src, direction)))
- connectdir |= direction
-
- //Check the diagonal connections for corners, where you have, for example, connections both north and east. In this case it checks for a north-east connection to determine whether to add a corner marker or not.
- var/diagonalconnect = 0 //1 = NE; 2 = SE; 4 = NW; 8 = SW
- //NORTHEAST
- if(connectdir & NORTH && connectdir & EAST)
- if(locate(/obj/structure/catwalk, get_step(src, NORTHEAST)))
- diagonalconnect |= 1
- //SOUTHEAST
- if(connectdir & SOUTH && connectdir & EAST)
- if(locate(/obj/structure/catwalk, get_step(src, SOUTHEAST)))
- diagonalconnect |= 2
- //NORTHWEST
- if(connectdir & NORTH && connectdir & WEST)
- if(locate(/obj/structure/catwalk, get_step(src, NORTHWEST)))
- diagonalconnect |= 4
- //SOUTHWEST
- if(connectdir & SOUTH && connectdir & WEST)
- if(locate(/obj/structure/catwalk, get_step(src, SOUTHWEST)))
- diagonalconnect |= 8
-
- icon_state = "catwalk[connectdir]-[diagonalconnect]"
-
+ update_connections()
+ cut_overlays()
+ icon_state = ""
+ var/image/I
+ if(!hatch_open)
+ for(var/i = 1 to 4)
+ I = image(icon, "catwalk[connections[i]]", dir = 1<<(i-1))
+ add_overlay(I)
+ if(plating_color)
+ I = image(icon, "plated")
+ I.color = plating_color
+ add_overlay(I)
/obj/structure/catwalk/ex_act(severity)
switch(severity)
- if(1.0)
+ if(1)
+ new /obj/item/stack/rods(src.loc)
qdel(src)
- if(2.0)
+ if(2)
+ new /obj/item/stack/rods(src.loc)
qdel(src)
- if(3.0)
- qdel(src)
- return
+
+/obj/structure/catwalk/attack_robot(var/mob/user)
+ if(Adjacent(user))
+ attack_hand(user)
+
+/obj/structure/catwalk/proc/deconstruct(mob/user)
+ playsound(src, 'sound/items/Welder.ogg', 100, 1)
+ to_chat(user, "Slicing \the [src] joints ...")
+ new /obj/item/stack/rods(src.loc)
+ new /obj/item/stack/rods(src.loc)
+ //Lattice would delete itself, but let's save ourselves a new obj
+ if(isspace(loc) || isopenspace(loc))
+ new /obj/structure/lattice/(src.loc)
+ if(plated_tile)
+ new plated_tile(src.loc)
+ qdel(src)
/obj/structure/catwalk/attackby(obj/item/C as obj, mob/user as mob)
if(istype(C, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = C
- if(WT.isOn())
- if(WT.remove_fuel(0, user))
- to_chat(user, "Slicing lattice joints ...")
- new /obj/item/stack/rods(src.loc)
- new /obj/item/stack/rods(src.loc)
- new /obj/structure/lattice(src.loc)
- qdel(src)
- if(C.is_screwdriver())
- if(health < maxhealth)
- to_chat(user, "You begin repairing \the [src.name] with \the [C.name].")
- if(do_after(user, 20, src))
- health = maxhealth
- else
- take_damage(C.force)
- user.setClickCooldown(user.get_attack_speed(C))
- return ..()
+ if(WT.isOn() && WT.remove_fuel(0, user))
+ deconstruct(user)
+ return
+ if(C.is_crowbar() && plated_tile)
+ hatch_open = !hatch_open
+ if(hatch_open)
+ playsound(src, 'sound/items/Crowbar.ogg', 100, 2)
+ to_chat(user, "You pry open \the [src]'s maintenance hatch.")
+ else
+ playsound(src, 'sound/items/Deconstruct.ogg', 100, 2)
+ to_chat(user, "You shut \the [src]'s maintenance hatch.")
+ update_icon()
+ return
+ if(istype(C, /obj/item/stack/tile/floor) && !plated_tile)
+ var/obj/item/stack/tile/floor/ST = C
+ to_chat(user, "Placing tile...")
+ if (!do_after(user, 10))
+ return
+ if(!ST.use(1))
+ return
+ to_chat(user, "You plate \the [src]")
+ name = "plated catwalk"
+ plated_tile = C.type
+ src.add_fingerprint(user)
+ for(var/tiletype in plating_colors)
+ if(istype(ST, tiletype))
+ plating_color = plating_colors[tiletype]
+ update_icon()
+
+/obj/structure/catwalk/refresh_neighbors()
+ return
+
+/obj/structure/catwalk/take_damage(amount)
+ health -= amount
+ if(health <= 0)
+ visible_message("\The [src] breaks down!")
+ playsound(src, 'sound/effects/grillehit.ogg', 50, 1)
+ new /obj/item/stack/rods(get_turf(src))
+ Destroy()
/obj/structure/catwalk/Crossed()
. = ..()
if(isliving(usr) && !usr.is_incorporeal())
playsound(src, pick('sound/effects/footstep/catwalk1.ogg', 'sound/effects/footstep/catwalk2.ogg', 'sound/effects/footstep/catwalk3.ogg', 'sound/effects/footstep/catwalk4.ogg', 'sound/effects/footstep/catwalk5.ogg'), 25, 1)
-/obj/structure/catwalk/CheckExit(atom/movable/O, turf/target)
- if(O.checkpass(PASSGRILLE))
- return 1
- if(target && target.z < src.z)
- return 0
- return 1
+/obj/effect/catwalk_plated
+ name = "plated catwalk spawner"
+ icon = 'icons/turf/catwalks.dmi'
+ icon_state = "catwalk_plated"
+ density = 1
+ anchored = 1.0
+ var/activated = FALSE
+ plane = DECAL_PLANE
+ layer = ABOVE_UTILITY
+ var/tile = /obj/item/stack/tile/floor
+ var/platecolor = "#858a8f"
-/obj/structure/catwalk/take_damage(amount)
- health -= amount
- if(health <= 0)
- visible_message("\The [src] breaks down!")
- playsound(loc, 'sound/effects/grillehit.ogg', 50, 1)
- new /obj/item/stack/rods(get_turf(src))
- Destroy()
\ No newline at end of file
+/obj/effect/catwalk_plated/Initialize(mapload)
+ . = ..()
+ activate()
+
+/obj/effect/catwalk_plated/CanPass()
+ return 0
+
+/obj/effect/catwalk_plated/attack_hand()
+ attack_generic()
+
+/obj/effect/catwalk_plated/attack_ghost()
+ attack_generic()
+
+/obj/effect/catwalk_plated/attack_generic()
+ activate()
+
+/obj/effect/catwalk_plated/proc/activate()
+ if(activated) return
+
+ if(locate(/obj/structure/catwalk) in loc)
+ warning("Frame Spawner: A catwalk already exists at [loc.x]-[loc.y]-[loc.z]")
+ else
+ var/obj/structure/catwalk/C = new /obj/structure/catwalk(loc)
+ C.plated_tile = tile
+ C.plating_color = platecolor
+ C.name = "plated catwalk"
+ C.update_icon()
+ activated = 1
+ /* We don't have wallframes - yet
+ for(var/turf/T in orange(src, 1))
+ for(var/obj/effect/wallframe_spawn/other in T)
+ if(!other.activated) other.activate()
+ */
+ qdel(src)
+
+/obj/effect/catwalk_plated/dark
+ icon_state = "catwalk_plateddark"
+ tile = /obj/item/stack/tile/floor/dark
+ platecolor = "#4f4f4f"
+
+/obj/effect/catwalk_plated/white
+ icon_state = "catwalk_platedwhite"
+ tile = /obj/item/stack/tile/floor/white
+ platecolor = "#e8e8e8"
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 3ff2f5fdd7..7573057a94 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -1,474 +1,473 @@
-/obj/structure/closet
- name = "closet"
- desc = "It's a basic storage unit."
- icon = 'icons/obj/closet.dmi'
- icon_state = "closed"
- density = 1
- w_class = ITEMSIZE_HUGE
- layer = UNDER_JUNK_LAYER
- var/icon_closed = "closed"
- var/icon_opened = "open"
- var/opened = 0
- var/sealed = 0
- var/seal_tool = /obj/item/weapon/weldingtool //Tool used to seal the closet, defaults to welder
- var/wall_mounted = 0 //never solid (You can always pass over it)
- var/health = 100
-
- var/breakout = 0 //if someone is currently breaking out. mutex
- var/breakout_time = 2 //2 minutes by default
- var/breakout_sound = 'sound/effects/grillehit.ogg' //Sound that plays while breaking out
-
- var/storage_capacity = 2 * MOB_MEDIUM //This is so that someone can't pack hundreds of items in a locker/crate
- //then open it in a populated area to crash clients.
- var/storage_cost = 40 //How much space this closet takes up if it's stuffed in another closet
-
- var/open_sound = 'sound/machines/click.ogg'
- var/close_sound = 'sound/machines/click.ogg'
-
- var/store_misc = 1 //Chameleon item check
- var/store_items = 1 //Will the closet store items?
- var/store_mobs = 1 //Will the closet store mobs?
- var/max_closets = 0 //Number of other closets allowed on tile before it won't close.
-
- var/list/starts_with
-
-/obj/structure/closet/Initialize()
- ..()
- // Closets need to come later because of spawners potentially creating objects during init.
- return INITIALIZE_HINT_LATELOAD
-
-/obj/structure/closet/LateInitialize()
- . = ..()
- if(starts_with)
- create_objects_in_loc(src, starts_with)
- starts_with = null
-
- if(!opened) // if closed, any item at the crate's loc is put in the contents
- var/obj/item/I
- for(I in src.loc)
- if(I.density || I.anchored || I == src) continue
- I.forceMove(src)
- // adjust locker size to hold all items with 5 units of free store room
- var/content_size = 0
- for(I in src.contents)
- content_size += CEILING(I.w_class/2, 1)
- if(content_size > storage_capacity-5)
- storage_capacity = content_size + 5
- update_icon()
-
-/obj/structure/closet/examine(mob/user)
- . = ..()
- if(Adjacent(user) || isobserver(user))
- var/content_size = 0
- for(var/obj/item/I in src.contents)
- if(!I.anchored)
- content_size += CEILING(I.w_class/2, 1)
- if(!content_size)
- . += "It is empty."
- else if(storage_capacity > content_size*4)
- . += "It is barely filled."
- else if(storage_capacity > content_size*2)
- . += "It is less than half full."
- else if(storage_capacity > content_size)
- . += "There is still some free space."
- else
- . += "It is full."
-
- if(!src.opened && isobserver(user))
- . += "It contains: [counting_english_list(contents)]"
-
-/obj/structure/closet/CanPass(atom/movable/mover, turf/target)
- if(wall_mounted)
- return TRUE
- return ..()
-
-/obj/structure/closet/proc/can_open()
- if(src.sealed)
- return 0
- return 1
-
-/obj/structure/closet/proc/can_close()
- var/closet_count = 0
- for(var/obj/structure/closet/closet in get_turf(src))
- if(closet != src)
- if(!closet.anchored)
- closet_count ++
- if(closet_count > max_closets)
- return 0
- return 1
-
-/obj/structure/closet/proc/dump_contents()
- //Cham Projector Exception
- for(var/obj/effect/dummy/chameleon/AD in src)
- AD.forceMove(src.loc)
-
- for(var/obj/I in src)
- I.forceMove(src.loc)
-
- for(var/mob/M in src)
- M.forceMove(src.loc)
- if(M.client)
- M.client.eye = M.client.mob
- M.client.perspective = MOB_PERSPECTIVE
-
-/obj/structure/closet/proc/open()
- if(src.opened)
- return 0
-
- if(!src.can_open())
- return 0
-
- src.dump_contents()
-
- src.icon_state = src.icon_opened
- src.opened = 1
- playsound(src.loc, open_sound, 15, 1, -3)
- if(initial(density))
- density = !density
- return 1
-
-/obj/structure/closet/proc/close()
- if(!src.opened)
- return 0
- if(!src.can_close())
- return 0
-
- var/stored_units = 0
-
- if(store_misc)
- stored_units += store_misc(stored_units)
- if(store_items)
- stored_units += store_items(stored_units)
- if(store_mobs)
- stored_units += store_mobs(stored_units)
- if(max_closets)
- stored_units += store_closets(stored_units)
-
- src.icon_state = src.icon_closed
- src.opened = 0
-
- playsound(src.loc, close_sound, 15, 1, -3)
- if(initial(density))
- density = !density
- return 1
-
-//Cham Projector Exception
-/obj/structure/closet/proc/store_misc(var/stored_units)
- var/added_units = 0
- for(var/obj/effect/dummy/chameleon/AD in src.loc)
- if((stored_units + added_units) > storage_capacity)
- break
- AD.forceMove(src)
- added_units++
- return added_units
-
-/obj/structure/closet/proc/store_items(var/stored_units)
- var/added_units = 0
- for(var/obj/item/I in src.loc)
- var/item_size = CEILING(I.w_class / 2, 1)
- if(stored_units + added_units + item_size > storage_capacity)
- continue
- if(!I.anchored)
- I.forceMove(src)
- added_units += item_size
- return added_units
-
-/obj/structure/closet/proc/store_mobs(var/stored_units)
- var/added_units = 0
- for(var/mob/living/M in src.loc)
- if(M.buckled || M.pinned.len)
- continue
- if(stored_units + added_units + M.mob_size > storage_capacity)
- break
- if(M.client)
- M.client.perspective = EYE_PERSPECTIVE
- M.client.eye = src
- M.forceMove(src)
- added_units += M.mob_size
- return added_units
-
-/obj/structure/closet/proc/store_closets(var/stored_units)
- var/added_units = 0
- for(var/obj/structure/closet/C in src.loc)
- if(C == src) //Don't store ourself
- continue
- if(C.anchored) //Don't worry about anchored things on the same tile
- continue
- if(C.max_closets) //Prevents recursive storage
- continue
- if(stored_units + added_units + storage_cost > storage_capacity)
- break
- C.forceMove(src)
- added_units += storage_cost
- return added_units
-
-
-/obj/structure/closet/proc/toggle(mob/user as mob)
- if(!(src.opened ? src.close() : src.open()))
- to_chat(user, "It won't budge!")
- return
- update_icon()
-
-// this should probably use dump_contents()
-/obj/structure/closet/ex_act(severity)
- switch(severity)
- if(1)
- for(var/atom/movable/A as mob|obj in src)//pulls everything out of the locker and hits it with an explosion
- A.forceMove(src.loc)
- A.ex_act(severity + 1)
- qdel(src)
- if(2)
- if(prob(50))
- for (var/atom/movable/A as mob|obj in src)
- A.forceMove(src.loc)
- A.ex_act(severity + 1)
- qdel(src)
- if(3)
- if(prob(5))
- for(var/atom/movable/A as mob|obj in src)
- A.forceMove(src.loc)
- qdel(src)
-
-/obj/structure/closet/blob_act()
- damage(100)
-
-/obj/structure/closet/proc/damage(var/damage)
- health -= damage
- if(health <= 0)
- for(var/atom/movable/A in src)
- A.forceMove(src.loc)
- qdel(src)
-
-/obj/structure/closet/bullet_act(var/obj/item/projectile/Proj)
- var/proj_damage = Proj.get_structure_damage()
- if(!proj_damage)
- return
-
- ..()
- damage(proj_damage)
-
- return
-
-/obj/structure/closet/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(src.opened)
- if(istype(W, /obj/item/weapon/grab))
- var/obj/item/weapon/grab/G = W
- src.MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet
- return 0
- if(istype(W,/obj/item/tk_grab))
- return 0
- if(istype(W, /obj/item/weapon/weldingtool))
- var/obj/item/weapon/weldingtool/WT = W
- if(!WT.remove_fuel(0,user))
- if(!WT.isOn())
- return
- else
- to_chat(user, "You need more welding fuel to complete this task.")
- return
- playsound(src, WT.usesound, 50)
- new /obj/item/stack/material/steel(src.loc)
- for(var/mob/M in viewers(src))
- M.show_message("\The [src] has been cut apart by [user] with \the [WT].", 3, "You hear welding.", 2)
- qdel(src)
- return
- if(istype(W, /obj/item/weapon/storage/laundry_basket) && W.contents.len)
- var/obj/item/weapon/storage/laundry_basket/LB = W
- var/turf/T = get_turf(src)
- for(var/obj/item/I in LB.contents)
- LB.remove_from_storage(I, T)
- user.visible_message("[user] empties \the [LB] into \the [src].", \
- "You empty \the [LB] into \the [src].", \
- "You hear rustling of clothes.")
- return
- if(isrobot(user))
- return
- if(W.loc != user) // This should stop mounted modules ending up outside the module.
- return
- usr.drop_item()
- if(W)
- W.forceMove(src.loc)
- else if(istype(W, /obj/item/weapon/packageWrap))
- return
- else if(seal_tool)
- if(istype(W, seal_tool))
- var/obj/item/weapon/S = W
- if(istype(S, /obj/item/weapon/weldingtool))
- var/obj/item/weapon/weldingtool/WT = S
- if(!WT.remove_fuel(0,user))
- if(!WT.isOn())
- return
- else
- to_chat(user, "You need more welding fuel to complete this task.")
- return
- if(do_after(user, 20 * S.toolspeed))
- playsound(src, S.usesound, 50)
- src.sealed = !src.sealed
- src.update_icon()
- for(var/mob/M in viewers(src))
- M.show_message("[src] has been [sealed?"sealed":"unsealed"] by [user.name].", 3)
- else if(W.is_wrench())
- if(sealed)
- if(anchored)
- user.visible_message("\The [user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
- else
- user.visible_message("\The [user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.")
- playsound(src, W.usesound, 50)
- if(do_after(user, 20 * W.toolspeed))
- if(!src) return
- to_chat(user, "You [anchored? "un" : ""]secured \the [src]!")
- anchored = !anchored
- else
- src.attack_hand(user)
- return
-
-/obj/structure/closet/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob)
- if(istype(O, /obj/screen)) //fix for HUD elements making their way into the world -Pete
- return
- if(O.loc == user)
- return
- if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis)
- return
- if((!( istype(O, /atom/movable) ) || O.anchored || !Adjacent(user) || !Adjacent(O) || !user.Adjacent(O) || user.contents.Find(src)))
- return
- if(!isturf(user.loc)) // are you in a container/closet/pod/etc?
- return
- if(!src.opened)
- return
- if(istype(O, /obj/structure/closet))
- return
- step_towards(O, src.loc)
- if(user != O)
- user.show_viewers("[user] stuffs [O] into [src]!")
- src.add_fingerprint(user)
- return
-
-/obj/structure/closet/attack_robot(mob/user)
- if(Adjacent(user))
- attack_hand(user)
-
-/obj/structure/closet/relaymove(mob/user as mob)
- if(user.stat || !isturf(src.loc))
- return
-
- if(!src.open())
- to_chat(user, "It won't budge!")
-
-/obj/structure/closet/attack_hand(mob/user as mob)
- src.add_fingerprint(user)
- src.toggle(user)
-
-// tk grab then use on self
-/obj/structure/closet/attack_self_tk(mob/user as mob)
- src.add_fingerprint(user)
- if(!src.toggle())
- to_chat(usr, "It won't budge!")
-
-/obj/structure/closet/verb/verb_toggleopen()
- set src in oview(1)
- set category = "Object"
- set name = "Toggle Open"
-
- if(!usr.canmove || usr.stat || usr.restrained())
- return
-
- if(ishuman(usr) || isrobot(usr))
- src.add_fingerprint(usr)
- src.toggle(usr)
- else
- to_chat(usr, "This mob type can't use this verb.")
-
-/obj/structure/closet/update_icon()//Putting the sealed stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot)
- overlays.Cut()
- if(!opened)
- icon_state = icon_closed
- if(sealed)
- overlays += "welded"
- else
- icon_state = icon_opened
-
-/obj/structure/closet/attack_generic(var/mob/user, var/damage, var/attack_message = "destroys")
- if(damage < STRUCTURE_MIN_DAMAGE_THRESHOLD)
- return
- user.do_attack_animation(src)
- visible_message("[user] [attack_message] the [src]!")
- dump_contents()
- spawn(1) qdel(src)
- return 1
-
-/obj/structure/closet/proc/req_breakout()
- if(opened)
- return 0 //Door's open... wait, why are you in it's contents then?
- if(!sealed)
- return 0 //closed but not sealed...
- return 1
-
-/obj/structure/closet/proc/mob_breakout(var/mob/living/escapee)
-
- if(breakout || !req_breakout())
- return
-
- escapee.setClickCooldown(100)
-
- //okay, so the closet is either sealed or locked... resist!!!
- to_chat(escapee, "You lean on the back of \the [src] and start pushing the door open. (this will take about [breakout_time] minutes)")
-
- visible_message("\The [src] begins to shake violently!")
-
- breakout = 1 //can't think of a better way to do this right now.
- for(var/i in 1 to (6*breakout_time * 2)) //minutes * 6 * 5seconds * 2
- if(!do_after(escapee, 50)) //5 seconds
- breakout = 0
- return
- if(!escapee || escapee.incapacitated() || escapee.loc != src)
- breakout = 0
- return //closet/user destroyed OR user dead/unconcious OR user no longer in closet OR closet opened
- //Perform the same set of checks as above for weld and lock status to determine if there is even still a point in 'resisting'...
- if(!req_breakout())
- breakout = 0
- return
-
- playsound(src.loc, breakout_sound, 100, 1)
- animate_shake()
- add_fingerprint(escapee)
-
- //Well then break it!
- breakout = 0
- to_chat(escapee, "You successfully break out!")
- visible_message("\The [escapee] successfully broke out of \the [src]!")
- playsound(src.loc, breakout_sound, 100, 1)
- break_open()
- animate_shake()
-
-/obj/structure/closet/proc/break_open()
- sealed = 0
- update_icon()
- //Do this to prevent contents from being opened into nullspace (read: bluespace)
- if(istype(loc, /obj/structure/bigDelivery))
- var/obj/structure/bigDelivery/BD = loc
- BD.unwrap()
- open()
-
-/obj/structure/closet/proc/animate_shake()
- var/init_px = pixel_x
- var/shake_dir = pick(-1, 1)
- animate(src, transform=turn(matrix(), 8*shake_dir), pixel_x=init_px + 2*shake_dir, time=1)
- animate(transform=null, pixel_x=init_px, time=6, easing=ELASTIC_EASING)
-
-/obj/structure/closet/onDropInto(var/atom/movable/AM)
- return
-
-/obj/structure/closet/AllowDrop()
- return TRUE
-
-/obj/structure/closet/return_air_for_internal_lifeform(var/mob/living/L)
- if(src.loc)
- if(istype(src.loc, /obj/structure/closet))
- return (loc.return_air_for_internal_lifeform(L))
- return return_air()
-
-/obj/structure/closet/take_damage(var/damage)
- if(damage < STRUCTURE_MIN_DAMAGE_THRESHOLD)
- return
- dump_contents()
- spawn(1) qdel(src)
- return 1
+/obj/structure/closet
+ name = "closet"
+ desc = "It's a basic storage unit."
+ icon = 'icons/obj/closet.dmi'
+ icon_state = "closed"
+ density = 1
+ w_class = ITEMSIZE_HUGE
+ layer = UNDER_JUNK_LAYER
+ var/icon_closed = "closed"
+ var/icon_opened = "open"
+ var/opened = 0
+ var/sealed = 0
+ var/seal_tool = /obj/item/weapon/weldingtool //Tool used to seal the closet, defaults to welder
+ var/wall_mounted = 0 //never solid (You can always pass over it)
+ var/health = 100
+
+ var/breakout = 0 //if someone is currently breaking out. mutex
+ var/breakout_time = 2 //2 minutes by default
+ var/breakout_sound = 'sound/effects/grillehit.ogg' //Sound that plays while breaking out
+
+ var/storage_capacity = 2 * MOB_MEDIUM //This is so that someone can't pack hundreds of items in a locker/crate
+ //then open it in a populated area to crash clients.
+ var/storage_cost = 40 //How much space this closet takes up if it's stuffed in another closet
+
+ var/open_sound = 'sound/machines/click.ogg'
+ var/close_sound = 'sound/machines/click.ogg'
+
+ var/store_misc = 1 //Chameleon item check
+ var/store_items = 1 //Will the closet store items?
+ var/store_mobs = 1 //Will the closet store mobs?
+ var/max_closets = 0 //Number of other closets allowed on tile before it won't close.
+
+ var/list/starts_with
+
+/obj/structure/closet/Initialize()
+ ..()
+ // Closets need to come later because of spawners potentially creating objects during init.
+ return INITIALIZE_HINT_LATELOAD
+
+/obj/structure/closet/LateInitialize()
+ . = ..()
+ if(starts_with)
+ create_objects_in_loc(src, starts_with)
+ starts_with = null
+
+ if(!opened) // if closed, any item at the crate's loc is put in the contents
+ var/obj/item/I
+ for(I in src.loc)
+ if(I.density || I.anchored || I == src) continue
+ I.forceMove(src)
+ // adjust locker size to hold all items with 5 units of free store room
+ var/content_size = 0
+ for(I in src.contents)
+ content_size += CEILING(I.w_class/2, 1)
+ if(content_size > storage_capacity-5)
+ storage_capacity = content_size + 5
+ update_icon()
+
+/obj/structure/closet/examine(mob/user)
+ . = ..()
+ if(Adjacent(user) || isobserver(user))
+ var/content_size = 0
+ for(var/obj/item/I in src.contents)
+ if(!I.anchored)
+ content_size += CEILING(I.w_class/2, 1)
+ if(!content_size)
+ . += "It is empty."
+ else if(storage_capacity > content_size*4)
+ . += "It is barely filled."
+ else if(storage_capacity > content_size*2)
+ . += "It is less than half full."
+ else if(storage_capacity > content_size)
+ . += "There is still some free space."
+ else
+ . += "It is full."
+
+ if(!src.opened && isobserver(user))
+ . += "It contains: [counting_english_list(contents)]"
+
+/obj/structure/closet/CanPass(atom/movable/mover, turf/target)
+ if(wall_mounted)
+ return TRUE
+ return ..()
+
+/obj/structure/closet/proc/can_open()
+ if(src.sealed)
+ return 0
+ return 1
+
+/obj/structure/closet/proc/can_close()
+ var/closet_count = 0
+ for(var/obj/structure/closet/closet in get_turf(src))
+ if(closet != src)
+ if(!closet.anchored)
+ closet_count ++
+ if(closet_count > max_closets)
+ return 0
+ return 1
+
+/obj/structure/closet/proc/dump_contents()
+ //Cham Projector Exception
+ for(var/obj/effect/dummy/chameleon/AD in src)
+ AD.forceMove(src.loc)
+
+ for(var/obj/I in src)
+ I.forceMove(src.loc)
+
+ for(var/mob/M in src)
+ M.forceMove(src.loc)
+ if(M.client)
+ M.client.eye = M.client.mob
+ M.client.perspective = MOB_PERSPECTIVE
+
+/obj/structure/closet/proc/open()
+ if(src.opened)
+ return 0
+
+ if(!src.can_open())
+ return 0
+
+ src.dump_contents()
+
+ src.icon_state = src.icon_opened
+ src.opened = 1
+ playsound(src, open_sound, 15, 1, -3)
+ if(initial(density))
+ density = !density
+ return 1
+
+/obj/structure/closet/proc/close()
+ if(!src.opened)
+ return 0
+ if(!src.can_close())
+ return 0
+
+ var/stored_units = 0
+
+ if(store_misc)
+ stored_units += store_misc(stored_units)
+ if(store_items)
+ stored_units += store_items(stored_units)
+ if(store_mobs)
+ stored_units += store_mobs(stored_units)
+ if(max_closets)
+ stored_units += store_closets(stored_units)
+
+ src.icon_state = src.icon_closed
+ src.opened = 0
+
+ playsound(src, close_sound, 15, 1, -3)
+ if(initial(density))
+ density = !density
+ return 1
+
+//Cham Projector Exception
+/obj/structure/closet/proc/store_misc(var/stored_units)
+ var/added_units = 0
+ for(var/obj/effect/dummy/chameleon/AD in src.loc)
+ if((stored_units + added_units) > storage_capacity)
+ break
+ AD.forceMove(src)
+ added_units++
+ return added_units
+
+/obj/structure/closet/proc/store_items(var/stored_units)
+ var/added_units = 0
+ for(var/obj/item/I in src.loc)
+ var/item_size = CEILING(I.w_class / 2, 1)
+ if(stored_units + added_units + item_size > storage_capacity)
+ continue
+ if(!I.anchored)
+ I.forceMove(src)
+ added_units += item_size
+ return added_units
+
+/obj/structure/closet/proc/store_mobs(var/stored_units)
+ var/added_units = 0
+ for(var/mob/living/M in src.loc)
+ if(M.buckled || M.pinned.len)
+ continue
+ if(stored_units + added_units + M.mob_size > storage_capacity)
+ break
+ if(M.client)
+ M.client.perspective = EYE_PERSPECTIVE
+ M.client.eye = src
+ M.forceMove(src)
+ added_units += M.mob_size
+ return added_units
+
+/obj/structure/closet/proc/store_closets(var/stored_units)
+ var/added_units = 0
+ for(var/obj/structure/closet/C in src.loc)
+ if(C == src) //Don't store ourself
+ continue
+ if(C.anchored) //Don't worry about anchored things on the same tile
+ continue
+ if(C.max_closets) //Prevents recursive storage
+ continue
+ if(stored_units + added_units + storage_cost > storage_capacity)
+ break
+ C.forceMove(src)
+ added_units += storage_cost
+ return added_units
+
+
+/obj/structure/closet/proc/toggle(mob/user as mob)
+ if(!(src.opened ? src.close() : src.open()))
+ to_chat(user, "It won't budge!")
+ return
+ update_icon()
+
+// this should probably use dump_contents()
+/obj/structure/closet/ex_act(severity)
+ switch(severity)
+ if(1)
+ for(var/atom/movable/A as mob|obj in src)//pulls everything out of the locker and hits it with an explosion
+ A.forceMove(src.loc)
+ A.ex_act(severity + 1)
+ qdel(src)
+ if(2)
+ if(prob(50))
+ for (var/atom/movable/A as mob|obj in src)
+ A.forceMove(src.loc)
+ A.ex_act(severity + 1)
+ qdel(src)
+ if(3)
+ if(prob(5))
+ for(var/atom/movable/A as mob|obj in src)
+ A.forceMove(src.loc)
+ qdel(src)
+
+/obj/structure/closet/blob_act()
+ damage(100)
+
+/obj/structure/closet/proc/damage(var/damage)
+ health -= damage
+ if(health <= 0)
+ for(var/atom/movable/A in src)
+ A.forceMove(src.loc)
+ qdel(src)
+
+/obj/structure/closet/bullet_act(var/obj/item/projectile/Proj)
+ var/proj_damage = Proj.get_structure_damage()
+ if(!proj_damage)
+ return
+
+ ..()
+ damage(proj_damage)
+
+ return
+
+/obj/structure/closet/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(src.opened)
+ if(istype(W, /obj/item/weapon/grab))
+ var/obj/item/weapon/grab/G = W
+ src.MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet
+ return 0
+ if(istype(W,/obj/item/tk_grab))
+ return 0
+ if(istype(W, /obj/item/weapon/weldingtool))
+ var/obj/item/weapon/weldingtool/WT = W
+ if(!WT.remove_fuel(0,user))
+ if(!WT.isOn())
+ return
+ else
+ to_chat(user, "You need more welding fuel to complete this task.")
+ return
+ playsound(src, WT.usesound, 50)
+ new /obj/item/stack/material/steel(src.loc)
+ for(var/mob/M in viewers(src))
+ M.show_message("\The [src] has been cut apart by [user] with \the [WT].", 3, "You hear welding.", 2)
+ qdel(src)
+ return
+ if(istype(W, /obj/item/weapon/storage/laundry_basket) && W.contents.len)
+ var/obj/item/weapon/storage/laundry_basket/LB = W
+ var/turf/T = get_turf(src)
+ for(var/obj/item/I in LB.contents)
+ LB.remove_from_storage(I, T)
+ user.visible_message("[user] empties \the [LB] into \the [src].", \
+ "You empty \the [LB] into \the [src].", \
+ "You hear rustling of clothes.")
+ return
+ if(isrobot(user))
+ return
+ if(W.loc != user) // This should stop mounted modules ending up outside the module.
+ return
+ usr.drop_item()
+ if(W)
+ W.forceMove(src.loc)
+ else if(istype(W, /obj/item/weapon/packageWrap))
+ return
+ else if(seal_tool)
+ if(istype(W, seal_tool))
+ var/obj/item/weapon/S = W
+ if(istype(S, /obj/item/weapon/weldingtool))
+ var/obj/item/weapon/weldingtool/WT = S
+ if(!WT.remove_fuel(0,user))
+ if(!WT.isOn())
+ return
+ else
+ to_chat(user, "You need more welding fuel to complete this task.")
+ return
+ if(do_after(user, 20 * S.toolspeed))
+ playsound(src, S.usesound, 50)
+ src.sealed = !src.sealed
+ src.update_icon()
+ for(var/mob/M in viewers(src))
+ M.show_message("[src] has been [sealed?"sealed":"unsealed"] by [user.name].", 3)
+ else if(W.is_wrench())
+ if(sealed)
+ if(anchored)
+ user.visible_message("\The [user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
+ else
+ user.visible_message("\The [user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.")
+ playsound(src, W.usesound, 50)
+ if(do_after(user, 20 * W.toolspeed))
+ if(!src) return
+ to_chat(user, "You [anchored? "un" : ""]secured \the [src]!")
+ anchored = !anchored
+ else
+ src.attack_hand(user)
+ return
+
+/obj/structure/closet/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob)
+ if(istype(O, /obj/screen)) //fix for HUD elements making their way into the world -Pete
+ return
+ if(O.loc == user)
+ return
+ if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis)
+ return
+ if((!( istype(O, /atom/movable) ) || O.anchored || !Adjacent(user) || !Adjacent(O) || !user.Adjacent(O) || user.contents.Find(src)))
+ return
+ if(!isturf(user.loc)) // are you in a container/closet/pod/etc?
+ return
+ if(!src.opened)
+ return
+ if(istype(O, /obj/structure/closet))
+ return
+ step_towards(O, src.loc)
+ if(user != O)
+ user.show_viewers("[user] stuffs [O] into [src]!")
+ src.add_fingerprint(user)
+ return
+
+/obj/structure/closet/attack_robot(mob/user)
+ if(Adjacent(user))
+ attack_hand(user)
+
+/obj/structure/closet/relaymove(mob/user as mob)
+ if(user.stat || !isturf(src.loc))
+ return
+
+ if(!src.open())
+ to_chat(user, "It won't budge!")
+
+/obj/structure/closet/attack_hand(mob/user as mob)
+ src.add_fingerprint(user)
+ src.toggle(user)
+
+// tk grab then use on self
+/obj/structure/closet/attack_self_tk(mob/user as mob)
+ src.add_fingerprint(user)
+ if(!src.toggle())
+ to_chat(usr, "It won't budge!")
+
+/obj/structure/closet/verb/verb_toggleopen()
+ set src in oview(1)
+ set category = "Object"
+ set name = "Toggle Open"
+
+ if(!usr.canmove || usr.stat || usr.restrained())
+ return
+
+ if(ishuman(usr) || isrobot(usr))
+ src.add_fingerprint(usr)
+ src.toggle(usr)
+ else
+ to_chat(usr, "This mob type can't use this verb.")
+
+/obj/structure/closet/update_icon()//Putting the sealed stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot)
+ overlays.Cut()
+ if(!opened)
+ icon_state = icon_closed
+ if(sealed)
+ overlays += "welded"
+ else
+ icon_state = icon_opened
+
+/obj/structure/closet/attack_generic(var/mob/user, var/damage, var/attack_message = "destroys")
+ if(damage < STRUCTURE_MIN_DAMAGE_THRESHOLD)
+ return
+ user.do_attack_animation(src)
+ visible_message("[user] [attack_message] the [src]!")
+ dump_contents()
+ spawn(1) qdel(src)
+ return 1
+
+/obj/structure/closet/proc/req_breakout()
+ if(opened)
+ return 0 //Door's open... wait, why are you in it's contents then?
+ if(!sealed)
+ return 0 //closed but not sealed...
+ return 1
+
+/obj/structure/closet/container_resist(var/mob/living/escapee)
+ if(breakout || !req_breakout())
+ return
+
+ escapee.setClickCooldown(100)
+
+ //okay, so the closet is either sealed or locked... resist!!!
+ to_chat(escapee, "You lean on the back of \the [src] and start pushing the door open. (this will take about [breakout_time] minutes)")
+
+ visible_message("\The [src] begins to shake violently!")
+
+ breakout = 1 //can't think of a better way to do this right now.
+ for(var/i in 1 to (6*breakout_time * 2)) //minutes * 6 * 5seconds * 2
+ if(!do_after(escapee, 50)) //5 seconds
+ breakout = 0
+ return
+ if(!escapee || escapee.incapacitated() || escapee.loc != src)
+ breakout = 0
+ return //closet/user destroyed OR user dead/unconcious OR user no longer in closet OR closet opened
+ //Perform the same set of checks as above for weld and lock status to determine if there is even still a point in 'resisting'...
+ if(!req_breakout())
+ breakout = 0
+ return
+
+ playsound(src, breakout_sound, 100, 1)
+ animate_shake()
+ add_fingerprint(escapee)
+
+ //Well then break it!
+ breakout = 0
+ to_chat(escapee, "You successfully break out!")
+ visible_message("\The [escapee] successfully broke out of \the [src]!")
+ playsound(src, breakout_sound, 100, 1)
+ break_open()
+ animate_shake()
+
+/obj/structure/closet/proc/break_open()
+ sealed = 0
+ update_icon()
+ //Do this to prevent contents from being opened into nullspace (read: bluespace)
+ if(istype(loc, /obj/structure/bigDelivery))
+ var/obj/structure/bigDelivery/BD = loc
+ BD.unwrap()
+ open()
+
+/obj/structure/closet/proc/animate_shake()
+ var/init_px = pixel_x
+ var/shake_dir = pick(-1, 1)
+ animate(src, transform=turn(matrix(), 8*shake_dir), pixel_x=init_px + 2*shake_dir, time=1)
+ animate(transform=null, pixel_x=init_px, time=6, easing=ELASTIC_EASING)
+
+/obj/structure/closet/onDropInto(var/atom/movable/AM)
+ return
+
+/obj/structure/closet/AllowDrop()
+ return TRUE
+
+/obj/structure/closet/return_air_for_internal_lifeform(var/mob/living/L)
+ if(src.loc)
+ if(istype(src.loc, /obj/structure/closet))
+ return (loc.return_air_for_internal_lifeform(L))
+ return return_air()
+
+/obj/structure/closet/take_damage(var/damage)
+ if(damage < STRUCTURE_MIN_DAMAGE_THRESHOLD)
+ return
+ dump_contents()
+ spawn(1) qdel(src)
+ return 1
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm
index 0a77e4cafc..3094814d16 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm
@@ -78,8 +78,8 @@
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src.loc)
spark_system.start()
- playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1)
- playsound(src.loc, "sparks", 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, "sparks", 50, 1)
else
to_chat(user, "Access Denied")
return
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
index af07ceb9e5..c5732a337e 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
@@ -56,7 +56,7 @@
return
if(src.allowed(user))
src.locked = !src.locked
- playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3)
+ playsound(src, 'sound/machines/click.ogg', 15, 1, -3)
for(var/mob/O in viewers(user, 3))
if((O.client && !( O.blinded )))
to_chat(O, "The locker has been [locked ? null : "un"]locked by [user].")
@@ -86,8 +86,8 @@
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src.loc)
spark_system.start()
- playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1)
- playsound(src.loc, "sparks", 50, 1)
+ playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
+ playsound(src, "sparks", 50, 1)
else if(W.is_wrench())
if(sealed)
if(anchored)
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index 55378be679..e6f37f64d0 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -34,7 +34,7 @@
if(usr.stunned)
return 2
- playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3)
+ playsound(src, 'sound/machines/click.ogg', 15, 1, -3)
for(var/obj/O in src)
O.forceMove(get_turf(src))
icon_state = icon_opened
@@ -50,7 +50,7 @@
if(!src.can_close())
return 0
- playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3)
+ playsound(src, 'sound/machines/click.ogg', 15, 1, -3)
var/itemcount = 0
for(var/obj/O in get_turf(src))
if(itemcount >= storage_capacity)
@@ -97,7 +97,7 @@
else if(W.is_wirecutter())
if(rigged)
to_chat(user , "You cut away the wiring.")
- playsound(src.loc, W.usesound, 100, 1)
+ playsound(src, W.usesound, 100, 1)
rigged = 0
return
else return attack_hand(user)
@@ -206,7 +206,7 @@
overlays += emag
overlays += sparks
spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface*
- playsound(src.loc, "sparks", 60, 1)
+ playsound(src, "sparks", 60, 1)
src.locked = 0
src.broken = 1
to_chat(user, "You unlock \the [src].")
@@ -225,7 +225,7 @@
overlays += emag
overlays += sparks
spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface*
- playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1)
+ playsound(src, 'sound/effects/sparks4.ogg', 75, 1)
src.locked = 0
if(!opened && prob(20/severity))
if(!locked)
diff --git a/code/game/objects/structures/crates_lockers/vehiclecage.dm b/code/game/objects/structures/crates_lockers/vehiclecage.dm
index b565124e78..b98636eb16 100644
--- a/code/game/objects/structures/crates_lockers/vehiclecage.dm
+++ b/code/game/objects/structures/crates_lockers/vehiclecage.dm
@@ -32,11 +32,11 @@
if(!T)
to_chat(user, "You can't open this here!")
if(W.is_wrench() && do_after(user, 60 * W.toolspeed, src))
- playsound(loc, W.usesound, 50, 1)
+ playsound(src, W.usesound, 50, 1)
disassemble(W, user)
user.visible_message("[user] begins loosening \the [src]'s bolts.")
if(W.is_wirecutter() && do_after(user, 70 * W.toolspeed, src))
- playsound(loc, W.usesound, 50, 1)
+ playsound(src, W.usesound, 50, 1)
disassemble(W, user)
user.visible_message("[user] begins cutting \the [src]'s bolts.")
else
diff --git a/code/game/objects/structures/curtains.dm b/code/game/objects/structures/curtains.dm
index c44f714cc5..9de63fd3d0 100644
--- a/code/game/objects/structures/curtains.dm
+++ b/code/game/objects/structures/curtains.dm
@@ -22,7 +22,7 @@
..(P, def_zone)
/obj/structure/curtain/attack_hand(mob/user)
- playsound(get_turf(loc), "rustle", 15, 1, -5)
+ playsound(src, "rustle", 15, 1, -5)
toggle()
..()
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index 088dbd33c6..0f18d967b3 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -43,7 +43,7 @@
playsound(src, "shatter", 70, 1)
update_icon()
else
- playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
return
/obj/structure/displaycase/update_icon()
@@ -57,7 +57,7 @@
/obj/structure/displaycase/attackby(obj/item/weapon/W as obj, mob/user as mob)
user.setClickCooldown(user.get_attack_speed(W))
user.do_attack_animation(src)
- playsound(loc, 'sound/effects/Glasshit.ogg', 50, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 50, 1)
src.health -= W.force
src.healthcheck()
..()
diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm
index f8ea5d2f77..5a786cacd8 100644
--- a/code/game/objects/structures/door_assembly.dm
+++ b/code/game/objects/structures/door_assembly.dm
@@ -14,8 +14,8 @@
var/glass = 0 // 0 = glass can be installed. -1 = glass can't be installed. 1 = glass is already installed. Text = mineral plating is installed instead.
var/created_name = null
- New()
- update_state()
+/obj/structure/door_assembly/New()
+ update_state()
/obj/structure/door_assembly/door_assembly_com
base_icon_state = "com"
@@ -136,23 +136,23 @@
airlock_type = "/multi_tile/glass"
glass = -1 //To prevent bugs in deconstruction process.
- New()
- if(dir in list(EAST, WEST))
- bound_width = width * world.icon_size
- bound_height = world.icon_size
- else
- bound_width = world.icon_size
- bound_height = width * world.icon_size
- update_state()
+/obj/structure/door_assembly/multi_tile/New()
+ if(dir in list(EAST, WEST))
+ bound_width = width * world.icon_size
+ bound_height = world.icon_size
+ else
+ bound_width = world.icon_size
+ bound_height = width * world.icon_size
+ update_state()
- Move()
- . = ..()
- if(dir in list(EAST, WEST))
- bound_width = width * world.icon_size
- bound_height = world.icon_size
- else
- bound_width = world.icon_size
- bound_height = width * world.icon_size
+/obj/structure/door_assembly/multi_tile/Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
+ if(dir in list(EAST, WEST))
+ bound_width = width * world.icon_size
+ bound_height = world.icon_size
+ else
+ bound_width = world.icon_size
+ bound_height = width * world.icon_size
/obj/structure/door_assembly/proc/rename_door(mob/living/user)
var/t = sanitizeSafe(input(user, "Enter the name for the windoor.", src.name, src.created_name), MAX_NAME_LEN)
@@ -268,7 +268,7 @@
if (S)
if (S.get_amount() >= 1)
if(material_name == "rglass")
- playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 100, 1)
user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.")
if(do_after(user, 40) && !glass)
if (S.use(1))
@@ -280,7 +280,7 @@
to_chat(user, "You cannot make an airlock out of that material.")
return
if(S.get_amount() >= 2)
- playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 100, 1)
user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.")
if(do_after(user, 40) && !glass)
if (S.use(2))
diff --git a/code/game/objects/structures/electricchair.dm b/code/game/objects/structures/electricchair.dm
index ae5cba7cf0..b3f174e25a 100644
--- a/code/game/objects/structures/electricchair.dm
+++ b/code/game/objects/structures/electricchair.dm
@@ -56,7 +56,7 @@
return
if(!A.powered(EQUIP))
return
- A.use_power(EQUIP, 5000)
+ A.use_power_oneoff(5000, EQUIP)
var/light = A.power_light
A.updateicon()
diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm
index 0879e196f2..ed3669247a 100644
--- a/code/game/objects/structures/extinguisher.dm
+++ b/code/game/objects/structures/extinguisher.dm
@@ -38,7 +38,7 @@
if(O.is_wrench())
if(!has_extinguisher)
to_chat(user, "You start to unwrench the extinguisher cabinet.")
- playsound(src.loc, O.usesound, 50, 1)
+ playsound(src, O.usesound, 50, 1)
if(do_after(user, 15 * O.toolspeed))
to_chat(user, "You unwrench the extinguisher cabinet.")
new /obj/item/frame/extinguisher_cabinet( src.loc )
diff --git a/code/game/objects/structures/fireaxe.dm b/code/game/objects/structures/fireaxe.dm
index e5735d1255..2e2251fabe 100644
--- a/code/game/objects/structures/fireaxe.dm
+++ b/code/game/objects/structures/fireaxe.dm
@@ -31,7 +31,7 @@
if (isrobot(user) || locked)
if(istype(O, /obj/item/device/multitool))
to_chat(user, "Resetting circuitry...")
- playsound(user, 'sound/machines/lockreset.ogg', 50, 1)
+ playsound(src, 'sound/machines/lockreset.ogg', 50, 1)
if(do_after(user, 20 * O.toolspeed))
locked = 0
to_chat(user, " You disable the locking modules.")
@@ -44,13 +44,13 @@
toggle_close_open()
return
else
- playsound(user, 'sound/effects/Glasshit.ogg', 100, 1) //We don't want this playing every time
+ playsound(src, 'sound/effects/Glasshit.ogg', 100, 1) //We don't want this playing every time
if(W.force < 15)
to_chat(user, "The cabinet's protective glass glances off the hit.")
else
hitstaken++
if(hitstaken == 4)
- playsound(user, 'sound/effects/Glassbr3.ogg', 100, 1) //Break cabinet, receive goodies. Cabinet's fucked for life after that.
+ playsound(src, 'sound/effects/Glassbr3.ogg', 100, 1) //Break cabinet, receive goodies. Cabinet's fucked for life after that.
smashed = 1
locked = 0
open= 1
@@ -82,7 +82,7 @@
return
else
to_chat(user, "Resetting circuitry...")
- playsound(user, 'sound/machines/lockenable.ogg', 50, 1)
+ playsound(src, 'sound/machines/lockenable.ogg', 50, 1)
if(do_after(user,20 * O.toolspeed))
locked = 1
to_chat(user, " You re-enable the locking modules.")
diff --git a/code/game/objects/structures/fitness.dm b/code/game/objects/structures/fitness.dm
index 158bf5533b..729e578ba5 100644
--- a/code/game/objects/structures/fitness.dm
+++ b/code/game/objects/structures/fitness.dm
@@ -20,7 +20,7 @@
if(user.a_intent == I_HURT)
user.setClickCooldown(user.get_attack_speed())
flick("[icon_state]_hit", src)
- playsound(src.loc, 'sound/effects/woodhit.ogg', 25, 1, -1)
+ playsound(src, 'sound/effects/woodhit.ogg', 25, 1, -1)
user.do_attack_animation(src)
user.nutrition = user.nutrition - 5
to_chat(user, "You [pick(hit_message)] \the [src].")
@@ -34,7 +34,7 @@
/obj/structure/fitness/weightlifter/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(W.is_wrench())
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 75, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 75, 1)
weight = ((weight) % qualifiers.len) + 1
to_chat(user, "You set the machine's weight level to [weight].")
@@ -52,12 +52,12 @@
return
else
being_used = 1
- playsound(src.loc, 'sound/effects/weightlifter.ogg', 50, 1)
+ playsound(src, 'sound/effects/weightlifter.ogg', 50, 1)
user.set_dir(SOUTH)
flick("[icon_state]_[weight]", src)
if(do_after(user, 20 + (weight * 10)))
- playsound(src.loc, 'sound/effects/weightdrop.ogg', 25, 1)
- user.nutrition -= weight * 10
+ playsound(src, 'sound/effects/weightdrop.ogg', 25, 1)
+ user.adjust_nutrition(weight * -10)
to_chat(user, "You lift the weights [qualifiers[weight]].")
being_used = 0
else
diff --git a/code/game/objects/structures/flora/trees.dm b/code/game/objects/structures/flora/trees.dm
index c4d8f58ebd..a9f3658ff6 100644
--- a/code/game/objects/structures/flora/trees.dm
+++ b/code/game/objects/structures/flora/trees.dm
@@ -58,9 +58,9 @@
damage_to_do = round(damage_to_do / 4)
if(damage_to_do > 0)
if(W.sharp && W.edge)
- playsound(get_turf(src), 'sound/effects/woodcutting.ogg', 50, 1)
+ playsound(src, 'sound/effects/woodcutting.ogg', 50, 1)
else
- playsound(get_turf(src), W.hitsound, 50, 1)
+ playsound(src, W.hitsound, 50, 1)
if(damage_to_do > 5 && !indestructable)
adjust_health(-damage_to_do)
else
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index d959aaa1ee..2cc53ff821 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -27,7 +27,7 @@
/obj/structure/grille/attack_hand(mob/user as mob)
user.setClickCooldown(user.get_attack_speed())
- playsound(loc, 'sound/effects/grillehit.ogg', 80, 1)
+ playsound(src, 'sound/effects/grillehit.ogg', 80, 1)
user.do_attack_animation(src)
var/damage_dealt = 1
@@ -153,7 +153,7 @@
else if((W.flags & NOCONDUCT) || !shock(user, 70))
user.setClickCooldown(user.get_attack_speed(W))
user.do_attack_animation(src)
- playsound(loc, 'sound/effects/grillehit.ogg', 80, 1)
+ playsound(src, 'sound/effects/grillehit.ogg', 80, 1)
switch(W.damtype)
if("fire")
health -= W.force
diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm
index 995bf4eece..3e58a93850 100644
--- a/code/game/objects/structures/inflatable.dm
+++ b/code/game/objects/structures/inflatable.dm
@@ -86,7 +86,7 @@
/obj/structure/inflatable/proc/hit(var/damage, var/sound_effect = 1)
health = max(0, health - damage)
if(sound_effect)
- playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
if(health <= 0)
puncture()
@@ -102,7 +102,7 @@
qdel(src)
/obj/structure/inflatable/proc/deflate()
- playsound(loc, 'sound/machines/hiss.ogg', 75, 1)
+ playsound(src, 'sound/machines/hiss.ogg', 75, 1)
//to_chat(user, "You slowly deflate the inflatable wall.")
visible_message("[src] slowly deflates.")
spawn(50)
@@ -111,7 +111,7 @@
qdel(src)
/obj/structure/inflatable/proc/puncture()
- playsound(loc, 'sound/machines/hiss.ogg', 75, 1)
+ playsound(src, 'sound/machines/hiss.ogg', 75, 1)
visible_message("[src] rapidly deflates!")
var/obj/item/inflatable/torn/R = new /obj/item/inflatable/torn(loc)
src.transfer_fingerprints_to(R)
@@ -227,7 +227,7 @@
icon_state = "door_closed"
/obj/structure/inflatable/door/deflate()
- playsound(loc, 'sound/machines/hiss.ogg', 75, 1)
+ playsound(src, 'sound/machines/hiss.ogg', 75, 1)
visible_message("[src] slowly deflates.")
spawn(50)
var/obj/item/inflatable/door/R = new /obj/item/inflatable/door(loc)
@@ -235,7 +235,7 @@
qdel(src)
/obj/structure/inflatable/door/puncture()
- playsound(loc, 'sound/machines/hiss.ogg', 75, 1)
+ playsound(src, 'sound/machines/hiss.ogg', 75, 1)
visible_message("[src] rapidly deflates!")
var/obj/item/inflatable/door/torn/R = new /obj/item/inflatable/door/torn(loc)
src.transfer_fingerprints_to(R)
diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm
index 51b4270b25..f320c478b9 100644
--- a/code/game/objects/structures/janicart.dm
+++ b/code/game/objects/structures/janicart.dm
@@ -3,99 +3,152 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
/obj/structure/janitorialcart
name = "janitorial cart"
desc = "The ultimate in janitorial carts! Has space for water, mops, signs, trash bags, and more!"
+ description_info = "You can use alt-click while holding a mop to stow the mop. Alt-click holding a reagent container will empty the contents into the bucket without trying to put the container in any attached trash bag."
icon = 'icons/obj/janitor.dmi'
icon_state = "cart"
anchored = 0
density = 1
- climbable = 1
flags = OPENCONTAINER
+ climbable = TRUE
//copypaste sorry
var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite
var/obj/item/weapon/storage/bag/trash/mybag = null
var/obj/item/weapon/mop/mymop = null
var/obj/item/weapon/reagent_containers/spray/myspray = null
var/obj/item/device/lightreplacer/myreplacer = null
+ var/obj/structure/mopbucket/mybucket = null
+ var/has_items = FALSE
+ var/dismantled = TRUE
var/signs = 0 //maximum capacity hardcoded below
-/obj/structure/janitorialcart/New()
- create_reagents(300)
- ..()
+/obj/structure/janitorialcart/Destroy()
+ QDEL_NULL(mybag)
+ QDEL_NULL(mymop)
+ QDEL_NULL(myspray)
+ QDEL_NULL(myreplacer)
+ QDEL_NULL(mybucket)
+ return ..()
/obj/structure/janitorialcart/examine(mob/user)
- . = ..()
- if(Adjacent(user))
- . += "It contains [reagents.total_volume] unit\s of liquid!"
+ if(..(user, 1))
+ if (mybucket)
+ var/contains = mybucket.reagents.total_volume
+ to_chat(user, "\icon[src] The bucket contains [contains] unit\s of liquid!")
+ else
+ to_chat(user, "\icon[src] There is no bucket mounted on it!")
+
+/obj/structure/janitorialcart/MouseDrop_T(atom/movable/O as mob|obj, mob/living/user as mob)
+ if (istype(O, /obj/structure/mopbucket) && !mybucket)
+ O.forceMove(src)
+ mybucket = O
+ to_chat(user, "You mount the [O] on the janicart.")
+ update_icon()
+ else
+ ..()
/obj/structure/janitorialcart/attackby(obj/item/I, mob/user)
- if(istype(I, /obj/item/weapon/storage/bag/trash) && !mybag)
- user.drop_item()
- mybag = I
- I.loc = src
- update_icon()
- updateUsrDialog()
- to_chat(user, "You put [I] into [src].")
-
- else if(istype(I, /obj/item/weapon/mop))
- if(I.reagents.total_volume < I.reagents.maximum_volume) //if it's not completely soaked we assume they want to wet it, otherwise store it
- if(reagents.total_volume < 1)
- to_chat(user, "[src] is out of water!")
+ if(istype(I, /obj/item/weapon/mop) || istype(I, /obj/item/weapon/reagent_containers/glass/rag) || istype(I, /obj/item/weapon/soap))
+ if (mybucket)
+ if(I.reagents.total_volume < I.reagents.maximum_volume)
+ if(mybucket.reagents.total_volume < 1)
+ to_chat(user, "[mybucket] is empty!")
+ else
+ mybucket.reagents.trans_to_obj(I, 5) //
+ to_chat(user, "You wet [I] in [mybucket].")
+ playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
else
- reagents.trans_to_obj(I, 5) //
- to_chat(user, "You wet [I] in [src].")
- playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
- return
- if(!mymop)
- user.drop_item()
- mymop = I
- I.loc = src
- update_icon()
- updateUsrDialog()
- to_chat(user, "You put [I] into [src].")
+ to_chat(user, "[I] can't absorb anymore liquid!")
+ else
+ to_chat(user, "There is no bucket mounted here to dip [I] into!")
+ return 1
+
+ else if (istype(I, /obj/item/weapon/reagent_containers/glass/bucket) && mybucket)
+ I.afterattack(mybucket, usr, 1)
+ update_icon()
+ return 1
else if(istype(I, /obj/item/weapon/reagent_containers/spray) && !myspray)
- user.drop_item()
+ user.unEquip(I, 0, src)
myspray = I
- I.loc = src
update_icon()
updateUsrDialog()
to_chat(user, "You put [I] into [src].")
+ return 1
else if(istype(I, /obj/item/device/lightreplacer) && !myreplacer)
- user.drop_item()
+ user.unEquip(I, 0, src)
myreplacer = I
- I.loc = src
update_icon()
updateUsrDialog()
to_chat(user, "You put [I] into [src].")
+ return 1
+
+ else if(istype(I, /obj/item/weapon/storage/bag/trash) && !mybag)
+ user.unEquip(I, 0, src)
+ mybag = I
+ update_icon()
+ updateUsrDialog()
+ to_chat(user, "You put [I] into [src].")
+ return 1
else if(istype(I, /obj/item/weapon/caution))
if(signs < 4)
- user.drop_item()
- I.loc = src
+ user.unEquip(I, 0, src)
signs++
update_icon()
updateUsrDialog()
to_chat(user, "You put [I] into [src].")
else
to_chat(user, "[src] can't hold any more signs.")
-
- else if(istype(I, /obj/item/weapon/reagent_containers/glass))
- return // So we do not put them in the trash bag as we mean to fill the mop bucket
+ return 1
else if(mybag)
- mybag.attackby(I, user)
+ return mybag.attackby(I, user)
+ //This return will prevent afterattack from executing if the object goes into the trashbag,
+ //This prevents dumb stuff like splashing the cart with the contents of a container, after putting said container into trash
+
+ else if (!has_items)
+ if (I.is_wrench())
+ if (do_after(user, 5 SECONDS, src))
+ dismantle(user)
+ return
+ ..()
+
+
+//New Altclick functionality!
+//Altclick the cart with a mop to stow the mop away
+//Altclick the cart with a reagent container to pour things into the bucket without putting the bottle in trash
+/obj/structure/janitorialcart/AltClick(mob/living/user)
+ if(user.incapacitated() || !Adjacent(user)) return
+ var/obj/I = usr.get_active_hand()
+ if(istype(I, /obj/item/weapon/mop))
+ if(!mymop)
+ usr.drop_from_inventory(I,src)
+ mymop = I
+ update_icon()
+ updateUsrDialog()
+ to_chat(usr, "You put [I] into [src].")
+ update_icon()
+ else
+ to_chat(usr, "The cart already has a mop attached")
+ return
+ else if(istype(I, /obj/item/weapon/reagent_containers) && mybucket)
+ var/obj/item/weapon/reagent_containers/C = I
+ C.afterattack(mybucket, usr, 1)
+ update_icon()
/obj/structure/janitorialcart/attack_hand(mob/user)
ui_interact(user)
return
-/obj/structure/janitorialcart/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+/obj/structure/janitorialcart/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = TRUE)
var/data[0]
data["name"] = capitalize(name)
data["bag"] = mybag ? capitalize(mybag.name) : null
+ data["bucket"] = mybucket ? capitalize(mybucket.name) : null
data["mop"] = mymop ? capitalize(mymop.name) : null
data["spray"] = myspray ? capitalize(myspray.name) : null
data["replacer"] = myreplacer ? capitalize(myreplacer.name) : null
@@ -107,6 +160,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
ui.set_initial_data(data)
ui.open()
+
/obj/structure/janitorialcart/Topic(href, href_list)
if(!in_range(src, usr))
return
@@ -146,13 +200,24 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
else
warning("[src] signs ([signs]) didn't match contents")
signs = 0
+ if("bucket")
+ if(mybucket)
+ mybucket.forceMove(get_turf(user))
+ to_chat(user, "You unmount [mybucket] from [src].")
+ mybucket = null
update_icon()
updateUsrDialog()
+
/obj/structure/janitorialcart/update_icon()
- overlays = null
+ overlays.Cut()
+
+ if(mybucket)
+ overlays += "cart_bucket"
+ if(mybucket.reagents.total_volume >= 1)
+ overlays += "water_cart"
if(mybag)
overlays += "cart_garbage"
if(mymop)
@@ -165,6 +230,73 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
overlays += "cart_sign[signs]"
+
+
+
+
+//This is called if the cart is caught in an explosion, or destroyed by weapon fire
+/obj/structure/janitorialcart/proc/spill(var/chance = 100)
+ var/turf/dropspot = get_turf(src)
+ if (mymop && prob(chance))
+ mymop.forceMove(dropspot)
+ mymop.tumble(2)
+ mymop = null
+
+ if (myspray && prob(chance))
+ myspray.forceMove(dropspot)
+ myspray.tumble(3)
+ myspray = null
+
+ if (myreplacer && prob(chance))
+ myreplacer.forceMove(dropspot)
+ myreplacer.tumble(3)
+ myreplacer = null
+
+ if (mybucket && prob(chance*0.5))//bucket is heavier, harder to knock off
+ mybucket.forceMove(dropspot)
+ mybucket.tumble(1)
+ mybucket = null
+
+ if (signs)
+ for (var/obj/item/weapon/caution/Sign in src)
+ if (prob(min((chance*2),100)))
+ signs--
+ Sign.forceMove(dropspot)
+ Sign.tumble(3)
+ if (signs < 0)//safety for something that shouldn't happen
+ signs = 0
+ update_icon()
+ return
+
+ if (mybag && prob(min((chance*2),100)))//Bag is flimsy
+ mybag.forceMove(dropspot)
+ mybag.tumble(1)
+ mybag.spill()//trashbag spills its contents too
+ mybag = null
+
+ update_icon()
+
+
+
+/obj/structure/janitorialcart/proc/dismantle(var/mob/user = null)
+ if (!dismantled)
+ if (has_items)
+ spill()
+
+ new /obj/item/stack/material/steel(src.loc, 10)
+ new /obj/item/stack/material/plastic(src.loc, 10)
+ new /obj/item/stack/rods(src.loc, 20)
+ dismantled = 1
+ qdel(src)
+
+
+/obj/structure/janitorialcart/ex_act(severity)
+ spill(100 / severity)
+ ..()
+
+
+
+
//old style retardo-cart
/obj/structure/bed/chair/janicart
name = "janicart"
@@ -197,7 +329,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
if(reagents.total_volume > 1)
reagents.trans_to_obj(I, 2)
to_chat(user, "You wet [I] in the [callme].")
- playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
+ playsound(src, 'sound/effects/slosh.ogg', 25, 1)
else
to_chat(user, "This [callme] is out of water!")
else if(istype(I, /obj/item/key))
@@ -228,15 +360,6 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
to_chat(user, "You'll need the keys in one of your hands to drive this [callme].")
-/obj/structure/bed/chair/janicart/Move()
- ..()
- if(has_buckled_mobs())
- for(var/A in buckled_mobs)
- var/mob/living/L = A
- if(L.buckled == src)
- L.loc = loc
-
-
/obj/structure/bed/chair/janicart/post_buckle_mob(mob/living/M)
update_mob()
return ..()
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index 07cc774fb0..4705b39276 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -51,7 +51,7 @@
/obj/structure/mirror/attackby(obj/item/I as obj, mob/user as mob)
if(I.is_wrench())
if(!glass)
- playsound(src.loc, I.usesound, 50, 1)
+ playsound(src, I.usesound, 50, 1)
if(do_after(user, 20 * I.toolspeed))
to_chat(user, "You unfasten the frame.")
new /obj/item/frame/mirror( src.loc )
@@ -65,7 +65,7 @@
new /obj/item/weapon/material/shard( src.loc )
return
if(!shattered && glass)
- playsound(src.loc, I.usesound, 50, 1)
+ playsound(src, I.usesound, 50, 1)
to_chat(user, "You remove the glass.")
glass = !glass
icon_state = "mirror_frame"
@@ -88,7 +88,7 @@
return
if(shattered && glass)
- playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
return
if(prob(I.force * 2))
@@ -97,13 +97,13 @@
shatter()
else
visible_message("[user] hits [src] with [I]!")
- playsound(src.loc, 'sound/effects/Glasshit.ogg', 70, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 70, 1)
/obj/structure/mirror/attack_generic(var/mob/user, var/damage)
user.do_attack_animation(src)
if(shattered && glass)
- playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
return 0
if(damage)
diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm
index 13e3ca4cdc..e7e80206f2 100644
--- a/code/game/objects/structures/mop_bucket.dm
+++ b/code/game/objects/structures/mop_bucket.dm
@@ -28,4 +28,4 @@ GLOBAL_LIST_BOILERPLATE(all_mopbuckets, /obj/structure/mopbucket)
else
reagents.trans_to_obj(I, 5)
to_chat(user, "You wet \the [I] in \the [src].")
- playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
+ playsound(src, 'sound/effects/slosh.ogg', 25, 1)
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index c1ccfb6c69..d22d903861 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -95,13 +95,13 @@
for(var/atom/movable/A as mob|obj in src.connected.loc)
if (!( A.anchored ))
A.forceMove(src)
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
qdel(src.connected)
src.connected = null
/obj/structure/morgue/proc/open()
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
src.connected = new /obj/structure/m_tray( src.loc )
step(src.connected, src.dir)
src.connected.layer = OBJ_LAYER
@@ -225,11 +225,11 @@ GLOBAL_LIST_BOILERPLATE(all_crematoriums, /obj/structure/morgue/crematorium)
for(var/atom/movable/A as mob|obj in src.connected.loc)
if (!( A.anchored ))
A.forceMove(src)
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
//src.connected = null
qdel(src.connected)
else if (src.locked == 0)
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
src.connected = new /obj/structure/m_tray/c_tray( src.loc )
step(src.connected, EAST)
src.connected.layer = OBJ_LAYER
@@ -319,7 +319,7 @@ GLOBAL_LIST_BOILERPLATE(all_crematoriums, /obj/structure/morgue/crematorium)
sleep(30)
cremating = 0
locked = 0
- playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
+ playsound(src, 'sound/machines/ding.ogg', 50, 1)
return
diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm
index 39eea11236..cfd036b9bb 100644
--- a/code/game/objects/structures/musician.dm
+++ b/code/game/objects/structures/musician.dm
@@ -345,7 +345,7 @@
/obj/structure/device/piano/attackby(obj/item/O as obj, mob/user as mob)
if(O.is_wrench())
if(anchored)
- playsound(src.loc, O.usesound, 50, 1)
+ playsound(src, O.usesound, 50, 1)
to_chat(user, "You begin to loosen \the [src]'s casters...")
if (do_after(user, 40 * O.toolspeed))
user.visible_message( \
@@ -354,7 +354,7 @@
"You hear ratchet.")
src.anchored = 0
else
- playsound(src.loc, O.usesound, 50, 1)
+ playsound(src, O.usesound, 50, 1)
to_chat(user, "You begin to tighten \the [src] to the floor...")
if (do_after(user, 20 * O.toolspeed))
user.visible_message( \
diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm
index c701ae9015..629bc1c41e 100644
--- a/code/game/objects/structures/noticeboard.dm
+++ b/code/game/objects/structures/noticeboard.dm
@@ -43,7 +43,7 @@
to_chat(user, "You reach to pin your paper to the board but hesitate. You are certain your paper will not be seen among the many others already attached.")
if(O.is_wrench())
to_chat(user, "You start to unwrench the noticeboard.")
- playsound(src.loc, O.usesound, 50, 1)
+ playsound(src, O.usesound, 50, 1)
if(do_after(user, 15 * O.toolspeed))
to_chat(user, "You unwrench the noticeboard.")
new /obj/item/frame/noticeboard( src.loc )
diff --git a/code/game/objects/structures/props/swarm.dm b/code/game/objects/structures/props/swarm.dm
index 181001036a..128254a456 100644
--- a/code/game/objects/structures/props/swarm.dm
+++ b/code/game/objects/structures/props/swarm.dm
@@ -37,7 +37,7 @@
if(prob(1 + damage * 3))
visible_message("[shatter_message]")
STOP_PROCESSING(SSobj, src)
- playsound(get_turf(src),shatter_sound, 75, 1)
+ playsound(src,shatter_sound, 75, 1)
isbroken = 1
density = 0
icon_state = "[initial(icon_state)]-broken"
@@ -53,21 +53,21 @@
)
STOP_PROCESSING(SSobj, src)
user.do_attack_animation(src)
- playsound(get_turf(src),shatter_sound, 75, 1)
+ playsound(src,shatter_sound, 75, 1)
isbroken = 1
density = 0
icon_state = "[initial(icon_state)]-broken"
set_light(0)
else
to_chat(user, "You hit \the [src]!")
- playsound(get_turf(src),impact_sound, 75, 1)
+ playsound(src,impact_sound, 75, 1)
else
if(prob(damage * 2))
to_chat(user, "You pulverize what was left of \the [src]!")
qdel(src)
else
to_chat(user, "You hit \the [src]!")
- playsound(get_turf(src),impact_sound, 75, 1)
+ playsound(src,impact_sound, 75, 1)
/obj/structure/cult/pylon/swarm/pylon_unique()
. = ..()
@@ -114,10 +114,10 @@
/obj/structure/cult/pylon/swarm/defender/pylonhit(var/damage)
if(!isbroken)
- if(prob(1 + damage * 3) && round(damage * 0.8) >= 30)
+ if(prob(1 + damage * 3) && damage >= 25)
visible_message("[shatter_message]")
STOP_PROCESSING(SSobj, src)
- playsound(get_turf(src),shatter_sound, 75, 1)
+ playsound(src,shatter_sound, 75, 1)
isbroken = 1
density = 0
icon_state = "[initial(icon_state)]-broken"
@@ -125,7 +125,7 @@
/obj/structure/cult/pylon/swarm/defender/attackpylon(mob/user as mob, var/damage)
if(!isbroken)
- if(prob(1 + damage * 3) && round(damage * 0.8) >= 25)
+ if(prob(1 + damage * 2) && damage >= 15)
user.visible_message(
"[user] smashed \the [src]!",
"You hit \the [src], and its crystal breaks apart!",
@@ -133,18 +133,18 @@
)
STOP_PROCESSING(SSobj, src)
user.do_attack_animation(src)
- playsound(get_turf(src),shatter_sound, 75, 1)
+ playsound(src,shatter_sound, 75, 1)
isbroken = 1
density = 0
icon_state = "[initial(icon_state)]-broken"
set_light(0)
else
to_chat(user, "You hit \the [src]!")
- playsound(get_turf(src),impact_sound, 75, 1)
+ playsound(src,impact_sound, 75, 1)
else
- if(prob(damage * 2))
+ if(prob(damage * 3))
to_chat(user, "You pulverize what was left of \the [src]!")
qdel(src)
else
to_chat(user, "You hit \the [src]!")
- playsound(get_turf(src),impact_sound, 75, 1)
+ playsound(src,impact_sound, 75, 1)
diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm
index 17b457b49e..5a4ce00a8c 100644
--- a/code/game/objects/structures/railing.dm
+++ b/code/game/objects/structures/railing.dm
@@ -1,7 +1,7 @@
// Based on railing.dmi from https://github.com/Endless-Horizon/CEV-Eris
/obj/structure/railing
name = "railing"
- desc = "A standard steel railing. Play stupid games, win stupid prizes."
+ desc = "A standard steel railing, painted orange. Play stupid games, win stupid prizes."
icon = 'icons/obj/railing.dmi'
density = 1
throwpass = 1
@@ -14,6 +14,13 @@
var/health = 70
var/maxhealth = 70
var/check = 0
+ var/icon_modifier = ""
+
+/obj/structure/railing/grey
+ name = "grey railing"
+ desc = "A standard steel railing. Prevents stupid people from falling to their doom."
+ icon_modifier = "grey_"
+ icon_state = "grey_railing0"
/obj/structure/railing/New(loc, constructed = 0)
..()
@@ -56,7 +63,7 @@
health -= amount
if(health <= 0)
visible_message("\The [src] breaks down!")
- playsound(loc, 'sound/effects/grillehit.ogg', 50, 1)
+ playsound(src, 'sound/effects/grillehit.ogg', 50, 1)
new /obj/item/stack/rods(get_turf(src))
qdel(src)
@@ -103,25 +110,25 @@
//layer = (dir == SOUTH) ? FLY_LAYER : initial(layer) // wtf does this even do
overlays.Cut()
if (!check || !anchored)//|| !anchored
- icon_state = "railing0"
+ icon_state = "[icon_modifier]railing0"
else
- icon_state = "railing1"
+ icon_state = "[icon_modifier]railing1"
if (check & 32)
- overlays += image ('icons/obj/railing.dmi', src, "corneroverlay")
+ overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]corneroverlay")
if ((check & 16) || !(check & 32) || (check & 64))
- overlays += image ('icons/obj/railing.dmi', src, "frontoverlay_l")
+ overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]frontoverlay_l")
if (!(check & 2) || (check & 1) || (check & 4))
- overlays += image ('icons/obj/railing.dmi', src, "frontoverlay_r")
+ overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]frontoverlay_r")
if(check & 4)
switch (src.dir)
if (NORTH)
- overlays += image ('icons/obj/railing.dmi', src, "mcorneroverlay", pixel_x = 32)
+ overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]mcorneroverlay", pixel_x = 32)
if (SOUTH)
- overlays += image ('icons/obj/railing.dmi', src, "mcorneroverlay", pixel_x = -32)
+ overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]mcorneroverlay", pixel_x = -32)
if (EAST)
- overlays += image ('icons/obj/railing.dmi', src, "mcorneroverlay", pixel_y = -32)
+ overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]mcorneroverlay", pixel_y = -32)
if (WEST)
- overlays += image ('icons/obj/railing.dmi', src, "mcorneroverlay", pixel_y = 32)
+ overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]mcorneroverlay", pixel_y = 32)
/obj/structure/railing/verb/rotate_counterclockwise()
set name = "Rotate Railing Counter-Clockwise"
@@ -196,7 +203,7 @@
/obj/structure/railing/attackby(obj/item/W as obj, mob/user as mob)
// Dismantle
if(W.is_wrench() && !anchored)
- playsound(src.loc, W.usesound, 50, 1)
+ playsound(src, W.usesound, 50, 1)
if(do_after(user, 20, src))
user.visible_message("\The [user] dismantles \the [src].", "You dismantle \the [src].")
new /obj/item/stack/material/steel(get_turf(usr), 2)
@@ -207,7 +214,7 @@
if(health < maxhealth && istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/F = W
if(F.welding)
- playsound(src.loc, F.usesound, 50, 1)
+ playsound(src, F.usesound, 50, 1)
if(do_after(user, 20, src))
user.visible_message("\The [user] repairs some damage to \the [src].", "You repair some damage to \the [src].")
health = min(health+(maxhealth/5), maxhealth) // 20% repair per application
@@ -216,7 +223,7 @@
// Install
if(W.is_screwdriver())
user.visible_message(anchored ? "\The [user] begins unscrewing \the [src]." : "\The [user] begins fasten \the [src]." )
- playsound(loc, W.usesound, 75, 1)
+ playsound(src, W.usesound, 75, 1)
if(do_after(user, 10, src))
to_chat(user, (anchored ? "You have unfastened \the [src] from the floor." : "You have fastened \the [src] to the floor."))
anchored = !anchored
@@ -238,7 +245,7 @@
M.apply_damage(8,def_zone = "head")
take_damage(8)
visible_message("[G.assailant] slams [G.affecting]'s face against \the [src]!")
- playsound(loc, 'sound/effects/grillehit.ogg', 50, 1)
+ playsound(src, 'sound/effects/grillehit.ogg', 50, 1)
else
to_chat(user, "You need a better grip to do that!")
return
@@ -253,7 +260,7 @@
return
else
- playsound(loc, 'sound/effects/grillehit.ogg', 50, 1)
+ playsound(src, 'sound/effects/grillehit.ogg', 50, 1)
take_damage(W.force)
user.setClickCooldown(user.get_attack_speed(W))
diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm
index 9de9dc082b..e68fa43640 100644
--- a/code/game/objects/structures/safe.dm
+++ b/code/game/objects/structures/safe.dm
@@ -114,7 +114,7 @@ FLOOR SAFES
tumbler_2_pos = decrement(tumbler_2_pos)
if(canhear)
to_chat(user, "You hear a [pick("click", "chink", "clink")] from \the [src].")
- playsound(user, 'sound/machines/click.ogg', 20, 1)
+ playsound(src, 'sound/machines/click.ogg', 20, 1)
check_unlocked(user, canhear)
updateUsrDialog()
@@ -130,7 +130,7 @@ FLOOR SAFES
tumbler_2_pos = increment(tumbler_2_pos)
if(canhear)
to_chat(user, "You hear a [pick("click", "chink", "clink")] from \the [src].")
- playsound(user, 'sound/machines/click.ogg', 20, 1)
+ playsound(src, 'sound/machines/click.ogg', 20, 1)
check_unlocked(user, canhear)
updateUsrDialog()
return
diff --git a/code/game/objects/structures/salvageable.dm b/code/game/objects/structures/salvageable.dm
index 2703a7eed6..201b203acc 100644
--- a/code/game/objects/structures/salvageable.dm
+++ b/code/game/objects/structures/salvageable.dm
@@ -15,7 +15,7 @@
/obj/structure/salvageable/attackby(obj/item/I, mob/user)
if(I.is_crowbar())
- playsound(loc, I.usesound, 50, 1)
+ playsound(src, I.usesound, 50, 1)
var/actual_time = I.toolspeed * 170
user.visible_message( \
"\The [user] begins salvaging from \the [src].", \
@@ -240,7 +240,7 @@ obj/structure/salvageable/bliss/Initialize()
/obj/structure/salvageable/bliss/attackby(obj/item/I, mob/user)
if((. = ..()))
- playsound(user, 'sound/machines/shutdown.ogg', 60, 1)
+ playsound(src, 'sound/machines/shutdown.ogg', 60, 1)
//////////////////
//// ONE STAR ////
diff --git a/code/game/objects/structures/simple_doors.dm b/code/game/objects/structures/simple_doors.dm
index ff8dbe141e..95689683a5 100644
--- a/code/game/objects/structures/simple_doors.dm
+++ b/code/game/objects/structures/simple_doors.dm
@@ -95,7 +95,7 @@
/obj/structure/simple_door/proc/Open()
isSwitchingStates = 1
- playsound(loc, material.dooropen_noise, 100, 1)
+ playsound(src, material.dooropen_noise, 100, 1)
flick("[material.door_icon_base]opening",src)
sleep(10)
density = 0
@@ -107,7 +107,7 @@
/obj/structure/simple_door/proc/Close()
isSwitchingStates = 1
- playsound(loc, material.dooropen_noise, 100, 1)
+ playsound(src, material.dooropen_noise, 100, 1)
flick("[material.door_icon_base]closing",src)
sleep(10)
density = 1
@@ -135,9 +135,9 @@
hardness -= W.force/10
visible_message("[user] hits [src] with [W]!")
if(material == get_material_by_name("resin"))
- playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
+ playsound(src, 'sound/effects/attackblob.ogg', 100, 1)
else if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD)))
- playsound(loc, 'sound/effects/woodcutting.ogg', 100, 1)
+ playsound(src, 'sound/effects/woodcutting.ogg', 100, 1)
else
playsound(src, 'sound/weapons/smash.ogg', 50, 1)
CheckHardness()
@@ -160,9 +160,9 @@
/obj/structure/simple_door/attack_generic(var/mob/user, var/damage, var/attack_verb)
visible_message("[user] [attack_verb] the [src]!")
if(material == get_material_by_name("resin"))
- playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
+ playsound(src, 'sound/effects/attackblob.ogg', 100, 1)
else if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD)))
- playsound(loc, 'sound/effects/woodcutting.ogg', 100, 1)
+ playsound(src, 'sound/effects/woodcutting.ogg', 100, 1)
else
playsound(src, 'sound/weapons/smash.ogg', 50, 1)
user.do_attack_animation(src)
diff --git a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm
index 270583011d..ebba811fb9 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm
@@ -73,7 +73,7 @@
/obj/structure/bed/nest/attackby(obj/item/weapon/W as obj, mob/user as mob)
var/aforce = W.force
health = max(0, health - aforce)
- playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
+ playsound(src, 'sound/effects/attackblob.ogg', 100, 1)
for(var/mob/M in viewers(src, 7))
M.show_message("[user] hits [src] with [W]!", 1)
healthcheck()
diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm
index ed18290861..3d6743d82b 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm
@@ -124,7 +124,7 @@
to_chat(user, "\The [src] has no padding to remove.")
return
to_chat(user, "You remove the padding from \the [src].")
- playsound(src.loc, W.usesound, 100, 1)
+ playsound(src, W.usesound, 100, 1)
remove_padding()
else if(istype(W, /obj/item/weapon/grab))
@@ -286,15 +286,10 @@
held = null
-/obj/structure/bed/roller/Move()
- ..()
+/obj/structure/bed/roller/Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
+
playsound(src, 'sound/effects/roll.ogg', 100, 1)
- if(has_buckled_mobs())
- for(var/A in buckled_mobs)
- var/mob/living/L = A
-
- if(L.buckled == src)
- L.loc = src.loc
/obj/structure/bed/roller/post_buckle_mob(mob/living/M as mob)
if(M.buckled == src)
diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
index 5f136bbe5d..593e1db1f2 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
@@ -21,7 +21,7 @@
return
user.drop_item()
var/obj/structure/bed/chair/e_chair/E = new (src.loc, material.name)
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
E.set_dir(dir)
E.part = SK
SK.loc = E
@@ -139,22 +139,38 @@
return
..()
-/obj/structure/bed/chair/office/Move()
- ..()
+/obj/structure/bed/chair/office/Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
+
playsound(src, 'sound/effects/roll.ogg', 100, 1)
- if(has_buckled_mobs())
- for(var/A in buckled_mobs)
- var/mob/living/occupant = A
- occupant.buckled = null
- occupant.Move(src.loc)
- occupant.buckled = src
- if (occupant && (src.loc != occupant.loc))
- if (propelled)
- for (var/mob/O in src.loc)
- if (O != occupant)
- Bump(O)
- else
- unbuckle_mob()
+
+/obj/structure/bed/chair/office/handle_buckled_mob_movement(atom/new_loc, direction)
+ for(var/A in buckled_mobs)
+ var/mob/living/occupant = A
+ occupant.buckled = null
+ occupant.Move(src.loc)
+ occupant.buckled = src
+ if (occupant && (src.loc != occupant.loc))
+ if (propelled)
+ for (var/mob/O in src.loc)
+ if (O != occupant)
+ Bump(O)
+ else
+ unbuckle_mob()
+
+/obj/structure/bed/chair/office/handle_buckled_mob_movement(atom/new_loc, direction, movetime)
+ for(var/A in buckled_mobs)
+ var/mob/living/occupant = A
+ occupant.buckled = null
+ occupant.Move(loc, direction, movetime)
+ occupant.buckled = src
+ if (occupant && (loc != occupant.loc))
+ if (propelled)
+ for (var/mob/O in src.loc)
+ if (O != occupant)
+ Bump(O)
+ else
+ unbuckle_mob()
/obj/structure/bed/chair/office/Bump(atom/A)
..()
@@ -172,7 +188,7 @@
occupant.apply_effect(6, WEAKEN, blocked)
occupant.apply_effect(6, STUTTER, blocked)
occupant.apply_damage(10, BRUTE, def_zone, blocked, soaked)
- playsound(src.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/punch1.ogg', 50, 1, -1)
if(istype(A, /mob/living))
var/mob/living/victim = A
def_zone = ran_zone()
@@ -231,6 +247,14 @@
else
name = "[sofa_material] [initial(name)]"
+/obj/structure/bed/chair/update_layer()
+ // Corner east/west should be on top of mobs, any other state's north should be.
+ if((icon_state == "sofacorner" && ((dir & EAST) || (dir & WEST))) || (icon_state != "sofacorner" && (dir & NORTH)))
+ plane = MOB_PLANE
+ layer = MOB_LAYER + 0.1
+ else
+ reset_plane_and_layer()
+
/obj/structure/bed/chair/sofa/left
icon_state = "sofaend_left"
base_icon = "sofaend_left"
diff --git a/code/game/objects/structures/stool_bed_chair_nest/stools.dm b/code/game/objects/structures/stool_bed_chair_nest/stools.dm
index 88b07f3243..407591b285 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/stools.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/stools.dm
@@ -145,7 +145,7 @@ var/global/list/stool_cache = list() //haha stool
to_chat(user, "\The [src] has no padding to remove.")
return
to_chat(user, "You remove the padding from \the [src].")
- playsound(src.loc, W.usesound, 50, 1)
+ playsound(src, W.usesound, 50, 1)
remove_padding()
else
..()
diff --git a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
index 8a3902fa1d..089e65fc04 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
@@ -91,8 +91,9 @@
create_track()
driving = 0
-/obj/structure/bed/chair/wheelchair/Move()
- ..()
+/obj/structure/bed/chair/wheelchair/Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
+
cut_overlays()
playsound(src, 'sound/effects/roll.ogg', 75, 1)
if(has_buckled_mobs())
@@ -165,7 +166,7 @@
occupant.apply_effect(6, WEAKEN, blocked)
occupant.apply_effect(6, STUTTER, blocked)
occupant.apply_damage(10, BRUTE, def_zone, soaked)
- playsound(src.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/punch1.ogg', 50, 1, -1)
if(istype(A, /mob/living))
var/mob/living/victim = A
def_zone = ran_zone()
diff --git a/code/game/objects/structures/target_stake.dm b/code/game/objects/structures/target_stake.dm
index 55d8b37d0f..7802e258ea 100644
--- a/code/game/objects/structures/target_stake.dm
+++ b/code/game/objects/structures/target_stake.dm
@@ -8,45 +8,45 @@
w_class = ITEMSIZE_HUGE
var/obj/item/target/pinned_target // the current pinned target
- Move()
- ..()
- // Move the pinned target along with the stake
- if(pinned_target in view(3, src))
- pinned_target.loc = loc
+/obj/structure/target_stake/Moved(atom/old_loc, direction, forced = FALSE)
+ . = ..()
+ // Move the pinned target along with the stake
+ if(pinned_target in view(3, src))
+ pinned_target.forceMove(loc)
- else // Sanity check: if the pinned target can't be found in immediate view
- pinned_target = null
- density = 1
+ else // Sanity check: if the pinned target can't be found in immediate view
+ pinned_target = null
+ density = 1
- attackby(obj/item/W as obj, mob/user as mob)
- // Putting objects on the stake. Most importantly, targets
- if(pinned_target)
- return // get rid of that pinned target first!
+/obj/structure/target_stake/attackby(obj/item/W as obj, mob/user as mob)
+ // Putting objects on the stake. Most importantly, targets
+ if(pinned_target)
+ return // get rid of that pinned target first!
- if(istype(W, /obj/item/target))
- density = 0
- W.density = 1
- user.remove_from_mob(W)
- W.loc = loc
- W.layer = ABOVE_JUNK_LAYER
- pinned_target = W
- to_chat(user, "You slide the target into the stake.")
- return
+ if(istype(W, /obj/item/target))
+ density = 0
+ W.density = 1
+ user.remove_from_mob(W)
+ W.loc = loc
+ W.layer = ABOVE_JUNK_LAYER
+ pinned_target = W
+ to_chat(user, "You slide the target into the stake.")
+ return
- attack_hand(mob/user as mob)
- // taking pinned targets off!
- if(pinned_target)
- density = 1
- pinned_target.density = 0
- pinned_target.layer = OBJ_LAYER
+/obj/structure/target_stake/attack_hand(mob/user as mob)
+ // taking pinned targets off!
+ if(pinned_target)
+ density = 1
+ pinned_target.density = 0
+ pinned_target.layer = OBJ_LAYER
- pinned_target.loc = user.loc
- if(ishuman(user))
- if(!user.get_active_hand())
- user.put_in_hands(pinned_target)
- to_chat(user, "You take the target out of the stake.")
- else
- pinned_target.loc = get_turf(user)
+ pinned_target.loc = user.loc
+ if(ishuman(user))
+ if(!user.get_active_hand())
+ user.put_in_hands(pinned_target)
to_chat(user, "You take the target out of the stake.")
+ else
+ pinned_target.loc = get_turf(user)
+ to_chat(user, "You take the target out of the stake.")
- pinned_target = null
+ pinned_target = null
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 467579a225..27330786b1 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -46,7 +46,7 @@
/obj/structure/toilet/attackby(obj/item/I as obj, mob/living/user as mob)
if(I.is_crowbar())
to_chat(user, "You start to [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"].")
- playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 50, 1)
+ playsound(src, 'sound/effects/stonedoor_openclose.ogg', 50, 1)
if(do_after(user, 30))
user.visible_message("[user] [cistern ? "replaces the lid on the cistern" : "lifts the lid off the cistern"]!", "You [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"]!", "You hear grinding porcelain.")
cistern = !cistern
@@ -172,7 +172,7 @@
if(I.is_wrench())
var/newtemp = input(user, "What setting would you like to set the temperature valve to?", "Water Temperature Valve") in temperature_settings
to_chat(user, "You begin to adjust the temperature valve with \the [I].")
- playsound(src.loc, I.usesound, 50, 1)
+ playsound(src, I.usesound, 50, 1)
if(do_after(user, 50 * I.toolspeed))
watertemp = newtemp
user.visible_message("[user] adjusts the shower with \the [I].", "You adjust the shower with \the [I].")
@@ -384,14 +384,15 @@
return
to_chat(usr, "You start washing your hands.")
- playsound(loc, 'sound/effects/sink_long.ogg', 75, 1)
+ playsound(src, 'sound/effects/sink_long.ogg', 75, 1)
busy = 1
- sleep(40)
+ if(!do_after(user, 40, src))
+ busy = 0
+ to_chat(usr, "You stop washing your hands.")
+ return
busy = 0
- if(!Adjacent(user)) return //Person has moved away from the sink
-
user.clean_blood()
if(ishuman(user))
user:update_inv_gloves()
@@ -407,7 +408,7 @@
if (istype(RG) && RG.is_open_container())
RG.reagents.add_reagent("water", min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this))
user.visible_message("[user] fills \the [RG] using \the [src].","You fill \the [RG] using \the [src].")
- playsound(loc, 'sound/effects/sink.ogg', 75, 1)
+ playsound(src, 'sound/effects/sink.ogg', 75, 1)
return 1
else if (istype(O, /obj/item/weapon/melee/baton))
@@ -431,7 +432,7 @@
else if(istype(O, /obj/item/weapon/mop))
O.reagents.add_reagent("water", 5)
to_chat(user, "You wet \the [O] in \the [src].")
- playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
+ playsound(src, 'sound/effects/slosh.ogg', 25, 1)
return
var/turf/location = user.loc
@@ -443,13 +444,12 @@
to_chat(usr, "You start washing \the [I].")
busy = 1
- sleep(40)
+ if(!do_after(user, 40, src))
+ busy = 0
+ to_chat(usr, "You stop washing \the [I].")
+ return
busy = 0
- if(user.loc != location) return //User has moved
- if(!I) return //Item's been destroyed while washing
- if(user.get_active_hand() != I) return //Person has switched hands or the item in their hands
-
O.clean_blood()
user.visible_message( \
"[user] washes \a [I] using \the [src].", \
diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm
index 353df5ecb8..400b997dc5 100644
--- a/code/game/objects/structures/windoor_assembly.dm
+++ b/code/game/objects/structures/windoor_assembly.dm
@@ -91,7 +91,7 @@ obj/structure/windoor_assembly/Destroy()
var/obj/item/weapon/weldingtool/WT = W
if (WT.remove_fuel(0,user))
user.visible_message("[user] disassembles the windoor assembly.", "You start to disassemble the windoor assembly.")
- playsound(src.loc, WT.usesound, 50, 1)
+ playsound(src, WT.usesound, 50, 1)
if(do_after(user, 40 * WT.toolspeed))
if(!src || !WT.isOn()) return
@@ -157,7 +157,7 @@ obj/structure/windoor_assembly/Destroy()
//Adding airlock electronics for access. Step 6 complete.
else if(istype(W, /obj/item/weapon/airlock_electronics))
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 100, 1)
user.visible_message("[user] installs the electronics into the airlock assembly.", "You start to install electronics into the airlock assembly.")
if(do_after(user, 40))
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index c3c3689bfc..762608d5c0 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -59,7 +59,7 @@
shatter()
else
if(sound_effect)
- playsound(loc, 'sound/effects/Glasshit.ogg', 100, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 100, 1)
if(health < maxhealth / 4 && initialhealth >= maxhealth / 4)
visible_message("[src] looks like it's about to shatter!" )
update_icon()
@@ -172,7 +172,7 @@
/obj/structure/window/attack_tk(mob/user as mob)
user.visible_message("Something knocks on [src].")
- playsound(loc, 'sound/effects/Glasshit.ogg', 50, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 50, 1)
/obj/structure/window/attack_hand(mob/user as mob)
user.setClickCooldown(user.get_attack_speed())
@@ -190,13 +190,13 @@
attack_generic(H,25)
return
- playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1)
+ playsound(src, 'sound/effects/glassknock.ogg', 80, 1)
user.do_attack_animation(src)
usr.visible_message("\The [usr] bangs against \the [src]!",
"You bang against \the [src]!",
"You hear a banging sound.")
else
- playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1)
+ playsound(src, 'sound/effects/glassknock.ogg', 80, 1)
usr.visible_message("[usr.name] knocks on the [src.name].",
"You knock on the [src.name].",
"You hear a knocking sound.")
@@ -297,13 +297,13 @@
else if(istype(W, /obj/item/stack/cable_coil) && reinf && state == 0 && !istype(src, /obj/structure/window/reinforced/polarized))
var/obj/item/stack/cable_coil/C = W
if (C.use(1))
- playsound(src.loc, 'sound/effects/sparks1.ogg', 75, 1)
+ playsound(src, 'sound/effects/sparks1.ogg', 75, 1)
user.visible_message( \
"\The [user] begins to wire \the [src] for electrochromic tinting.", \
"You begin to wire \the [src] for electrochromic tinting.", \
"You hear sparks.")
if(do_after(user, 20 * C.toolspeed, src) && state == 0)
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
var/obj/structure/window/reinforced/polarized/P = new(loc, dir)
if(is_fulltile())
P.fulltile = TRUE
@@ -326,7 +326,7 @@
update_nearby_icons()
step(src, get_dir(user, src))
else
- playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
..()
return
@@ -412,7 +412,7 @@
/obj/structure/window/Move()
var/ini_dir = dir
update_nearby_tiles(need_rebuild=1)
- ..()
+ . = ..()
set_dir(ini_dir)
update_nearby_tiles(need_rebuild=1)
@@ -420,6 +420,11 @@
/obj/structure/window/proc/is_fulltile()
return fulltile
+/obj/structure/window/is_between_turfs(var/turf/origin, var/turf/target)
+ if(fulltile)
+ return TRUE
+ return ..()
+
//This proc is used to update the icons of nearby windows. It should not be confused with update_nearby_tiles(), which is an atmos proc!
/obj/structure/window/proc/update_nearby_icons()
update_icon()
diff --git a/code/game/turfs/flooring/flooring.dm b/code/game/turfs/flooring/flooring.dm
index b6fcfdda3b..cc93478e86 100644
--- a/code/game/turfs/flooring/flooring.dm
+++ b/code/game/turfs/flooring/flooring.dm
@@ -26,9 +26,10 @@ var/list/flooring_types
var/name = "floor"
var/desc
var/icon
- var/icon_base
+ var/icon_base // initial base icon_state without edges or corners.
- var/has_base_range
+ var/has_base_range // This will pick between a range of 0 - x. Number icon_states accordingly.
+ // Note that this will append a 0 - x number automatically to icon_base, but NOT the dmi. Do icon_base = "grass", but name grass0 inside the dmi. etc etc.
var/has_damage_range
var/has_burn_range
var/damage_temperature
@@ -42,25 +43,176 @@ var/list/flooring_types
var/descriptor = "tiles"
var/flags
var/can_paint
- var/list/footstep_sounds = list() // key=species name, value = list of soundss
+ var/list/footstep_sounds = list() // key=species name, value = list of sounds,
+ // For instance, footstep_sounds = list("key" = list(sound.ogg))
+ var/is_plating = FALSE
+ var/list/flooring_cache = list() // Cached overlays for our edges and corners and junk
+
+ //Plating types, can be overridden
+ var/plating_type = null
+
+ //Resistance is subtracted from all incoming damage
+ //var/resistance = RESISTANCE_FRAGILE
+
+ //Damage the floor can take before being destroyed
+ //var/health = 50
+
+ //var/removal_time = WORKTIME_FAST * 0.75
+
+ //Flooring Icon vars
+ var/smooth_nothing = FALSE //True/false only, optimisation
+ //If true, all smoothing logic is entirely skipped
+
+ //The rest of these x_smooth vars use one of the following options
+ //SMOOTH_NONE: Ignore all of type
+ //SMOOTH_ALL: Smooth with all of type
+ //SMOOTH_WHITELIST: Ignore all except types on this list
+ //SMOOTH_BLACKLIST: Smooth with all except types on this list
+ //SMOOTH_GREYLIST: Objects only: Use both lists
+
+ //How we smooth with other flooring
+ var/floor_smooth = SMOOTH_NONE
+ var/list/flooring_whitelist = list() //Smooth with nothing except the contents of this list
+ var/list/flooring_blacklist = list() //Smooth with everything except the contents of this list
+
+ //How we smooth with walls
+ var/wall_smooth = SMOOTH_NONE
+ //There are no lists for walls at this time
+
+ //How we smooth with space and openspace tiles
+ var/space_smooth = SMOOTH_NONE
+ //There are no lists for spaces
+
+ /*
+ How we smooth with movable atoms
+ These are checked after the above turf based smoothing has been handled
+ SMOOTH_ALL or SMOOTH_NONE are treated the same here. Both of those will just ignore atoms
+ Using the white/blacklists will override what the turfs concluded, to force or deny smoothing
+
+ Movable atom lists are much more complex, to account for many possibilities
+ Each entry in a list, is itself a list consisting of three items:
+ Type: The typepath to allow/deny. This will be checked against istype, so all subtypes are included
+ Priority: Used when items in two opposite lists conflict. The one with the highest priority wins out.
+ Vars: An associative list of variables (varnames in text) and desired values
+ Code will look for the desired vars on the target item and only call it a match if all desired values match
+ This can be used, for example, to check that objects are dense and anchored
+ there are no safety checks on this, it will probably throw runtimes if you make typos
+
+ Common example:
+ Don't smooth with dense anchored objects except airlocks
+
+ smooth_movable_atom = SMOOTH_GREYLIST
+ movable_atom_blacklist = list(
+ list(/obj, list("density" = TRUE, "anchored" = TRUE), 1)
+ )
+ movable_atom_whitelist = list(
+ list(/obj/machinery/door/airlock, list(), 2)
+ )
+
+ */
+ var/smooth_movable_atom = SMOOTH_NONE
+ var/list/movable_atom_whitelist = list()
+ var/list/movable_atom_blacklist = list()
+
+/decl/flooring/proc/get_plating_type(var/turf/T)
+ return plating_type
+
+/decl/flooring/proc/get_flooring_overlay(var/cache_key, var/icon_base, var/icon_dir = 0, var/layer = ABOVE_TURF_LAYER)
+ if(!flooring_cache[cache_key])
+ var/image/I = image(icon = icon, icon_state = icon_base, dir = icon_dir)
+ I.layer = layer
+ flooring_cache[cache_key] = I
+ return flooring_cache[cache_key]
/decl/flooring/grass
name = "grass"
desc = "Do they smoke grass out in space, Bowie? Or do they smoke AstroTurf?"
icon = 'icons/turf/flooring/grass.dmi'
icon_base = "grass"
- has_base_range = 3
+ has_base_range = 1
damage_temperature = T0C+80
- flags = TURF_HAS_EDGES | TURF_REMOVE_SHOVEL
+ flags = TURF_HAS_EDGES | TURF_HAS_CORNERS | TURF_REMOVE_SHOVEL
build_type = /obj/item/stack/tile/grass
+ footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/grass1.ogg',
+ 'sound/effects/footstep/grass2.ogg',
+ 'sound/effects/footstep/grass3.ogg',
+ 'sound/effects/footstep/grass4.ogg'))
+
+/decl/flooring/grass/sif // Subtype for Sif's grass.
+ name = "growth"
+ desc = "A natural moss that has adapted to the sheer cold climate."
+ flags = TURF_REMOVE_SHOVEL
+ icon = 'icons/turf/outdoors.dmi'
+ icon_base = "grass_sif"
+ has_base_range = 1
+
+/decl/flooring/water
+ name = "water"
+ desc = "Water is wet, gosh, who knew!"
+ icon = 'icons/turf/outdoors.dmi'
+ icon_base = "seashallow"
+ footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/water1.ogg',
+ 'sound/effects/footstep/water2.ogg',
+ 'sound/effects/footstep/water3.ogg',
+ 'sound/effects/footstep/water4.ogg'))
+
+/decl/flooring/sand
+ name = "sand"
+ desc = "I don't like sand. It's coarse and rough and irritating and it gets everywhere."
+ icon = 'icons/misc/beach.dmi'
+ icon_base = "sand"
+ footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/HeavySand1.ogg',
+ 'sound/effects/footstep/HeavySand2.ogg',
+ 'sound/effects/footstep/HeavySand3.ogg',
+ 'sound/effects/footstep/HeavySand4.ogg'))
+
+/decl/flooring/sand/desert // Subtype of sand, desert.
+ name = "desert"
+ desc = "I don't like sand. It's coarse and rough and irritating and it gets everywhere."
+ icon = 'icons/turf/desert.dmi'
+ icon_base = "desert"
+
+/decl/flooring/mud
+ name = "mud"
+ desc = "STICKY AND WET!"
+ icon = 'icons/turf/outdoors.dmi'
+ icon_base = "mud_dark"
+ footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/mud1.ogg',
+ 'sound/effects/footstep/mud2.ogg',
+ 'sound/effects/footstep/mud3.ogg',
+ 'sound/effects/footstep/mud4.ogg'))
/decl/flooring/asteroid
name = "coarse sand"
desc = "Gritty and unpleasant."
icon = 'icons/turf/flooring/asteroid.dmi'
icon_base = "asteroid"
+ flags = TURF_REMOVE_SHOVEL
+ build_type = null
+ footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/asteroid1.ogg',
+ 'sound/effects/footstep/asteroid2.ogg',
+ 'sound/effects/footstep/asteroid3.ogg',
+ 'sound/effects/footstep/asteroid4.ogg',
+ 'sound/effects/footstep/asteroid5.ogg'))
+
+/decl/flooring/dirt
+ name = "dirt"
+ desc = "Gritty and unpleasant, just like dirt."
+ icon = 'icons/turf/outdoors.dmi'
+ icon_base = "dirt-dark"
flags = TURF_HAS_EDGES | TURF_REMOVE_SHOVEL
build_type = null
+ footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/asteroid1.ogg',
+ 'sound/effects/footstep/asteroid2.ogg',
+ 'sound/effects/footstep/asteroid3.ogg',
+ 'sound/effects/footstep/asteroid4.ogg',
+ 'sound/effects/footstep/asteroid5.ogg'))
/decl/flooring/snow
name = "snow"
@@ -312,6 +464,12 @@ var/list/flooring_types
apply_thermal_conductivity = 0.025
apply_heat_capacity = 325000
can_paint = 1
+ footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/hull1.ogg',
+ 'sound/effects/footstep/hull2.ogg',
+ 'sound/effects/footstep/hull3.ogg',
+ 'sound/effects/footstep/hull4.ogg',
+ 'sound/effects/footstep/hull5.ogg'))
/decl/flooring/reinforced/circuit
name = "processing strata"
@@ -333,4 +491,14 @@ var/list/flooring_types
build_type = null
has_damage_range = 6
flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK
- can_paint = null
\ No newline at end of file
+ can_paint = null
+
+/decl/flooring/lava // Defining this in case someone DOES step on lava and survive. Somehow.
+ name = "lava"
+ desc = "Lava. Y'know. Sets you on fire. AAAAAAAAAAA"
+ icon = 'icons/turf/outdoors.dmi'
+ icon_base = "lava"
+ footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/lava1.ogg',
+ 'sound/effects/footstep/lava2.ogg',
+ 'sound/effects/footstep/lava3.ogg'))
\ No newline at end of file
diff --git a/code/game/turfs/flooring/flooring_decals.dm b/code/game/turfs/flooring/flooring_decals.dm
index 81aa348891..1ddfa79f82 100644
--- a/code/game/turfs/flooring/flooring_decals.dm
+++ b/code/game/turfs/flooring/flooring_decals.dm
@@ -29,7 +29,7 @@ var/list/floor_decals = list()
var/image/I = floor_decals[cache_key]
if(!I)
I = image(icon = icon, icon_state = icon_state, dir = dir)
- I.layer = T.layer
+ I.layer = TURF_DECAL_LAYER
I.color = color
I.alpha = alpha
floor_decals[cache_key] = I
diff --git a/code/game/turfs/flooring/flooring_premade.dm b/code/game/turfs/flooring/flooring_premade.dm
index 440ca2a813..a6c26a7bb9 100644
--- a/code/game/turfs/flooring/flooring_premade.dm
+++ b/code/game/turfs/flooring/flooring_premade.dm
@@ -386,6 +386,7 @@
name = "snow"
icon = 'icons/turf/snow_new.dmi'
icon_state = "snow"
+ initial_flooring = /decl/flooring/snow
var/list/crossed_dirs = list()
/turf/simulated/floor/snow/snow2
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index 866103376a..e18cf118bd 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -33,7 +33,7 @@
var/lava = 0
/turf/simulated/floor/is_plating()
- return !flooring
+ return (!flooring || flooring.is_plating)
/turf/simulated/floor/Initialize(mapload, floortype)
. = ..()
@@ -41,6 +41,7 @@
floortype = initial_flooring
if(floortype)
set_flooring(get_flooring_data(floortype), TRUE)
+ . = INITIALIZE_HINT_LATELOAD // We'll update our icons after everyone is ready
else
footstep_sounds = base_footstep_sounds
if(can_dirty && can_start_dirty)
@@ -48,18 +49,23 @@
dirt += rand(50,100)
update_dirt() //5% chance to start with dirt on a floor tile- give the janitor something to do
+/turf/simulated/floor/LateInitialize()
+ . = ..()
+ update_icon(1)
+
/turf/simulated/floor/proc/swap_decals()
var/current_decals = decals
decals = old_decals
old_decals = current_decals
/turf/simulated/floor/proc/set_flooring(var/decl/flooring/newflooring, var/initializing)
- make_plating(defer_icon_update = 1)
- if(!flooring && !initializing) // Plating -> Flooring
+ //make_plating(defer_icon_update = 1)
+ if(is_plating() && !initializing) // Plating -> Flooring
swap_decals()
flooring = newflooring
footstep_sounds = newflooring.footstep_sounds
- update_icon(1)
+ if(!initializing)
+ update_icon(1)
levelupdate()
//This proc will set floor_type to null and the update_icon() proc will then change the icon_state of the turf
@@ -73,11 +79,15 @@
icon_state = base_icon_state
footstep_sounds = base_footstep_sounds
- if(flooring) // Flooring -> Plating
+ if(!is_plating()) // Flooring -> Plating
swap_decals()
if(flooring.build_type && place_product)
new flooring.build_type(src)
- flooring = null
+ var/newtype = flooring.get_plating_type()
+ if(newtype) // Has a custom plating type to become
+ set_flooring(get_flooring_data(newtype))
+ else
+ flooring = null
set_light(0)
broken = null
@@ -89,8 +99,9 @@
update_icon(1)
/turf/simulated/floor/levelupdate()
+ var/floored_over = !is_plating()
for(var/obj/O in src)
- O.hide(O.hides_under_flooring() && src.flooring)
+ O.hide(O.hides_under_flooring() && floored_over)
/turf/simulated/floor/rcd_values(mob/living/user, obj/item/weapon/rcd/the_rcd, passed_mode)
switch(passed_mode)
diff --git a/code/game/turfs/simulated/floor_attackby.dm b/code/game/turfs/simulated/floor_attackby.dm
index 70bc2646a2..df13c2162c 100644
--- a/code/game/turfs/simulated/floor_attackby.dm
+++ b/code/game/turfs/simulated/floor_attackby.dm
@@ -53,7 +53,7 @@
break
return
- if(flooring)
+ if(!is_plating())
if(istype(C, /obj/item/weapon))
try_deconstruct_tile(C, user)
return
@@ -64,7 +64,6 @@
try_replace_tile(C, user)
return
else
-
if(istype(C, /obj/item/stack/cable_coil))
if(broken || burnt)
to_chat(user, "This section is too damaged to support anything. Use a welder to fix the damage.")
@@ -94,7 +93,7 @@
// Stay still and focus...
if(use_flooring.build_time && !do_after(user, use_flooring.build_time))
return
- if(flooring || !S || !user || !use_flooring)
+ if(!is_plating() || !S || !user || !use_flooring)
return
if(S.use(use_flooring.build_cost))
set_flooring(use_flooring)
diff --git a/code/game/turfs/simulated/floor_icon.dm b/code/game/turfs/simulated/floor_icon.dm
index e11ad7e998..e82edc294d 100644
--- a/code/game/turfs/simulated/floor_icon.dm
+++ b/code/game/turfs/simulated/floor_icon.dm
@@ -1,4 +1,4 @@
-GLOBAL_LIST_EMPTY(flooring_cache)
+var/list/flooring_cache = list()
var/image/no_ceiling_image = null
@@ -36,40 +36,39 @@ var/image/no_ceiling_image = null
if(flooring.flags & TURF_HAS_EDGES)
for(var/step_dir in cardinal)
var/turf/simulated/floor/T = get_step(src, step_dir)
- if(!istype(T) || !T.flooring || T.flooring.name != flooring.name)
+ if(!flooring.test_link(src, T))
has_border |= step_dir
- add_overlay(get_flooring_overlay("[flooring.icon_base]-edge-[step_dir]", "[flooring.icon_base]_edges", step_dir))
+ add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-edge-[step_dir]", "[flooring.icon_base]_edges", step_dir))
- // There has to be a concise numerical way to do this but I am too noob.
- if((has_border & NORTH) && (has_border & EAST))
- add_overlay(get_flooring_overlay("[flooring.icon_base]-edge-[NORTHEAST]", "[flooring.icon_base]_edges", NORTHEAST))
- if((has_border & NORTH) && (has_border & WEST))
- add_overlay(get_flooring_overlay("[flooring.icon_base]-edge-[NORTHWEST]", "[flooring.icon_base]_edges", NORTHWEST))
- if((has_border & SOUTH) && (has_border & EAST))
- add_overlay(get_flooring_overlay("[flooring.icon_base]-edge-[SOUTHEAST]", "[flooring.icon_base]_edges", SOUTHEAST))
- if((has_border & SOUTH) && (has_border & WEST))
- add_overlay(get_flooring_overlay("[flooring.icon_base]-edge-[SOUTHWEST]", "[flooring.icon_base]_edges", SOUTHWEST))
+ //Note: Doesn't actually check northeast, this is bitmath to check if we're edge'd (aka not smoothed) to NORTH and EAST
+ //North = 0001, East = 0100, Northeast = 0101, so (North|East) == Northeast, therefore (North|East)&Northeast == Northeast
+ if((has_border & NORTHEAST) == NORTHEAST)
+ add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-edge-[NORTHEAST]", "[flooring.icon_base]_edges", NORTHEAST))
+ if((has_border & NORTHWEST) == NORTHWEST)
+ add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-edge-[NORTHWEST]", "[flooring.icon_base]_edges", NORTHWEST))
+ if((has_border & SOUTHEAST) == SOUTHEAST)
+ add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-edge-[SOUTHEAST]", "[flooring.icon_base]_edges", SOUTHEAST))
+ if((has_border & SOUTHWEST) == SOUTHWEST)
+ add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-edge-[SOUTHWEST]", "[flooring.icon_base]_edges", SOUTHWEST))
if(flooring.flags & TURF_HAS_CORNERS)
- // As above re: concise numerical way to do this.
- if(!(has_border & NORTH))
- if(!(has_border & EAST))
- var/turf/simulated/floor/T = get_step(src, NORTHEAST)
- if(!(istype(T) && T.flooring && T.flooring.name == flooring.name))
- add_overlay(get_flooring_overlay("[flooring.icon_base]-corner-[NORTHEAST]", "[flooring.icon_base]_corners", NORTHEAST))
- if(!(has_border & WEST))
- var/turf/simulated/floor/T = get_step(src, NORTHWEST)
- if(!(istype(T) && T.flooring && T.flooring.name == flooring.name))
- add_overlay(get_flooring_overlay("[flooring.icon_base]-corner-[NORTHWEST]", "[flooring.icon_base]_corners", NORTHWEST))
- if(!(has_border & SOUTH))
- if(!(has_border & EAST))
- var/turf/simulated/floor/T = get_step(src, SOUTHEAST)
- if(!(istype(T) && T.flooring && T.flooring.name == flooring.name))
- add_overlay(get_flooring_overlay("[flooring.icon_base]-corner-[SOUTHEAST]", "[flooring.icon_base]_corners", SOUTHEAST))
- if(!(has_border & WEST))
- var/turf/simulated/floor/T = get_step(src, SOUTHWEST)
- if(!(istype(T) && T.flooring && T.flooring.name == flooring.name))
- add_overlay(get_flooring_overlay("[flooring.icon_base]-corner-[SOUTHWEST]", "[flooring.icon_base]_corners", SOUTHWEST))
+ //Like above but checking for NO similar bits rather than both similar bits.
+ if((has_border & NORTHEAST) == 0) //Are connected NORTH and EAST
+ var/turf/simulated/floor/T = get_step(src, NORTHEAST)
+ if(!flooring.test_link(src, T)) //But not NORTHEAST
+ add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-corner-[NORTHEAST]", "[flooring.icon_base]_corners", NORTHEAST))
+ if((has_border & NORTHWEST) == 0)
+ var/turf/simulated/floor/T = get_step(src, NORTHWEST)
+ if(!flooring.test_link(src, T))
+ add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-corner-[NORTHWEST]", "[flooring.icon_base]_corners", NORTHWEST))
+ if((has_border & SOUTHEAST) == 0)
+ var/turf/simulated/floor/T = get_step(src, SOUTHEAST)
+ if(!flooring.test_link(src, T))
+ add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-corner-[SOUTHEAST]", "[flooring.icon_base]_corners", SOUTHEAST))
+ if((has_border & SOUTHWEST) == 0)
+ var/turf/simulated/floor/T = get_step(src, SOUTHWEST)
+ if(!flooring.test_link(src, T))
+ add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-corner-[SOUTHWEST]", "[flooring.icon_base]_corners", SOUTHWEST))
// Re-apply floor decals
if(LAZYLEN(decals))
@@ -79,11 +78,10 @@ var/image/no_ceiling_image = null
icon = 'icons/turf/flooring/plating.dmi'
icon_state = "dmg[rand(1,4)]"
else if(flooring)
- var/rand_key = rand(0,2)
if(!isnull(broken) && (flooring.flags & TURF_CAN_BREAK))
- add_overlay(get_flooring_overlay("[flooring.icon_base]-broken-[rand_key]","broken[rand_key]"))
+ add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-broken-[broken]","broken[broken]"))
if(!isnull(burnt) && (flooring.flags & TURF_CAN_BURN))
- add_overlay(get_flooring_overlay("[flooring.icon_base]-burned-[rand_key]","burned[rand_key]"))
+ add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-burned-[burnt]","burned[burnt]"))
if(update_neighbors)
for(var/turf/simulated/floor/F in range(src, 1))
@@ -96,9 +94,193 @@ var/image/no_ceiling_image = null
if(above && isopenspace(above) && !istype(src, /turf/simulated/floor/outdoors)) // This won't apply to outdoor turfs since its assumed they don't have a ceiling anyways.
add_overlay(no_ceiling_image)
+ // Update our 'them-to-us' edges, aka edges from external turfs we feel should spill onto us
+ if(edge_blending_priority && !forbid_turf_edge())
+ update_icon_edge()
+
+// This updates an edge from an adjacent turf onto us, not our own 'internal' edges.
+// For e.g. we might be outdoor metal plating, and we want to find sand next to us to have it 'spill onto' our turf with an overlay.
+/turf/simulated/proc/update_icon_edge()
+ for(var/checkdir in cardinal) // Check every direction
+ var/turf/simulated/T = get_step(src, checkdir) // Get the turf in that direction
+ // Our conditions:
+ // Has to be a /turf/simulated
+ // Has to have it's own edge_blending_priority
+ // Has to have a higher priority than us
+ // Their icon_state is not our icon_state
+ // They don't forbid_turf_edge
+ if(istype(T) && T.edge_blending_priority && edge_blending_priority < T.edge_blending_priority && icon_state != T.icon_state && !T.forbid_turf_edge())
+ var/cache_key = "[T.get_edge_icon_state()]-[checkdir]" // Usually [icon_state]-[dirnum]
+ if(!turf_edge_cache[cache_key])
+ var/image/I = image(icon = 'icons/turf/outdoors_edge.dmi', icon_state = "[T.get_edge_icon_state()]-edge", dir = checkdir, layer = ABOVE_TURF_LAYER) // Icon should be abstracted out
+ I.plane = TURF_PLANE
+ turf_edge_cache[cache_key] = I
+ add_overlay(turf_edge_cache[cache_key])
+
+// We will take this state and use it for a cache key, and append '-edge' to it to get the edge overlay (edges *from other turfs*, not our own internal edges)
+/turf/simulated/proc/get_edge_icon_state()
+ return icon_state
+
+// Tests if we shouldn't apply a turf edge.
+// Returns the blocker if one exists.
+/turf/simulated/proc/forbid_turf_edge()
+ for(var/obj/structure/S in contents)
+ if(S.block_turf_edges)
+ return S
+ return null
+
+//Tests whether this flooring will smooth with the specified turf
+//You can override this if you want a flooring to have super special snowflake smoothing behaviour
+/decl/flooring/proc/test_link(var/turf/origin, var/turf/T, var/countercheck = FALSE)
+
+ var/is_linked = FALSE
+ if (countercheck)
+ //If this is a countercheck, we skip all of the above, start off with true, and go straight to the atom lists
+ is_linked = TRUE
+ else if(T)
+
+ //If it's a wall, use the wall_smooth setting
+ if(istype(T, /turf/simulated/wall))
+ if(wall_smooth == SMOOTH_ALL)
+ is_linked = TRUE
+
+ //If it's space or openspace, use the space_smooth setting
+ else if(isspace(T) || isopenspace(T))
+ if(space_smooth == SMOOTH_ALL)
+ is_linked = TRUE
+
+ //If we get here then its a normal floor
+ else if (istype(T, /turf/simulated/floor))
+ var/turf/simulated/floor/t = T
+ //If the floor is the same as us,then we're linked,
+ if (t.flooring?.type == type)
+ is_linked = TRUE
+ /*
+ But there's a caveat. To make atom black/whitelists work correctly, we also need to check that
+ they smooth with us. Ill call this counterchecking for simplicity.
+ This is needed to make both turfs have the correct borders
+
+ To prevent infinite loops we have a countercheck var, which we'll set true
+ */
+
+ if (smooth_movable_atom != SMOOTH_NONE)
+ //We do the countercheck, passing countercheck as true
+ is_linked = test_link(T, origin, countercheck = TRUE)
+
+ else if (floor_smooth == SMOOTH_ALL)
+ is_linked = TRUE
+
+ else if (floor_smooth != SMOOTH_NONE)
+ //If we get here it must be using a whitelist or blacklist
+ if (floor_smooth == SMOOTH_WHITELIST)
+ for (var/v in flooring_whitelist)
+ if (istype(t.flooring, v))
+ //Found a match on the list
+ is_linked = TRUE
+ break
+ else if(floor_smooth == SMOOTH_BLACKLIST)
+ is_linked = TRUE //Default to true for the blacklist, then make it false if a match comes up
+ for (var/v in flooring_whitelist)
+ if (istype(t.flooring, v))
+ //Found a match on the list
+ is_linked = FALSE
+ break
+
+ //Alright now we have a preliminary answer about smoothing, however that answer may change with the following
+ //Atom lists!
+ var/best_priority = -1
+ //A white or blacklist entry will only override smoothing if its priority is higher than this
+ //And then this value becomes its priority
+ if (smooth_movable_atom != SMOOTH_NONE)
+ if (smooth_movable_atom == SMOOTH_WHITELIST || smooth_movable_atom == SMOOTH_GREYLIST)
+ for (var/list/v in movable_atom_whitelist)
+ var/d_type = v[1]
+ var/list/d_vars = v[2]
+ var/d_priority = v[3]
+ //Priority is the quickest thing to check first
+ if (d_priority <= best_priority)
+ continue
+
+ //Ok, now we start testing all the atoms in the target turf
+ for (var/a in T) //No implicit typecasting here, faster
+
+ if (istype(a, d_type))
+ //It's the right type, so we're sure it will have the vars we want.
+
+ var/atom/movable/AM = a
+ //Typecast it to a movable atom
+ //Lets make sure its in the way before we consider it
+ if (!AM.is_between_turfs(origin, T))
+ continue
+
+ //From here on out, we do dangerous stuff that may runtime if the coder screwed up
+
+
+ var/match = TRUE
+ for (var/d_var in d_vars)
+ //For each variable we want to check
+ if (AM.vars[d_var] != d_vars[d_var])
+ //We get a var of the same name from the atom's vars list.
+ //And check if it equals our desired value
+ match = FALSE
+ break //If any var doesn't match the desired value, then this atom is not a match, move on
+
+
+ if (match)
+ //If we've successfully found an atom which matches a list entry
+ best_priority = d_priority //This one is king until a higher priority overrides it
+
+ //And this is a whitelist, so this match forces is_linked to true
+ is_linked = TRUE
+
+
+ if (smooth_movable_atom == SMOOTH_BLACKLIST || smooth_movable_atom == SMOOTH_GREYLIST)
+ //All of this blacklist code is copypasted from above, with only minor name changes
+ for (var/list/v in movable_atom_blacklist)
+ var/d_type = v[1]
+ var/list/d_vars = v[2]
+ var/d_priority = v[3]
+ //Priority is the quickest thing to check first
+ if (d_priority <= best_priority)
+ continue
+
+ //Ok, now we start testing all the atoms in the target turf
+ for (var/a in T) //No implicit typecasting here, faster
+
+ if (istype(a, d_type))
+ //It's the right type, so we're sure it will have the vars we want.
+
+ var/atom/movable/AM = a
+ //Typecast it to a movable atom
+ //Lets make sure its in the way before we consider it
+ if (!AM.is_between_turfs(origin, T))
+ continue
+
+ //From here on out, we do dangerous stuff that may runtime if the coder screwed up
+
+ var/match = TRUE
+ for (var/d_var in d_vars)
+ //For each variable we want to check
+ if (AM.vars[d_var] != d_vars[d_var])
+ //We get a var of the same name from the atom's vars list.
+ //And check if it equals our desired value
+ match = FALSE
+ break //If any var doesn't match the desired value, then this atom is not a match, move on
+
+
+ if (match)
+ //If we've successfully found an atom which matches a list entry
+ best_priority = d_priority //This one is king until a higher priority overrides it
+
+ //And this is a blacklist, so this match forces is_linked to false
+ is_linked = FALSE
+
+ return is_linked
+
/turf/simulated/floor/proc/get_flooring_overlay(var/cache_key, var/icon_base, var/icon_dir = 0)
- if(!GLOB.flooring_cache[cache_key])
+ if(!flooring_cache[cache_key])
var/image/I = image(icon = flooring.icon, icon_state = icon_base, dir = icon_dir)
I.layer = layer
- GLOB.flooring_cache[cache_key] = I
- return GLOB.flooring_cache[cache_key]
+ flooring_cache[cache_key] = I
+ return flooring_cache[cache_key]
+
diff --git a/code/game/turfs/simulated/floor_types_eris.dm b/code/game/turfs/simulated/floor_types_eris.dm
new file mode 100644
index 0000000000..00b66d0d8a
--- /dev/null
+++ b/code/game/turfs/simulated/floor_types_eris.dm
@@ -0,0 +1,1010 @@
+
+////////////////////////////
+/// ERIS FLOOR DECLS ///////
+////////////////////////////
+
+/decl/flooring/tiling/eris
+ name = "floor"
+ desc = "Scuffed from the passage of countless greyshirts."
+ icon = 'icons/turf/flooring/eris/tiles.dmi'
+ icon_base = "tiles"
+ has_damage_range = 2
+ damage_temperature = T0C+1400
+ flags = TURF_HAS_EDGES | TURF_HAS_CORNERS | TURF_REMOVE_CROWBAR | TURF_CAN_BREAK
+ build_type = /obj/item/stack/tile/floor/eris
+ can_paint = 1
+
+ plating_type = /decl/flooring/reinforced/plating/under
+
+ floor_smooth = SMOOTH_WHITELIST
+ flooring_whitelist = list(
+ /decl/flooring/reinforced/plating/under
+ )
+
+ smooth_movable_atom = SMOOTH_GREYLIST
+ movable_atom_whitelist = list(
+ list(/obj/machinery/door/airlock, list(), 1) // Smooth Eris floors with airlocks
+ )
+ movable_atom_blacklist = list(
+ list(/obj/machinery/door/airlock/maintenance, list(), 2), // But not maintenance airlocks
+ list(/obj/structure/window, list("anchored" = TRUE, "fulltile" = TRUE), 2) // Don't blend under full windows
+ )
+
+/decl/flooring/tiling/eris/steel
+ name = "steel floor"
+ icon_base = "tiles"
+ icon = 'icons/turf/flooring/eris/tiles_steel.dmi'
+ build_type = /obj/item/stack/tile/floor/eris/steel
+
+/decl/flooring/tiling/eris/steel/panels
+ icon_base = "panels"
+ build_type = /obj/item/stack/tile/floor/eris/steel/panels
+
+/decl/flooring/tiling/eris/steel/techfloor
+ icon_base = "techfloor"
+ build_type = /obj/item/stack/tile/floor/eris/steel/techfloor
+
+/decl/flooring/tiling/eris/steel/techfloor_grid
+ icon_base = "techfloor_grid"
+ build_type = /obj/item/stack/tile/floor/eris/steel/techfloor_grid
+
+/decl/flooring/tiling/eris/steel/brown_perforated
+ icon_base = "brown_perforated"
+ build_type = /obj/item/stack/tile/floor/eris/steel/brown_perforated
+
+/decl/flooring/tiling/eris/steel/gray_perforated
+ icon_base = "gray_perforated"
+ build_type = /obj/item/stack/tile/floor/eris/steel/gray_perforated
+
+/decl/flooring/tiling/eris/steel/cargo
+ icon_base = "cargo"
+ build_type = /obj/item/stack/tile/floor/eris/steel/cargo
+
+/decl/flooring/tiling/eris/steel/brown_platform
+ icon_base = "brown_platform"
+ build_type = /obj/item/stack/tile/floor/eris/steel/brown_platform
+
+/decl/flooring/tiling/eris/steel/gray_platform
+ icon_base = "gray_platform"
+ build_type = /obj/item/stack/tile/floor/eris/steel/gray_platform
+
+/decl/flooring/tiling/eris/steel/danger
+ icon_base = "danger"
+ build_type = /obj/item/stack/tile/floor/eris/steel/danger
+
+/decl/flooring/tiling/eris/steel/golden
+ icon_base = "golden"
+ build_type = /obj/item/stack/tile/floor/eris/steel/golden
+
+/decl/flooring/tiling/eris/steel/bluecorner
+ icon_base = "bluecorner"
+ build_type = /obj/item/stack/tile/floor/eris/steel/bluecorner
+
+/decl/flooring/tiling/eris/steel/orangecorner
+ icon_base = "orangecorner"
+ build_type = /obj/item/stack/tile/floor/eris/steel/orangecorner
+
+/decl/flooring/tiling/eris/steel/cyancorner
+ icon_base = "cyancorner"
+ build_type = /obj/item/stack/tile/floor/eris/steel/cyancorner
+
+/decl/flooring/tiling/eris/steel/violetcorener
+ icon_base = "violetcorener"
+ build_type = /obj/item/stack/tile/floor/eris/steel/violetcorener
+
+/decl/flooring/tiling/eris/steel/monofloor
+ icon_base = "monofloor"
+ build_type = /obj/item/stack/tile/floor/eris/steel/monofloor
+ has_base_range = 15
+
+/decl/flooring/tiling/eris/steel/bar_flat
+ name = "flat bar floor"
+ icon_base = "bar_flat"
+ build_type = /obj/item/stack/tile/floor/eris/steel/bar_flat
+ floor_smooth = SMOOTH_NONE
+ smooth_movable_atom = SMOOTH_NONE
+
+/decl/flooring/tiling/eris/steel/bar_dance
+ name = "dancefloor"
+ icon_base = "bar_dance"
+ build_type = /obj/item/stack/tile/floor/eris/steel/bar_dance
+ floor_smooth = SMOOTH_NONE
+ smooth_movable_atom = SMOOTH_NONE
+
+/decl/flooring/tiling/eris/steel/bar_light
+ name = "lit bar floor"
+ icon_base = "bar_light"
+ build_type = /obj/item/stack/tile/floor/eris/steel/bar_light
+ floor_smooth = SMOOTH_NONE
+ smooth_movable_atom = SMOOTH_NONE
+
+/decl/flooring/tiling/eris/white
+ name = "white floor"
+ icon_base = "tiles"
+ icon = 'icons/turf/flooring/eris/tiles_white.dmi'
+ build_type = /obj/item/stack/tile/floor/eris/white
+
+/decl/flooring/tiling/eris/white/panels
+ icon_base = "panels"
+ build_type = /obj/item/stack/tile/floor/eris/white/panels
+
+/decl/flooring/tiling/eris/white/techfloor
+ icon_base = "techfloor"
+ build_type = /obj/item/stack/tile/floor/eris/white/techfloor
+
+/decl/flooring/tiling/eris/white/techfloor_grid
+ icon_base = "techfloor_grid"
+ build_type = /obj/item/stack/tile/floor/eris/white/techfloor_grid
+
+/decl/flooring/tiling/eris/white/brown_perforated
+ icon_base = "brown_perforated"
+ build_type = /obj/item/stack/tile/floor/eris/white/brown_perforated
+
+/decl/flooring/tiling/eris/white/gray_perforated
+ icon_base = "gray_perforated"
+ build_type = /obj/item/stack/tile/floor/eris/white/gray_perforated
+
+/decl/flooring/tiling/eris/white/cargo
+ icon_base = "cargo"
+ build_type = /obj/item/stack/tile/floor/eris/white/cargo
+
+/decl/flooring/tiling/eris/white/brown_platform
+ icon_base = "brown_platform"
+ build_type = /obj/item/stack/tile/floor/eris/white/brown_platform
+
+/decl/flooring/tiling/eris/white/gray_platform
+ icon_base = "gray_platform"
+ build_type = /obj/item/stack/tile/floor/eris/white/gray_platform
+
+/decl/flooring/tiling/eris/white/danger
+ icon_base = "danger"
+ build_type = /obj/item/stack/tile/floor/eris/white/danger
+
+/decl/flooring/tiling/eris/white/golden
+ icon_base = "golden"
+ build_type = /obj/item/stack/tile/floor/eris/white/golden
+
+/decl/flooring/tiling/eris/white/bluecorner
+ icon_base = "bluecorner"
+ build_type = /obj/item/stack/tile/floor/eris/white/bluecorner
+
+/decl/flooring/tiling/eris/white/orangecorner
+ icon_base = "orangecorner"
+ build_type = /obj/item/stack/tile/floor/eris/white/orangecorner
+
+/decl/flooring/tiling/eris/white/cyancorner
+ icon_base = "cyancorner"
+ build_type = /obj/item/stack/tile/floor/eris/white/cyancorner
+
+/decl/flooring/tiling/eris/white/violetcorener
+ icon_base = "violetcorener"
+ build_type = /obj/item/stack/tile/floor/eris/white/violetcorener
+
+/decl/flooring/tiling/eris/white/monofloor
+ icon_base = "monofloor"
+ build_type = /obj/item/stack/tile/floor/eris/white/monofloor
+ has_base_range = 15
+
+/decl/flooring/tiling/eris/dark
+ name = "dark floor"
+ icon_base = "tiles"
+ icon = 'icons/turf/flooring/eris/tiles_dark.dmi'
+ build_type = /obj/item/stack/tile/floor/eris/dark
+
+/decl/flooring/tiling/eris/dark/panels
+ icon_base = "panels"
+ build_type = /obj/item/stack/tile/floor/eris/dark/panels
+
+/decl/flooring/tiling/eris/dark/techfloor
+ icon_base = "techfloor"
+ build_type = /obj/item/stack/tile/floor/eris/dark/techfloor
+
+/decl/flooring/tiling/eris/dark/techfloor_grid
+ icon_base = "techfloor_grid"
+ build_type = /obj/item/stack/tile/floor/eris/dark/techfloor_grid
+
+/decl/flooring/tiling/eris/dark/brown_perforated
+ icon_base = "brown_perforated"
+ build_type = /obj/item/stack/tile/floor/eris/dark/brown_perforated
+
+/decl/flooring/tiling/eris/dark/gray_perforated
+ icon_base = "gray_perforated"
+ build_type = /obj/item/stack/tile/floor/eris/dark/gray_perforated
+
+/decl/flooring/tiling/eris/dark/cargo
+ icon_base = "cargo"
+ build_type = /obj/item/stack/tile/floor/eris/dark/cargo
+
+/decl/flooring/tiling/eris/dark/brown_platform
+ icon_base = "brown_platform"
+ build_type = /obj/item/stack/tile/floor/eris/dark/brown_platform
+
+/decl/flooring/tiling/eris/dark/gray_platform
+ icon_base = "gray_platform"
+ build_type = /obj/item/stack/tile/floor/eris/dark/gray_platform
+
+/decl/flooring/tiling/eris/dark/danger
+ icon_base = "danger"
+ build_type = /obj/item/stack/tile/floor/eris/dark/danger
+
+/decl/flooring/tiling/eris/dark/golden
+ icon_base = "golden"
+ build_type = /obj/item/stack/tile/floor/eris/dark/golden
+
+/decl/flooring/tiling/eris/dark/bluecorner
+ icon_base = "bluecorner"
+ build_type = /obj/item/stack/tile/floor/eris/dark/bluecorner
+
+/decl/flooring/tiling/eris/dark/orangecorner
+ icon_base = "orangecorner"
+ build_type = /obj/item/stack/tile/floor/eris/dark/orangecorner
+
+/decl/flooring/tiling/eris/dark/cyancorner
+ icon_base = "cyancorner"
+ build_type = /obj/item/stack/tile/floor/eris/dark/cyancorner
+
+/decl/flooring/tiling/eris/dark/violetcorener
+ icon_base = "violetcorener"
+ build_type = /obj/item/stack/tile/floor/eris/dark/violetcorener
+
+/decl/flooring/tiling/eris/dark/monofloor
+ icon_base = "monofloor"
+ build_type = /obj/item/stack/tile/floor/eris/dark/monofloor
+ has_base_range = 15
+
+/decl/flooring/tiling/eris/cafe
+ name = "linoleum floor"
+ icon_base = "cafe"
+ icon = 'icons/turf/flooring/eris/tiles.dmi'
+ build_type = /obj/item/stack/tile/floor/eris/cafe
+ floor_smooth = SMOOTH_NONE
+ smooth_movable_atom = SMOOTH_NONE
+
+/decl/flooring/tiling/eris/techmaint
+ name = "techmaint floor"
+ icon_base = "techmaint"
+ icon = 'icons/turf/flooring/eris/tiles_maint.dmi'
+ build_type = /obj/item/stack/tile/floor/eris/techmaint
+ floor_smooth = SMOOTH_NONE
+ smooth_movable_atom = SMOOTH_NONE
+
+/decl/flooring/tiling/eris/techmaint_perforated
+ name = "techmaint floor"
+ icon_base = "techmaint_perforated"
+ icon = 'icons/turf/flooring/eris/tiles_maint.dmi'
+ build_type = /obj/item/stack/tile/floor/eris/techmaint/perforated
+ floor_smooth = SMOOTH_NONE
+ smooth_movable_atom = SMOOTH_NONE
+
+/decl/flooring/tiling/eris/techmaint_panels
+ name = "techmaint floor"
+ icon_base = "techmaint_panels"
+ icon = 'icons/turf/flooring/eris/tiles_maint.dmi'
+ build_type = /obj/item/stack/tile/floor/eris/techmaint/panels
+ floor_smooth = SMOOTH_NONE
+ smooth_movable_atom = SMOOTH_NONE
+
+/decl/flooring/tiling/eris/techmaint_cargo
+ name = "techmaint floor"
+ icon_base = "techmaint_cargo"
+ icon = 'icons/turf/flooring/eris/tiles_maint.dmi'
+ build_type = /obj/item/stack/tile/floor/eris/techmaint/cargo
+ floor_smooth = SMOOTH_NONE
+ smooth_movable_atom = SMOOTH_NONE
+
+///////////////////////
+/// TILE OBJS ///////
+///////////////////////
+/obj/item/stack/tile/floor/eris
+ icon = 'icons/turf/flooring/eris/tilestack.dmi'
+
+// Cafe
+/obj/item/stack/tile/floor/eris/cafe
+ name = "cafe floor tile"
+ singular_name = "cafe floor tile"
+ desc = "A chekered pattern, an ancient style for a familiar feeling."
+ icon_state = "tile_cafe"
+ matter = list(MAT_PLASTIC = 1)
+
+// Techmaint
+/obj/item/stack/tile/floor/eris/techmaint
+ name = "maint floor tile"
+ singular_name = "maint floor tile"
+ icon_state = "tile_techmaint"
+ matter = list(MAT_STEEL = 1)
+
+/obj/item/stack/tile/floor/eris/techmaint/perforated
+ name = "perforated maint floor tile"
+ singular_name = "perforated maint floor tile"
+ icon_state = "tile_techmaint_perforated"
+
+/obj/item/stack/tile/floor/eris/techmaint/panels
+ name = "panel maint floor tile"
+ singular_name = "panel maint floor tile"
+ icon_state = "tile_techmaint_panels"
+
+/obj/item/stack/tile/floor/eris/techmaint/cargo
+ name = "cargo maint floor tile"
+ singular_name = "cargo maint floor tile"
+ icon_state = "tile_techmaint_cargo"
+
+/*
+ * Steel
+ */
+/obj/item/stack/tile/floor/eris/steel
+ name = "steel floor tile"
+ singular_name = "steel floor tile"
+ icon_state = "tile_steel"
+ matter = list(MAT_STEEL = 1)
+
+/obj/item/stack/tile/floor/eris/steel/panels
+ name = "steel panel tile"
+ singular_name = "steel panel tile"
+ icon_state = "tile_steel_panels"
+
+/obj/item/stack/tile/floor/eris/steel/techfloor
+ name = "steel techfloor tile"
+ singular_name = "steel techfloor tile"
+ icon_state = "tile_steel_techfloor"
+
+/obj/item/stack/tile/floor/eris/steel/techfloor_grid
+ name = "steel techfloor tile with vents"
+ singular_name = "steel techfloor tile with vents"
+ icon_state = "tile_steel_techfloor_grid"
+
+/obj/item/stack/tile/floor/eris/steel/brown_perforated
+ name = "steel brown perforated tile"
+ singular_name = "steel brown perforated tile"
+ icon_state = "tile_steel_brownperforated"
+
+/obj/item/stack/tile/floor/eris/steel/gray_perforated
+ name = "steel gray perforated tile"
+ singular_name = "steel gray perforated tile"
+ icon_state = "tile_steel_grayperforated"
+
+/obj/item/stack/tile/floor/eris/steel/cargo
+ name = "steel cargo tile"
+ singular_name = "steel cargo tile"
+ icon_state = "tile_steel_cargo"
+
+/obj/item/stack/tile/floor/eris/steel/brown_platform
+ name = "steel brown platform tile"
+ singular_name = "steel brown platform tile"
+ icon_state = "tile_steel_brownplatform"
+
+/obj/item/stack/tile/floor/eris/steel/gray_platform
+ name = "steel gray platform tile"
+ singular_name = "steel gray platform tile"
+ icon_state = "tile_steel_grayplatform"
+
+/obj/item/stack/tile/floor/eris/steel/danger
+ name = "steel danger tile"
+ singular_name = "steel danger tile"
+ icon_state = "tile_steel_danger"
+
+/obj/item/stack/tile/floor/eris/steel/golden
+ name = "steel golden tile"
+ singular_name = "steel golden tile"
+ icon_state = "tile_steel_golden"
+
+/obj/item/stack/tile/floor/eris/steel/bluecorner
+ name = "steel blue corner tile"
+ singular_name = "steel blue corner tile"
+ icon_state = "tile_steel_bluecorner"
+
+/obj/item/stack/tile/floor/eris/steel/orangecorner
+ name = "steel orange corner tile"
+ singular_name = "steel orange corner tilee"
+ icon_state = "tile_steel_orangecorner"
+
+/obj/item/stack/tile/floor/eris/steel/cyancorner
+ name = "steel cyan corner tile"
+ singular_name = "steel cyan corner tile"
+ icon_state = "tile_steel_cyancorner"
+
+/obj/item/stack/tile/floor/eris/steel/violetcorener
+ name = "steel violet corener tile"
+ singular_name = "steel violet corener tile"
+ icon_state = "tile_steel_violetcorener"
+
+/obj/item/stack/tile/floor/eris/steel/monofloor
+ name = "steel monofloor tile"
+ singular_name = "steel monofloor tile"
+ icon_state = "tile_steel_monofloor"
+
+/obj/item/stack/tile/floor/eris/steel/bar_flat
+ name = "steel bar flat tile"
+ singular_name = "steel bar flat tile"
+ icon_state = "tile_steel_bar_flat"
+
+/obj/item/stack/tile/floor/eris/steel/bar_dance
+ name = "steel bar dance tile"
+ singular_name = "steel bar dance tile"
+ icon_state = "tile_steel_bar_dance"
+
+/obj/item/stack/tile/floor/eris/steel/bar_light
+ name = "steel bar light tile"
+ singular_name = "steel bar light tile"
+ icon_state = "tile_steel_bar_light"
+
+/*
+ * Plastic
+ */
+/obj/item/stack/tile/floor/eris/white
+ name = "white floor tile"
+ singular_name = "white floor tile"
+ desc = "Appears to be made out of a lighter mat."
+ icon_state = "tile_white"
+ matter = list(MAT_PLASTIC = 1)
+
+/obj/item/stack/tile/floor/eris/white/panels
+ name = "white panel tile"
+ singular_name = "white panel tile"
+ icon_state = "tile_white_panels"
+
+/obj/item/stack/tile/floor/eris/white/techfloor
+ name = "white techfloor tile"
+ singular_name = "white techfloor tile"
+ icon_state = "tile_white_techfloor"
+
+/obj/item/stack/tile/floor/eris/white/techfloor_grid
+ name = "white techfloor tile with vents"
+ singular_name = "white techfloor tile with vents"
+ icon_state = "tile_white_techfloor_grid"
+
+/obj/item/stack/tile/floor/eris/white/brown_perforated
+ name = "white brown perforated tile"
+ singular_name = "white brown perforated tile"
+ icon_state = "tile_white_brownperforated"
+
+/obj/item/stack/tile/floor/eris/white/gray_perforated
+ name = "white gray perforated tile"
+ singular_name = "white gray perforated tile"
+ icon_state = "tile-white-grayperforated"
+
+/obj/item/stack/tile/floor/eris/white/cargo
+ name = "white cargo tile"
+ singular_name = "white cargo tile"
+ icon_state = "tile_white_cargo"
+
+/obj/item/stack/tile/floor/eris/white/brown_platform
+ name = "white brown platform tile"
+ singular_name = "white brown platform tile"
+ icon_state = "tile_white_brownplatform"
+
+/obj/item/stack/tile/floor/eris/white/gray_platform
+ name = "white gray platform tile"
+ singular_name = "white gray platform tile"
+ icon_state = "tile_white_grayplatform"
+
+/obj/item/stack/tile/floor/eris/white/danger
+ name = "white danger tile"
+ singular_name = "white danger tile"
+ icon_state = "tile_white_danger"
+
+/obj/item/stack/tile/floor/eris/white/golden
+ name = "white golden tile"
+ singular_name = "white golden tile"
+ icon_state = "tile_white_golden"
+
+/obj/item/stack/tile/floor/eris/white/bluecorner
+ name = "white blue corner tile"
+ singular_name = "white blue corner tile"
+ icon_state = "tile_white_bluecorner"
+
+/obj/item/stack/tile/floor/eris/white/orangecorner
+ name = "white orange corner tile"
+ singular_name = "white orange corner tilee"
+ icon_state = "tile_white_orangecorner"
+
+/obj/item/stack/tile/floor/eris/white/cyancorner
+ name = "white cyan corner tile"
+ singular_name = "white cyan corner tile"
+ icon_state = "tile_white_cyancorner"
+
+/obj/item/stack/tile/floor/eris/white/violetcorener
+ name = "white violet corener tile"
+ singular_name = "white violet corener tile"
+ icon_state = "tile_white_violetcorener"
+
+/obj/item/stack/tile/floor/eris/white/monofloor
+ name = "white monofloor tile"
+ singular_name = "white monofloor tile"
+ icon_state = "tile_white_monofloor"
+
+/*
+ * Steel
+ */
+/obj/item/stack/tile/floor/eris/dark
+ name = "dark floor tile"
+ singular_name = "dark floor tile"
+ icon_state = "tile_dark"
+ matter = list(MAT_STEEL = 1)
+
+/obj/item/stack/tile/floor/eris/dark/panels
+ name = "dark panel tile"
+ singular_name = "dark panel tile"
+ icon_state = "tile_dark_panels"
+
+/obj/item/stack/tile/floor/eris/dark/techfloor
+ name = "dark techfloor tile"
+ singular_name = "dark techfloor tile"
+ icon_state = "tile_dark_techfloor"
+
+/obj/item/stack/tile/floor/eris/dark/techfloor_grid
+ name = "dark techfloor tile with vents"
+ singular_name = "dark techfloor tile with vents"
+ icon_state = "tile_dark_techfloor_grid"
+
+/obj/item/stack/tile/floor/eris/dark/brown_perforated
+ name = "dark brown perforated tile"
+ singular_name = "dark brown perforated tile"
+ icon_state = "tile_dark_brownperforated"
+
+/obj/item/stack/tile/floor/eris/dark/gray_perforated
+ name = "dark gray perforated tile"
+ singular_name = "dark gray perforated tile"
+ icon_state = "tile_dark_grayperforated"
+
+/obj/item/stack/tile/floor/eris/dark/cargo
+ name = "dark cargo tile"
+ singular_name = "dark cargo tile"
+ icon_state = "tile_dark_cargo"
+
+/obj/item/stack/tile/floor/eris/dark/brown_platform
+ name = "dark brown platform tile"
+ singular_name = "dark brown platform tile"
+ icon_state = "tile_dark_brownplatform"
+
+/obj/item/stack/tile/floor/eris/dark/gray_platform
+ name = "dark gray platform tile"
+ singular_name = "dark gray platform tile"
+ icon_state = "tile_dark_grayplatform"
+
+/obj/item/stack/tile/floor/eris/dark/danger
+ name = "dark danger tile"
+ singular_name = "dark danger tile"
+ icon_state = "tile_dark_danger"
+
+/obj/item/stack/tile/floor/eris/dark/golden
+ name = "dark golden tile"
+ singular_name = "dark golden tile"
+ icon_state = "tile_dark_golden"
+
+/obj/item/stack/tile/floor/eris/dark/bluecorner
+ name = "dark blue corner tile"
+ singular_name = "dark blue corner tile"
+ icon_state = "tile_dark_bluecorner"
+
+/obj/item/stack/tile/floor/eris/dark/orangecorner
+ name = "dark orange corner tile"
+ singular_name = "dark orange corner tilee"
+ icon_state = "tile_dark_orangecorner"
+
+/obj/item/stack/tile/floor/eris/dark/cyancorner
+ name = "dark cyan corner tile"
+ singular_name = "dark cyan corner tile"
+ icon_state = "tile_dark_cyancorner"
+
+/obj/item/stack/tile/floor/eris/dark/violetcorener
+ name = "dark violet corener tile"
+ singular_name = "dark violet corener tile"
+ icon_state = "tile_dark_violetcorener"
+
+/obj/item/stack/tile/floor/eris/dark/monofloor
+ name = "dark monofloor tile"
+ singular_name = "dark monofloor tile"
+ icon_state = "tile_dark_monofloor"
+
+
+///////////////////////
+/// PREMADE TURFS /////
+///////////////////////
+/turf/simulated/floor/tiled/eris
+ name = "floor"
+ icon = 'icons/turf/flooring/eris/tiles.dmi'
+ icon_state = "tiles"
+ initial_flooring = /decl/flooring/tiling/eris
+
+
+
+//Steel tiles
+/turf/simulated/floor/tiled/eris/steel
+ name = "floor"
+ icon = 'icons/turf/flooring/eris/tiles_steel.dmi'
+ icon_state = "tiles"
+ initial_flooring = /decl/flooring/tiling/eris/steel
+
+/turf/simulated/floor/tiled/eris/steel/panels
+ icon_state = "panels"
+ initial_flooring = /decl/flooring/tiling/eris/steel/panels
+
+/turf/simulated/floor/tiled/eris/steel/techfloor
+ icon_state = "techfloor"
+ initial_flooring = /decl/flooring/tiling/eris/steel/techfloor
+
+/turf/simulated/floor/tiled/eris/steel/techfloor_grid
+ icon_state = "techfloor_grid"
+ initial_flooring = /decl/flooring/tiling/eris/steel/techfloor_grid
+
+/turf/simulated/floor/tiled/eris/steel/brown_perforated
+ icon_state = "brown_perforated"
+ initial_flooring = /decl/flooring/tiling/eris/steel/brown_perforated
+
+/turf/simulated/floor/tiled/eris/steel/gray_perforated
+ icon_state = "gray_perforated"
+ initial_flooring = /decl/flooring/tiling/eris/steel/gray_perforated
+
+/turf/simulated/floor/tiled/eris/steel/cargo
+ icon_state = "cargo"
+ initial_flooring = /decl/flooring/tiling/eris/steel/cargo
+
+/turf/simulated/floor/tiled/eris/steel/brown_platform
+ icon_state = "brown_platform"
+ initial_flooring = /decl/flooring/tiling/eris/steel/brown_platform
+
+/turf/simulated/floor/tiled/eris/steel/gray_platform
+ icon_state = "gray_platform"
+ initial_flooring = /decl/flooring/tiling/eris/steel/gray_platform
+
+/turf/simulated/floor/tiled/eris/steel/danger
+ icon_state = "danger"
+ initial_flooring = /decl/flooring/tiling/eris/steel/danger
+
+/turf/simulated/floor/tiled/eris/steel/golden
+ icon_state = "golden"
+ initial_flooring = /decl/flooring/tiling/eris/steel/golden
+
+/turf/simulated/floor/tiled/eris/steel/bluecorner
+ icon_state = "bluecorner"
+ initial_flooring = /decl/flooring/tiling/eris/steel/bluecorner
+
+/turf/simulated/floor/tiled/eris/steel/orangecorner
+ icon_state = "orangecorner"
+ initial_flooring = /decl/flooring/tiling/eris/steel/orangecorner
+
+/turf/simulated/floor/tiled/eris/steel/cyancorner
+ icon_state = "cyancorner"
+ initial_flooring = /decl/flooring/tiling/eris/steel/cyancorner
+
+/turf/simulated/floor/tiled/eris/steel/violetcorener
+ icon_state = "violetcorener"
+ initial_flooring = /decl/flooring/tiling/eris/steel/violetcorener
+
+/turf/simulated/floor/tiled/eris/steel/monofloor
+ icon_state = "monofloor"
+ initial_flooring = /decl/flooring/tiling/eris/steel/monofloor
+
+/turf/simulated/floor/tiled/eris/steel/bar_flat
+ icon_state = "bar_flat"
+ initial_flooring = /decl/flooring/tiling/eris/steel/bar_flat
+
+/turf/simulated/floor/tiled/eris/steel/bar_dance
+ icon_state = "bar_dance"
+ initial_flooring = /decl/flooring/tiling/eris/steel/bar_dance
+
+/turf/simulated/floor/tiled/eris/steel/bar_light
+ icon_state = "bar_light"
+ initial_flooring = /decl/flooring/tiling/eris/steel/bar_light
+
+/turf/simulated/floor/tiled/eris/steel/bar_light/Initialize()
+ . = ..()
+ set_light(3,4,"#00AAFF")
+
+
+
+//White Tiles
+/turf/simulated/floor/tiled/eris/white
+ name = "floor"
+ icon = 'icons/turf/flooring/eris/tiles_white.dmi'
+ icon_state = "tiles"
+ initial_flooring = /decl/flooring/tiling/eris/white
+
+/turf/simulated/floor/tiled/eris/white/panels
+ icon_state = "panels"
+ initial_flooring = /decl/flooring/tiling/eris/white/panels
+
+/turf/simulated/floor/tiled/eris/white/techfloor
+ icon_state = "techfloor"
+ initial_flooring = /decl/flooring/tiling/eris/white/techfloor
+
+/turf/simulated/floor/tiled/eris/white/techfloor_grid
+ icon_state = "techfloor_grid"
+ initial_flooring = /decl/flooring/tiling/eris/white/techfloor_grid
+
+/turf/simulated/floor/tiled/eris/white/brown_perforated
+ icon_state = "brown_perforated"
+ initial_flooring = /decl/flooring/tiling/eris/white/brown_perforated
+
+/turf/simulated/floor/tiled/eris/white/gray_perforated
+ icon_state = "gray_perforated"
+ initial_flooring = /decl/flooring/tiling/eris/white/gray_perforated
+
+/turf/simulated/floor/tiled/eris/white/cargo
+ icon_state = "cargo"
+ initial_flooring = /decl/flooring/tiling/eris/white/cargo
+
+/turf/simulated/floor/tiled/eris/white/brown_platform
+ icon_state = "brown_platform"
+ initial_flooring = /decl/flooring/tiling/eris/white/brown_platform
+
+/turf/simulated/floor/tiled/eris/white/gray_platform
+ icon_state = "gray_platform"
+ initial_flooring = /decl/flooring/tiling/eris/white/gray_platform
+
+/turf/simulated/floor/tiled/eris/white/danger
+ icon_state = "danger"
+ initial_flooring = /decl/flooring/tiling/eris/white/danger
+
+/turf/simulated/floor/tiled/eris/white/golden
+ icon_state = "golden"
+ initial_flooring = /decl/flooring/tiling/eris/white/golden
+
+/turf/simulated/floor/tiled/eris/white/bluecorner
+ icon_state = "bluecorner"
+ initial_flooring = /decl/flooring/tiling/eris/white/bluecorner
+
+/turf/simulated/floor/tiled/eris/white/orangecorner
+ icon_state = "orangecorner"
+ initial_flooring = /decl/flooring/tiling/eris/white/orangecorner
+
+/turf/simulated/floor/tiled/eris/white/cyancorner
+ icon_state = "cyancorner"
+ initial_flooring = /decl/flooring/tiling/eris/white/cyancorner
+
+/turf/simulated/floor/tiled/eris/white/violetcorener
+ icon_state = "violetcorener"
+ initial_flooring = /decl/flooring/tiling/eris/white/violetcorener
+
+/turf/simulated/floor/tiled/eris/white/monofloor
+ icon_state = "monofloor"
+ initial_flooring = /decl/flooring/tiling/eris/white/monofloor
+
+
+
+// Dark Tiles
+/turf/simulated/floor/tiled/eris/dark
+ name = "floor"
+ icon = 'icons/turf/flooring/eris/tiles_dark.dmi'
+ icon_state = "tiles"
+ initial_flooring = /decl/flooring/tiling/eris/dark
+
+/turf/simulated/floor/tiled/eris/dark/panels
+ icon_state = "panels"
+ initial_flooring = /decl/flooring/tiling/eris/dark/panels
+
+/turf/simulated/floor/tiled/eris/dark/techfloor
+ icon_state = "techfloor"
+ initial_flooring = /decl/flooring/tiling/eris/dark/techfloor
+
+/turf/simulated/floor/tiled/eris/dark/techfloor_grid
+ icon_state = "techfloor_grid"
+ initial_flooring = /decl/flooring/tiling/eris/dark/techfloor_grid
+
+/turf/simulated/floor/tiled/eris/dark/brown_perforated
+ icon_state = "brown_perforated"
+ initial_flooring = /decl/flooring/tiling/eris/dark/brown_perforated
+
+/turf/simulated/floor/tiled/eris/dark/gray_perforated
+ icon_state = "gray_perforated"
+ initial_flooring = /decl/flooring/tiling/eris/dark/gray_perforated
+
+/turf/simulated/floor/tiled/eris/dark/cargo
+ icon_state = "cargo"
+ initial_flooring = /decl/flooring/tiling/eris/dark/cargo
+
+/turf/simulated/floor/tiled/eris/dark/brown_platform
+ icon_state = "brown_platform"
+ initial_flooring = /decl/flooring/tiling/eris/dark/brown_platform
+
+/turf/simulated/floor/tiled/eris/dark/gray_platform
+ icon_state = "gray_platform"
+ initial_flooring = /decl/flooring/tiling/eris/dark/gray_platform
+
+/turf/simulated/floor/tiled/eris/dark/danger
+ icon_state = "danger"
+ initial_flooring = /decl/flooring/tiling/eris/dark/danger
+
+/turf/simulated/floor/tiled/eris/dark/golden
+ icon_state = "golden"
+ initial_flooring = /decl/flooring/tiling/eris/dark/golden
+
+/turf/simulated/floor/tiled/eris/dark/bluecorner
+ icon_state = "bluecorner"
+ initial_flooring = /decl/flooring/tiling/eris/dark/bluecorner
+
+/turf/simulated/floor/tiled/eris/dark/orangecorner
+ icon_state = "orangecorner"
+ initial_flooring = /decl/flooring/tiling/eris/dark/orangecorner
+
+/turf/simulated/floor/tiled/eris/dark/cyancorner
+ icon_state = "cyancorner"
+ initial_flooring = /decl/flooring/tiling/eris/dark/cyancorner
+
+/turf/simulated/floor/tiled/eris/dark/violetcorener
+ icon_state = "violetcorener"
+ initial_flooring = /decl/flooring/tiling/eris/dark/violetcorener
+
+/turf/simulated/floor/tiled/eris/dark/monofloor
+ icon_state = "monofloor"
+ initial_flooring = /decl/flooring/tiling/eris/dark/monofloor
+
+
+
+
+/turf/simulated/floor/tiled/eris/cafe
+ name = "floor"
+ icon = 'icons/turf/flooring/eris/tiles.dmi'
+ icon_state = "cafe"
+ initial_flooring = /decl/flooring/tiling/eris/cafe
+
+/turf/simulated/floor/tiled/eris/techmaint
+ name = "floor"
+ icon = 'icons/turf/flooring/eris/tiles_maint.dmi'
+ icon_state = "techmaint"
+ initial_flooring = /decl/flooring/tiling/eris/techmaint
+
+/turf/simulated/floor/tiled/eris/techmaint_perforated
+ name = "floor"
+ icon = 'icons/turf/flooring/eris/tiles_maint.dmi'
+ icon_state = "techmaint_perforated"
+ initial_flooring = /decl/flooring/tiling/eris/techmaint_perforated
+
+/turf/simulated/floor/tiled/eris/techmaint_panels
+ name = "floor"
+ icon = 'icons/turf/flooring/eris/tiles_maint.dmi'
+ icon_state = "techmaint_panels"
+ initial_flooring = /decl/flooring/tiling/eris/techmaint_panels
+
+/turf/simulated/floor/tiled/eris/techmaint_cargo
+ name = "floor"
+ icon = 'icons/turf/flooring/eris/tiles_maint.dmi'
+ icon_state = "techmaint_cargo"
+ initial_flooring = /decl/flooring/tiling/eris/techmaint_cargo
+
+//=========ERIS GRASS==========\\
+/decl/flooring/grass/heavy
+ name = "heavy grass"
+ desc = "A dense ground coating of grass"
+ flags = TURF_REMOVE_SHOVEL
+ icon = 'icons/turf/outdoors.dmi'
+ icon_base = "grass-heavy"
+ has_base_range = 3
+
+/turf/simulated/floor/outdoors/grass/heavy
+ name = "heavy grass"
+ icon_state = "grass-heavy0"
+ edge_blending_priority = 4
+ initial_flooring = /decl/flooring/grass/heavy
+ turf_layers = list(
+ /turf/simulated/floor/outdoors/rocks,
+ /turf/simulated/floor/outdoors/dirt
+ )
+ grass_chance = 40
+
+ grass_types = list(
+ /obj/structure/flora/ausbushes/sparsegrass,
+ /obj/structure/flora/ausbushes/fullgrass
+ )
+
+//=========R. PLATING==========\\
+/decl/flooring/reinforced/plating
+ name = "reinforced plating"
+ descriptor = "reinforced plating"
+ icon = 'icons/turf/flooring/eris/plating.dmi'
+ icon_base = "plating"
+ flags = TURF_REMOVE_WRENCH | TURF_HAS_CORNERS | TURF_HAS_EDGES | TURF_CAN_BURN | TURF_CAN_BREAK
+ can_paint = 1
+ has_base_range = 18
+ is_plating = TRUE
+ //build_type = /obj/item/stack/material/steel
+
+ plating_type = /decl/flooring/reinforced/plating/under
+ /*
+ footstep_sound = "plating"
+ space_smooth = FALSE
+ removal_time = 150
+ health = 100
+
+ floor_smooth = SMOOTH_BLACKLIST
+ flooring_blacklist = list(/decl/flooring/reinforced/plating/under,/decl/flooring/reinforced/plating/hull) //Smooth with everything except the contents of this list
+ smooth_movable_atom = SMOOTH_GREYLIST
+ movable_atom_blacklist = list(list(/obj, list("density" = TRUE, "anchored" = TRUE), 1))
+ movable_atom_whitelist = list(list(/obj/machinery/door/airlock, list(), 2))
+ */
+
+/obj/item/stack/tile/floor/rplating
+ name = "reinforced plating"
+ singular_name = "dark floor tile"
+ icon_state = "tile_dark"
+ matter = list(MAT_STEEL = 1)
+
+/turf/simulated/floor/plating/eris
+ name = "reinforced plating"
+ icon = 'icons/turf/flooring/eris/plating.dmi'
+ icon_state = "plating"
+ initial_flooring = /decl/flooring/reinforced/plating
+
+//==========UNDERPLATING==============\\
+/decl/flooring/reinforced/plating/under
+ name = "underplating"
+ icon = 'icons/turf/flooring/eris/plating.dmi'
+ descriptor = "support beams"
+ icon_base = "under"
+ flags = TURF_HAS_CORNERS | TURF_HAS_EDGES | TURF_CAN_BURN | TURF_CAN_BREAK
+ can_paint = 1
+ has_base_range = 0
+ is_plating = TRUE
+
+ floor_smooth = SMOOTH_WHITELIST
+ flooring_whitelist = list(
+ /decl/flooring/tiling/eris
+ )
+
+ plating_type = null
+
+ //build_type = /obj/item/stack/material/underplating
+
+ /* Eris features we lack on flooring decls
+ removal_time = 250
+ health = 200
+ resistance = RESISTANCE_ARMOURED
+ footstep_sound = "catwalk"
+ space_smooth = SMOOTH_ALL
+ floor_smooth = SMOOTH_NONE
+ smooth_movable_atom = SMOOTH_NONE
+ */
+
+/turf/simulated/floor/plating/eris/under
+ name = "underplating"
+ icon_state = "under"
+ icon = 'icons/turf/flooring/eris/plating.dmi'
+ initial_flooring = /decl/flooring/reinforced/plating/under
+
+//============HULL PLATING=========\\
+/decl/flooring/reinforced/plating/hull
+ name = "hull"
+ descriptor = "outer hull"
+ icon = 'icons/turf/flooring/eris/hull.dmi'
+ icon_base = "hullcenter"
+ flags = TURF_HAS_EDGES | TURF_HAS_CORNERS | TURF_REMOVE_WRENCH | TURF_CAN_BURN | TURF_CAN_BREAK
+ build_type = /obj/item/stack/material/plasteel
+ has_base_range = 35
+ is_plating = FALSE
+
+ /* Eris features we lack on flooring decls
+ try_update_icon = 0
+ plating_type = null
+ health = 350
+ resistance = RESISTANCE_HEAVILY_ARMOURED
+ removal_time = 1 MINUTES //Cutting through the hull is very slow work
+ footstep_sound = "hull"
+ wall_smooth = SMOOTH_ALL
+ space_smooth = SMOOTH_NONE
+ smooth_movable_atom = SMOOTH_NONE
+ */
+
+/* Eris features we lack on flooring decls
+//Hull can upgrade to underplating
+/decl/flooring/reinforced/plating/hull/can_build_floor(var/decl/flooring/newfloor)
+ return FALSE //Not allowed to build directly on hull, you must first remove it and then build on the underplating
+
+/decl/flooring/reinforced/plating/hull/get_plating_type(var/turf/location)
+ if (turf_is_lower_hull(location)) //Hull plating is only on the lowest level of the ship
+ return null
+ else if (turf_is_upper_hull(location))
+ return /decl/flooring/reinforced/plating/under
+ else
+ return null //This should never happen, hull plawell,ting should only be on the exterior
+*/
+/turf/simulated/floor/hull
+ name = "hull"
+ icon = 'icons/turf/flooring/eris/hull.dmi'
+ icon_state = "hullcenter0"
+ initial_flooring = /decl/flooring/reinforced/plating/hull
+/*
+/turf/simulated/floor/hull/New()
+ if(icon_state != "hullcenter0")
+ overrided_icon_state = icon_state
+ ..()
+*/
\ No newline at end of file
diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm
index 01ad912b70..237a28635c 100644
--- a/code/game/turfs/simulated/lava.dm
+++ b/code/game/turfs/simulated/lava.dm
@@ -13,6 +13,7 @@
movement_cost = 2
can_build_into_floor = TRUE
can_dirty = FALSE
+ initial_flooring = /decl/flooring/lava // Defining this in case someone DOES step on lava and survive. Somehow.
/turf/simulated/floor/lava/outdoors
outdoors = TRUE
@@ -32,11 +33,6 @@
..()
name = "magma"
-/turf/simulated/floor/lava/update_icon()
- cut_overlays()
- ..()
- update_icon_edge()
-
/turf/simulated/floor/lava/Entered(atom/movable/AM)
if(burn_stuff(AM))
START_PROCESSING(SSturfs, src)
diff --git a/code/game/turfs/simulated/outdoors/dirt.dm b/code/game/turfs/simulated/outdoors/dirt.dm
index 4d14205072..02677760fa 100644
--- a/code/game/turfs/simulated/outdoors/dirt.dm
+++ b/code/game/turfs/simulated/outdoors/dirt.dm
@@ -3,4 +3,5 @@
desc = "Quite dirty!"
icon_state = "dirt-dark"
edge_blending_priority = 2
- turf_layers = list(/turf/simulated/floor/outdoors/rocks)
\ No newline at end of file
+ turf_layers = list(/turf/simulated/floor/outdoors/rocks)
+ initial_flooring = /decl/flooring/asteroid
\ No newline at end of file
diff --git a/code/game/turfs/simulated/outdoors/grass.dm b/code/game/turfs/simulated/outdoors/grass.dm
index 6ee01d5087..3752c3825c 100644
--- a/code/game/turfs/simulated/outdoors/grass.dm
+++ b/code/game/turfs/simulated/outdoors/grass.dm
@@ -4,8 +4,9 @@ var/list/grass_types = list(
/turf/simulated/floor/outdoors/grass
name = "grass"
- icon_state = "grass"
+ icon_state = "grass0"
edge_blending_priority = 4
+ initial_flooring = /decl/flooring/grass
turf_layers = list(
/turf/simulated/floor/outdoors/rocks,
/turf/simulated/floor/outdoors/dirt
@@ -34,13 +35,14 @@ var/list/grass_types = list(
/turf/simulated/floor/outdoors/grass/sif
name = "growth"
- icon_state = "grass_sif"
+ icon_state = "grass_sif0"
+ initial_flooring = /decl/flooring/grass/sif
edge_blending_priority = 4
grass_chance = 5
var/tree_chance = 2
/*
animal_chance = 0.5
-
+
animal_types = list(
/mob/living/simple_mob/animal/sif/diyaab = 10,
/mob/living/simple_mob/animal/sif/glitterfly = 2,
@@ -63,10 +65,6 @@ var/list/grass_types = list(
. = ..()
/turf/simulated/floor/outdoors/grass/Initialize()
- if(prob(50))
- icon_state = "[initial(icon_state)]2"
- //edge_blending_priority++
-
if(grass_chance && prob(grass_chance) && !check_density())
var/grass_type = pickweight(grass_types)
new grass_type(src)
@@ -79,14 +77,14 @@ var/list/grass_types = list(
/turf/simulated/floor/outdoors/grass/forest
name = "thick grass"
- icon_state = "grass-dark"
+ icon_state = "grass-dark0"
grass_chance = 80
//tree_chance = 20
edge_blending_priority = 5
/turf/simulated/floor/outdoors/grass/sif/forest
name = "thick growth"
- icon_state = "grass_sif_dark"
+ icon_state = "grass_sif_dark0"
edge_blending_priority = 5
tree_chance = 10
grass_chance = 0
diff --git a/code/game/turfs/simulated/outdoors/outdoors.dm b/code/game/turfs/simulated/outdoors/outdoors.dm
index 42016e8081..cc5f256c5a 100644
--- a/code/game/turfs/simulated/outdoors/outdoors.dm
+++ b/code/game/turfs/simulated/outdoors/outdoors.dm
@@ -20,10 +20,6 @@ var/list/turf_edge_cache = list()
// When a turf gets demoted or promoted, this list gets adjusted. The top-most layer is the layer on the bottom of the list, due to how pop() works.
var/list/turf_layers = list(/turf/simulated/floor/outdoors/rocks)
-/turf/simulated/floor/outdoors/Initialize()
- update_icon()
- . = ..()
-
/turf/simulated/floor/Initialize(mapload)
if(outdoors)
SSplanets.addTurf(src)
@@ -50,37 +46,11 @@ var/list/turf_edge_cache = list()
else
make_indoors()
-/turf/simulated/proc/update_icon_edge()
- if(edge_blending_priority && !forbid_turf_edge())
- for(var/checkdir in cardinal)
- var/turf/simulated/T = get_step(src, checkdir)
- if(istype(T) && T.edge_blending_priority && edge_blending_priority < T.edge_blending_priority && icon_state != T.icon_state && !T.forbid_turf_edge())
- var/cache_key = "[T.get_edge_icon_state()]-[checkdir]"
- if(!turf_edge_cache[cache_key])
- var/image/I = image(icon = 'icons/turf/outdoors_edge.dmi', icon_state = "[T.get_edge_icon_state()]-edge", dir = checkdir, layer = ABOVE_TURF_LAYER)
- I.plane = TURF_PLANE
- turf_edge_cache[cache_key] = I
- add_overlay(turf_edge_cache[cache_key])
-
-/turf/simulated/proc/get_edge_icon_state()
- return icon_state
-
-// Tests if we shouldn't apply a turf edge.
-// Returns the blocker if one exists.
-/turf/simulated/proc/forbid_turf_edge()
- for(var/obj/structure/S in contents)
- if(S.block_turf_edges)
- return S
- return null
-
-/turf/simulated/floor/outdoors/update_icon()
- ..()
- update_icon_edge()
-
/turf/simulated/floor/outdoors/mud
name = "mud"
icon_state = "mud_dark"
edge_blending_priority = 3
+ initial_flooring = /decl/flooring/mud
/turf/simulated/floor/outdoors/rocks
name = "rocks"
diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm
index 3a5d8e46a8..9a5c0c4b48 100644
--- a/code/game/turfs/simulated/water.dm
+++ b/code/game/turfs/simulated/water.dm
@@ -20,6 +20,8 @@
/turf/simulated/floor/water/Initialize()
. = ..()
+ var/decl/flooring/F = get_flooring_data(/decl/flooring/water)
+ footstep_sounds = F?.footstep_sounds
update_icon()
handle_fish()
@@ -30,8 +32,6 @@
var/image/water_sprite = image(icon = 'icons/turf/outdoors.dmi', icon_state = water_state, layer = WATER_LAYER)
add_overlay(water_sprite)
- update_icon_edge()
-
/turf/simulated/floor/water/get_edge_icon_state()
return "water_shallow"
@@ -45,7 +45,7 @@
else if(istype(O, /obj/item/weapon/mop))
O.reagents.add_reagent(reagent_type, 5)
to_chat(user, "You wet \the [O] in \the [src].")
- playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
+ playsound(src, 'sound/effects/slosh.ogg', 25, 1)
return 1
else return ..()
@@ -146,6 +146,18 @@
var/list/shoreline_icon_cache = list()
+/turf/simulated/floor/water/beach
+ name = "beach shoreline"
+ desc = "The waves look calm and inviting."
+ icon_state = "beach"
+ depth = 0
+
+/turf/simulated/floor/water/beach/update_icon()
+ return
+
+/turf/simulated/floor/water/beach/corner
+ icon_state = "beachcorner"
+
/turf/simulated/floor/water/shoreline
name = "shoreline"
desc = "The waves look calm and inviting."
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 29bad72682..8b6e71aeda 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -136,15 +136,10 @@
return
/turf/space/Entered(var/atom/movable/A)
- ..()
-
- if (!A || src != A.loc)
- return
-
- inertial_drift(A)
+ . = ..()
if(edge && ticker?.mode)
- A.touch_map_edge()
+ A?.touch_map_edge()
/turf/space/proc/Sandbox_Spacemove(atom/movable/A as mob|obj)
var/cur_x
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 78c764f789..e93380d791 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -142,42 +142,6 @@ turf/attackby(obj/item/weapon/W as obj, mob/user as mob)
sleep(2)
O.update_transform()
-var/const/enterloopsanity = 100
-/turf/Entered(atom/atom as mob|obj)
-
- if(movement_disabled)
- to_chat(usr, "Movement is admin-disabled.") //This is to identify lag problems
- return
- ..()
-
- if(!istype(atom, /atom/movable))
- return
-
- var/atom/movable/A = atom
-
- if(ismob(A))
- var/mob/M = A
- if(!M.lastarea)
- M.lastarea = get_area(M.loc)
- if(M.lastarea.has_gravity == 0)
- inertial_drift(M)
- else if(!is_space())
- M.inertia_dir = 0
- M.make_floating(0)
- if(isliving(M))
- var/mob/living/L = M
- L.handle_footstep(src)
- ..()
- var/objects = 0
- if(A && (A.flags & PROXMOVE))
- for(var/atom/movable/thing in range(1))
- if(objects++ > enterloopsanity) break
- spawn(0)
- if(A) //Runtime prevention
- A.HasProximity(thing, 1)
- if ((thing && A) && (thing.flags & PROXMOVE))
- thing.HasProximity(A, 1)
-
/turf/CanPass(atom/movable/mover, turf/target)
if(!target)
return FALSE
@@ -246,22 +210,6 @@ var/const/enterloopsanity = 100
/turf/proc/is_plating()
return 0
-/turf/proc/inertial_drift(atom/movable/A as mob|obj)
- if(!(A.last_move)) return
- if((istype(A, /mob/) && src.x > 1 && src.x < (world.maxx) && src.y > 1 && src.y < (world.maxy)))
- var/mob/M = A
- if(M.Process_Spacemove(1))
- M.inertia_dir = 0
- return
- spawn(5)
- if((M && !(M.anchored) && !(M.pulledby) && (M.loc == src)))
- if(M.inertia_dir)
- step(M, M.inertia_dir)
- return
- M.inertia_dir = M.last_move
- step(M, M.inertia_dir)
- return
-
/turf/proc/levelupdate()
for(var/obj/O in src)
O.hide(O.hides_under_flooring() && !is_plating())
diff --git a/code/game/turfs/unsimulated/beach.dm b/code/game/turfs/unsimulated/beach.dm
index 52c2618a79..c5338b3db9 100644
--- a/code/game/turfs/unsimulated/beach.dm
+++ b/code/game/turfs/unsimulated/beach.dm
@@ -15,6 +15,7 @@
name = "Water"
icon_state = "water"
initialized = FALSE
+ movement_cost = 4 // Water should slow you down, just like simulated turf.
/turf/unsimulated/beach/water/Initialize()
. = ..()
@@ -23,13 +24,22 @@
/turf/simulated/floor/beach
name = "Beach"
icon = 'icons/misc/beach.dmi'
+ initial_flooring = /decl/flooring/sand
/turf/simulated/floor/beach/sand
name = "Sand"
icon_state = "sand"
+ initial_flooring = /decl/flooring/sand
/turf/simulated/floor/beach/sand/desert
+ icon = 'icons/turf/desert.dmi'
icon_state = "desert"
+ initial_flooring = /decl/flooring/sand/desert
+
+/turf/simulated/floor/beach/sand/desert/Initialize()
+ . = ..()
+ if(prob(5))
+ icon_state = "desert[rand(0,4)]"
/turf/simulated/floor/beach/coastline
name = "Coastline"
@@ -39,10 +49,24 @@
/turf/simulated/floor/beach/water
name = "Water"
icon_state = "water"
+ movement_cost = 4 // Water should slow you down, just like the original simulated turf.
+ initial_flooring = /decl/flooring/water
/turf/simulated/floor/beach/water/ocean
icon_state = "seadeep"
+ movement_cost = 8 // Deep water should be difficult to wade through.
+ initial_flooring = /decl/flooring/water/beach/deep
/turf/simulated/floor/beach/water/Initialize()
. = ..()
add_overlay(image("icon"='icons/misc/beach.dmi',"icon_state"="water5","layer"=MOB_LAYER+0.1))
+
+/decl/flooring/water/beach/deep // We're custom-defining a 'deep' water turf for the beach.
+ name = "deep water"
+ desc = "Deep Ocean Water"
+ icon = 'icons/misc/beach.dmi'
+ icon_base = "seadeep"
+ footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/bubbles3.ogg', // No I don't get why it's named 3/4/5 either. Whatever.
+ 'sound/effects/footstep/bubbles4.ogg',
+ 'sound/effects/footstep/bubbles5.ogg'))
diff --git a/code/game/verbs/advanced_who.dm b/code/game/verbs/advanced_who.dm
index 9f067054f2..4498136b2b 100644
--- a/code/game/verbs/advanced_who.dm
+++ b/code/game/verbs/advanced_who.dm
@@ -7,24 +7,36 @@
var/list/Lines = list()
- if(holder && (R_ADMIN & holder.rights || R_MOD & holder.rights))
+ if(holder)
for(var/client/C in GLOB.clients)
- var/entry = "\t[C.key]"
+ var/entry = "| [C.key]"
if(C.holder && C.holder.fakekey)
entry += " (as [C.holder.fakekey])"
- entry += " - Playing as [C.mob.real_name]"
- switch(C.mob.stat)
- if(UNCONSCIOUS)
- entry += " - Unconscious"
- if(DEAD)
- if(isobserver(C.mob))
- var/mob/observer/dead/O = C.mob
- if(O.started_as_observer)
- entry += " - Observing"
- else
- entry += " - DEAD"
+
+ entry += " | "
+
+ if(C.mob.real_name)
+ switch(C.mob.stat)
+ if(UNCONSCIOUS)
+ entry += "Unconscious" // these are literally all spans so I can apply .inverted to them because black on dark grey isn't legible
+
+ if(DEAD)
+ if(isobserver(C.mob))
+ var/mob/observer/dead/O = C.mob
+ if(O.started_as_observer)
+ entry += "Observing"
+ else
+ entry += "Died"
+
else
- entry += " - DEAD"
+ entry += "Playing"
+
+ entry += " as [C.mob.real_name]"
+
+ else if(isnewplayer(C.mob))
+ entry += "In lobby"
+
+ entry += " | "
var/age
if(isnum(C.player_age))
@@ -33,14 +45,20 @@
age = 0
if(age <= 1)
- age = "[age]"
+ age = "[age]"
else if(age < 10)
- age = "[age]"
+ age = "[age]"
- entry += " - [age]"
+ entry += "Age: [age]"
+ entry += " | "
if(is_special_character(C.mob))
- entry += " - Antagonist"
+ if(C.mob?.mind?.special_role)
+ entry += "[C.mob.mind.special_role]"
+ else
+ entry += "Antagonist"
+
+ entry += " | "
if(C.is_afk())
var/seconds = C.last_activity_seconds()
@@ -48,7 +66,9 @@
entry += "[round(seconds / 60)] minutes, "
entry += "[seconds % 60] seconds)"
+ entry += " | "
entry += " (?)"
+ entry += " |
"
Lines += entry
else
@@ -60,16 +80,17 @@
entry += "[C.key]"
var/mob/observer/dead/O = C.mob
if(isobserver(O))
- entry += " - Observing"
+ entry += " - Observing
"
else if(istype(O,/mob/new_player))
- entry += " - In Lobby"
+ entry += " - In Lobby
"
else
- entry += " - Playing"
+ entry += " - Playing
"
Lines += entry
+ msg += ""
for(var/line in sortList(Lines))
- msg += "[line]\n"
-
+ msg += "[line]"
+ msg += "
"
msg += "Total Players: [length(Lines)]"
- msg = "" + msg + ""
+ msg = "" + msg + ""
to_chat(src, msg)
\ No newline at end of file
diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm
index 5df51c1dd0..d7b649505d 100644
--- a/code/game/verbs/ooc.dm
+++ b/code/game/verbs/ooc.dm
@@ -29,11 +29,21 @@
if(prefs.muted & MUTE_OOC)
to_chat(src, "You cannot use OOC (muted).")
return
- if(findtext(msg, "byond://"))
+ if(findtext(msg, "byond://") && !config.allow_byond_links)
to_chat(src, "Advertising other servers is not allowed.")
log_admin("[key_name(src)] has attempted to advertise in OOC: [msg]")
message_admins("[key_name_admin(src)] has attempted to advertise in OOC: [msg]")
return
+ if(findtext(msg, "discord.gg") && !config.allow_discord_links)
+ to_chat(src, "Advertising discords is not allowed.")
+ log_admin("[key_name(src)] has attempted to advertise a discord server in OOC: [msg]")
+ message_admins("[key_name_admin(src)] has attempted to advertise a discord server in OOC: [msg]")
+ return
+ if((findtext(msg, "http://") || findtext(msg, "https://")) && !config.allow_url_links)
+ to_chat(src, "Posting external links is not allowed.")
+ log_admin("[key_name(src)] has attempted to post a link in OOC: [msg]")
+ message_admins("[key_name_admin(src)] has attempted to post a link in OOC: [msg]")
+ return
log_ooc(msg, src)
@@ -43,14 +53,15 @@
var/ooc_style = "everyone"
if(holder && !holder.fakekey)
ooc_style = "elevated"
- if(holder.rights & R_EVENT)
- ooc_style = "event_manager"
- if(holder.rights & R_MOD)
- ooc_style = "moderator"
- if(holder.rights & R_DEBUG)
- ooc_style = "developer"
if(holder.rights & R_ADMIN)
ooc_style = "admin"
+ else if(holder.rights & R_EVENT)
+ ooc_style = "event_manager"
+ else if(holder.rights & R_DEBUG)
+ ooc_style = "developer"
+ else if(holder.rights & R_MOD)
+ ooc_style = "moderator"
+
for(var/client/target in GLOB.clients)
if(target.is_preference_enabled(/datum/client_preference/show_ooc))
@@ -102,11 +113,21 @@
if(prefs.muted & MUTE_OOC)
to_chat(src, "You cannot use OOC (muted).")
return
- if(findtext(msg, "byond://"))
+ if(findtext(msg, "byond://") && !config.allow_byond_links)
to_chat(src, "Advertising other servers is not allowed.")
log_admin("[key_name(src)] has attempted to advertise in OOC: [msg]")
message_admins("[key_name_admin(src)] has attempted to advertise in OOC: [msg]")
return
+ if(findtext(msg, "discord.gg") && !config.allow_discord_links)
+ to_chat(src, "Advertising discords is not allowed.")
+ log_admin("[key_name(src)] has attempted to advertise a discord server in OOC: [msg]")
+ message_admins("[key_name_admin(src)] has attempted to advertise a discord server in OOC: [msg]")
+ return
+ if((findtext(msg, "http://") || findtext(msg, "https://")) && !config.allow_url_links)
+ to_chat(src, "Posting external links is not allowed.")
+ log_admin("[key_name(src)] has attempted to post a link in OOC: [msg]")
+ message_admins("[key_name_admin(src)] has attempted to post a link in OOC: [msg]")
+ return
log_looc(msg,src)
diff --git a/code/game/world.dm b/code/game/world.dm
index 6715efe9b9..e7d0a8bd31 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -16,7 +16,7 @@
if(config && config.log_runtime)
log = file("data/logs/runtime/[time2text(world.realtime,"YYYY-MM-DD-(hh-mm-ss)")]-runtime.log")
- GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
+ GLOB.timezoneOffset = get_timezone_offset()
callHook("startup")
init_vchat()
diff --git a/code/modules/admin/admin_attack_log.dm b/code/modules/admin/admin_attack_log.dm
index c1f5c67464..4c5b1b481e 100644
--- a/code/modules/admin/admin_attack_log.dm
+++ b/code/modules/admin/admin_attack_log.dm
@@ -1,4 +1,4 @@
-/mob/var/lastattacker = null
+/atom/var/lastattacker = null
/mob/var/lastattacked = null
/mob/var/attack_log = list( )
/mob/var/dialogue_log = list( )
diff --git a/code/modules/admin/admin_tools.dm b/code/modules/admin/admin_tools.dm
index 376aa2da44..8b4e1ae44c 100644
--- a/code/modules/admin/admin_tools.dm
+++ b/code/modules/admin/admin_tools.dm
@@ -9,18 +9,18 @@
if(M.mind)
dat += "Current Antag?: [(M.mind.special_role)?"Yes":"No"]
"
dat += "
Note: This is arranged from earliest to latest.
"
-
+
if(!isemptylist(M.attack_log))
- dat += "