mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 18:53:06 +00:00
Merge branch 'master' into upstream-merge-5985
This commit is contained in:
@@ -70,12 +70,12 @@
|
||||
hidden = 1
|
||||
|
||||
/datum/category_item/autolathe/arms/tommymag
|
||||
name = "Tommygun magazine (.45)"
|
||||
name = "Tommy Gun magazine (.45)"
|
||||
path =/obj/item/ammo_magazine/m45tommy
|
||||
hidden = 1
|
||||
|
||||
/datum/category_item/autolathe/arms/tommydrum
|
||||
name = "Tommygun drum magazine (.45)"
|
||||
name = "Tommy Gun drum magazine (.45)"
|
||||
path =/obj/item/ammo_magazine/m45tommydrum
|
||||
hidden = 1
|
||||
|
||||
@@ -234,13 +234,13 @@
|
||||
hidden = 1
|
||||
|
||||
/datum/category_item/autolathe/arms/tommymag
|
||||
name = "Tommygun magazine (.45)"
|
||||
name = "Tommy Gun magazine (.45)"
|
||||
path =/obj/item/ammo_magazine/m45tommy/empty
|
||||
category = "Arms and Ammunition"
|
||||
hidden = 1
|
||||
|
||||
/datum/category_item/autolathe/arms/tommydrum
|
||||
name = "Tommygun drum magazine (.45)"
|
||||
name = "Tommy Gun drum magazine (.45)"
|
||||
path =/obj/item/ammo_magazine/m45tommydrum/empty
|
||||
category = "Arms and Ammunition"
|
||||
hidden = 1
|
||||
|
||||
3
code/datums/autolathe/general_vr.dm
Normal file
3
code/datums/autolathe/general_vr.dm
Normal file
@@ -0,0 +1,3 @@
|
||||
/datum/category_item/autolathe/general/holocollar
|
||||
name = "Holo-collar"
|
||||
path =/obj/item/clothing/accessory/collar/holo
|
||||
@@ -59,7 +59,7 @@
|
||||
return ..()
|
||||
|
||||
/datum/beam/proc/Draw()
|
||||
if(QDELETED(target) || !QDELETED(origin))
|
||||
if(QDELETED(target) || QDELETED(origin))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
@@ -144,12 +144,12 @@
|
||||
// 'Reactive' beam parts do something when touched or stood in.
|
||||
/obj/effect/ebeam/reactive
|
||||
|
||||
/obj/effect/ebeam/reactive/initialize()
|
||||
processing_objects += src
|
||||
/obj/effect/ebeam/reactive/Initialize()
|
||||
START_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/ebeam/reactive/Destroy()
|
||||
processing_objects -= src
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/ebeam/reactive/on_drawn()
|
||||
|
||||
@@ -105,6 +105,10 @@
|
||||
"}
|
||||
|
||||
/datum/browser/proc/open(var/use_onclose = 1)
|
||||
if(isnull(window_id)) //null check because this can potentially nuke goonchat
|
||||
WARNING("Browser [title] tried to open with a null ID")
|
||||
to_chat(user, "<span class='userdanger'>The [title] browser you tried to open failed a sanity check! Please report this on github!</span>")
|
||||
return
|
||||
var/window_size = ""
|
||||
if (width && height)
|
||||
window_size = "size=[width]x[height];"
|
||||
@@ -112,9 +116,6 @@
|
||||
if (use_onclose)
|
||||
onclose(user, window_id, ref)
|
||||
|
||||
/datum/browser/proc/close()
|
||||
user << browse(null, "window=[window_id]")
|
||||
|
||||
// This will allow you to show an icon in the browse window
|
||||
// This is added to mob so that it can be used without a reference to the browser object
|
||||
// There is probably a better place for this...
|
||||
@@ -157,12 +158,12 @@
|
||||
|
||||
//world << "OnClose [user]: [windowid] : ["on-close=\".windowclose [param]\""]"
|
||||
|
||||
|
||||
// the on-close client verb
|
||||
// called when a browser popup window is closed after registering with proc/onclose()
|
||||
// if a valid atom reference is supplied, call the atom's Topic() with "close=1"
|
||||
// otherwise, just reset the client mob's machine var.
|
||||
//
|
||||
|
||||
/client/verb/windowclose(var/atomref as text)
|
||||
set hidden = 1 // hide this verb from the user's panel
|
||||
set name = ".windowclose" // no autocomplete on cmd line
|
||||
@@ -182,3 +183,198 @@
|
||||
//world << "[src] was [src.mob.machine], setting to null"
|
||||
src.mob.unset_machine()
|
||||
return
|
||||
|
||||
/datum/browser/proc/close()
|
||||
if(!isnull(window_id))//null check because this can potentially nuke goonchat
|
||||
user << browse(null, "window=[window_id]")
|
||||
else
|
||||
WARNING("Browser [title] tried to close with a null ID")
|
||||
|
||||
/datum/browser/modal/alert/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1,Timeout=6000)
|
||||
if (!User)
|
||||
return
|
||||
|
||||
var/output = {"<center><b>[Message]</b></center><br />
|
||||
<div style="text-align:center">
|
||||
<a style="font-size:large;float:[( Button2 ? "left" : "right" )]" href="?src=\ref[src];button=1">[Button1]</a>"}
|
||||
|
||||
if (Button2)
|
||||
output += {"<a style="font-size:large;[( Button3 ? "" : "float:right" )]" href="?src=\ref[src];button=2">[Button2]</a>"}
|
||||
|
||||
if (Button3)
|
||||
output += {"<a style="font-size:large;float:right" href="?src=\ref[src];button=3">[Button3]</a>"}
|
||||
|
||||
output += {"</div>"}
|
||||
|
||||
..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, 350, 150, src, StealFocus, Timeout)
|
||||
set_content(output)
|
||||
|
||||
/datum/browser/modal/alert/Topic(href,href_list)
|
||||
if (href_list["close"] || !user || !user.client)
|
||||
opentime = 0
|
||||
return
|
||||
if (href_list["button"])
|
||||
var/button = text2num(href_list["button"])
|
||||
if (button <= 3 && button >= 1)
|
||||
selectedbutton = button
|
||||
opentime = 0
|
||||
close()
|
||||
|
||||
//designed as a drop in replacement for alert(); functions the same. (outside of needing User specified)
|
||||
/proc/tgalert(var/mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000)
|
||||
if (!User)
|
||||
User = usr
|
||||
switch(askuser(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout))
|
||||
if (1)
|
||||
return Button1
|
||||
if (2)
|
||||
return Button2
|
||||
if (3)
|
||||
return Button3
|
||||
|
||||
//Same shit, but it returns the button number, could at some point support unlimited button amounts.
|
||||
/proc/askuser(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000)
|
||||
if (!istype(User))
|
||||
if (istype(User, /client/))
|
||||
var/client/C = User
|
||||
User = C.mob
|
||||
else
|
||||
return
|
||||
var/datum/browser/modal/alert/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout)
|
||||
A.open()
|
||||
A.wait()
|
||||
if (A.selectedbutton)
|
||||
return A.selectedbutton
|
||||
|
||||
/datum/browser/modal
|
||||
var/opentime = 0
|
||||
var/timeout
|
||||
var/selectedbutton = 0
|
||||
var/stealfocus
|
||||
|
||||
/datum/browser/modal/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, StealFocus = 1, Timeout = 6000)
|
||||
..()
|
||||
stealfocus = StealFocus
|
||||
if (!StealFocus)
|
||||
window_options += "focus=false;"
|
||||
timeout = Timeout
|
||||
|
||||
|
||||
/datum/browser/modal/close()
|
||||
.=..()
|
||||
opentime = 0
|
||||
|
||||
/datum/browser/modal/open()
|
||||
set waitfor = 0
|
||||
opentime = world.time
|
||||
|
||||
if (stealfocus)
|
||||
. = ..(use_onclose = 1)
|
||||
else
|
||||
var/focusedwindow = winget(user, null, "focus")
|
||||
. = ..(use_onclose = 1)
|
||||
|
||||
//waits for the window to show up client side before attempting to un-focus it
|
||||
//winexists sleeps until it gets a reply from the client, so we don't need to bother sleeping
|
||||
for (var/i in 1 to 10)
|
||||
if (user && winexists(user, window_id))
|
||||
if (focusedwindow)
|
||||
winset(user, focusedwindow, "focus=true")
|
||||
else
|
||||
winset(user, "mapwindow", "focus=true")
|
||||
break
|
||||
if (timeout)
|
||||
addtimer(CALLBACK(src, .proc/close), timeout)
|
||||
|
||||
/datum/browser/modal/proc/wait()
|
||||
while (opentime && selectedbutton <= 0 && (!timeout || opentime+timeout > world.time))
|
||||
stoplag(1)
|
||||
|
||||
/datum/browser/modal/listpicker
|
||||
var/valueslist = list()
|
||||
|
||||
/datum/browser/modal/listpicker/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1, Timeout = FALSE,list/values,inputtype="checkbox", width, height, slidecolor)
|
||||
if (!User)
|
||||
return
|
||||
|
||||
var/output = {"<form><input type="hidden" name="src" value="\ref[src]"><ul class="sparse">"}
|
||||
if (inputtype == "checkbox" || inputtype == "radio")
|
||||
for (var/i in values)
|
||||
var/div_slider = slidecolor
|
||||
if(!i["allowed_edit"])
|
||||
div_slider = "locked"
|
||||
output += {"<li>
|
||||
<label class="switch">
|
||||
<input type="[inputtype]" value="1" name="[i["name"]]"[i["checked"] ? " checked" : ""][i["allowed_edit"] ? "" : " onclick='return false' onkeydown='return false'"]>
|
||||
<div class="slider [div_slider ? "[div_slider]" : ""]"></div>
|
||||
<span>[i["name"]]</span>
|
||||
</label>
|
||||
</li>"}
|
||||
else
|
||||
for (var/i in values)
|
||||
output += {"<li><input id="name="[i["name"]]"" style="width: 50px" type="[type]" name="[i["name"]]" value="[i["value"]]">
|
||||
<label for="[i["name"]]">[i["name"]]</label></li>"}
|
||||
output += {"</ul><div style="text-align:center">
|
||||
<button type="submit" name="button" value="1" style="font-size:large;float:[( Button2 ? "left" : "right" )]">[Button1]</button>"}
|
||||
|
||||
if (Button2)
|
||||
output += {"<button type="submit" name="button" value="2" style="font-size:large;[( Button3 ? "" : "float:right" )]">[Button2]</button>"}
|
||||
|
||||
if (Button3)
|
||||
output += {"<button type="submit" name="button" value="3" style="font-size:large;float:right">[Button3]</button>"}
|
||||
|
||||
output += {"</form></div>"}
|
||||
..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, width, height, src, StealFocus, Timeout)
|
||||
set_content(output)
|
||||
|
||||
/datum/browser/modal/listpicker/Topic(href,href_list)
|
||||
if (href_list["close"] || !user || !user.client)
|
||||
opentime = 0
|
||||
return
|
||||
if (href_list["button"])
|
||||
var/button = text2num(href_list["button"])
|
||||
if (button <= 3 && button >= 1)
|
||||
selectedbutton = button
|
||||
for (var/item in href_list)
|
||||
switch(item)
|
||||
if ("close", "button", "src")
|
||||
continue
|
||||
else
|
||||
valueslist[item] = href_list[item]
|
||||
opentime = 0
|
||||
close()
|
||||
|
||||
/proc/presentpicker(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/values, inputtype = "checkbox", width, height, slidecolor)
|
||||
if (!istype(User))
|
||||
if (istype(User, /client/))
|
||||
var/client/C = User
|
||||
User = C.mob
|
||||
else
|
||||
return
|
||||
var/datum/browser/modal/listpicker/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus,Timeout, values, inputtype, width, height, slidecolor)
|
||||
A.open()
|
||||
A.wait()
|
||||
if (A.selectedbutton)
|
||||
return list("button" = A.selectedbutton, "values" = A.valueslist)
|
||||
|
||||
/proc/input_bitfield(var/mob/User, title, bitfield, current_value, nwidth = 350, nheight = 350, nslidecolor, allowed_edit_list = null)
|
||||
if (!User || !(bitfield in GLOB.bitfields))
|
||||
return
|
||||
var/list/pickerlist = list()
|
||||
for (var/i in GLOB.bitfields[bitfield])
|
||||
var/can_edit = 1
|
||||
if(!isnull(allowed_edit_list) && !(allowed_edit_list & GLOB.bitfields[bitfield][i]))
|
||||
can_edit = 0
|
||||
if (current_value & GLOB.bitfields[bitfield][i])
|
||||
pickerlist += list(list("checked" = 1, "value" = GLOB.bitfields[bitfield][i], "name" = i, "allowed_edit" = can_edit))
|
||||
else
|
||||
pickerlist += list(list("checked" = 0, "value" = GLOB.bitfields[bitfield][i], "name" = i, "allowed_edit" = can_edit))
|
||||
var/list/result = presentpicker(User, "", title, Button1="Save", Button2 = "Cancel", Timeout=FALSE, values = pickerlist, width = nwidth, height = nheight, slidecolor = nslidecolor)
|
||||
if (islist(result))
|
||||
if (result["button"] == 2) // If the user pressed the cancel button
|
||||
return
|
||||
. = 0
|
||||
for (var/flag in result["values"])
|
||||
. |= GLOB.bitfields[bitfield][flag]
|
||||
else
|
||||
return
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
// Use sparingly
|
||||
/world/proc/PushUsr(mob/M, datum/callback/CB)
|
||||
var/temp = usr
|
||||
testing("PushUsr() in use")
|
||||
// testing("PushUsr() in use")
|
||||
usr = M
|
||||
. = CB.Invoke()
|
||||
usr = temp
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
|
||||
/datum
|
||||
var/gc_destroyed //Time when this object was destroyed.
|
||||
var/list/active_timers //for SStimer
|
||||
var/weakref/weakref // Holder of weakref instance pointing to this datum
|
||||
var/is_processing = FALSE // If this datum is in an MC processing list, this will be set to its name.
|
||||
var/datum_flags = NONE
|
||||
|
||||
#ifdef TESTING
|
||||
var/tmp/running_find_references
|
||||
@@ -17,7 +18,18 @@
|
||||
// This should be overridden to remove all references pointing to the object being destroyed.
|
||||
// Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE.
|
||||
/datum/proc/Destroy(force=FALSE)
|
||||
|
||||
//clear timers
|
||||
var/list/timers = active_timers
|
||||
active_timers = null
|
||||
for(var/thing in timers)
|
||||
var/datum/timedevent/timer = thing
|
||||
if (timer.spent)
|
||||
continue
|
||||
qdel(timer)
|
||||
|
||||
weakref = null // Clear this reference to ensure it's kept for as brief duration as possible.
|
||||
|
||||
tag = null
|
||||
GLOB.nanomanager.close_uis(src)
|
||||
SSnanoui.close_uis(src)
|
||||
return QDEL_HINT_QUEUE
|
||||
|
||||
68
code/datums/datumvars.dm
Normal file
68
code/datums/datumvars.dm
Normal file
@@ -0,0 +1,68 @@
|
||||
/datum/proc/CanProcCall(procname)
|
||||
return TRUE
|
||||
|
||||
/datum/proc/can_vv_get(var_name)
|
||||
return TRUE
|
||||
|
||||
/datum/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited
|
||||
if(var_name == NAMEOF(src, vars) || var_name == NAMEOF(src, parent_type))
|
||||
return FALSE
|
||||
vars[var_name] = var_value
|
||||
datum_flags |= DF_VAR_EDITED
|
||||
return TRUE
|
||||
|
||||
/datum/proc/vv_get_var(var_name)
|
||||
switch(var_name)
|
||||
if ("vars")
|
||||
return debug_variable(var_name, list(), 0, src)
|
||||
return debug_variable(var_name, vars[var_name], 0, src)
|
||||
|
||||
//please call . = ..() first and append to the result, that way parent items are always at the top and child items are further down
|
||||
//add separaters by doing . += "---"
|
||||
/datum/proc/vv_get_dropdown()
|
||||
. = list()
|
||||
VV_DROPDOWN_OPTION("", "---")
|
||||
VV_DROPDOWN_OPTION(VV_HK_CALLPROC, "Call Proc")
|
||||
VV_DROPDOWN_OPTION(VV_HK_MARK, "Mark Object")
|
||||
VV_DROPDOWN_OPTION(VV_HK_DELETE, "Delete")
|
||||
VV_DROPDOWN_OPTION(VV_HK_EXPOSE, "Show VV To Player")
|
||||
|
||||
//This proc is only called if everything topic-wise is verified. The only verifications that should happen here is things like permission checks!
|
||||
//href_list is a reference, modifying it in these procs WILL change the rest of the proc in topic.dm of admin/view_variables!
|
||||
/datum/proc/vv_do_topic(list/href_list)
|
||||
if(!usr || !usr.client.holder)
|
||||
return //This is VV, not to be called by anything else.
|
||||
IF_VV_OPTION(VV_HK_EXPOSE)
|
||||
if(!check_rights(R_ADMIN, FALSE))
|
||||
return
|
||||
var/value = usr.client.vv_get_value(VV_CLIENT)
|
||||
if (value["class"] != VV_CLIENT)
|
||||
return
|
||||
var/client/C = value["value"]
|
||||
if (!C)
|
||||
return
|
||||
var/prompt = alert("Do you want to grant [C] access to view this VV window? (they will not be able to edit or change anysrc nor open nested vv windows unless they themselves are an admin)", "Confirm", "Yes", "No")
|
||||
if (prompt != "Yes" || !usr.client)
|
||||
return
|
||||
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='?_src_=vars;datumrefresh=\ref[src]'>VV window</a>")
|
||||
log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [src]")
|
||||
to_chat(C, "[usr.client.holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window")
|
||||
C.debug_variables(src)
|
||||
IF_VV_OPTION(VV_HK_DELETE)
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
usr.client.admin_delete(src)
|
||||
if (isturf(src)) // show the turf that took its place
|
||||
usr.client.debug_variables(src)
|
||||
IF_VV_OPTION(VV_HK_MARK)
|
||||
usr.client.mark_datum(src)
|
||||
IF_VV_OPTION(VV_HK_CALLPROC)
|
||||
usr.client.callproc_datum(src)
|
||||
|
||||
/datum/proc/vv_get_header()
|
||||
. = list()
|
||||
if(("name" in vars) && !isatom(src))
|
||||
. += "<b>[vars["name"]]</b><br>"
|
||||
|
||||
/datum/proc/on_reagent_change(changetype)
|
||||
return
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
DO NOT USE THIS. THIS IS BEING DEPRECATED BY PROCESSING SUBSYSTEMS (controllers/subsystems/processing) AND TIMERS.
|
||||
*/
|
||||
|
||||
/*
|
||||
README:
|
||||
|
||||
@@ -109,9 +113,6 @@ Data storage vars:
|
||||
CRASH("The global_iterator loop \ref[src] failed to terminate in designated timeframe. This may be caused by server lagging.")
|
||||
return 1
|
||||
|
||||
proc/process()
|
||||
return
|
||||
|
||||
proc/active()
|
||||
return control_switch
|
||||
|
||||
|
||||
111
code/datums/looping_sounds/_looping_sound.dm
Normal file
111
code/datums/looping_sounds/_looping_sound.dm
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
output_atoms (list of atoms) The destination(s) for the sounds
|
||||
|
||||
mid_sounds (list or soundfile) Since this can be either a list or a single soundfile you can have random sounds. May contain further lists but must contain a soundfile at the end.
|
||||
mid_length (num) The length to wait between playing mid_sounds
|
||||
|
||||
start_sound (soundfile) Played before starting the mid_sounds loop
|
||||
start_length (num) How long to wait before starting the main loop after playing start_sound
|
||||
|
||||
end_sound (soundfile) The sound played after the main loop has concluded
|
||||
|
||||
chance (num) Chance per loop to play a mid_sound
|
||||
volume (num) Sound output volume
|
||||
muted (bool) Private. Used to stop the sound loop.
|
||||
max_loops (num) The max amount of loops to run for.
|
||||
direct (bool) If true plays directly to provided atoms instead of from them
|
||||
opacity_check (bool) If true, things behind walls/opaque things won't hear the sounds.
|
||||
pref_check (type) If set to a /datum/client_preference type, will check if the hearer has that preference active before playing it to them.
|
||||
*/
|
||||
/datum/looping_sound
|
||||
var/list/atom/output_atoms
|
||||
var/mid_sounds
|
||||
var/mid_length
|
||||
var/start_sound
|
||||
var/start_length
|
||||
var/end_sound
|
||||
var/chance
|
||||
var/volume = 100
|
||||
var/max_loops
|
||||
var/direct
|
||||
var/opacity_check
|
||||
var/pref_check
|
||||
|
||||
var/timerid
|
||||
|
||||
/datum/looping_sound/New(list/_output_atoms=list(), start_immediately=FALSE, _direct=FALSE)
|
||||
if(!mid_sounds)
|
||||
WARNING("A looping sound datum was created without sounds to play.")
|
||||
return
|
||||
|
||||
output_atoms = _output_atoms
|
||||
direct = _direct
|
||||
|
||||
if(start_immediately)
|
||||
start()
|
||||
|
||||
/datum/looping_sound/Destroy()
|
||||
stop()
|
||||
output_atoms = null
|
||||
return ..()
|
||||
|
||||
/datum/looping_sound/proc/start(atom/add_thing)
|
||||
if(add_thing)
|
||||
output_atoms |= add_thing
|
||||
if(timerid)
|
||||
return
|
||||
on_start()
|
||||
|
||||
/datum/looping_sound/proc/stop(atom/remove_thing)
|
||||
if(remove_thing)
|
||||
output_atoms -= remove_thing
|
||||
if(!timerid)
|
||||
return
|
||||
on_stop()
|
||||
deltimer(timerid)
|
||||
timerid = null
|
||||
|
||||
/datum/looping_sound/proc/sound_loop(starttime)
|
||||
if(max_loops && world.time >= starttime + mid_length * max_loops)
|
||||
stop()
|
||||
return
|
||||
if(!chance || prob(chance))
|
||||
play(get_sound(starttime))
|
||||
if(!timerid)
|
||||
timerid = addtimer(CALLBACK(src, .proc/sound_loop, world.time), mid_length, TIMER_STOPPABLE | TIMER_LOOP)
|
||||
|
||||
/datum/looping_sound/proc/play(soundfile)
|
||||
var/list/atoms_cache = output_atoms
|
||||
var/sound/S = sound(soundfile)
|
||||
if(direct)
|
||||
S.channel = open_sound_channel()
|
||||
S.volume = volume
|
||||
for(var/i in 1 to atoms_cache.len)
|
||||
var/atom/thing = atoms_cache[i]
|
||||
if(direct)
|
||||
if(ismob(thing))
|
||||
var/mob/M = thing
|
||||
if(!M.is_preference_enabled(pref_check))
|
||||
continue
|
||||
SEND_SOUND(thing, S)
|
||||
else
|
||||
playsound(thing, S, volume, ignore_walls = !opacity_check, preference = pref_check)
|
||||
|
||||
/datum/looping_sound/proc/get_sound(starttime, _mid_sounds)
|
||||
if(!_mid_sounds)
|
||||
. = mid_sounds
|
||||
else
|
||||
. = _mid_sounds
|
||||
while(!isfile(.) && !isnull(.))
|
||||
. = pickweight(.)
|
||||
|
||||
/datum/looping_sound/proc/on_start()
|
||||
var/start_wait = 1 // On TG this is 0, however it needs to be 1 to work around an issue.
|
||||
if(start_sound)
|
||||
play(start_sound)
|
||||
start_wait = start_length
|
||||
addtimer(CALLBACK(src, .proc/sound_loop), start_wait)
|
||||
|
||||
/datum/looping_sound/proc/on_stop()
|
||||
if(end_sound)
|
||||
play(end_sound)
|
||||
29
code/datums/looping_sounds/item_sounds.dm
Normal file
29
code/datums/looping_sounds/item_sounds.dm
Normal file
@@ -0,0 +1,29 @@
|
||||
/datum/looping_sound/geiger
|
||||
mid_sounds = list(
|
||||
list('sound/items/geiger/low1.ogg'=1, 'sound/items/geiger/low2.ogg'=1, 'sound/items/geiger/low3.ogg'=1, 'sound/items/geiger/low4.ogg'=1),
|
||||
list('sound/items/geiger/med1.ogg'=1, 'sound/items/geiger/med2.ogg'=1, 'sound/items/geiger/med3.ogg'=1, 'sound/items/geiger/med4.ogg'=1),
|
||||
list('sound/items/geiger/high1.ogg'=1, 'sound/items/geiger/high2.ogg'=1, 'sound/items/geiger/high3.ogg'=1, 'sound/items/geiger/high4.ogg'=1),
|
||||
list('sound/items/geiger/ext1.ogg'=1, 'sound/items/geiger/ext2.ogg'=1, 'sound/items/geiger/ext3.ogg'=1, 'sound/items/geiger/ext4.ogg'=1)
|
||||
)
|
||||
mid_length = 1 SECOND
|
||||
volume = 25
|
||||
var/last_radiation
|
||||
|
||||
/datum/looping_sound/geiger/get_sound(starttime)
|
||||
var/danger
|
||||
switch(last_radiation)
|
||||
if(0 to RAD_LEVEL_MODERATE)
|
||||
danger = 1
|
||||
if(RAD_LEVEL_MODERATE to RAD_LEVEL_HIGH)
|
||||
danger = 2
|
||||
if(RAD_LEVEL_HIGH to RAD_LEVEL_VERY_HIGH)
|
||||
danger = 3
|
||||
if(RAD_LEVEL_VERY_HIGH to INFINITY)
|
||||
danger = 4
|
||||
else
|
||||
return null
|
||||
return ..(starttime, mid_sounds[danger])
|
||||
|
||||
/datum/looping_sound/geiger/stop()
|
||||
. = ..()
|
||||
last_radiation = 0
|
||||
46
code/datums/looping_sounds/machinery_sounds.dm
Normal file
46
code/datums/looping_sounds/machinery_sounds.dm
Normal file
@@ -0,0 +1,46 @@
|
||||
/datum/looping_sound/showering
|
||||
start_sound = 'sound/machines/shower/shower_start.ogg'
|
||||
start_length = 2
|
||||
mid_sounds = list('sound/machines/shower/shower_mid1.ogg'=1,'sound/machines/shower/shower_mid2.ogg'=1,'sound/machines/shower/shower_mid3.ogg'=1)
|
||||
mid_length = 10
|
||||
end_sound = 'sound/machines/shower/shower_end.ogg'
|
||||
volume = 20
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/datum/looping_sound/supermatter
|
||||
mid_sounds = list('sound/machines/sm/supermatter1.ogg'=1,'sound/machines/sm/supermatter2.ogg'=1,'sound/machines/sm/supermatter3.ogg'=1)
|
||||
mid_length = 10
|
||||
volume = 1
|
||||
pref_check = /datum/client_preference/supermatter_hum
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/datum/looping_sound/generator
|
||||
start_sound = 'sound/machines/generator/generator_start.ogg'
|
||||
start_length = 4
|
||||
mid_sounds = list('sound/machines/generator/generator_mid1.ogg'=1, 'sound/machines/generator/generator_mid2.ogg'=1, 'sound/machines/generator/generator_mid3.ogg'=1)
|
||||
mid_length = 4
|
||||
end_sound = 'sound/machines/generator/generator_end.ogg'
|
||||
volume = 40
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/datum/looping_sound/deep_fryer
|
||||
start_sound = 'sound/machines/fryer/deep_fryer_immerse.ogg' //my immersions
|
||||
start_length = 10
|
||||
mid_sounds = list('sound/machines/fryer/deep_fryer_1.ogg' = 1, 'sound/machines/fryer/deep_fryer_2.ogg' = 1)
|
||||
mid_length = 2
|
||||
end_sound = 'sound/machines/fryer/deep_fryer_emerge.ogg'
|
||||
volume = 15
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/datum/looping_sound/microwave
|
||||
start_sound = 'sound/machines/microwave/microwave-start.ogg'
|
||||
start_length = 10
|
||||
mid_sounds = list('sound/machines/microwave/microwave-mid1.ogg'=10, 'sound/machines/microwave/microwave-mid2.ogg'=1)
|
||||
mid_length = 10
|
||||
end_sound = 'sound/machines/microwave/microwave-end.ogg'
|
||||
volume = 90
|
||||
79
code/datums/looping_sounds/weather_sounds.dm
Normal file
79
code/datums/looping_sounds/weather_sounds.dm
Normal file
@@ -0,0 +1,79 @@
|
||||
/datum/looping_sound/weather
|
||||
pref_check = /datum/client_preference/weather_sounds
|
||||
|
||||
/datum/looping_sound/weather/outside_blizzard
|
||||
mid_sounds = list(
|
||||
'sound/effects/weather/snowstorm/outside/active_mid1.ogg' = 1,
|
||||
'sound/effects/weather/snowstorm/outside/active_mid1.ogg' = 1,
|
||||
'sound/effects/weather/snowstorm/outside/active_mid1.ogg' = 1
|
||||
)
|
||||
mid_length = 8 SECONDS
|
||||
start_sound = 'sound/effects/weather/snowstorm/outside/active_start.ogg'
|
||||
start_length = 13 SECONDS
|
||||
end_sound = 'sound/effects/weather/snowstorm/outside/active_end.ogg'
|
||||
volume = 80
|
||||
|
||||
/datum/looping_sound/weather/inside_blizzard
|
||||
mid_sounds = list(
|
||||
'sound/effects/weather/snowstorm/inside/active_mid1.ogg' = 1,
|
||||
'sound/effects/weather/snowstorm/inside/active_mid2.ogg' = 1,
|
||||
'sound/effects/weather/snowstorm/inside/active_mid3.ogg' = 1
|
||||
)
|
||||
mid_length = 8 SECONDS
|
||||
start_sound = 'sound/effects/weather/snowstorm/inside/active_start.ogg'
|
||||
start_length = 13 SECONDS
|
||||
end_sound = 'sound/effects/weather/snowstorm/inside/active_end.ogg'
|
||||
volume = 60
|
||||
|
||||
/datum/looping_sound/weather/outside_snow
|
||||
mid_sounds = list(
|
||||
'sound/effects/weather/snowstorm/outside/weak_mid1.ogg' = 1,
|
||||
'sound/effects/weather/snowstorm/outside/weak_mid2.ogg' = 1,
|
||||
'sound/effects/weather/snowstorm/outside/weak_mid3.ogg' = 1
|
||||
)
|
||||
mid_length = 8 SECONDS
|
||||
start_sound = 'sound/effects/weather/snowstorm/outside/weak_start.ogg'
|
||||
start_length = 13 SECONDS
|
||||
end_sound = 'sound/effects/weather/snowstorm/outside/weak_end.ogg'
|
||||
volume = 50
|
||||
|
||||
/datum/looping_sound/weather/inside_snow
|
||||
mid_sounds = list(
|
||||
'sound/effects/weather/snowstorm/inside/weak_mid1.ogg' = 1,
|
||||
'sound/effects/weather/snowstorm/inside/weak_mid2.ogg' = 1,
|
||||
'sound/effects/weather/snowstorm/inside/weak_mid3.ogg' = 1
|
||||
)
|
||||
mid_length = 8 SECONDS
|
||||
start_sound = 'sound/effects/weather/snowstorm/inside/weak_start.ogg'
|
||||
start_length = 13 SECONDS
|
||||
end_sound = 'sound/effects/weather/snowstorm/inside/weak_end.ogg'
|
||||
volume = 30
|
||||
|
||||
/datum/looping_sound/weather/wind
|
||||
mid_sounds = list(
|
||||
'sound/effects/weather/wind/wind_2_1.ogg' = 1,
|
||||
'sound/effects/weather/wind/wind_2_2.ogg' = 1,
|
||||
'sound/effects/weather/wind/wind_3_1.ogg' = 1,
|
||||
'sound/effects/weather/wind/wind_4_1.ogg' = 1,
|
||||
'sound/effects/weather/wind/wind_4_2.ogg' = 1,
|
||||
'sound/effects/weather/wind/wind_5_1.ogg' = 1
|
||||
)
|
||||
mid_length = 10 SECONDS // The lengths for the files vary, but the longest is ten seconds, so this will make it sound like intermittent wind.
|
||||
volume = 50
|
||||
|
||||
// Don't have special sounds so we just make it quieter indoors.
|
||||
/datum/looping_sound/weather/wind/indoors
|
||||
volume = 30
|
||||
|
||||
/datum/looping_sound/weather/rain
|
||||
mid_sounds = list(
|
||||
'sound/effects/weather/acidrain_mid.ogg' = 1
|
||||
)
|
||||
mid_length = 15 SECONDS // The lengths for the files vary, but the longest is ten seconds, so this will make it sound like intermittent wind.
|
||||
start_sound = 'sound/effects/weather/acidrain_start.ogg'
|
||||
start_length = 13 SECONDS
|
||||
end_sound = 'sound/effects/weather/acidrain_end.ogg'
|
||||
volume = 50
|
||||
|
||||
/datum/looping_sound/weather/rain/indoors
|
||||
volume = 30
|
||||
@@ -85,7 +85,7 @@
|
||||
current.verbs -= /datum/changeling/proc/EvolutionMenu
|
||||
current.mind = null
|
||||
|
||||
GLOB.nanomanager.user_transferred(current, new_character) // transfer active NanoUI instances to new user
|
||||
SSnanoui.user_transferred(current, new_character) // transfer active NanoUI instances to new user
|
||||
if(new_character.mind) //remove any mind currently in our new body's mind variable
|
||||
new_character.mind.current = null
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
//
|
||||
// Observer Pattern Implementation: Scheduled task triggered
|
||||
// Registration type: /datum/scheduled_task
|
||||
//
|
||||
// Raised when: When a scheduled task reaches its trigger time.
|
||||
//
|
||||
// Arguments that the called proc should expect:
|
||||
// /datum/scheduled_task/task: The task that reached its trigger time.
|
||||
var/decl/observ/task_triggered/task_triggered_event = new()
|
||||
|
||||
/decl/observ/task_triggered
|
||||
name = "Task Triggered"
|
||||
expected_type = /datum/scheduled_task
|
||||
16
code/datums/observation/z_moved.dm
Normal file
16
code/datums/observation/z_moved.dm
Normal file
@@ -0,0 +1,16 @@
|
||||
// Observer Pattern Implementation: Z_Moved
|
||||
// Registration type: /atom/movable
|
||||
//
|
||||
// Raised when: An /atom/movable instance has changed z-levels by any means.
|
||||
//
|
||||
// Arguments that the called proc should expect:
|
||||
// /atom/movable/moving_instance: The instance that moved
|
||||
// old_z: The z number before the move.
|
||||
// new_z: The z number after the move.
|
||||
|
||||
|
||||
GLOBAL_DATUM_INIT(z_moved_event, /decl/observ/z_moved, new)
|
||||
|
||||
/decl/observ/z_moved
|
||||
name = "Z_Moved"
|
||||
expected_type = /atom/movable
|
||||
@@ -52,4 +52,9 @@
|
||||
name = "Merchant - Vox"
|
||||
shoes = /obj/item/clothing/shoes/boots/jackboots/toeless
|
||||
uniform = /obj/item/clothing/under/vox/vox_robes
|
||||
suit = /obj/item/clothing/suit/armor/vox_scrap
|
||||
suit = /obj/item/clothing/suit/armor/vox_scrap
|
||||
|
||||
/decl/hierarchy/outfit/zaddat
|
||||
name = "Zaddat Suit"
|
||||
suit = /obj/item/clothing/suit/space/void/zaddat/
|
||||
mask = /obj/item/clothing/mask/gas/zaddat
|
||||
227
code/datums/position_point_vector.dm
Normal file
227
code/datums/position_point_vector.dm
Normal file
@@ -0,0 +1,227 @@
|
||||
//Designed for things that need precision trajectories like projectiles.
|
||||
//Don't use this for anything that you don't absolutely have to use this with (like projectiles!) because it isn't worth using a datum unless you need accuracy down to decimal places in pixels.
|
||||
|
||||
//You might see places where it does - 16 - 1. This is intentionally 17 instead of 16, because of how byond's tiles work and how not doing it will result in rounding errors like things getting put on the wrong turf.
|
||||
|
||||
#define RETURN_PRECISE_POSITION(A) new /datum/position(A)
|
||||
#define RETURN_PRECISE_POINT(A) new /datum/point(A)
|
||||
|
||||
#define RETURN_POINT_VECTOR(ATOM, ANGLE, SPEED) {new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED)}
|
||||
#define RETURN_POINT_VECTOR_INCREMENT(ATOM, ANGLE, SPEED, AMT) {new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED, AMT)}
|
||||
|
||||
/datum/position //For positions with map x/y/z and pixel x/y so you don't have to return lists. Could use addition/subtraction in the future I guess.
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
var/z = 0
|
||||
var/pixel_x = 0
|
||||
var/pixel_y = 0
|
||||
|
||||
/datum/position/proc/valid()
|
||||
return x && y && z && !isnull(pixel_x) && !isnull(pixel_y)
|
||||
|
||||
/datum/position/New(_x = 0, _y = 0, _z = 0, _pixel_x = 0, _pixel_y = 0) //first argument can also be a /datum/point.
|
||||
if(istype(_x, /datum/point))
|
||||
var/datum/point/P = _x
|
||||
var/turf/T = P.return_turf()
|
||||
_x = T.x
|
||||
_y = T.y
|
||||
_z = T.z
|
||||
_pixel_x = P.return_px()
|
||||
_pixel_y = P.return_py()
|
||||
else if(istype(_x, /atom))
|
||||
var/atom/A = _x
|
||||
_x = A.x
|
||||
_y = A.y
|
||||
_z = A.z
|
||||
_pixel_x = A.pixel_x
|
||||
_pixel_y = A.pixel_y
|
||||
x = _x
|
||||
y = _y
|
||||
z = _z
|
||||
pixel_x = _pixel_x
|
||||
pixel_y = _pixel_y
|
||||
|
||||
/datum/position/proc/return_turf()
|
||||
return locate(x, y, z)
|
||||
|
||||
/datum/position/proc/return_px()
|
||||
return pixel_x
|
||||
|
||||
/datum/position/proc/return_py()
|
||||
return pixel_y
|
||||
|
||||
/datum/position/proc/return_point()
|
||||
return new /datum/point(src)
|
||||
|
||||
/proc/point_midpoint_points(datum/point/a, datum/point/b) //Obviously will not support multiZ calculations! Same for the two below.
|
||||
var/datum/point/P = new
|
||||
P.x = a.x + (b.x - a.x) / 2
|
||||
P.y = a.y + (b.y - a.y) / 2
|
||||
P.z = a.z
|
||||
return P
|
||||
|
||||
/proc/pixel_length_between_points(datum/point/a, datum/point/b)
|
||||
return sqrt(((b.x - a.x) ** 2) + ((b.y - a.y) ** 2))
|
||||
|
||||
/proc/angle_between_points(datum/point/a, datum/point/b)
|
||||
return ATAN2((b.y - a.y), (b.x - a.x))
|
||||
|
||||
/datum/point //A precise point on the map in absolute pixel locations based on world.icon_size. Pixels are FROM THE EDGE OF THE MAP!
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
var/z = 0
|
||||
|
||||
/datum/point/proc/valid()
|
||||
return x && y && z
|
||||
|
||||
/datum/point/proc/copy_to(datum/point/p = new)
|
||||
p.x = x
|
||||
p.y = y
|
||||
p.z = z
|
||||
return p
|
||||
|
||||
/datum/point/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0) //first argument can also be a /datum/position or /atom.
|
||||
if(istype(_x, /datum/position))
|
||||
var/datum/position/P = _x
|
||||
_x = P.x
|
||||
_y = P.y
|
||||
_z = P.z
|
||||
_pixel_x = P.pixel_x
|
||||
_pixel_y = P.pixel_y
|
||||
else if(istype(_x, /atom))
|
||||
var/atom/A = _x
|
||||
_x = A.x
|
||||
_y = A.y
|
||||
_z = A.z
|
||||
_pixel_x = A.pixel_x
|
||||
_pixel_y = A.pixel_y
|
||||
initialize_location(_x, _y, _z, _pixel_x, _pixel_y)
|
||||
|
||||
/datum/point/proc/initialize_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0)
|
||||
if(!isnull(tile_x))
|
||||
x = ((tile_x - 1) * world.icon_size) + world.icon_size / 2 + p_x + 1
|
||||
if(!isnull(tile_y))
|
||||
y = ((tile_y - 1) * world.icon_size) + world.icon_size / 2 + p_y + 1
|
||||
if(!isnull(tile_z))
|
||||
z = tile_z
|
||||
|
||||
/datum/point/proc/debug_out()
|
||||
var/turf/T = return_turf()
|
||||
return "\ref[src] aX [x] aY [y] aZ [z] pX [return_px()] pY [return_py()] mX [T.x] mY [T.y] mZ [T.z]"
|
||||
|
||||
/datum/point/proc/move_atom_to_src(atom/movable/AM)
|
||||
AM.forceMove(return_turf())
|
||||
AM.pixel_x = return_px()
|
||||
AM.pixel_y = return_py()
|
||||
|
||||
/datum/point/proc/return_turf()
|
||||
return locate(CEILING(x / world.icon_size, 1), CEILING(y / world.icon_size, 1), z)
|
||||
|
||||
/datum/point/proc/return_coordinates() //[turf_x, turf_y, z]
|
||||
return list(CEILING(x / world.icon_size, 1), CEILING(y / world.icon_size, 1), z)
|
||||
|
||||
/datum/point/proc/return_position()
|
||||
return new /datum/position(src)
|
||||
|
||||
/datum/point/proc/return_px()
|
||||
return MODULUS(x, world.icon_size) - 16 - 1
|
||||
|
||||
/datum/point/proc/return_py()
|
||||
return MODULUS(y, world.icon_size) - 16 - 1
|
||||
|
||||
|
||||
/datum/point/vector
|
||||
var/speed = 32 //pixels per iteration
|
||||
var/iteration = 0
|
||||
var/angle = 0
|
||||
var/mpx = 0 //calculated x/y movement amounts to prevent having to do trig every step.
|
||||
var/mpy = 0
|
||||
var/starting_x = 0 //just like before, pixels from EDGE of map! This is set in initialize_location().
|
||||
var/starting_y = 0
|
||||
var/starting_z = 0
|
||||
|
||||
/datum/point/vector/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0, _angle, _speed, initial_increment = 0)
|
||||
..()
|
||||
initialize_trajectory(_speed, _angle)
|
||||
if(initial_increment)
|
||||
increment(initial_increment)
|
||||
|
||||
/datum/point/vector/initialize_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0)
|
||||
. = ..()
|
||||
starting_x = x
|
||||
starting_y = y
|
||||
starting_z = z
|
||||
|
||||
/datum/point/vector/copy_to(datum/point/vector/v = new)
|
||||
..(v)
|
||||
v.speed = speed
|
||||
v.iteration = iteration
|
||||
v.angle = angle
|
||||
v.mpx = mpx
|
||||
v.mpy = mpy
|
||||
v.starting_x = starting_x
|
||||
v.starting_y = starting_y
|
||||
v.starting_z = starting_z
|
||||
return v
|
||||
|
||||
/datum/point/vector/proc/initialize_trajectory(pixel_speed, new_angle)
|
||||
if(!isnull(pixel_speed))
|
||||
speed = pixel_speed
|
||||
set_angle(new_angle)
|
||||
|
||||
/datum/point/vector/proc/set_angle(new_angle) //calculations use "byond angle" where north is 0 instead of 90, and south is 180 instead of 270.
|
||||
if(isnull(angle))
|
||||
return
|
||||
angle = new_angle
|
||||
update_offsets()
|
||||
|
||||
/datum/point/vector/proc/update_offsets()
|
||||
mpx = sin(angle) * speed
|
||||
mpy = cos(angle) * speed
|
||||
|
||||
/datum/point/vector/proc/set_speed(new_speed)
|
||||
if(isnull(new_speed) || speed == new_speed)
|
||||
return
|
||||
speed = new_speed
|
||||
update_offsets()
|
||||
|
||||
/datum/point/vector/proc/increment(multiplier = 1)
|
||||
iteration++
|
||||
x += mpx * multiplier
|
||||
y += mpy * multiplier
|
||||
|
||||
/datum/point/vector/proc/return_vector_after_increments(amount = 7, multiplier = 1, force_simulate = FALSE)
|
||||
var/datum/point/vector/v = copy_to()
|
||||
if(force_simulate)
|
||||
for(var/i in 1 to amount)
|
||||
v.increment(multiplier)
|
||||
else
|
||||
v.increment(multiplier * amount)
|
||||
return v
|
||||
|
||||
/datum/point/vector/proc/on_z_change()
|
||||
return
|
||||
|
||||
/datum/point/vector/processed //pixel_speed is per decisecond.
|
||||
var/last_process = 0
|
||||
var/last_move = 0
|
||||
var/paused = FALSE
|
||||
|
||||
/datum/point/vector/processed/Destroy()
|
||||
STOP_PROCESSING(SSprojectiles, src)
|
||||
return ..()
|
||||
|
||||
/datum/point/vector/processed/proc/start()
|
||||
last_process = world.time
|
||||
last_move = world.time
|
||||
START_PROCESSING(SSprojectiles, src)
|
||||
|
||||
/datum/point/vector/processed/process()
|
||||
if(paused)
|
||||
last_move += world.time - last_process
|
||||
last_process = world.time
|
||||
return
|
||||
var/needed_time = world.time - last_move
|
||||
last_process = world.time
|
||||
last_move = world.time
|
||||
increment(needed_time / SSprojectiles.wait)
|
||||
@@ -39,7 +39,7 @@
|
||||
shown = 0
|
||||
client = user.client
|
||||
|
||||
progress = Clamp(progress, 0, goal)
|
||||
progress = CLAMP(progress, 0, goal)
|
||||
bar.icon_state = "prog_bar_[round(((progress / goal) * 100), 5)]"
|
||||
if (!shown && user.is_preference_enabled(/datum/client_preference/show_progress_bar))
|
||||
user.client.images += bar
|
||||
|
||||
@@ -42,6 +42,13 @@
|
||||
containertype = /obj/structure/largecrate/animal/corgi
|
||||
containername = "Corgi Crate"
|
||||
|
||||
/datum/supply_pack/hydro/cat
|
||||
name = "Cat Crate"
|
||||
contains = list()
|
||||
cost = 45
|
||||
containertype = /obj/structure/largecrate/animal/cat
|
||||
containername = "Cat Crate"
|
||||
|
||||
/datum/supply_pack/hydro/hydroponics
|
||||
name = "Hydroponics Supply Crate"
|
||||
contains = list(
|
||||
|
||||
@@ -23,6 +23,64 @@
|
||||
containertype = /obj/structure/closet/crate
|
||||
containername = "cards crate"
|
||||
|
||||
/datum/supply_pack/randomised/misc/dnd
|
||||
num_contained = 4
|
||||
contains = list(
|
||||
/obj/item/toy/character/alien,
|
||||
/obj/item/toy/character/warrior,
|
||||
/obj/item/toy/character/cleric,
|
||||
/obj/item/toy/character/thief,
|
||||
/obj/item/toy/character/wizard,
|
||||
/obj/item/toy/character/voidone,
|
||||
/obj/item/toy/character/lich
|
||||
)
|
||||
name = "Miniatures Crate"
|
||||
cost = 200
|
||||
containertype = /obj/structure/closet/crate
|
||||
containername = "Miniature Crate"
|
||||
|
||||
/datum/supply_pack/randomised/misc/plushies
|
||||
num_contained = 5
|
||||
contains = list(
|
||||
/obj/item/toy/plushie/nymph,
|
||||
/obj/item/toy/plushie/mouse,
|
||||
/obj/item/toy/plushie/kitten,
|
||||
/obj/item/toy/plushie/lizard,
|
||||
/obj/item/toy/plushie/spider,
|
||||
/obj/item/toy/plushie/farwa,
|
||||
/obj/item/toy/plushie/corgi,
|
||||
/obj/item/toy/plushie/girly_corgi,
|
||||
/obj/item/toy/plushie/robo_corgi,
|
||||
/obj/item/toy/plushie/octopus,
|
||||
/obj/item/toy/plushie/face_hugger,
|
||||
/obj/item/toy/plushie/red_fox,
|
||||
/obj/item/toy/plushie/black_fox,
|
||||
/obj/item/toy/plushie/marble_fox,
|
||||
/obj/item/toy/plushie/blue_fox,
|
||||
/obj/item/toy/plushie/coffee_fox,
|
||||
/obj/item/toy/plushie/pink_fox,
|
||||
/obj/item/toy/plushie/purple_fox,
|
||||
/obj/item/toy/plushie/crimson_fox,
|
||||
/obj/item/toy/plushie/deer,
|
||||
/obj/item/toy/plushie/black_cat,
|
||||
/obj/item/toy/plushie/grey_cat,
|
||||
/obj/item/toy/plushie/white_cat,
|
||||
/obj/item/toy/plushie/orange_cat,
|
||||
/obj/item/toy/plushie/siamese_cat,
|
||||
/obj/item/toy/plushie/tabby_cat,
|
||||
/obj/item/toy/plushie/tuxedo_cat,
|
||||
/obj/item/toy/plushie/squid/green,
|
||||
/obj/item/toy/plushie/squid/mint,
|
||||
/obj/item/toy/plushie/squid/blue,
|
||||
/obj/item/toy/plushie/squid/orange,
|
||||
/obj/item/toy/plushie/squid/yellow,
|
||||
/obj/item/toy/plushie/squid/pink
|
||||
)
|
||||
name = "Plushies Crate"
|
||||
cost = 15
|
||||
containertype = /obj/structure/closet/crate
|
||||
containername = "Plushies Crate"
|
||||
|
||||
/datum/supply_pack/misc/eftpos
|
||||
contains = list(/obj/item/device/eftpos)
|
||||
name = "EFTPOS scanner"
|
||||
@@ -77,3 +135,12 @@
|
||||
cost = 15
|
||||
containertype = /obj/structure/closet/crate
|
||||
containername = "Holoplant crate"
|
||||
|
||||
/datum/supply_pack/misc/glucose_hypos
|
||||
name = "Glucose Hypoinjectors"
|
||||
contains = list(
|
||||
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose = 5
|
||||
)
|
||||
cost = 25
|
||||
containertype = "obj/structure/closet/crate"
|
||||
containername = "Glucose Hypo Crate"
|
||||
@@ -50,21 +50,17 @@
|
||||
containertype = /obj/structure/closet/crate
|
||||
containername = "Action figures crate"
|
||||
|
||||
/datum/supply_pack/recreation/characters_vr
|
||||
name = "Tabletop miniatures"
|
||||
/datum/supply_pack/recreation/collars
|
||||
name = "Collar bundle"
|
||||
contains = list(
|
||||
/obj/item/weapon/storage/box/characters
|
||||
/obj/item/clothing/accessory/collar/shock = 1,
|
||||
/obj/item/clothing/accessory/collar/spike = 1,
|
||||
/obj/item/clothing/accessory/collar/silver = 1,
|
||||
/obj/item/clothing/accessory/collar/gold = 1,
|
||||
/obj/item/clothing/accessory/collar/bell = 1,
|
||||
/obj/item/clothing/accessory/collar/pink = 1,
|
||||
/obj/item/clothing/accessory/collar/holo = 1
|
||||
)
|
||||
cost = 25
|
||||
containertype = /obj/structure/closet/crate
|
||||
containername = "Tabletop miniatures crate"
|
||||
cost = 50
|
||||
|
||||
/datum/supply_pack/randomised/recreation/plushies_vr
|
||||
name = "Plushies crate"
|
||||
num_contained = 3
|
||||
contains = list(
|
||||
/obj/random/plushie
|
||||
)
|
||||
cost = 60
|
||||
containertype = /obj/structure/closet/crate
|
||||
containername = "Plushies crate"
|
||||
containername = "collar crate"
|
||||
|
||||
@@ -212,4 +212,15 @@
|
||||
cost = 50
|
||||
containertype = "/obj/structure/closet/crate/secure"
|
||||
containername = "Frontier Mining voidsuit crate"
|
||||
access = access_mining
|
||||
access = access_mining
|
||||
|
||||
/datum/supply_pack/voidsuits/zaddat
|
||||
name = "Zaddat Shroud"
|
||||
contains = list(
|
||||
/obj/item/clothing/suit/space/void/zaddat = 1,
|
||||
/obj/item/clothing/mask/gas/zaddat = 1
|
||||
)
|
||||
cost = 30
|
||||
containertype = "/obj/structure/closet/crate"
|
||||
containername = "Zaddat Shroud crate"
|
||||
access = null
|
||||
@@ -40,20 +40,20 @@
|
||||
path = /obj/item/ammo_magazine/s45/ap
|
||||
|
||||
/datum/uplink_item/item/ammo/tommymag
|
||||
name = "Tommygun Magazine (.45)"
|
||||
name = "Tommy Gun Magazine (.45)"
|
||||
path = /obj/item/ammo_magazine/m45tommy
|
||||
|
||||
/datum/uplink_item/item/ammo/tommymagap
|
||||
name = "Tommygun Magazine (.45 AP)"
|
||||
name = "Tommy Gun Magazine (.45 AP)"
|
||||
path = /obj/item/ammo_magazine/m45tommy/ap
|
||||
|
||||
/datum/uplink_item/item/ammo/tommydrum
|
||||
name = "Tommygun Drum Magazine (.45)"
|
||||
name = "Tommy Gun Drum Magazine (.45)"
|
||||
path = /obj/item/ammo_magazine/m45tommydrum
|
||||
item_cost = 40
|
||||
|
||||
/datum/uplink_item/item/ammo/tommydrumap
|
||||
name = "Tommygun Drum Magazine (.45 AP)"
|
||||
name = "Tommy Gun Drum Magazine (.45 AP)"
|
||||
path = /obj/item/ammo_magazine/m45tommydrum/ap
|
||||
|
||||
/datum/uplink_item/item/ammo/darts
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
path = /obj/item/weapon/storage/secure/briefcase/fuelrod
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/tommygun
|
||||
name = "Tommygun (.45)" // We're keeping this because it's CLASSY. -Spades
|
||||
name = "Tommy Gun (.45)" // We're keeping this because it's CLASSY. -Spades
|
||||
item_cost = 60
|
||||
path = /obj/item/weapon/gun/projectile/automatic/tommygun
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ var/const/WIRE_TRANSMIT = 4
|
||||
|
||||
if(WIRE_TRANSMIT)
|
||||
R.broadcasting = !R.broadcasting && !IsIndexCut(WIRE_SIGNAL)
|
||||
GLOB.nanomanager.update_uis(holder)
|
||||
SSnanoui.update_uis(holder)
|
||||
|
||||
/datum/wires/radio/UpdateCut(var/index, var/mended)
|
||||
var/obj/item/device/radio/R = holder
|
||||
@@ -38,4 +38,4 @@ var/const/WIRE_TRANSMIT = 4
|
||||
|
||||
if(WIRE_TRANSMIT)
|
||||
R.broadcasting = mended && !IsIndexCut(WIRE_SIGNAL)
|
||||
GLOB.nanomanager.update_uis(holder)
|
||||
SSnanoui.update_uis(holder)
|
||||
|
||||
Reference in New Issue
Block a user