Merge branch 'master' of https://github.com/PolarisSS13/Polaris into teshhair2

This commit is contained in:
Greenjoe12345
2022-10-16 22:55:40 +01:00
33 changed files with 551 additions and 386 deletions
+1
View File
@@ -53,6 +53,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
// Subsystem init_order, from highest priority to lowest priority
// Subsystems shutdown in the reverse of the order they initialize in
// The numbers just define the ordering, they are meaningless otherwise.
#define INIT_ORDER_MISC_EARLY 60
#define INIT_ORDER_WEBHOOKS 50
#define INIT_ORDER_SQLITE 40
#define INIT_ORDER_INPUT 37
+41 -20
View File
@@ -253,29 +253,50 @@
/proc/key_name_admin(var/whom, var/include_name = 1)
return key_name(whom, 1, include_name)
// Helper procs for building detailed log lines
/datum/proc/log_info_line()
return "[src] ([type])"
/atom/log_info_line()
var/turf/t = get_turf(src)
if(istype(t))
return "([t]) ([t.x],[t.y],[t.z]) ([t.type])"
else if(loc)
return "([loc]) (0,0,0) ([loc.type])"
else
return "(NULL) (0,0,0) (NULL)"
/mob/log_info_line()
return "[..()] ([ckey])"
/proc/log_info_line(var/datum/d)
if(!istype(d))
return
return d.log_info_line()
/mob/proc/simple_info_line()
return "[key_name(src)] ([x],[y],[z])"
/client/proc/simple_info_line()
return "[key_name(src)] ([mob.x],[mob.y],[mob.z])"
/proc/log_info_line(datum/thing)
if (isnull(thing))
return "*null*"
if (islist(thing))
var/list/result = list()
var/list/thing_list = thing
for (var/key in thing_list)
var/value = isnum(key) ? null : thing[key]
result += "[log_info_line(key)][value ? " - [log_info_line(value)]" : ""]"
return "\[[jointext(result, ", ")]\]"
if (!istype(thing))
return json_encode(thing)
return thing.get_log_info_line()
/datum/proc/get_log_info_line()
return "[src] ([type])"
/weakref/get_log_info_line()
return "[ref_name] ([ref_type]) ([ref]) (WEAKREF)"
/area/get_log_info_line()
return "[..()] ([isnum(z) ? "[x],[y],[z]" : "0,0,0"])"
/turf/get_log_info_line()
return "[..()] ([x],[y],[z]) ([loc ? loc.type : "NULL"])"
/atom/movable/get_log_info_line()
var/turf/turf = get_turf(src)
return "[..()] ([turf ? turf : "NULL"]) ([turf ? "[turf.x],[turf.y],[turf.z]" : "0,0,0"]) ([turf ? turf.type : "NULL"])"
/mob/get_log_info_line()
return ckey ? "[..()] ([ckey])" : ..()
-5
View File
@@ -27,11 +27,6 @@ SUBSYSTEM_DEF(antags)
var/datum/antagonist/A = new antag_type
antag_datums[A.id] = A
/datum/controller/subsystem/antags/Shutdown()
for(var/thing in antag_datums)
qdel(thing)
. = ..()
/datum/controller/subsystem/antags/proc/get_antag_id_from_name(var/role_text)
for(var/datum/antagonist/A as anything in antag_datums)
+100 -140
View File
@@ -1,159 +1,119 @@
#define BAD_INIT_QDEL_BEFORE 1
#define BAD_INIT_DIDNT_INIT 2
#define BAD_INIT_SLEPT 4
#define BAD_INIT_NO_HINT 8
SUBSYSTEM_DEF(atoms)
name = "Atoms"
init_order = INIT_ORDER_ATOMS
flags = SS_NO_FIRE
// override and GetArguments() exists for mod-override/downstream hook functionality.
// Useful for total-overhaul type modifications.
var/adjust_init_arguments = FALSE
// Bad initialization types.
var/const/QDEL_BEFORE_INITIALIZE = 1
var/const/DID_NOT_SET_INITIALIZED = 2
var/const/SLEPT_IN_INITIALIZE = 4
var/const/DID_NOT_RETURN_HINT = 8
var/atom_init_stage = INITIALIZATION_INSSATOMS
var/old_init_stage
var/static/atom_init_stage = INITIALIZATION_INSSATOMS
var/static/old_init_stage
var/static/list/late_loaders = list()
var/static/list/created_atoms = list()
var/static/list/bad_init_calls = list()
var/list/late_loaders
var/list/BadInitializeCalls = list()
/datum/controller/subsystem/atoms/Initialize(timeofday)
if(!plant_controller) // Initialize seed repo for /obj/item/seed and /obj/item/grown
plant_controller = new
setupgenetics() //to set the mutations' place in structural enzymes, so initializers know where to put mutations.
/datum/controller/subsystem/atoms/Initialize(start_uptime)
atom_init_stage = INITIALIZATION_INNEW_MAPLOAD
InitializeAtoms()
/datum/controller/subsystem/atoms/proc/InitializeAtoms(var/list/supplied_atoms)
if(atom_init_stage <= INITIALIZATION_INSSATOMS_LATE)
return
atom_init_stage = INITIALIZATION_INNEW_MAPLOAD
LAZYINITLIST(late_loaders)
var/list/mapload_arg = list(TRUE)
var/count = LAZYLEN(supplied_atoms)
if(count)
while(supplied_atoms.len)
var/atom/A = supplied_atoms[supplied_atoms.len]
supplied_atoms.len--
if(!A.initialized)
InitAtom(A, GetArguments(A, mapload_arg))
CHECK_TICK
else if(!subsystem_initialized)
// If wondering why not just store all atoms in a list and use the block above: that turns out unbearably expensive.
// Instead, atoms without extra arguments in New created on server start are fished out of world directly.
// We do this exactly once.
for(var/atom/A in world)
if(!A.initialized)
InitAtom(A, GetArguments(A, mapload_arg, FALSE))
++count
CHECK_TICK
report_progress("Initialized [count] atom\s")
atom_init_stage = INITIALIZATION_INNEW_REGULAR
if(late_loaders.len)
for(var/I in late_loaders)
var/atom/A = I
A.LateInitialize(arglist(late_loaders[A]))
report_progress("Late initialized [late_loaders.len] atom\s")
late_loaders.Cut()
/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, list/arguments)
LAZYREMOVE(global.pre_init_created_atoms, A)
var/the_type = A.type
if(QDELING(A))
BadInitializeCalls[the_type] |= BAD_INIT_QDEL_BEFORE
return TRUE
var/start_tick = world.time
var/result = A.Initialize(arglist(arguments))
if(start_tick != world.time)
BadInitializeCalls[the_type] |= BAD_INIT_SLEPT
var/qdeleted = FALSE
if(result != INITIALIZE_HINT_NORMAL)
switch(result)
if(INITIALIZE_HINT_LATELOAD)
if(arguments[1]) //mapload
late_loaders[A] = arguments
else
A.LateInitialize(arglist(arguments))
if(INITIALIZE_HINT_QDEL)
qdel(A)
qdeleted = TRUE
else
BadInitializeCalls[the_type] |= BAD_INIT_NO_HINT
if(!A) //possible harddel
qdeleted = TRUE
else if(!A.initialized)
BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT
return qdeleted || QDELING(A)
// override and GetArguments() exists for mod-override/downstream hook functionality.
// Useful for total-overhaul type modifications.
/atom/proc/AdjustInitializeArguments(list/arguments)
// Lists are passed by reference so can simply modify the arguments list without returning it
/datum/controller/subsystem/atoms/proc/GetArguments(atom/A, list/mapload_arg, created=TRUE)
if(!created && !adjust_init_arguments)
return mapload_arg // Performance optimization. Nothing to do.
var/list/arguments = mapload_arg.Copy()
var/extra_args = LAZYACCESS(global.pre_init_created_atoms, A)
if(created && extra_args)
arguments += extra_args
if(adjust_init_arguments)
A.AdjustInitializeArguments(arguments)
return arguments
/datum/controller/subsystem/atoms/stat_entry(msg)
..("Bad Initialize Calls:[BadInitializeCalls.len]")
/datum/controller/subsystem/atoms/proc/map_loader_begin()
old_init_stage = atom_init_stage
atom_init_stage = INITIALIZATION_INSSATOMS_LATE
/datum/controller/subsystem/atoms/proc/map_loader_stop()
atom_init_stage = old_init_stage
/datum/controller/subsystem/atoms/Recover()
atom_init_stage = SSatoms.atom_init_stage
if(atom_init_stage == INITIALIZATION_INNEW_MAPLOAD)
created_atoms.Cut()
late_loaders.Cut()
if (atom_init_stage == INITIALIZATION_INNEW_MAPLOAD)
InitializeAtoms()
old_init_stage = SSatoms.old_init_stage
BadInitializeCalls = SSatoms.BadInitializeCalls
/datum/controller/subsystem/atoms/proc/InitLog()
. = ""
for(var/path in BadInitializeCalls)
. += "Path : [path] \n"
var/fails = BadInitializeCalls[path]
if(fails & BAD_INIT_DIDNT_INIT)
. += "- Didn't call atom/Initialize()\n"
if(fails & BAD_INIT_NO_HINT)
. += "- Didn't return an Initialize hint\n"
if(fails & BAD_INIT_QDEL_BEFORE)
. += "- Qdel'd in New()\n"
if(fails & BAD_INIT_SLEPT)
. += "- Slept during Initialize()\n"
/datum/controller/subsystem/atoms/Shutdown()
var/initlog = InitLog()
if(initlog)
text2file(initlog, "[log_path]-initialize.log")
if (!initlog)
return
text2file(initlog, "[log_path]/initialize.log")
#undef BAD_INIT_QDEL_BEFORE
#undef BAD_INIT_DIDNT_INIT
#undef BAD_INIT_SLEPT
#undef BAD_INIT_NO_HINT
/datum/controller/subsystem/atoms/proc/InitializeAtoms()
if (atom_init_stage <= INITIALIZATION_INSSATOMS_LATE)
return
atom_init_stage = INITIALIZATION_INNEW_MAPLOAD
var/list/mapload_arg = list(TRUE)
var/count = 0
var/atom/created
var/list/arguments
for (var/i = 1 to length(created_atoms))
created = created_atoms[i]
if (!created.initialized)
arguments = created_atoms[created] ? mapload_arg + created_atoms[created] : mapload_arg
InitAtom(created, arguments)
CHECK_TICK
created_atoms.Cut()
if (!subsystem_initialized)
for (var/atom/atom in world)
if (!atom.initialized)
InitAtom(atom, mapload_arg)
++count
CHECK_TICK
report_progress("Initialized [count] atom\s")
atom_init_stage = INITIALIZATION_INNEW_REGULAR
if (!length(late_loaders))
return
for (var/atom/atom as anything in late_loaders)
atom.LateInitialize(arglist(late_loaders[atom]))
report_progress("Late initialized [length(late_loaders)] atom\s")
late_loaders.Cut()
/datum/controller/subsystem/atoms/proc/InitAtom(atom/atom, list/arguments)
var/atom_type = atom?.type
if (QDELING(atom))
bad_init_calls[atom_type] |= QDEL_BEFORE_INITIALIZE
return TRUE
var/start_tick = world.time
var/result = atom.Initialize(arglist(arguments))
if (start_tick != world.time)
bad_init_calls[atom_type] |= SLEPT_IN_INITIALIZE
var/qdeleted = FALSE
if (result != INITIALIZE_HINT_NORMAL)
switch (result)
if (INITIALIZE_HINT_LATELOAD)
if (arguments[1]) //mapload
late_loaders[atom] = arguments
else
atom.LateInitialize(arglist(arguments))
if (INITIALIZE_HINT_QDEL)
qdel(atom)
qdeleted = TRUE
else
bad_init_calls[atom_type] |= DID_NOT_RETURN_HINT
if (!atom)
qdeleted = TRUE
else if (!atom.initialized)
bad_init_calls[atom_type] |= DID_NOT_SET_INITIALIZED
return qdeleted || QDELING(atom)
/datum/controller/subsystem/atoms/proc/BeginMapLoad()
old_init_stage = atom_init_stage
atom_init_stage = INITIALIZATION_INSSATOMS_LATE
/datum/controller/subsystem/atoms/proc/FinishMapLoad()
atom_init_stage = old_init_stage
/datum/controller/subsystem/atoms/proc/InitLog()
. = ""
for (var/path in bad_init_calls)
. += "Path : [path] \n"
var/fails = bad_init_calls[path]
if (fails & DID_NOT_SET_INITIALIZED)
. += "- Didn't call atom/Initialize()\n"
if (fails & DID_NOT_RETURN_HINT)
. += "- Didn't return an Initialize hint\n"
if (fails & QDEL_BEFORE_INITIALIZE)
. += "- Qdel'd in New()\n"
if (fails & SLEPT_IN_INITIALIZE)
. += "- Slept during Initialize()\n"
+41 -39
View File
@@ -273,71 +273,73 @@ SUBSYSTEM_DEF(garbage)
// Should be treated as a replacement for the 'del' keyword.
// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
/proc/qdel(datum/D, force=FALSE)
if(!istype(D))
del(D)
/proc/qdel(datum/thing, force)
if (!thing)
return
var/datum/qdel_item/I = SSgarbage.items[D.type]
if (!I)
I = SSgarbage.items[D.type] = new /datum/qdel_item(D.type)
I.qdels++
if(isnull(D.gc_destroyed))
if(SEND_SIGNAL(D, COMSIG_PARENT_PREQDELETED, force)) // Give the components a chance to prevent their parent from being deleted
if (!istype(thing))
crash_with("qdel() can only handle /datum (sub)types, was passed: [log_info_line(thing)]")
del(thing)
return
var/datum/qdel_item/qdel_item = SSgarbage.items[thing.type]
if (!qdel_item)
qdel_item = new (thing.type)
SSgarbage.items[thing.type] = qdel_item
qdel_item.qdels++
if (isnull(thing.gc_destroyed))
if (SEND_SIGNAL(thing, COMSIG_PARENT_PREQDELETED, force)) // Give the components a chance to prevent their parent from being deleted
return
D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
thing.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
var/start_time = world.time
var/start_tick = world.tick_usage
SEND_SIGNAL(D, COMSIG_PARENT_QDELETING, force) // Let the (remaining) components know about the result of Destroy
var/hint = D.Destroy(force) // Let our friend know they're about to get fucked up.
if(world.time != start_time)
I.slept_destroy++
SEND_SIGNAL(thing, COMSIG_PARENT_QDELETING, force) // Let the (remaining) components know about the result of Destroy
var/hint = thing.Destroy(force) // Let our friend know they're about to get fucked up.
if (world.time != start_time)
qdel_item.slept_destroy++
else
I.destroy_time += TICK_USAGE_TO_MS(start_tick)
if(!D)
qdel_item.destroy_time += TICK_USAGE_TO_MS(start_tick)
if (!thing)
return
switch(hint)
switch (hint)
if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion.
SSgarbage.PreQueue(D)
SSgarbage.PreQueue(thing)
if (QDEL_HINT_IWILLGC)
D.gc_destroyed = world.time
thing.gc_destroyed = world.time
return
if (QDEL_HINT_LETMELIVE) //qdel should let the object live after calling destory.
if(!force)
D.gc_destroyed = null //clear the gc variable (important!)
thing.gc_destroyed = null //clear the gc variable (important!)
return
// Returning LETMELIVE after being told to force destroy
// indicates the objects Destroy() does not respect force
#ifdef TESTING
if(!I.no_respect_force)
crash_with("[D.type] has been force deleted, but is \
#ifdef TESTING
if(!qdel_item.no_respect_force)
crash_with("[thing.type] has been force deleted, but is \
returning an immortal QDEL_HINT, indicating it does \
not respect the force flag for qdel(). It has been \
placed in the queue, further instances of this type \
will also be queued.")
#endif
I.no_respect_force++
SSgarbage.PreQueue(D)
#endif
qdel_item.no_respect_force++
SSgarbage.PreQueue(thing)
if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete using a hard reference to save time from the locate()
SSgarbage.HardQueue(D)
SSgarbage.HardQueue(thing)
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
SSgarbage.HardDelete(D)
SSgarbage.HardDelete(thing)
if (QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion.
SSgarbage.PreQueue(D)
SSgarbage.PreQueue(thing)
#ifdef TESTING
D.find_references()
thing.find_references()
#endif
else
#ifdef TESTING
if(!I.no_hint)
crash_with("[D.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.")
if (!qdel_item.no_hint)
crash_with("[thing.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.")
#endif
I.no_hint++
SSgarbage.PreQueue(D)
else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic")
qdel_item.no_hint++
SSgarbage.PreQueue(thing)
else if (thing.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
CRASH("[thing.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic")
#ifdef TESTING
@@ -0,0 +1,9 @@
SUBSYSTEM_DEF(init_misc_early)
name = "Early Misc Initialization"
init_order = INIT_ORDER_MISC_EARLY
flags = SS_NO_FIRE
/datum/controller/subsystem/init_misc_early/Initialize(timeofday)
plant_controller = new
setupgenetics()
+23 -19
View File
@@ -1,26 +1,30 @@
//obtain a weak reference to a datum
/proc/weakref(datum/D)
if(!istype(D))
return
if(QDELETED(D))
return
if(!D.weakref)
D.weakref = new/weakref(D)
return D.weakref
/weakref
var/ref
var/ref_name
var/ref_type
/weakref/New(datum/D)
ref = "\ref[D]"
/weakref/Destroy()
// A weakref datum should not be manually destroyed as it is a shared resource,
// rather it should be automatically collected by the BYOND GC when all references are gone.
return QDEL_HINT_LETMELIVE
SHOULD_CALL_PARENT(FALSE)
return QDEL_HINT_IWILLGC
/weakref/New(datum/thing)
ref = "\ref[thing]"
ref_name = "[thing]"
ref_type = thing.type
/weakref/proc/resolve()
var/datum/D = locate(ref)
if(D && D.weakref == src)
return D
return null
var/datum/thing = locate(ref)
if (thing && thing.weakref == src)
return thing
return null
/proc/weakref(datum/thing)
if (!istype(thing) || QDELING(thing))
return
if (!thing.weakref)
thing.weakref = new /weakref (thing)
return thing.weakref
+7 -3
View File
@@ -133,15 +133,19 @@
var/stasis_level = 3 //Every 'this' life ticks are applied to the mob (when life_ticks%stasis_level == 1)
var/obj/item/reagent_containers/syringe/syringe
/obj/structure/closet/body_bag/cryobag/Initialize()
tank = new tank_type(null) //It's in nullspace to prevent ejection when the bag is opened.
..()
/obj/structure/closet/body_bag/cryobag/Destroy()
QDEL_NULL(syringe)
QDEL_NULL(tank)
return ..()
/obj/structure/closet/body_bag/cryobag/Initialize()
. = ..()
if (ispath(tank_type, /obj/item/tank))
tank = new tank_type // no loc to prevent tank being dropped when opened
/obj/structure/closet/body_bag/cryobag/attack_hand(mob/living/user)
if(used)
var/confirm = alert(user, "Are you sure you want to open \the [src]? \
+39 -45
View File
@@ -1,24 +1,22 @@
//Let's get some REAL contraband stuff in here. Because come on, getting brigged for LIPSTICK is no fun.
//
// Includes drug powder.
//
//Illicit drugs~
/obj/item/storage/pill_bottle/happy
name = "bottle of Happy pills"
desc = "A recreational drug. When you want to see the rainbow. Probably not work-approved..."
wrapper_color = COLOR_PINK
starts_with = list(/obj/item/reagent_containers/pill/happy = 7)
/obj/item/storage/pill_bottle/zoom
name = "bottle of Zoom pills"
desc = "Probably illegal. Trade brain for speed."
wrapper_color = COLOR_BLUE
starts_with = list(/obj/item/reagent_containers/pill/zoom = 7)
/obj/item/reagent_containers/glass/beaker/vial/random
flags = 0
var/list/random_reagent_list = list(list("water" = 15) = 1, list("cleaner" = 15) = 1)
/obj/item/reagent_containers/glass/beaker/vial/random/toxin
random_reagent_list = list(
list("mindbreaker" = 10, "bliss" = 20) = 3,
@@ -26,26 +24,21 @@
list("impedrezene" = 15) = 2,
list("zombiepowder" = 10) = 1)
/obj/item/reagent_containers/glass/beaker/vial/random/Initialize()
. = ..()
if(is_open_container())
flags ^= OPENCONTAINER
var/list/picked_reagents = pickweight(random_reagent_list)
for(var/reagent in picked_reagents)
reagents.add_reagent(reagent, picked_reagents[reagent])
var/list/names = new
for(var/datum/reagent/R in reagents.reagent_list)
names += R.name
desc = "Contains [english_list(names)]."
update_icon()
/*/////////////////////////////////////
// DRUG POWDER //
//////////////////////////////////////
*/
/obj/item/reagent_containers/powder
name = "powder"
desc = "A powdered form of... something."
@@ -57,46 +50,47 @@
w_class = ITEMSIZE_TINY
volume = 50
/// The name of the reagent with the most volume in this powder.
var/main_reagent_name
/obj/item/reagent_containers/powder/Initialize(mapload, datum/reagents/initial_reagents)
. = ..()
if (istype(initial_reagents))
initial_reagents.trans_to_holder(reagents, volume)
else if (islist(initial_reagents))
var/list/initial_reagents_list = initial_reagents
for (var/reagent_type in initial_reagents_list)
reagents.add_reagent(reagent_type, initial_reagents[reagent_type])
if (!reagents.total_volume)
return INITIALIZE_HINT_QDEL
var/datum/reagent/main_reagent = reagents.get_master_reagent()
main_reagent_name = lowertext(main_reagent.name)
color = reagents.get_color()
/obj/item/reagent_containers/powder/examine(mob/user)
if(reagents)
var/datum/reagent/R = reagents.get_master_reagent()
desc = "A powdered form of what appears to be [R.name]. There's about [reagents.total_volume] units here."
return ..()
. = ..()
if (isliving(user) && get_dist(user, src) > 2)
return
. += "It seems to be about [reagents.total_volume] units of [main_reagent_name]."
/obj/item/reagent_containers/powder/Initialize()
..()
get_appearance()
/obj/item/reagent_containers/powder/proc/get_appearance()
/// Names and colors based on dominant reagent.
if (reagents.reagent_list.len > 0)
color = reagents.get_color()
var/datum/reagent/R = reagents.get_master_reagent()
var/new_name = lowertext(R)
name = "powdered [new_name]"
/// Snorting.
/obj/item/reagent_containers/powder/attackby(var/obj/item/W, var/mob/living/user)
if(!ishuman(user)) /// You gotta be fleshy to snort the naughty drugs.
/obj/item/reagent_containers/powder/attackby(obj/item/item, mob/living/user)
if (!ishuman(user))
return ..()
if(!istype(W, /obj/item/glass_extra/straw) && !istype(W, /obj/item/reagent_containers/rollingpaper))
if (!istype(item, /obj/item/glass_extra/straw) && !istype(item, /obj/item/reagent_containers/rollingpaper))
return ..()
user.visible_message("<span class='warning'>[user] snorts [src] with [W]!</span>")
reagents.trans_to_mob(user, amount_per_transfer_from_this, CHEM_BLOOD)
var/used_up = !reagents.total_volume
user.visible_message(
SPAN_ITALIC("\The [user] snorts some [name] with \a [item]."),
SPAN_ITALIC("You snort [used_up ? "the last" : "some"] of the [main_reagent_name] with \the [item].")
)
playsound(loc, 'sound/effects/snort.ogg', 50, 1)
if(reagents)
reagents.trans_to_mob(user, amount_per_transfer_from_this, CHEM_BLOOD)
if(!reagents.total_volume) /// Did we use all of it?
if (used_up)
qdel(src)
////// End powder. ///////////
//////////////////////////////
///// Drugs for loadout///////
/obj/item/storage/pill_bottle/bliss
name = "unlabeled pill bottle"
@@ -126,4 +120,4 @@
/obj/item/storage/pill_bottle/schnappi
name = "unlabeled pill bottle"
desc = "A pill bottle with its label suspiciously scratched out."
starts_with = list(/obj/item/reagent_containers/pill/unidentified/schnappi = 7)
starts_with = list(/obj/item/reagent_containers/pill/unidentified/schnappi = 7)
+6 -4
View File
@@ -7,12 +7,14 @@
var/drop_get_turf = TRUE
var/start_anomalous = FALSE
// creates a new object and deletes itself
/obj/random/Initialize()
. = INITIALIZE_HINT_QDEL
..()
if(!prob(spawn_nothing_percentage))
try_spawn_item()
return INITIALIZE_HINT_QDEL
if (prob(spawn_nothing_percentage))
return
try_spawn_item()
/obj/random/proc/try_spawn_item()
var/atom/result = spawn_item()
+3 -3
View File
@@ -404,13 +404,13 @@
// As this is only done at runtime, we have to create all the vending machines in existence and force them
// to register their products when this asset initializes.
/datum/asset/spritesheet/vending/proc/populate_vending_products()
SSatoms.map_loader_begin()
SSatoms.BeginMapLoad()
for(var/path in subtypesof(/obj/machinery/vending))
var/obj/machinery/vending/x = new path(null)
// force an inventory build; with map_loader_begin active, init isn't called
// force an inventory build; with BeginMapLoad active, init isn't called
x.build_inventory()
qdel(x)
SSatoms.map_loader_stop()
SSatoms.FinishMapLoad()
// /datum/asset/simple/genetics
// assets = list(
@@ -730,6 +730,24 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.h_style = new_h_style
return TOPIC_REFRESH_UPDATE_PREVIEW
else if (href_list["hair_style_left"])
var/list/valid_hairstyles = pref.get_valid_hairstyles()
var/index = valid_hairstyles.Find(href_list["hair_style_left"])
if (!index || index == 1)
pref.h_style = valid_hairstyles[length(valid_hairstyles)]
else
pref.h_style = valid_hairstyles[index - 1]
return TOPIC_REFRESH_UPDATE_PREVIEW
else if (href_list["hair_style_right"])
var/list/valid_hairstyles = pref.get_valid_hairstyles()
var/index = valid_hairstyles.Find(href_list["hair_style_right"])
if (!index || index == length(valid_hairstyles))
pref.h_style = valid_hairstyles[1]
else
pref.h_style = valid_hairstyles[index + 1]
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["grad_style"])
var/list/valid_gradients = GLOB.hair_gradients
@@ -738,26 +756,22 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.grad_style = new_grad_style
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["hair_style_left"])
var/H = href_list["hair_style_left"]
var/list/valid_hairstyles = pref.get_valid_hairstyles()
var/start = valid_hairstyles.Find(H)
if(start != 1) //If we're not the beginning of the list, become the previous element.
pref.h_style = valid_hairstyles[start-1]
else //But if we ARE, become the final element.
pref.h_style = valid_hairstyles[valid_hairstyles.len]
else if (href_list["grad_style_left"])
var/list/valid_hair_gradients = GLOB.hair_gradients
var/index = valid_hair_gradients.Find(href_list["grad_style_left"])
if (!index || index == 1)
pref.grad_style = valid_hair_gradients[length(valid_hair_gradients)]
else
pref.grad_style = valid_hair_gradients[index - 1]
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["hair_style_right"])
var/H = href_list["hair_style_right"]
var/list/valid_hairstyles = pref.get_valid_hairstyles()
var/start = valid_hairstyles.Find(H)
if(start != valid_hairstyles.len) //If we're not the end of the list, become the next element.
pref.h_style = valid_hairstyles[start+1]
else //But if we ARE, become the first element.
pref.h_style = valid_hairstyles[1]
else if (href_list["grad_style_right"])
var/list/valid_hair_gradients = GLOB.hair_gradients
var/index = valid_hair_gradients.Find(href_list["grad_style_right"])
if (!index || index == length(valid_hair_gradients))
pref.grad_style = valid_hair_gradients[1]
else
pref.grad_style = valid_hair_gradients[index + 1]
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["facial_color"])
@@ -806,26 +820,22 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.f_style = new_f_style
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["facial_style_left"])
var/F = href_list["facial_style_left"]
else if (href_list["facial_style_left"])
var/list/valid_facialhairstyles = pref.get_valid_facialhairstyles()
var/start = valid_facialhairstyles.Find(F)
if(start != 1) //If we're not the beginning of the list, become the previous element.
pref.f_style = valid_facialhairstyles[start-1]
else //But if we ARE, become the final element.
pref.f_style = valid_facialhairstyles[valid_facialhairstyles.len]
var/index = valid_facialhairstyles.Find(href_list["facial_style_left"])
if (!index || index == 1)
pref.f_style = valid_facialhairstyles[length(valid_facialhairstyles)]
else
pref.f_style = valid_facialhairstyles[index - 1]
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["facial_style_right"])
var/F = href_list["facial_style_right"]
else if (href_list["facial_style_right"])
var/list/valid_facialhairstyles = pref.get_valid_facialhairstyles()
var/start = valid_facialhairstyles.Find(F)
if(start != valid_facialhairstyles.len) //If we're not the end of the list, become the next element.
pref.f_style = valid_facialhairstyles[start+1]
else //But if we ARE, become the first element.
var/index = valid_facialhairstyles.Find(href_list["facial_style_right"])
if (!index || index == length(valid_facialhairstyles))
pref.f_style = valid_facialhairstyles[1]
else
pref.f_style = valid_facialhairstyles[index + 1]
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["marking_style"])
+30
View File
@@ -153,6 +153,36 @@
desc = "A starry winter hood."
icon_state = "winterhood_cosmic"
/obj/item/clothing/head/hood/winter/parka_red
name = "red parka hood"
desc = "A red fur-lined hood."
icon_state = "redpark_hood"
/obj/item/clothing/head/hood/winter/parka_green
name = "green parka hood"
desc = "A green fur-lined hood."
icon_state = "greenpark_hood"
/obj/item/clothing/head/hood/winter/parka_blue
name = "blue parka hood"
desc = "A blue fur-lined hood."
icon_state = "bluepark_hood"
/obj/item/clothing/head/hood/winter/parka_yellow
name = "yellow parka hood"
desc = "A yellow fur-lined hood."
icon_state = "yellowpark_hood"
/obj/item/clothing/head/hood/winter/parka_purple
name = "purple parka hood"
desc = "A purple fur-lined hood."
icon_state = "purplepark_hood"
/obj/item/clothing/head/hood/winter/parka_vintage
name = "vintage parka hood"
desc = "An old-fashioned fur-lined hood."
icon_state = "vintagepark_hood"
// Explorer gear
/obj/item/clothing/head/hood/explorer
name = "explorer hood"
+39
View File
@@ -335,6 +335,45 @@
light_power = 1.8
light_range = 1.2
/obj/item/clothing/suit/storage/hooded/wintercoat/parka
name = "red parka"
desc = "A heavy fur-lined jacket designed to keep you extra warm in sub-zero conditions."
icon_state = "redpark"
item_state_slots = list(slot_r_hand_str = "coatwinter", slot_l_hand_str = "coatwinter")
hoodtype = /obj/item/clothing/head/hood/winter/parka_red
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/green
name = "green parka"
icon_state = "greenpark"
hoodtype = /obj/item/clothing/head/hood/winter/parka_green
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/blue
name = "blue parka"
icon_state = "bluepark"
hoodtype = /obj/item/clothing/head/hood/winter/parka_blue
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/yellow
name = "yellow parka"
icon_state = "yellowpark"
hoodtype = /obj/item/clothing/head/hood/winter/parka_yellow
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/purple
name = "purple parka"
icon_state = "purplepark"
hoodtype = /obj/item/clothing/head/hood/winter/parka_purple
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/nanotrasen
name = "corporate blue parka"
desc = "A NanoTrasen branded fur-lined jacket made to keep you nice and toasty on cold winter days. Or at least alive"
icon_state = "corppark"
hoodtype = /obj/item/clothing/head/hood/winter/parka_blue //No point having a unique hood when it's just blue anyway!
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/vintage
name = "vintage parka"
desc = "An old-fashioned fur-lined jacket made to keep you nice and toasty on cold winter days. Or at least alive."
icon_state = "vintagepark"
hoodtype = /obj/item/clothing/head/hood/winter/parka_vintage
// winter coats end here
/obj/item/clothing/suit/storage/hooded/explorer
+4 -4
View File
@@ -366,7 +366,7 @@ var/global/use_preloader = FALSE
first_turf_index++
//turn off base new Initialization until the whole thing is loaded
SSatoms.map_loader_begin()
SSatoms.BeginMapLoad()
//instanciate the first /turf
var/turf/T
if(members[first_turf_index] != /turf/template_noop)
@@ -385,7 +385,7 @@ var/global/use_preloader = FALSE
for(index in 1 to first_turf_index-1)
instance_atom(members[index],members_attributes[index],crds,no_changeturf,orientation)
//Restore initialization to the previous value
SSatoms.map_loader_stop()
SSatoms.FinishMapLoad()
////////////////
//Helpers procs
@@ -406,9 +406,9 @@ var/global/use_preloader = FALSE
//custom CHECK_TICK here because we don't want things created while we're sleeping to not initialize
if(TICK_CHECK)
SSatoms.map_loader_stop()
SSatoms.FinishMapLoad()
stoplag()
SSatoms.map_loader_begin()
SSatoms.BeginMapLoad()
// Rotate the atom now that it exists, rather than changing its orientation beforehand through the fields["dir"]
if(orientation != 0) // 0 means no rotation
@@ -7,8 +7,7 @@
if (istype(loc, /turf/space))
return ..() - 1
if(species.slowdown)
. += species.slowdown
. += species.get_slowdown(src)
if(force_max_speed)
return ..() + HUMAN_LOWEST_SLOWDOWN
@@ -263,4 +262,4 @@
/mob/living/carbon/human/set_dir(var/new_dir)
. = ..()
if(. && species.tail)
update_tail_showing()
update_tail_showing()
+22 -20
View File
@@ -82,7 +82,7 @@
handle_shock()
handle_pain()
handle_allergens()
handle_medical_side_effects()
@@ -167,11 +167,12 @@
var/pressure_difference
// First get the absolute pressure difference.
if(pressure < species.safe_pressure) // We are in an underpressure.
pressure_difference = species.safe_pressure - pressure
var/species_safe_pressure = species.get_safe_pressure(src)
if(pressure < species_safe_pressure) // We are in an underpressure.
pressure_difference = species_safe_pressure - pressure
else //We are in an overpressure or standard atmosphere.
pressure_difference = pressure - species.safe_pressure
pressure_difference = pressure - species_safe_pressure
if(pressure_difference < 5) // If the difference is small, don't bother calculating the fraction.
pressure_difference = 0
@@ -184,10 +185,10 @@
// The difference is always positive to avoid extra calculations.
// Apply the relative difference on a standard atmosphere to get the final result.
// The return value will be the adjusted_pressure of the human that is the basis of pressure warnings and damage.
if(pressure < species.safe_pressure)
return species.safe_pressure - pressure_difference
if(pressure < species_safe_pressure)
return species_safe_pressure - pressure_difference
else
return species.safe_pressure + pressure_difference
return species_safe_pressure + pressure_difference
/mob/living/carbon/human/handle_disabilities()
..()
@@ -565,7 +566,7 @@
else
failed_last_breath = 0
adjustOxyLoss(-5)
if(!does_not_breathe && client) // If we breathe, and have an active client, check if we have synthetic lungs.
var/obj/item/organ/internal/lungs/L = internal_organs_by_name[O_LUNGS]
var/turf = get_turf(src)
@@ -588,7 +589,7 @@
to_chat(src, "<span class='danger'>You feel your face burning and a searing heat in your lungs!</span>")
if(breath.temperature >= species.heat_discomfort_level)
if(breath.temperature >= species.breath_heat_level_3)
apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, BP_HEAD, used_weapon = "Excessive Heat")
throw_alert("temp", /obj/screen/alert/hot, HOT_ALERT_SEVERITY_MAX)
@@ -641,25 +642,25 @@
breath.update_values()
return 1
/mob/living/carbon/human/proc/play_inhale(var/mob/living/M, var/exhale)
var/suit_inhale_sound
if(species.suit_inhale_sound)
suit_inhale_sound = species.suit_inhale_sound
else // Failsafe
suit_inhale_sound = 'sound/effects/mob_effects/suit_breathe_in.ogg'
playsound_local(get_turf(src), suit_inhale_sound, 100, pressure_affected = FALSE, volume_channel = VOLUME_CHANNEL_AMBIENCE)
if(!exhale) // Did we fail exhale? If no, play it after inhale finishes.
addtimer(CALLBACK(src, .proc/play_exhale, M), 5 SECONDS)
/mob/living/carbon/human/proc/play_exhale(var/mob/living/M)
var/suit_exhale_sound
if(species.suit_exhale_sound)
suit_exhale_sound = species.suit_exhale_sound
else // Failsafe
suit_exhale_sound = 'sound/effects/mob_effects/suit_breathe_out.ogg'
playsound_local(get_turf(src), suit_exhale_sound, 100, pressure_affected = FALSE, volume_channel = VOLUME_CHANNEL_AMBIENCE)
/mob/living/carbon/human/proc/handle_allergens()
@@ -729,7 +730,7 @@
else
loc_temp = environment.temperature
if(adjusted_pressure < species.warning_high_pressure && adjusted_pressure > species.warning_low_pressure && abs(loc_temp - bodytemperature) < 20 && bodytemperature < species.heat_level_1 && bodytemperature > species.cold_level_1)
if(adjusted_pressure < species.get_warning_high_pressure(src) && adjusted_pressure > species.get_warning_low_pressure(src) && abs(loc_temp - bodytemperature) < 20 && bodytemperature < species.heat_level_1 && bodytemperature > species.cold_level_1)
clear_alert("pressure")
return // Temperatures are within normal ranges, fuck all this processing. ~Ccomp
@@ -798,15 +799,16 @@
if(status_flags & GODMODE)
return 1 //godmode
if(adjusted_pressure >= species.hazard_high_pressure)
var/pressure_damage = min( ( (adjusted_pressure / species.hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE)
var/species_hazard_high_pressure = species.get_hazard_high_pressure(src)
if(adjusted_pressure >= species_hazard_high_pressure)
var/pressure_damage = min( ( (adjusted_pressure / species_hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE)
take_overall_damage(brute=pressure_damage, used_weapon = "High Pressure")
throw_alert("pressure", /obj/screen/alert/highpressure, 2)
else if(adjusted_pressure >= species.warning_high_pressure)
else if(adjusted_pressure >= species.get_warning_high_pressure(src))
throw_alert("pressure", /obj/screen/alert/highpressure, 1)
else if(adjusted_pressure >= species.warning_low_pressure)
else if(adjusted_pressure >= species.get_warning_low_pressure(src))
clear_alert("pressure")
else if(adjusted_pressure >= species.hazard_low_pressure)
else if(adjusted_pressure >= species.get_hazard_low_pressure(src))
throw_alert("pressure", /obj/screen/alert/lowpressure, 1)
else
if( !(COLD_RESISTANCE in mutations))
@@ -814,7 +816,7 @@
if(getOxyLoss() < 55) // 12 OxyLoss per 4 ticks when wearing internals; unconsciousness in 16 ticks, roughly half a minute
var/pressure_dam = 3 // 16 OxyLoss per 4 ticks when no internals present; unconsciousness in 13 ticks, roughly twenty seconds
// (Extra 1 oxyloss from failed breath)
// Being in higher pressure decreases the damage taken, down to a minimum of (species.hazard_low_pressure / ONE_ATMOSPHERE) at species.hazard_low_pressure
// Being in higher pressure decreases the damage taken, down to a minimum of (species.get_hazard_low_pressure(src) / ONE_ATMOSPHERE) at species.get_hazard_low_pressure(src)
pressure_dam *= (ONE_ATMOSPHERE - adjusted_pressure) / ONE_ATMOSPHERE
if(wear_suit && wear_suit.min_pressure_protection && head && head.min_pressure_protection)
@@ -14,6 +14,7 @@
/datum/unarmed_attack/claws/strong,
/datum/unarmed_attack/bite/strong
)
rarity_value = 5
blurb = "The Vox are the broken remnants of a once-proud race, now reduced to little more than \
scavenging vermin who prey on isolated stations, ships or planets to keep their own ancient arkships \
@@ -40,9 +41,6 @@
male_sneeze_sound = 'sound/voice/shrieksneeze.ogg'
female_sneeze_sound = 'sound/voice/shrieksneeze.ogg'
warning_low_pressure = 50
hazard_low_pressure = 0
cold_level_1 = 210 //Default 260
cold_level_2 = 150 //Default 200
cold_level_3 = 90 //Default 120
@@ -98,6 +96,8 @@
default_emotes = list(
/decl/emote/audible/vox_shriek
)
inherent_verbs = list(/mob/living/carbon/human/proc/toggle_vox_pressure_seal)
var/list/current_pressure_toggle = list()
/datum/species/vox/get_random_name(var/gender)
var/datum/language/species_language = GLOB.all_languages[default_language]
@@ -106,3 +106,57 @@
/datum/species/vox/equip_survival_gear(var/mob/living/carbon/human/H, var/extendedtank = 0,var/comprehensive = 0)
. = ..()
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/vox(H), slot_wear_mask)
/datum/species/vox/get_slowdown(var/mob/living/carbon/human/H)
if(current_pressure_toggle["\ref[H]"])
return 1.5
return ..()
/datum/species/vox/get_warning_low_pressure(var/mob/living/carbon/human/H)
if(current_pressure_toggle["\ref[H]"])
return 50
return ..()
/datum/species/vox/get_hazard_low_pressure(var/mob/living/carbon/human/H)
if(current_pressure_toggle["\ref[H]"])
return 0
return ..()
/mob/living/carbon/human/proc/toggle_vox_pressure_seal()
set name = "Toggle Vox Pressure Seal"
set category = "Abilities"
set src = usr
if(!istype(species, /datum/species/vox))
verbs -= /mob/living/carbon/human/proc/toggle_vox_pressure_seal
return
if(incapacitated(INCAPACITATION_KNOCKOUT))
to_chat(src, SPAN_WARNING("You are in no state to do that."))
return
var/datum/gender/G = gender_datums[get_visible_gender()]
visible_message(SPAN_NOTICE("\The [src] begins flexing and realigning [G.his] scaling..."))
if(!do_after(src, 2 SECONDS, src, FALSE))
visible_message(
SPAN_NOTICE("\The [src] ceases adjusting [G.his] scaling."),
self_message = SPAN_WARNING("You must remain still to seal or unseal your scaling."))
return
if(incapacitated(INCAPACITATION_KNOCKOUT))
to_chat(src, SPAN_WARNING("You are in no state to do that."))
return
// TODO: maybe add cold and heat thresholds to this.
var/my_ref = "\ref[src]"
var/datum/species/vox/kikiki = species
if((kikiki.current_pressure_toggle[my_ref] = !kikiki.current_pressure_toggle[my_ref]))
visible_message(
SPAN_NOTICE("\The [src]'s scaling flattens and smooths out."),
self_message = SPAN_NOTICE("You flatten your scaling and inflate internal bladders, protecting yourself against low pressure at the cost of dexterity.")
)
else
visible_message(
SPAN_NOTICE("\The [src]'s scaling bristles roughly."),
self_message = SPAN_NOTICE("You bristle your scaling and deflate your internal bladders, restoring mobility but leaving yourself vulnerable to low pressure.")
)
@@ -113,3 +113,21 @@
/datum/species/proc/get_vision_flags(var/mob/living/carbon/human/H)
return vision_flags
/datum/species/proc/get_hazard_high_pressure(var/mob/living/carbon/human/H)
return hazard_high_pressure
/datum/species/proc/get_warning_high_pressure(var/mob/living/carbon/human/H)
return warning_high_pressure
/datum/species/proc/get_warning_low_pressure(var/mob/living/carbon/human/H)
return warning_low_pressure
/datum/species/proc/get_hazard_low_pressure(var/mob/living/carbon/human/H)
return hazard_low_pressure
/datum/species/proc/get_safe_pressure(var/mob/living/carbon/human/H)
return safe_pressure
/datum/species/proc/get_slowdown(var/mob/living/carbon/human/H)
return slowdown
@@ -225,7 +225,7 @@ var/global/datum/species/shapeshifter/promethean/prometheans
var/datum/gas_mixture/environment = T.return_air()
var/pressure = environment.return_pressure()
var/affecting_pressure = H.calculate_affecting_pressure(pressure)
if(affecting_pressure <= hazard_low_pressure) // Dangerous low pressure stops the regeneration of physical wounds. Body is focusing on keeping them intact rather than sealing.
if(affecting_pressure <= get_hazard_low_pressure(H)) // Dangerous low pressure stops the regeneration of physical wounds. Body is focusing on keeping them intact rather than sealing.
regen_brute = FALSE
regen_burn = FALSE
@@ -1721,22 +1721,49 @@ shaved
//Skrell 'hairstyles'
/datum/sprite_accessory/hair/skr
name = "Skrell Average Tentacles"
icon_state = "skrell_hair_average"
name = "Tentacles, Average"
icon_state = "skrell_short"
species_allowed = list(SPECIES_SKRELL, SPECIES_EVENT1, SPECIES_EVENT2, SPECIES_EVENT3)
/datum/sprite_accessory/hair/skr/tentacle_veryshort
name = "Skrell Short Tentacles"
icon_state = "skrell_hair_short"
gender = MALE
/datum/sprite_accessory/hair/skr/pullback
name = "Tentacles, Average, Pullback"
icon_state = "skrell_short_pullback"
/datum/sprite_accessory/hair/skr/tentacle_average
name = "Skrell Long Tentacles"
icon_state = "skrell_hair_long"
/datum/sprite_accessory/hair/skr/very_short
name = "Tentacles, Short"
icon_state = "skrell_very_short"
/datum/sprite_accessory/hair/skr/tentacle_verylong
name = "Skrell Very Long Tentacles"
icon_state = "skrell_hair_verylong"
/datum/sprite_accessory/hair/skr/long
name = "Tentacles, Long"
icon_state = "skrell_long"
/datum/sprite_accessory/hair/skr/long/pullback
name = "Tentacles, Long, Pullback"
icon_state = "skrell_long_pullback"
/datum/sprite_accessory/hair/skr/long/scarf
name = "Tentacles, Long, Scarf"
icon_state = "skrell_long_scarf"
/datum/sprite_accessory/hair/skr/long/wavy
name = "Tentacles, Long, Wavy"
icon_state = "skrell_long_wavy"
/datum/sprite_accessory/hair/skr/very_long
name = "Tentacles, Very Long"
icon_state = "skrell_very_long"
/datum/sprite_accessory/hair/skr/very_long/pullback
name = "Tentacles, Very Long, Pullback"
icon_state = "skrell_very_long_pullback"
/datum/sprite_accessory/hair/skr/very_long/scarf
name = "Tentacles, Very Long, Scarf"
icon_state = "skrell_very_long_scarf"
/datum/sprite_accessory/hair/skr/very_long/wavy
name = "Tentacles, Very Long, Wavy"
icon_state = "skrell_very_long_wavy"
//Tajaran hairstyles
/datum/sprite_accessory/hair/taj
@@ -91,27 +91,16 @@
return
/obj/item/reagent_containers/pill/attackby(obj/item/W as obj, mob/user as mob)
if(is_sharp(W))
var/obj/item/reagent_containers/powder/J = new /obj/item/reagent_containers/powder(src.loc)
user.visible_message("<span class='warning'>[user] gently cuts up [src] with [W]!</span>")
playsound(src.loc, 'sound/effects/chop.ogg', 50, 1)
if(reagents)
reagents.trans_to_obj(J, reagents.total_volume)
J.get_appearance()
/obj/item/reagent_containers/pill/attackby(obj/item/item, mob/living/user)
if (is_sharp(item) || istype(item, /obj/item/card))
user.visible_message(
SPAN_ITALIC("\The [user] cuts up \a [src] with \a [item]."),
SPAN_ITALIC("You cut up \the [src] with \the [item].")
)
playsound(loc, 'sound/effects/chop.ogg', 50, 1)
new /obj/item/reagent_containers/powder (loc, reagents)
qdel(src)
if(istype(W, /obj/item/card/id))
var/obj/item/reagent_containers/powder/J = new /obj/item/reagent_containers/powder(src.loc)
user.visible_message("<span class='warning'>[user] clumsily chops up [src] with [W]!</span>")
playsound(src.loc, 'sound/effects/chop.ogg', 50, 1)
if(reagents)
reagents.trans_to_obj(J, reagents.total_volume)
J.get_appearance()
qdel(src)
return TRUE
return ..()
////////////////////////////////////////////////////////////////////////////////
+2 -2
View File
@@ -20,7 +20,7 @@
name = "SUBSYSTEM - ATOMS: Shall have no bad init calls"
/datum/unit_test/subsystem_atom_shall_have_no_bad_init_calls/start_test()
if(SSatoms.BadInitializeCalls.len)
if(SSatoms.bad_init_calls.len)
log_bad(jointext(SSatoms.InitLog(), null))
fail("[SSatoms] had bad initialization calls.")
else
@@ -35,7 +35,7 @@
var/fail = FALSE
for(var/atom/atom in world)
if(!atom.initialized && !QDELETED(atom)) // Not ideal to skip over qdeleted atoms, but a lot of current code uses pre-init qdels
log_bad("Uninitialized atom: [atom.type] - [atom.log_info_line()]")
log_bad("Uninitialized atom: [atom.type] - [atom.get_log_info_line()]")
fail = TRUE
if(fail)
fail("There were uninitialized atoms.")
Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 KiB

After

Width:  |  Height:  |  Size: 261 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 KiB

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 351 KiB

After

Width:  |  Height:  |  Size: 363 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 55 KiB

+15 -10
View File
@@ -1147,8 +1147,6 @@
/obj/item/clothing/shoes/boots/winter,
/obj/item/clothing/shoes/boots/winter,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/effect/floor_decal/steeldecal/steel_decals_central7{
dir = 8
},
@@ -1168,6 +1166,8 @@
},
/obj/item/melee/umbrella/random,
/obj/item/melee/umbrella/random,
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/nanotrasen,
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/nanotrasen,
/turf/simulated/floor/tiled,
/area/surface/station/arrivals/cynosure)
"aGP" = (
@@ -2610,12 +2610,12 @@
/obj/item/clothing/shoes/boots/winter,
/obj/item/clothing/shoes/boots/winter,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/item/melee/umbrella/random{
pixel_y = -4
},
/obj/item/melee/umbrella/random,
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/nanotrasen,
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/nanotrasen,
/turf/simulated/floor/tiled,
/area/surface/station/arrivals/cynosure)
"bkP" = (
@@ -27785,6 +27785,12 @@
name = "Biohazard Shutter"
},
/obj/structure/closet/emcloset,
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/nanotrasen,
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/nanotrasen,
/obj/item/clothing/shoes/boots/winter,
/obj/item/clothing/shoes/boots/winter,
/obj/item/melee/umbrella/random,
/obj/item/melee/umbrella/random,
/turf/simulated/floor/tiled/techfloor,
/area/surface/station/rnd/hallway/gnd)
"mHN" = (
@@ -35441,12 +35447,12 @@
/obj/item/clothing/shoes/boots/winter,
/obj/item/clothing/shoes/boots/winter,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/item/melee/umbrella/random{
pixel_y = -4
},
/obj/item/melee/umbrella/random,
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/nanotrasen,
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/nanotrasen,
/turf/simulated/floor/tiled,
/area/surface/station/arrivals/cynosure)
"pVb" = (
@@ -42243,9 +42249,8 @@
/obj/item/melee/umbrella/random{
pixel_y = -4
},
/obj/effect/floor_decal/arrows,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/nanotrasen,
/turf/simulated/floor/plating,
/area/surface/station/hallway/primary/groundfloor/south)
"sWe" = (
@@ -50374,14 +50379,14 @@
/obj/item/clothing/shoes/boots/winter,
/obj/item/clothing/shoes/boots/winter,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/item/clothing/suit/storage/hooded/wintercoat,
/obj/item/melee/umbrella/random,
/obj/item/melee/umbrella/random,
/obj/machinery/camera/network/ground_floor{
c_tag = "Ground Floor - Arrivals North";
dir = 8
},
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/nanotrasen,
/obj/item/clothing/suit/storage/hooded/wintercoat/parka/nanotrasen,
/turf/simulated/floor/tiled,
/area/surface/station/arrivals/cynosure)
"wNJ" = (