a
This commit is contained in:
@@ -98,8 +98,8 @@ jobs:
|
||||
bash tools/ci/install_byond.sh
|
||||
source $HOME/BYOND/byond/bin/byondsetup
|
||||
tgui/bin/tgui --build
|
||||
# bash tools/ci/dm.sh -DCIBUILDING tgstation.dme
|
||||
# bash tools/ci/run_server.sh
|
||||
bash tools/ci/dm.sh -DCIBUILDING tgstation.dme
|
||||
# bash tools/ci/run_server.sh
|
||||
|
||||
test_windows:
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
|
||||
+28
-16
@@ -1247,28 +1247,40 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
|
||||
|
||||
#define FOR_DVIEW_END GLOB.dview_mob.loc = null
|
||||
|
||||
//can a window be here, or is there a window blocking it?
|
||||
/proc/valid_window_location(turf/T, dir_to_check)
|
||||
if(!T)
|
||||
/**
|
||||
* Checks whether the target turf is in a valid state to accept a directional window
|
||||
* or other directional pseudo-dense object such as railings.
|
||||
*
|
||||
* Returns FALSE if the target turf cannot accept a directional window or railing.
|
||||
* Returns TRUE otherwise.
|
||||
*
|
||||
* Arguments:
|
||||
* * dest_turf - The destination turf to check for existing windows and railings
|
||||
* * test_dir - The prospective dir of some atom you'd like to put on this turf.
|
||||
* * is_fulltile - Whether the thing you're attempting to move to this turf takes up the entire tile or whether it supports multiple movable atoms on its tile.
|
||||
*/
|
||||
/proc/valid_window_location(turf/dest_turf, test_dir, is_fulltile = FALSE)
|
||||
if(!dest_turf)
|
||||
return FALSE
|
||||
for(var/obj/O in T)
|
||||
if(istype(O, /obj/machinery/door/window) && (O.dir == dir_to_check || dir_to_check == FULLTILE_WINDOW_DIR))
|
||||
return FALSE
|
||||
if(istype(O, /obj/structure/windoor_assembly))
|
||||
var/obj/structure/windoor_assembly/W = O
|
||||
if(W.ini_dir == dir_to_check || dir_to_check == FULLTILE_WINDOW_DIR)
|
||||
for(var/obj/turf_content in dest_turf)
|
||||
if(istype(turf_content, /obj/machinery/door/window))
|
||||
if((turf_content.dir == test_dir) || is_fulltile)
|
||||
return FALSE
|
||||
if(istype(O, /obj/structure/window))
|
||||
var/obj/structure/window/W = O
|
||||
if(W.ini_dir == dir_to_check || W.ini_dir == FULLTILE_WINDOW_DIR || dir_to_check == FULLTILE_WINDOW_DIR)
|
||||
if(istype(turf_content, /obj/structure/windoor_assembly))
|
||||
var/obj/structure/windoor_assembly/windoor_assembly = turf_content
|
||||
if(windoor_assembly.dir == test_dir || is_fulltile)
|
||||
return FALSE
|
||||
if(istype(O, /obj/structure/railing))
|
||||
var/obj/structure/railing/rail = O
|
||||
if(rail.ini_dir == dir_to_check || rail.ini_dir == FULLTILE_WINDOW_DIR || dir_to_check == FULLTILE_WINDOW_DIR)
|
||||
if(istype(turf_content, /obj/structure/window))
|
||||
var/obj/structure/window/window_structure = turf_content
|
||||
if(window_structure.dir == test_dir || window_structure.fulltile || is_fulltile)
|
||||
return FALSE
|
||||
if(istype(turf_content, /obj/structure/railing))
|
||||
var/obj/structure/railing/rail = turf_content
|
||||
if(rail.dir == test_dir || is_fulltile)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/proc/pass()
|
||||
/proc/pass(...)
|
||||
return
|
||||
|
||||
/proc/get_mob_or_brainmob(occupant)
|
||||
|
||||
@@ -38,9 +38,6 @@
|
||||
/obj/screen/plane_master/proc/shadow(_size, _offset = 0, _x = 0, _y = 0, _color = "#04080FAA")
|
||||
filters += filter(type = "drop_shadow", x = _x, y = _y, color = _color, size = _size, offset = _offset)
|
||||
|
||||
/obj/screen/plane_master/proc/clear_filters()
|
||||
filters = list()
|
||||
|
||||
///Contains just the floor
|
||||
/obj/screen/plane_master/floor
|
||||
name = "floor plane master"
|
||||
|
||||
+88
-88
@@ -1,53 +1,53 @@
|
||||
/**
|
||||
*# Callback Datums
|
||||
*A datum that holds a proc to be called on another object, used to track proccalls to other objects
|
||||
*
|
||||
* ## USAGE
|
||||
*
|
||||
* ```
|
||||
* var/datum/callback/C = new(object|null, /proc/type/path|"procstring", arg1, arg2, ... argn)
|
||||
* var/timerid = addtimer(C, time, timertype)
|
||||
* you can also use the compiler define shorthand
|
||||
* var/timerid = addtimer(CALLBACK(object|null, /proc/type/path|procstring, arg1, arg2, ... argn), time, timertype)
|
||||
* ```
|
||||
*
|
||||
* Note: proc strings can only be given for datum proc calls, global procs must be proc paths
|
||||
*
|
||||
* Also proc strings are strongly advised against because they don't compile error if the proc stops existing
|
||||
*
|
||||
* In some cases you can provide a shortform of the procname, see the proc typepath shortcuts documentation below
|
||||
*
|
||||
* ## INVOKING THE CALLBACK
|
||||
*`var/result = C.Invoke(args, to, add)` additional args are added after the ones given when the callback was created
|
||||
*
|
||||
* `var/result = C.InvokeAsync(args, to, add)` Asyncronous - returns . on the first sleep then continues on in the background
|
||||
* after the sleep/block ends, otherwise operates normally.
|
||||
*
|
||||
* ## PROC TYPEPATH SHORTCUTS
|
||||
* (these operate on paths, not types, so to these shortcuts, datum is NOT a parent of atom, etc...)
|
||||
*
|
||||
* ### global proc while in another global proc:
|
||||
* .procname
|
||||
*
|
||||
* `CALLBACK(GLOBAL_PROC, .some_proc_here)`
|
||||
*
|
||||
* ### proc defined on current(src) object (when in a /proc/ and not an override) OR overridden at src or any of it's parents:
|
||||
* .procname
|
||||
*
|
||||
* `CALLBACK(src, .some_proc_here)`
|
||||
*
|
||||
* ### when the above doesn't apply:
|
||||
*.proc/procname
|
||||
*
|
||||
* `CALLBACK(src, .proc/some_proc_here)`
|
||||
*
|
||||
*
|
||||
* proc defined on a parent of a some type
|
||||
*
|
||||
* `/some/type/.proc/some_proc_here`
|
||||
*
|
||||
* Otherwise you must always provide the full typepath of the proc (/type/of/thing/proc/procname)
|
||||
*/
|
||||
*# Callback Datums
|
||||
*A datum that holds a proc to be called on another object, used to track proccalls to other objects
|
||||
*
|
||||
* ## USAGE
|
||||
*
|
||||
* ```
|
||||
* var/datum/callback/C = new(object|null, /proc/type/path|"procstring", arg1, arg2, ... argn)
|
||||
* var/timerid = addtimer(C, time, timertype)
|
||||
* you can also use the compiler define shorthand
|
||||
* var/timerid = addtimer(CALLBACK(object|null, /proc/type/path|procstring, arg1, arg2, ... argn), time, timertype)
|
||||
* ```
|
||||
*
|
||||
* Note: proc strings can only be given for datum proc calls, global procs must be proc paths
|
||||
*
|
||||
* Also proc strings are strongly advised against because they don't compile error if the proc stops existing
|
||||
*
|
||||
* In some cases you can provide a shortform of the procname, see the proc typepath shortcuts documentation below
|
||||
*
|
||||
* ## INVOKING THE CALLBACK
|
||||
*`var/result = C.Invoke(args, to, add)` additional args are added after the ones given when the callback was created
|
||||
*
|
||||
* `var/result = C.InvokeAsync(args, to, add)` Asyncronous - returns . on the first sleep then continues on in the background
|
||||
* after the sleep/block ends, otherwise operates normally.
|
||||
*
|
||||
* ## PROC TYPEPATH SHORTCUTS
|
||||
* (these operate on paths, not types, so to these shortcuts, datum is NOT a parent of atom, etc...)
|
||||
*
|
||||
* ### global proc while in another global proc:
|
||||
* .procname
|
||||
*
|
||||
* `CALLBACK(GLOBAL_PROC, .some_proc_here)`
|
||||
*
|
||||
* ### proc defined on current(src) object (when in a /proc/ and not an override) OR overridden at src or any of it's parents:
|
||||
* .procname
|
||||
*
|
||||
* `CALLBACK(src, .some_proc_here)`
|
||||
*
|
||||
* ### when the above doesn't apply:
|
||||
*.proc/procname
|
||||
*
|
||||
* `CALLBACK(src, .proc/some_proc_here)`
|
||||
*
|
||||
*
|
||||
* proc defined on a parent of a some type
|
||||
*
|
||||
* `/some/type/.proc/some_proc_here`
|
||||
*
|
||||
* Otherwise you must always provide the full typepath of the proc (/type/of/thing/proc/procname)
|
||||
*/
|
||||
/datum/callback
|
||||
|
||||
///The object we will be calling the proc on
|
||||
@@ -60,13 +60,13 @@
|
||||
var/datum/weakref/user
|
||||
|
||||
/**
|
||||
* Create a new callback datum
|
||||
*
|
||||
* Arguments
|
||||
* * thingtocall the object to call the proc on
|
||||
* * proctocall the proc to call on the target object
|
||||
* * ... an optional list of extra arguments to pass to the proc
|
||||
*/
|
||||
* Create a new callback datum
|
||||
*
|
||||
* Arguments
|
||||
* * thingtocall the object to call the proc on
|
||||
* * proctocall the proc to call on the target object
|
||||
* * ... an optional list of extra arguments to pass to the proc
|
||||
*/
|
||||
/datum/callback/New(thingtocall, proctocall, ...)
|
||||
if (thingtocall)
|
||||
object = thingtocall
|
||||
@@ -76,13 +76,13 @@
|
||||
if(usr)
|
||||
user = WEAKREF(usr)
|
||||
/**
|
||||
* Immediately Invoke proctocall on thingtocall, with waitfor set to false
|
||||
*
|
||||
* Arguments:
|
||||
* * thingtocall Object to call on
|
||||
* * proctocall Proc to call on that object
|
||||
* * ... optional list of arguments to pass as arguments to the proc being called
|
||||
*/
|
||||
* Immediately Invoke proctocall on thingtocall, with waitfor set to false
|
||||
*
|
||||
* Arguments:
|
||||
* * thingtocall Object to call on
|
||||
* * proctocall Proc to call on that object
|
||||
* * ... optional list of arguments to pass as arguments to the proc being called
|
||||
*/
|
||||
/world/proc/ImmediateInvokeAsync(thingtocall, proctocall, ...)
|
||||
set waitfor = FALSE
|
||||
|
||||
@@ -97,13 +97,13 @@
|
||||
call(thingtocall, proctocall)(arglist(calling_arguments))
|
||||
|
||||
/**
|
||||
* Invoke this callback
|
||||
*
|
||||
* Calls the registered proc on the registered object, if the user ref
|
||||
* can be resolved it also inclues that as an arg
|
||||
*
|
||||
* If the datum being called on is varedited, the call is wrapped via WrapAdminProcCall
|
||||
*/
|
||||
* Invoke this callback
|
||||
*
|
||||
* Calls the registered proc on the registered object, if the user ref
|
||||
* can be resolved it also inclues that as an arg
|
||||
*
|
||||
* If the datum being called on is varedited, the call is wrapped via [WrapAdminProcCall][/proc/WrapAdminProcCall]
|
||||
*/
|
||||
/datum/callback/proc/Invoke(...)
|
||||
if(!usr)
|
||||
var/datum/weakref/W = user
|
||||
@@ -130,13 +130,13 @@
|
||||
return call(object, delegate)(arglist(calling_arguments))
|
||||
|
||||
/**
|
||||
* Invoke this callback async (waitfor=false)
|
||||
*
|
||||
* Calls the registered proc on the registered object, if the user ref
|
||||
* can be resolved it also inclues that as an arg
|
||||
*
|
||||
* If the datum being called on is varedited, the call is wrapped via WrapAdminProcCall
|
||||
*/
|
||||
* Invoke this callback async (waitfor=false)
|
||||
*
|
||||
* Calls the registered proc on the registered object, if the user ref
|
||||
* can be resolved it also inclues that as an arg
|
||||
*
|
||||
* If the datum being called on is varedited, the call is wrapped via WrapAdminProcCall
|
||||
*/
|
||||
/datum/callback/proc/InvokeAsync(...)
|
||||
set waitfor = FALSE
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
|
||||
/**
|
||||
Helper datum for the select callbacks proc
|
||||
*/
|
||||
*/
|
||||
/datum/callback_select
|
||||
var/list/finished
|
||||
var/pendingcount
|
||||
@@ -192,16 +192,16 @@
|
||||
finished[index] = rtn
|
||||
|
||||
/**
|
||||
* Runs a list of callbacks asyncronously, returning only when all have finished
|
||||
*
|
||||
* Callbacks can be repeated, to call it multiple times
|
||||
*
|
||||
* Arguments:
|
||||
* * list/callbacks the list of callbacks to be called
|
||||
* * list/callback_args the list of lists of arguments to pass into each callback
|
||||
* * savereturns Optionally save and return the list of returned values from each of the callbacks
|
||||
* * resolution The number of byond ticks between each time you check if all callbacks are complete
|
||||
*/
|
||||
* Runs a list of callbacks asyncronously, returning only when all have finished
|
||||
*
|
||||
* Callbacks can be repeated, to call it multiple times
|
||||
*
|
||||
* Arguments:
|
||||
* * list/callbacks the list of callbacks to be called
|
||||
* * list/callback_args the list of lists of arguments to pass into each callback
|
||||
* * savereturns Optionally save and return the list of returned values from each of the callbacks
|
||||
* * resolution The number of byond ticks between each time you check if all callbacks are complete
|
||||
*/
|
||||
/proc/callback_select(list/callbacks, list/callback_args, savereturns = TRUE, resolution = 1)
|
||||
if (!callbacks)
|
||||
return
|
||||
|
||||
@@ -10,25 +10,37 @@
|
||||
*/
|
||||
|
||||
/datum/component/material_container
|
||||
/// The total amount of materials this material container contains
|
||||
var/total_amount = 0
|
||||
/// The maximum amount of materials this material container can contain
|
||||
var/max_amount
|
||||
var/sheet_type
|
||||
/// Map of material ref -> amount
|
||||
var/list/materials //Map of key = material ref | Value = amount
|
||||
/// The list of materials that this material container can accept
|
||||
var/list/allowed_materials
|
||||
var/show_on_examine
|
||||
var/disable_attackby
|
||||
var/list/allowed_typecache
|
||||
/// The last main material that was inserted into this container
|
||||
var/last_inserted_id
|
||||
/// Whether or not this material container allows specific amounts from sheets to be inserted
|
||||
var/precise_insertion = FALSE
|
||||
/// A callback invoked before materials are inserted into this container
|
||||
var/datum/callback/precondition
|
||||
/// A callback invoked after materials are inserted into this container
|
||||
var/datum/callback/after_insert
|
||||
|
||||
/// Sets up the proper signals and fills the list of materials with the appropriate references.
|
||||
/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _show_on_examine = FALSE, list/allowed_types, datum/callback/_precondition, datum/callback/_after_insert, _disable_attackby)
|
||||
if(!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
materials = list()
|
||||
max_amount = max(0, max_amt)
|
||||
show_on_examine = _show_on_examine
|
||||
disable_attackby = _disable_attackby
|
||||
|
||||
allowed_materials = mat_list || list()
|
||||
if(allowed_types)
|
||||
if(ispath(allowed_types) && allowed_types == /obj/item/stack)
|
||||
allowed_typecache = GLOB.typecache_stack
|
||||
@@ -38,14 +50,32 @@
|
||||
precondition = _precondition
|
||||
after_insert = _after_insert
|
||||
|
||||
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy)
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/OnExamine)
|
||||
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/on_attackby)
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
|
||||
|
||||
for(var/mat in mat_list) //Make the assoc list ref | amount
|
||||
var/datum/material/M = SSmaterials.GetMaterialRef(mat)
|
||||
materials[M] = 0
|
||||
for(var/mat in mat_list) //Make the assoc list material reference -> amount
|
||||
var/mat_ref = SSmaterials.GetMaterialRef(mat)
|
||||
if(isnull(mat_ref))
|
||||
continue
|
||||
var/mat_amt = mat_list[mat]
|
||||
if(isnull(mat_amt))
|
||||
mat_amt = 0
|
||||
materials[mat_ref] += mat_amt
|
||||
|
||||
/datum/component/material_container/Destroy(force, silent)
|
||||
materials = null
|
||||
allowed_typecache = null
|
||||
// if(insertion_check)
|
||||
// QDEL_NULL(insertion_check)
|
||||
if(precondition)
|
||||
QDEL_NULL(precondition)
|
||||
if(after_insert)
|
||||
QDEL_NULL(after_insert)
|
||||
return ..()
|
||||
|
||||
/datum/component/material_container/proc/on_examine(datum/source, mob/user, list/examine_list)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
/datum/component/material_container/proc/OnExamine(datum/source, mob/user, list/examine_list)
|
||||
if(show_on_examine)
|
||||
for(var/I in materials)
|
||||
var/datum/material/M = I
|
||||
@@ -54,7 +84,9 @@
|
||||
examine_list += "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>"
|
||||
|
||||
/// Proc that allows players to fill the parent with mats
|
||||
/datum/component/material_container/proc/OnAttackBy(datum/source, obj/item/I, mob/living/user)
|
||||
/datum/component/material_container/proc/on_attackby(datum/source, obj/item/I, mob/living/user)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/list/tc = allowed_typecache
|
||||
if(disable_attackby)
|
||||
return
|
||||
@@ -63,20 +95,21 @@
|
||||
if(I.item_flags & ABSTRACT)
|
||||
return
|
||||
if((I.flags_1 & HOLOGRAM_1) || (I.item_flags & NO_MAT_REDEMPTION) || (tc && !is_type_in_typecache(I, tc)))
|
||||
// if(!(mat_container_flags & MATCONTAINER_SILENT))
|
||||
to_chat(user, "<span class='warning'>[parent] won't accept [I]!</span>")
|
||||
return
|
||||
. = COMPONENT_NO_AFTERATTACK
|
||||
var/datum/callback/pc = precondition
|
||||
if(pc && !pc.Invoke(user))
|
||||
return
|
||||
var/material_amount = get_item_material_amount(I)
|
||||
var/material_amount = get_item_material_amount(I) //, mat_container_flags)
|
||||
if(!material_amount)
|
||||
to_chat(user, "<span class='warning'>[I] does not contain sufficient materials to be accepted by [parent].</span>")
|
||||
return
|
||||
if((!precise_insertion || !GLOB.typecache_stack[I.type]) && !has_space(material_amount))
|
||||
to_chat(user, "<span class='warning'>[parent] has not enough space. Please remove materials from [parent] in order to insert more.</span>")
|
||||
to_chat(user, "<span class='warning'>[parent] is full. Please remove materials from [parent] in order to insert more.</span>")
|
||||
return
|
||||
user_insert(I, user)
|
||||
user_insert(I, user) //, mat_container_flags)
|
||||
|
||||
/// Proc used for when player inserts materials
|
||||
/datum/component/material_container/proc/user_insert(obj/item/I, mob/living/user)
|
||||
@@ -94,7 +127,7 @@
|
||||
if(!user.temporarilyRemoveItemFromInventory(I))
|
||||
to_chat(user, "<span class='warning'>[I] is stuck to you and cannot be placed into [parent].</span>")
|
||||
return
|
||||
var/inserted = insert_item(I, stack_amt = requested_amount)
|
||||
var/inserted = insert_item(I, stack_amt = requested_amount)//, breakdown_flags= mat_container_flags)
|
||||
if(inserted)
|
||||
to_chat(user, "<span class='notice'>You insert a material total of [inserted] into [parent].</span>")
|
||||
qdel(I)
|
||||
@@ -117,16 +150,46 @@
|
||||
last_inserted_id = insert_item_materials(I, multiplier)
|
||||
return material_amount
|
||||
|
||||
/**
|
||||
* Inserts the relevant materials from an item into this material container.
|
||||
*
|
||||
* Arguments:
|
||||
* - [source][/obj/item]: The source of the materials we are inserting.
|
||||
* - multiplier: The multiplier for the materials being inserted.
|
||||
* - breakdown_flags: The breakdown bitflags that will be used to retrieve the materials from the source
|
||||
*/
|
||||
/datum/component/material_container/proc/insert_item_materials(obj/item/I, multiplier = 1)
|
||||
var/primary_mat
|
||||
var/max_mat_value = 0
|
||||
for(var/MAT in materials)
|
||||
materials[MAT] += I.custom_materials[MAT] * multiplier
|
||||
total_amount += I.custom_materials[MAT] * multiplier
|
||||
if(I.custom_materials[MAT] > max_mat_value)
|
||||
var/list/item_materials = I.custom_materials
|
||||
for(var/MAT in item_materials)
|
||||
if(!can_hold_material(MAT))
|
||||
continue
|
||||
materials[MAT] += item_materials[MAT] * multiplier
|
||||
total_amount += item_materials[MAT] * multiplier
|
||||
if(item_materials[MAT] > max_mat_value)
|
||||
max_mat_value = item_materials[MAT]
|
||||
primary_mat = MAT
|
||||
|
||||
return primary_mat
|
||||
|
||||
/**
|
||||
* The default check for whether we can add materials to this material container.
|
||||
*
|
||||
* Arguments:
|
||||
* - [mat][/atom/material]: The material we are checking for insertability.
|
||||
*/
|
||||
/datum/component/material_container/proc/can_hold_material(datum/material/mat)
|
||||
if(mat in allowed_typecache)
|
||||
return TRUE
|
||||
if(istype(mat) && (((mat.id in allowed_typecache) ||mat.type in allowed_materials)))
|
||||
allowed_materials += mat // This could get messy with passing lists by ref... but if you're doing that the list expansion is probably being taken care of elsewhere anyway...
|
||||
return TRUE
|
||||
// if(insertion_check?.Invoke(mat))
|
||||
// allowed_materials += mat
|
||||
// return TRUE
|
||||
return FALSE
|
||||
|
||||
/// For inserting an amount of material
|
||||
/datum/component/material_container/proc/insert_amount_mat(amt, var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
/*! Material datum
|
||||
|
||||
Simple datum which is instanced once per type and is used for every object of said material. It has a variety of variables that define behavior. Subtyping from this makes it easier to create your own materials.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/datum/material
|
||||
/// What the material is referred to as IC.
|
||||
var/name = "material"
|
||||
/// A short description of the material. Not used anywhere, yet...
|
||||
var/desc = "its..stuff."
|
||||
/// What the material is indexed by in the SSmaterials.materials list. Defaults to the type of the material.
|
||||
var/id
|
||||
|
||||
///Base color of the material, is used for greyscale. Item isn't changed in color if this is null.
|
||||
var/color
|
||||
///Base alpha of the material, is used for greyscale icons.
|
||||
var/alpha
|
||||
///Bitflags that influence how SSmaterials handles this material.
|
||||
// var/init_flags = MATERIAL_INIT_MAPLOAD
|
||||
///Materials "Traits". its a map of key = category | Value = Bool. Used to define what it can be used for
|
||||
var/list/categories = list()
|
||||
///The type of sheet this material creates. This should be replaced as soon as possible by greyscale sheets
|
||||
@@ -22,7 +31,7 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
var/value_per_unit = 0
|
||||
///Armor modifiers, multiplies an items normal armor vars by these amounts.
|
||||
var/armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1, "acid" = 1)
|
||||
///How beautiful is this material per unit?
|
||||
///How beautiful is this material per unit.
|
||||
var/beauty_modifier = 0
|
||||
///Can be used to override the sound items make, lets add some SLOSHing.
|
||||
var/item_sound_override
|
||||
@@ -30,14 +39,31 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
var/turf_sound_override
|
||||
///what texture icon state to overlay
|
||||
var/texture_layer_icon_state
|
||||
///a cached filter for the texture icon
|
||||
///a cached icon for the texture filter
|
||||
var/cached_texture_filter
|
||||
///What type of shard the material will shatter to
|
||||
var/obj/item/shard_type
|
||||
|
||||
|
||||
/** Handles initializing the material.
|
||||
*
|
||||
* Arugments:
|
||||
* - _id: The ID the material should use. Overrides the existing ID.
|
||||
*/
|
||||
/datum/material/proc/Initialize(_id, ...)
|
||||
if(_id)
|
||||
id = _id
|
||||
else if(isnull(id))
|
||||
id = type
|
||||
|
||||
if(texture_layer_icon_state)
|
||||
cached_texture_filter = icon('icons/materials/composite.dmi', texture_layer_icon_state)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/material/New()
|
||||
. = ..()
|
||||
if(texture_layer_icon_state)
|
||||
var/texture_icon = icon('icons/materials/composite.dmi', texture_layer_icon_state)
|
||||
cached_texture_filter = filter(type="layer", icon=texture_icon, blend_mode = BLEND_INSET_OVERLAY)
|
||||
Initialize()
|
||||
|
||||
///This proc is called when the material is added to an object.
|
||||
/datum/material/proc/on_applied(atom/source, amount, material_flags)
|
||||
@@ -48,8 +74,10 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
source.alpha = alpha
|
||||
if(texture_layer_icon_state)
|
||||
ADD_KEEP_TOGETHER(source, MATERIAL_SOURCE(src))
|
||||
source.filters += cached_texture_filter
|
||||
source.add_filter("material_texture_[name]",1,layering_filter(icon=cached_texture_filter,blend_mode=BLEND_INSET_OVERLAY))
|
||||
|
||||
if(alpha < 255)
|
||||
source.opacity = FALSE
|
||||
if(material_flags & MATERIAL_ADD_PREFIX)
|
||||
source.name = "[name] [source.name]"
|
||||
|
||||
@@ -59,7 +87,7 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
if(istype(source, /obj)) //objs
|
||||
on_applied_obj(source, amount, material_flags)
|
||||
|
||||
else if(isturf(source, /turf)) //turfs
|
||||
if(istype(source, /turf)) //turfs
|
||||
on_applied_turf(source, amount, material_flags)
|
||||
|
||||
source.mat_update_desc(src)
|
||||
@@ -67,8 +95,9 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
///This proc is called when a material updates an object's description
|
||||
/atom/proc/mat_update_desc(/datum/material/mat)
|
||||
return
|
||||
|
||||
///This proc is called when the material is added to an object specifically.
|
||||
/datum/material/proc/on_applied_obj(var/obj/o, amount, material_flags)
|
||||
/datum/material/proc/on_applied_obj(obj/o, amount, material_flags)
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/new_max_integrity = CEILING(o.max_integrity * integrity_modifier, 1)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
@@ -92,43 +121,73 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
I.hitsound = item_sound_override
|
||||
I.usesound = item_sound_override
|
||||
I.throwhitsound = item_sound_override
|
||||
// I.mob_throw_hit_sound = item_sound_override
|
||||
// I.equip_sound = item_sound_override
|
||||
// I.pickup_sound = item_sound_override
|
||||
// I.drop_sound = item_sound_override
|
||||
|
||||
/datum/material/proc/on_applied_turf(var/turf/T, amount, material_flags)
|
||||
/datum/material/proc/on_applied_turf(turf/T, amount, material_flags)
|
||||
if(isopenturf(T))
|
||||
if(!turf_sound_override)
|
||||
return
|
||||
var/turf/open/O = T
|
||||
O.footstep = turf_sound_override
|
||||
O.barefootstep = turf_sound_override
|
||||
O.clawfootstep = turf_sound_override
|
||||
O.heavyfootstep = turf_sound_override
|
||||
if(turf_sound_override)
|
||||
var/turf/open/O = T
|
||||
O.footstep = turf_sound_override
|
||||
O.barefootstep = turf_sound_override
|
||||
O.clawfootstep = turf_sound_override
|
||||
O.heavyfootstep = turf_sound_override
|
||||
// if(alpha < 255)
|
||||
// T.AddElement(/datum/element/turf_z_transparency, TRUE)
|
||||
return
|
||||
|
||||
///This proc is called when the material is removed from an object.
|
||||
/datum/material/proc/on_removed(atom/source, material_flags)
|
||||
/datum/material/proc/on_removed(atom/source, amount, material_flags)
|
||||
if(material_flags & MATERIAL_COLOR) //Prevent changing things with pre-set colors, to keep colored toolboxes their looks for example
|
||||
if(color)
|
||||
source.remove_atom_colour(FIXED_COLOUR_PRIORITY, color)
|
||||
source.alpha = initial(source.alpha)
|
||||
if(texture_layer_icon_state)
|
||||
source.filters -= cached_texture_filter
|
||||
source.remove_filter("material_texture_[name]")
|
||||
REMOVE_KEEP_TOGETHER(source, MATERIAL_SOURCE(src))
|
||||
source.alpha = initial(source.alpha)
|
||||
|
||||
if(material_flags & MATERIAL_ADD_PREFIX)
|
||||
source.name = initial(source.name)
|
||||
|
||||
if(istype(source, /obj)) //objs
|
||||
on_removed_obj(source, material_flags)
|
||||
if(beauty_modifier) //component/beauty/InheritComponent() will handle the removal.
|
||||
addtimer(CALLBACK(source, /datum.proc/_AddElement, list(/datum/element/beauty, -beauty_modifier * amount)), 0)
|
||||
|
||||
else if(istype(source, /turf)) //turfs
|
||||
on_removed_turf(source, material_flags)
|
||||
if(istype(source, /obj)) //objs
|
||||
on_removed_obj(source, amount, material_flags)
|
||||
|
||||
if(istype(source, /turf)) //turfs
|
||||
on_removed_turf(source, amount, material_flags)
|
||||
|
||||
///This proc is called when the material is removed from an object specifically.
|
||||
/datum/material/proc/on_removed_obj(obj/o, material_flags)
|
||||
/datum/material/proc/on_removed_obj(obj/o, amount, material_flags)
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/new_max_integrity = initial(o.max_integrity)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force = initial(o.force)
|
||||
o.throwforce = initial(o.throwforce)
|
||||
|
||||
/datum/material/proc/on_removed_turf(turf/T, material_flags)
|
||||
return
|
||||
/datum/material/proc/on_removed_turf(turf/T, amount, material_flags)
|
||||
// if(alpha)
|
||||
// RemoveElement(/datum/element/turf_z_transparency, FALSE)
|
||||
|
||||
/**
|
||||
* This proc is called when the mat is found in an item that's consumed by accident. see /obj/item/proc/on_accidental_consumption.
|
||||
* Arguments
|
||||
* * M - person consuming the mat
|
||||
* * S - (optional) item the mat is contained in (NOT the item with the mat itself)
|
||||
*/
|
||||
/datum/material/proc/on_accidental_mat_consumption(mob/living/carbon/M, obj/item/S)
|
||||
return FALSE
|
||||
|
||||
/** Returns the composition of this material.
|
||||
*
|
||||
* Mostly used for alloys when breaking down materials.
|
||||
*
|
||||
* Arguments:
|
||||
* - amount: The amount of the material to break down.
|
||||
* - breakdown_flags: Some flags dictating how exactly this material is being broken down.
|
||||
*/
|
||||
/datum/material/proc/return_composition(amount=1, breakdown_flags=NONE)
|
||||
return list((src) = amount) // Yes we need the parenthesis, without them BYOND stringifies src into "src" and things break.
|
||||
|
||||
+5
-1
@@ -1214,6 +1214,10 @@
|
||||
filter_data -= name
|
||||
update_filters()
|
||||
|
||||
/atom/proc/clear_filters()
|
||||
filter_data = null
|
||||
filters = null
|
||||
|
||||
/atom/proc/intercept_zImpact(atom/movable/AM, levels = 1)
|
||||
. |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, AM, levels)
|
||||
|
||||
@@ -1222,7 +1226,7 @@
|
||||
if(custom_materials) //Only runs if custom materials existed at first. Should usually be the case but check anyways
|
||||
for(var/i in custom_materials)
|
||||
var/datum/material/custom_material = SSmaterials.GetMaterialRef(i)
|
||||
custom_material.on_removed(src, material_flags) //Remove the current materials
|
||||
custom_material.on_removed(src, custom_materials[i], material_flags) //Remove the current materials
|
||||
|
||||
if(!length(materials))
|
||||
custom_materials = null
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
grind_results = list(/datum/reagent/cellulose = 10)
|
||||
var/value = 0
|
||||
|
||||
/obj/item/stack/spacecash/Initialize()
|
||||
/obj/item/stack/spacecash/Initialize(mapload, new_amount, merge = TRUE)
|
||||
. = ..()
|
||||
update_desc()
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
|
||||
material_type = /datum/material/glass
|
||||
point_value = 1
|
||||
tableVariant = /obj/structure/table/glass
|
||||
matter_amount = 4
|
||||
cost = 500
|
||||
shard_type = /obj/item/shard
|
||||
|
||||
/obj/item/stack/sheet/glass/suicide_act(mob/living/carbon/user)
|
||||
@@ -69,12 +71,13 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
|
||||
if (get_amount() < 1 || CC.get_amount() < 5)
|
||||
to_chat(user, "<span class='warning>You need five lengths of coil and one sheet of glass to make wired glass!</span>")
|
||||
return
|
||||
CC.use_tool(src, user, 0, 5, skill_gain_mult = TRIVIAL_USE_TOOL_MULT)
|
||||
CC.use(5)
|
||||
use(1)
|
||||
to_chat(user, "<span class='notice'>You attach wire to the [name].</span>")
|
||||
var/obj/item/stack/light_w/new_tile = new(user.loc)
|
||||
new_tile.add_fingerprint(user)
|
||||
else if(istype(W, /obj/item/stack/rods))
|
||||
return
|
||||
if(istype(W, /obj/item/stack/rods))
|
||||
var/obj/item/stack/rods/V = W
|
||||
if (V.get_amount() >= 1 && get_amount() >= 1)
|
||||
var/obj/item/stack/sheet/rglass/RG = new (get_turf(user))
|
||||
@@ -86,9 +89,8 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
|
||||
user.put_in_hands(RG)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need one rod and one sheet of glass to make reinforced glass!</span>")
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
@@ -164,6 +166,7 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \
|
||||
merge_type = /obj/item/stack/sheet/rglass
|
||||
grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/iron = 10)
|
||||
point_value = 4
|
||||
matter_amount = 6
|
||||
shard_type = /obj/item/shard
|
||||
|
||||
/obj/item/stack/sheet/rglass/attackby(obj/item/W, mob/user, params)
|
||||
@@ -211,6 +214,7 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \
|
||||
merge_type = /obj/item/stack/sheet/plasmarglass
|
||||
grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/toxin/plasma = 10, /datum/reagent/iron = 10)
|
||||
point_value = 23
|
||||
matter_amount = 8
|
||||
shard_type = /obj/item/shard/plasma
|
||||
|
||||
/obj/item/stack/sheet/plasmarglass/get_main_recipes()
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
///What type of wall does this sheet spawn
|
||||
var/walltype
|
||||
|
||||
/obj/item/stack/sheet/Initialize(mapload, new_amount, merge)
|
||||
/obj/item/stack/sheet/Initialize(mapload, new_amount, merge = TRUE)
|
||||
. = ..()
|
||||
pixel_x = rand(-4, 4)
|
||||
pixel_y = rand(-4, 4)
|
||||
|
||||
@@ -42,6 +42,11 @@
|
||||
var/matter_amount = 0
|
||||
|
||||
/obj/item/stack/Initialize(mapload, new_amount, merge = TRUE)
|
||||
//do this first, lazily inflate the value
|
||||
if(LAZYLEN(custom_materials))
|
||||
for(var/i in custom_materials)
|
||||
custom_materials[i] *= amount
|
||||
|
||||
if(new_amount != null)
|
||||
amount = new_amount
|
||||
while(amount > max_amount)
|
||||
@@ -88,7 +93,13 @@
|
||||
/** Updates the custom materials list of this stack.
|
||||
*/
|
||||
/obj/item/stack/proc/update_custom_materials()
|
||||
set_custom_materials(mats_per_unit, amount)
|
||||
set_custom_materials(mats_per_unit, amount, is_update=TRUE)
|
||||
|
||||
/**
|
||||
* Override to make things like metalgen accurately set custom materials
|
||||
*/
|
||||
/obj/item/stack/set_custom_materials(list/materials, multiplier=1, is_update=FALSE)
|
||||
return is_update ? ..() : set_mats_per_unit(materials, multiplier / (amount || 1))
|
||||
|
||||
/obj/item/stack/on_grind()
|
||||
. = ..()
|
||||
@@ -297,50 +308,55 @@
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/item/stack/proc/building_checks(datum/stack_recipe/R, multiplier)
|
||||
if (get_amount() < R.req_amount*multiplier)
|
||||
if (R.req_amount*multiplier>1)
|
||||
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [R.req_amount*multiplier] [R.title]\s!</span>")
|
||||
/obj/item/stack/proc/building_checks(datum/stack_recipe/recipe, multiplier)
|
||||
if (get_amount() < recipe.req_amount*multiplier)
|
||||
if (recipe.req_amount*multiplier>1)
|
||||
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [recipe.req_amount*multiplier] [recipe.title]\s!</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [R.title]!</span>")
|
||||
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [recipe.title]!</span>")
|
||||
return FALSE
|
||||
var/turf/T = get_turf(usr)
|
||||
var/turf/dest_turf = get_turf(usr)
|
||||
|
||||
var/obj/D = R.result_type
|
||||
if(R.window_checks && !valid_window_location(T, initial(D.dir) == FULLTILE_WINDOW_DIR ? FULLTILE_WINDOW_DIR : usr.dir))
|
||||
to_chat(usr, "<span class='warning'>The [R.title] won't fit here!</span>")
|
||||
return FALSE
|
||||
if(R.one_per_turf && (locate(R.result_type) in T))
|
||||
to_chat(usr, "<span class='warning'>There is another [R.title] here!</span>")
|
||||
return FALSE
|
||||
if(R.on_floor)
|
||||
if(!isfloorturf(T))
|
||||
to_chat(usr, "<span class='warning'>\The [R.title] must be constructed on the floor!</span>")
|
||||
// If we're making a window, we have some special snowflake window checks to do.
|
||||
if(ispath(recipe.result_type, /obj/structure/window))
|
||||
var/obj/structure/window/result_path = recipe.result_type
|
||||
if(!valid_window_location(dest_turf, usr.dir, is_fulltile = initial(result_path.fulltile)))
|
||||
to_chat(usr, "<span class='warning'>The [recipe.title] won't fit here!</span>")
|
||||
return FALSE
|
||||
for(var/obj/AM in T)
|
||||
if(istype(AM,/obj/structure/grille))
|
||||
|
||||
if(recipe.one_per_turf && (locate(recipe.result_type) in dest_turf))
|
||||
to_chat(usr, "<span class='warning'>There is another [recipe.title] here!</span>")
|
||||
return FALSE
|
||||
|
||||
if(recipe.on_floor)
|
||||
if(!isfloorturf(dest_turf))
|
||||
to_chat(usr, "<span class='warning'>\The [recipe.title] must be constructed on the floor!</span>")
|
||||
return FALSE
|
||||
|
||||
for(var/obj/object in dest_turf)
|
||||
if(istype(object, /obj/structure/grille))
|
||||
continue
|
||||
if(istype(AM,/obj/structure/table))
|
||||
if(istype(object, /obj/structure/table))
|
||||
continue
|
||||
if(istype(AM,/obj/structure/window))
|
||||
var/obj/structure/window/W = AM
|
||||
if(!W.fulltile)
|
||||
if(istype(object, /obj/structure/window))
|
||||
var/obj/structure/window/window_structure = object
|
||||
if(!window_structure.fulltile)
|
||||
continue
|
||||
if(AM.density)
|
||||
to_chat(usr, "<span class='warning'>Theres a [AM.name] here. You cant make a [R.title] here!</span>")
|
||||
if(object.density)
|
||||
to_chat(usr, "<span class='warning'>There is \a [object.name] here. You cant make \a [recipe.title] here!</span>")
|
||||
return FALSE
|
||||
if(R.placement_checks)
|
||||
switch(R.placement_checks)
|
||||
if(recipe.placement_checks)
|
||||
switch(recipe.placement_checks)
|
||||
if(STACK_CHECK_CARDINALS)
|
||||
var/turf/step
|
||||
for(var/direction in GLOB.cardinals)
|
||||
step = get_step(T, direction)
|
||||
if(locate(R.result_type) in step)
|
||||
to_chat(usr, "<span class='warning'>\The [R.title] must not be built directly adjacent to another!</span>")
|
||||
step = get_step(dest_turf, direction)
|
||||
if(locate(recipe.result_type) in step)
|
||||
to_chat(usr, "<span class='warning'>\The [recipe.title] must not be built directly adjacent to another!</span>")
|
||||
return FALSE
|
||||
if(STACK_CHECK_ADJACENT)
|
||||
if(locate(R.result_type) in range(1, T))
|
||||
to_chat(usr, "<span class='warning'>\The [R.title] must be constructed at least one tile away from others of its type!</span>")
|
||||
if(locate(recipe.result_type) in range(1, dest_turf))
|
||||
to_chat(usr, "<span class='warning'>\The [recipe.title] must be constructed at least one tile away from others of its type!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -513,15 +529,12 @@
|
||||
var/time = 0
|
||||
var/one_per_turf = FALSE
|
||||
var/on_floor = FALSE
|
||||
var/window_checks = FALSE
|
||||
var/placement_checks = FALSE
|
||||
var/applies_mats = FALSE
|
||||
var/trait_booster = null
|
||||
var/trait_modifier = 1
|
||||
|
||||
/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1,time = 0, one_per_turf = FALSE, on_floor = FALSE, window_checks = FALSE, placement_checks = FALSE, applies_mats = FALSE, trait_booster = null, trait_modifier = 1)
|
||||
|
||||
|
||||
src.title = title
|
||||
src.result_type = result_type
|
||||
src.req_amount = req_amount
|
||||
@@ -530,7 +543,6 @@
|
||||
src.time = time
|
||||
src.one_per_turf = one_per_turf
|
||||
src.on_floor = on_floor
|
||||
src.window_checks = window_checks
|
||||
src.placement_checks = placement_checks
|
||||
src.applies_mats = applies_mats
|
||||
src.trait_booster = trait_booster
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/client/proc/callproc()
|
||||
set category = "Debug"
|
||||
set name = "Advanced ProcCall"
|
||||
@@ -21,7 +20,7 @@
|
||||
return
|
||||
target = value["value"]
|
||||
if(!istype(target))
|
||||
to_chat(usr, "<span class='danger'>Invalid target.</span>")
|
||||
to_chat(usr, "<span class='danger'>Invalid target.</span>", confidential = TRUE)
|
||||
return
|
||||
if("No")
|
||||
target = null
|
||||
@@ -41,12 +40,12 @@
|
||||
|
||||
if(targetselected)
|
||||
if(!hascall(target, procname))
|
||||
to_chat(usr, "<span class='warning'>Error: callproc(): type [target.type] has no [proctype] named [procpath].</span>")
|
||||
to_chat(usr, "<span class='warning'>Error: callproc(): type [target.type] has no [proctype] named [procpath].</span>", confidential = TRUE)
|
||||
return
|
||||
else
|
||||
procpath = "/[proctype]/[procname]"
|
||||
if(!text2path(procpath))
|
||||
to_chat(usr, "<span class='warning'>Error: callproc(): [procpath] does not exist.</span>")
|
||||
to_chat(usr, "<span class='warning'>Error: callproc(): [procpath] does not exist.</span>", confidential = TRUE)
|
||||
return
|
||||
|
||||
var/list/lst = get_callproc_args()
|
||||
@@ -55,24 +54,24 @@
|
||||
|
||||
if(targetselected)
|
||||
if(!target)
|
||||
to_chat(usr, "<font color='red'>Error: callproc(): owner of proc no longer exists.</font>")
|
||||
to_chat(usr, "<font color='red'>Error: callproc(): owner of proc no longer exists.</font>", confidential = TRUE)
|
||||
return
|
||||
var/msg = "[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
|
||||
log_admin(msg)
|
||||
message_admins(msg) //Proccall announce removed.
|
||||
message_admins(msg) //Proccall announce removed.
|
||||
admin_ticket_log(target, msg)
|
||||
returnval = WrapAdminProcCall(target, procname, lst) // Pass the lst as an argument list to the proc
|
||||
else
|
||||
//this currently has no hascall protection. wasn't able to get it working.
|
||||
log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
|
||||
message_admins("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") //Proccall announce removed.
|
||||
message_admins("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") //Proccall announce removed.
|
||||
returnval = WrapAdminProcCall(GLOBAL_PROC, procname, lst) // Pass the lst as an argument list to the proc
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Advanced ProcCall") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
if(get_retval)
|
||||
get_retval += returnval
|
||||
. = get_callproc_returnval(returnval, procname)
|
||||
if(.)
|
||||
to_chat(usr, .)
|
||||
to_chat(usr, ., confidential = TRUE)
|
||||
|
||||
GLOBAL_VAR(AdminProcCaller)
|
||||
GLOBAL_PROTECT(AdminProcCaller)
|
||||
@@ -84,34 +83,30 @@ GLOBAL_VAR(LastAdminCalledTarget)
|
||||
GLOBAL_PROTECT(LastAdminCalledTarget)
|
||||
GLOBAL_VAR(LastAdminCalledProc)
|
||||
GLOBAL_PROTECT(LastAdminCalledProc)
|
||||
GLOBAL_LIST_EMPTY(AdminProcCallSpamPrevention)
|
||||
GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
|
||||
/// Wrapper for proccalls where the datum is flagged as vareditted
|
||||
/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
|
||||
if(target != GLOBAL_PROC && procname == "Del")
|
||||
to_chat(usr, "<span class='warning'>Calling Del() is not allowed</span>")
|
||||
if(target && procname == "Del")
|
||||
to_chat(usr, "Calling Del() is not allowed", confidential = TRUE)
|
||||
return
|
||||
|
||||
if(target != GLOBAL_PROC && !target.CanProcCall(procname))
|
||||
to_chat(usr, "Proccall on [target.type]/proc/[procname] is disallowed!")
|
||||
to_chat(usr, "Proccall on [target.type]/proc/[procname] is disallowed!", confidential = TRUE)
|
||||
return
|
||||
var/current_caller = GLOB.AdminProcCaller
|
||||
var/ckey = usr ? usr.client.ckey : GLOB.AdminProcCaller
|
||||
if(!ckey)
|
||||
CRASH("WrapAdminProcCall with no ckey: [target] [procname] [english_list(arguments)]")
|
||||
|
||||
if(current_caller && current_caller != ckey)
|
||||
if(!GLOB.AdminProcCallSpamPrevention[ckey])
|
||||
to_chat(usr, "<span class='adminnotice'>Another set of admin called procs are still running, your proc will be run after theirs finish.</span>")
|
||||
GLOB.AdminProcCallSpamPrevention[ckey] = TRUE
|
||||
UNTIL(!GLOB.AdminProcCaller)
|
||||
to_chat(usr, "<span class='adminnotice'>Running your proc</span>")
|
||||
GLOB.AdminProcCallSpamPrevention -= ckey
|
||||
else
|
||||
UNTIL(!GLOB.AdminProcCaller)
|
||||
// hey kev i removed the sleep here because it blocks this proc
|
||||
to_chat(usr, "<span class='adminnotice'>Another set of admin called procs are still running. Try again later.</span>", confidential = TRUE)
|
||||
return
|
||||
|
||||
GLOB.LastAdminCalledProc = procname
|
||||
if(target != GLOBAL_PROC)
|
||||
GLOB.LastAdminCalledTargetRef = "[REF(target)]"
|
||||
GLOB.AdminProcCaller = ckey //if this runtimes, too bad for you
|
||||
GLOB.LastAdminCalledTargetRef = REF(target)
|
||||
GLOB.AdminProcCaller = ckey //if this runtimes, too bad for you
|
||||
++GLOB.AdminProcCallCount
|
||||
. = world.WrapAdminProcCall(target, procname, arguments)
|
||||
if(--GLOB.AdminProcCallCount == 0)
|
||||
@@ -120,11 +115,11 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
//adv proc call this, ya nerds
|
||||
/world/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
|
||||
if(target == GLOBAL_PROC)
|
||||
return call(text2path("/proc/[procname]"))(arglist(arguments))
|
||||
return call("/proc/[procname]")(arglist(arguments))
|
||||
else if(target != world)
|
||||
return call(target, procname)(arglist(arguments))
|
||||
else
|
||||
log_admin_private("[key_name(usr)] attempted to call world/proc/[procname] with arguments: [english_list(arguments)]")
|
||||
log_admin("[key_name(usr)] attempted to call world/proc/[procname] with arguments: [english_list(arguments)]")
|
||||
|
||||
/proc/IsAdminAdvancedProcCall()
|
||||
#ifdef TESTING
|
||||
@@ -145,17 +140,17 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
if(!procname)
|
||||
return
|
||||
if(!hascall(A,procname))
|
||||
to_chat(usr, "<span class='warning'>Error: callproc_datum(): type [A.type] has no proc named [procname].</span>")
|
||||
to_chat(usr, "<font color='red'>Error: callproc_datum(): type [A.type] has no proc named [procname].</font>", confidential = TRUE)
|
||||
return
|
||||
var/list/lst = get_callproc_args()
|
||||
if(!lst)
|
||||
return
|
||||
|
||||
if(!A || !IsValidSrc(A))
|
||||
to_chat(usr, "<span class='warning'>Error: callproc_datum(): owner of proc no longer exists.</span>")
|
||||
to_chat(usr, "<span class='warning'>Error: callproc_datum(): owner of proc no longer exists.</span>", confidential = TRUE)
|
||||
return
|
||||
log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
|
||||
var/msg = "[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
|
||||
log_admin(msg)
|
||||
message_admins(msg)
|
||||
admin_ticket_log(A, msg)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Atom ProcCall") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
@@ -163,7 +158,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
var/returnval = WrapAdminProcCall(A, procname, lst) // Pass the lst as an argument list to the proc
|
||||
. = get_callproc_returnval(returnval,procname)
|
||||
if(.)
|
||||
to_chat(usr, .)
|
||||
to_chat(usr, ., confidential = TRUE)
|
||||
|
||||
/client/proc/get_callproc_args()
|
||||
var/argnum = input("Number of arguments","Number:",0) as num|null
|
||||
@@ -188,7 +183,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
. = ""
|
||||
if(islist(returnval))
|
||||
var/list/returnedlist = returnval
|
||||
. = "<span class='notice'>"
|
||||
. = "<font color='blue'>"
|
||||
if(returnedlist.len)
|
||||
var/assoc_check = returnedlist[1]
|
||||
if(istext(assoc_check) && (returnedlist[assoc_check] != null))
|
||||
@@ -202,7 +197,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
. += "\n[elem]"
|
||||
else
|
||||
. = "[procname] returned an empty list"
|
||||
. += "</span>"
|
||||
. += "</font>"
|
||||
|
||||
else
|
||||
. = "<span class='notice'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</span>"
|
||||
. = "<font color='blue'>[procname] returned: [!isnull(returnval) ? html_encode(returnval) : "null"]</font>"
|
||||
|
||||
@@ -194,7 +194,6 @@
|
||||
can_min_release_pressure = (ONE_ATMOSPHERE / 30)
|
||||
prototype = TRUE
|
||||
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/proto/default/oxygen
|
||||
name = "prototype canister"
|
||||
desc = "A prototype canister for a prototype bike, what could go wrong?"
|
||||
@@ -209,7 +208,6 @@
|
||||
air_contents.copy_from(existing_mixture)
|
||||
else
|
||||
create_gas()
|
||||
|
||||
update_icon()
|
||||
|
||||
|
||||
|
||||
@@ -531,7 +531,7 @@ By design, d1 is the smallest direction and d2 is the highest
|
||||
user.visible_message("<span class='suicide'>[user] is strangling [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return(OXYLOSS)
|
||||
|
||||
/obj/item/stack/cable_coil/Initialize(mapload, new_amount = null)
|
||||
/obj/item/stack/cable_coil/Initialize(mapload, new_amount, merge = TRUE)
|
||||
. = ..()
|
||||
pixel_x = rand(-2,2)
|
||||
pixel_y = rand(-2,2)
|
||||
@@ -823,7 +823,7 @@ By design, d1 is the smallest direction and d2 is the highest
|
||||
/obj/item/stack/cable_coil/random
|
||||
color = "#ffffff"
|
||||
|
||||
/obj/item/stack/cable_coil/random/Initialize(mapload, new_amount = null, param_color = null)
|
||||
/obj/item/stack/cable_coil/random/Initialize(mapload, new_amount, merge = TRUE, param_color = null)
|
||||
. = ..()
|
||||
var/list/cable_colors = GLOB.cable_colors
|
||||
color = pick(cable_colors)
|
||||
@@ -835,12 +835,13 @@ By design, d1 is the smallest direction and d2 is the highest
|
||||
amount = null
|
||||
icon_state = "coil2"
|
||||
|
||||
/obj/item/stack/cable_coil/cut/Initialize(mapload)
|
||||
. = ..()
|
||||
/obj/item/stack/cable_coil/cut/Initialize(mapload, new_amount, merge = TRUE)
|
||||
// do random amount calls BEFORE we add the mats or else the code eats shit and dies
|
||||
if(!amount)
|
||||
amount = rand(1,2)
|
||||
pixel_x = rand(-2,2)
|
||||
pixel_y = rand(-2,2)
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/stack/cable_coil/cut/red
|
||||
@@ -869,7 +870,7 @@ By design, d1 is the smallest direction and d2 is the highest
|
||||
/obj/item/stack/cable_coil/cut/random
|
||||
color = "#ffffff"
|
||||
|
||||
/obj/item/stack/cable_coil/cut/random/Initialize(mapload, new_amount = null, param_color = null)
|
||||
/obj/item/stack/cable_coil/cut/random/Initialize(mapload, new_amount, merge = TRUE, param_color = null)
|
||||
. = ..()
|
||||
var/list/cable_colors = GLOB.cable_colors
|
||||
color = pick(cable_colors)
|
||||
|
||||
@@ -48,6 +48,7 @@ const taskDm = new Task('dm')
|
||||
.depends('tgui/public/tgui.html')
|
||||
.depends('tgui/public/*.bundle.*')
|
||||
.depends('tgui/public/*.chunk.*')
|
||||
.depends(process.platform === 'win32' ? 'byond-extools.*' : 'libbyond-extools.*')
|
||||
.depends('tgstation.dme')
|
||||
.provides('tgstation.dmb')
|
||||
.provides('tgstation.rsc')
|
||||
|
||||
@@ -70,7 +70,7 @@ while read f; do
|
||||
done < <(find . -type f -name '*.dm')
|
||||
if grep -P '^/[\w/]\S+\(.*(var/|, ?var/.*).*\)' code/**/*.dm; then
|
||||
echo "changed files contains proc argument starting with 'var'"
|
||||
st=1
|
||||
# st=1
|
||||
fi;
|
||||
if grep -i 'centcomm' code/**/*.dm; then
|
||||
echo "ERROR: Misspelling(s) of CENTCOM detected in code, please remove the extra M(s)."
|
||||
|
||||
@@ -7,6 +7,11 @@ mkdir ci_test/config
|
||||
#test config
|
||||
cp tools/ci/ci_config.txt ci_test/config/config.txt
|
||||
|
||||
#throw extools into ldd
|
||||
cp libbyond-extools.so ~/.byond/bin/libbyond-extools.so
|
||||
chmod +x ~/.byond/bin/libbyond-extools.so
|
||||
ldd ~/.byond/bin/libbyond-extools.so
|
||||
|
||||
cd ci_test
|
||||
DreamDaemon tgstation.dmb -close -trusted -verbose -params "log-directory=ci"
|
||||
cd ..
|
||||
|
||||
Reference in New Issue
Block a user