mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-09 07:48:55 +00:00
config©paste chang.
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
//config files
|
||||
#define CONFIG_GET(X) global.config.Get(/datum/config_entry/##X)
|
||||
#define CONFIG_SET(X, Y) global.config.Set(/datum/config_entry/##X, ##Y)
|
||||
#define CONFIG_GET_ENTRY(X) global.config.GetEntryDatum(/datum/config_entry/##X)
|
||||
|
||||
#define CONFIG_MAPS_FILE "maps.txt"
|
||||
|
||||
|
||||
@@ -14,13 +14,15 @@
|
||||
var/list/modes // allowed modes
|
||||
var/list/gamemode_cache
|
||||
var/list/votable_modes // votable modes
|
||||
// var/list/ic_filter_regex
|
||||
var/list/storyteller_cache
|
||||
var/list/mode_names
|
||||
var/list/mode_reports
|
||||
var/list/mode_false_report_weight
|
||||
|
||||
var/motd
|
||||
// var/policy
|
||||
|
||||
// var/static/regex/ic_filter_regex
|
||||
|
||||
/datum/controller/configuration/proc/admin_reload()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
@@ -50,6 +52,11 @@
|
||||
break
|
||||
loadmaplist(CONFIG_MAPS_FILE)
|
||||
LoadMOTD()
|
||||
// LoadPolicy()
|
||||
// LoadChatFilter()
|
||||
|
||||
if (Master)
|
||||
Master.OnConfigLoad()
|
||||
|
||||
/datum/controller/configuration/proc/full_wipe()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
@@ -105,9 +112,7 @@
|
||||
var/list/lines = world.file2list("[directory]/[filename]")
|
||||
var/list/_entries = entries
|
||||
var/list/postload_required = list()
|
||||
var/linenumber = 0
|
||||
for(var/L in lines)
|
||||
linenumber++
|
||||
L = trim(L)
|
||||
if(!L)
|
||||
continue
|
||||
@@ -135,7 +140,7 @@
|
||||
|
||||
if(entry == "$include")
|
||||
if(!value)
|
||||
log_config("LINE [linenumber]: Invalid $include directive: [value]")
|
||||
log_config("Warning: Invalid $include directive: [value]")
|
||||
else
|
||||
LoadEntries(value, stack)
|
||||
++.
|
||||
@@ -143,7 +148,7 @@
|
||||
|
||||
var/datum/config_entry/E = _entries[entry]
|
||||
if(!E)
|
||||
log_config("LINE [linenumber]: Unknown setting: '[entry]'")
|
||||
log_config("Unknown setting in configuration: '[entry]'")
|
||||
continue
|
||||
|
||||
if(lockthis)
|
||||
@@ -153,9 +158,9 @@
|
||||
var/datum/config_entry/new_ver = entries_by_type[E.deprecated_by]
|
||||
var/new_value = E.DeprecationUpdate(value)
|
||||
var/good_update = istext(new_value)
|
||||
log_config("LINE [linenumber]: [entry] is deprecated and will be removed soon. Migrate to [new_ver.name]![good_update ? " Suggested new value is: [new_value]" : ""]")
|
||||
log_config("Entry [entry] is deprecated and will be removed soon. Migrate to [new_ver.name]![good_update ? " Suggested new value is: [new_value]" : ""]")
|
||||
if(!warned_deprecated_configs)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, /proc/message_admins, "This server is using deprecated configuration settings. Please check the logs and update accordingly."), 0)
|
||||
DelayedMessageAdmins("This server is using deprecated configuration settings. Please check the logs and update accordingly.")
|
||||
warned_deprecated_configs = TRUE
|
||||
if(good_update)
|
||||
value = new_value
|
||||
@@ -163,12 +168,12 @@
|
||||
else
|
||||
warning("[new_ver.type] is deprecated but gave no proper return for DeprecationUpdate()")
|
||||
|
||||
var/validated = E.ValidateAndSet(value, TRUE)
|
||||
var/validated = E.ValidateAndSet(value)
|
||||
if(!validated)
|
||||
log_config("LINE [linenumber]: Failed to validate setting \"[value]\" for [entry]")
|
||||
log_config("Failed to validate setting \"[value]\" for [entry]")
|
||||
else
|
||||
if(E.modified && !E.dupes_allowed)
|
||||
log_config("LINE [linenumber]: Duplicate setting for [entry] ([value], [E.resident_file]) detected! Using latest.")
|
||||
log_config("Duplicate setting for [entry] ([value], [E.resident_file]) detected! Using latest.")
|
||||
if(E.postload_required)
|
||||
postload_required[E] = TRUE
|
||||
|
||||
@@ -196,13 +201,6 @@
|
||||
stat("[name]:", statclick)
|
||||
|
||||
/datum/controller/configuration/proc/Get(entry_type)
|
||||
var/datum/config_entry/E = GetEntryDatum(entry_type)
|
||||
if((E.protection & CONFIG_ENTRY_HIDDEN) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
|
||||
log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]")
|
||||
return
|
||||
return E.config_entry_value
|
||||
|
||||
/datum/controller/configuration/proc/GetEntryDatum(entry_type)
|
||||
var/datum/config_entry/E = entry_type
|
||||
var/entry_is_abstract = initial(E.abstract_type) == entry_type
|
||||
if(entry_is_abstract)
|
||||
@@ -210,7 +208,10 @@
|
||||
E = entries_by_type[entry_type]
|
||||
if(!E)
|
||||
CRASH("Missing config entry for [entry_type]!")
|
||||
return E
|
||||
if((E.protection & CONFIG_ENTRY_HIDDEN) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
|
||||
log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]")
|
||||
return
|
||||
return E.config_entry_value
|
||||
|
||||
/datum/controller/configuration/proc/Set(entry_type, new_val)
|
||||
var/datum/config_entry/E = entry_type
|
||||
@@ -236,7 +237,6 @@
|
||||
for(var/T in gamemode_cache)
|
||||
// I wish I didn't have to instance the game modes in order to look up
|
||||
// their information, but it is the only way (at least that I know of).
|
||||
// for future reference: just use initial() lol
|
||||
var/datum/game_mode/M = new T()
|
||||
|
||||
if(M.config_tag)
|
||||
@@ -258,7 +258,37 @@
|
||||
var/tm_info = GLOB.revdata.GetTestMergeInfo()
|
||||
if(motd || tm_info)
|
||||
motd = motd ? "[motd]<br>[tm_info]" : tm_info
|
||||
/*
|
||||
Policy file should be a json file with a single object.
|
||||
Value is raw html.
|
||||
|
||||
Possible keywords :
|
||||
Job titles / Assigned roles (ghost spawners for example) : Assistant , Captain , Ash Walker
|
||||
Mob types : /mob/living/simple_animal/hostile/carp
|
||||
Antagonist types : /datum/antagonist/highlander
|
||||
Species types : /datum/species/lizard
|
||||
special keywords defined in _DEFINES/admin.dm
|
||||
|
||||
Example config:
|
||||
{
|
||||
"Assistant" : "Don't kill everyone",
|
||||
"/datum/antagonist/highlander" : "<b>Kill everyone</b>",
|
||||
"Ash Walker" : "Kill all spacemans"
|
||||
}
|
||||
|
||||
*/
|
||||
/*
|
||||
/datum/controller/configuration/proc/LoadPolicy()
|
||||
policy = list()
|
||||
var/rawpolicy = file2text("[directory]/policy.json")
|
||||
if(rawpolicy)
|
||||
var/parsed = safe_json_decode(rawpolicy)
|
||||
if(!parsed)
|
||||
log_config("JSON parsing failure for policy.json")
|
||||
DelayedMessageAdmins("JSON parsing failure for policy.json")
|
||||
else
|
||||
policy = parsed
|
||||
*/
|
||||
/datum/controller/configuration/proc/loadmaplist(filename)
|
||||
log_config("Loading config file [filename]...")
|
||||
filename = "[directory]/[filename]"
|
||||
@@ -305,6 +335,8 @@
|
||||
currentmap.voteweight = text2num(data)
|
||||
if ("default","defaultmap")
|
||||
defaultmap = currentmap
|
||||
//if ("votable")
|
||||
// currentmap.votable = TRUE
|
||||
if ("endmap")
|
||||
LAZYINITLIST(maplist)
|
||||
maplist[currentmap.map_name] = currentmap
|
||||
@@ -326,6 +358,7 @@
|
||||
return new T
|
||||
return new /datum/game_mode/extended()
|
||||
|
||||
/// For dynamic.
|
||||
/datum/controller/configuration/proc/pick_storyteller(storyteller_name)
|
||||
for(var/T in storyteller_cache)
|
||||
var/datum/dynamic_storyteller/S = T
|
||||
@@ -334,6 +367,32 @@
|
||||
return T
|
||||
return /datum/dynamic_storyteller/classic
|
||||
|
||||
/// Same with this
|
||||
/datum/controller/configuration/proc/get_runnable_storytellers()
|
||||
var/list/datum/dynamic_storyteller/runnable_storytellers = new
|
||||
var/list/probabilities = Get(/datum/config_entry/keyed_list/storyteller_weight)
|
||||
var/list/repeated_mode_adjust = Get(/datum/config_entry/number_list/repeated_mode_adjust)
|
||||
var/list/min_player_counts = Get(/datum/config_entry/keyed_list/storyteller_min_players)
|
||||
for(var/T in storyteller_cache)
|
||||
var/datum/dynamic_storyteller/S = T
|
||||
var/config_tag = initial(S.config_tag)
|
||||
var/probability = (config_tag in probabilities) ? probabilities[config_tag] : initial(S.weight)
|
||||
var/min_players = (config_tag in min_player_counts) ? min_player_counts[config_tag] : initial(S.min_players)
|
||||
if(probability <= 0)
|
||||
continue
|
||||
if(length(GLOB.player_list) < min_players)
|
||||
continue
|
||||
if(SSpersistence.saved_storytellers.len == repeated_mode_adjust.len)
|
||||
var/name = initial(S.name)
|
||||
var/recent_round = min(SSpersistence.saved_storytellers.Find(name),3)
|
||||
var/adjustment = 0
|
||||
while(recent_round)
|
||||
adjustment += repeated_mode_adjust[recent_round]
|
||||
recent_round = SSpersistence.saved_modes.Find(name,recent_round+1,0)
|
||||
probability *= ((100-adjustment)/100)
|
||||
runnable_storytellers[S] = probability
|
||||
return runnable_storytellers
|
||||
|
||||
/datum/controller/configuration/proc/get_runnable_modes()
|
||||
var/list/datum/game_mode/runnable_modes = new
|
||||
var/list/probabilities = Get(/datum/config_entry/keyed_list/probability)
|
||||
@@ -367,32 +426,6 @@
|
||||
runnable_modes[M] = final_weight
|
||||
return runnable_modes
|
||||
|
||||
/datum/controller/configuration/proc/get_runnable_storytellers()
|
||||
var/list/datum/dynamic_storyteller/runnable_storytellers = new
|
||||
var/list/probabilities = Get(/datum/config_entry/keyed_list/storyteller_weight)
|
||||
var/list/repeated_mode_adjust = Get(/datum/config_entry/number_list/repeated_mode_adjust)
|
||||
var/list/min_player_counts = Get(/datum/config_entry/keyed_list/storyteller_min_players)
|
||||
for(var/T in storyteller_cache)
|
||||
var/datum/dynamic_storyteller/S = T
|
||||
var/config_tag = initial(S.config_tag)
|
||||
var/probability = (config_tag in probabilities) ? probabilities[config_tag] : initial(S.weight)
|
||||
var/min_players = (config_tag in min_player_counts) ? min_player_counts[config_tag] : initial(S.min_players)
|
||||
if(probability <= 0)
|
||||
continue
|
||||
if(length(GLOB.player_list) < min_players)
|
||||
continue
|
||||
if(SSpersistence.saved_storytellers.len == repeated_mode_adjust.len)
|
||||
var/name = initial(S.name)
|
||||
var/recent_round = min(SSpersistence.saved_storytellers.Find(name),3)
|
||||
var/adjustment = 0
|
||||
while(recent_round)
|
||||
adjustment += repeated_mode_adjust[recent_round]
|
||||
recent_round = SSpersistence.saved_modes.Find(name,recent_round+1,0)
|
||||
probability *= ((100-adjustment)/100)
|
||||
runnable_storytellers[S] = probability
|
||||
return runnable_storytellers
|
||||
|
||||
|
||||
/datum/controller/configuration/proc/get_runnable_midround_modes(crew)
|
||||
var/list/datum/game_mode/runnable_modes = new
|
||||
var/list/probabilities = Get(/datum/config_entry/keyed_list/probability)
|
||||
@@ -418,7 +451,6 @@
|
||||
/*
|
||||
/datum/controller/configuration/proc/LoadChatFilter()
|
||||
var/list/in_character_filter = list()
|
||||
|
||||
if(!fexists("[directory]/in_character_filter.txt"))
|
||||
return
|
||||
log_config("Loading config file in_character_filter.txt...")
|
||||
@@ -428,8 +460,8 @@
|
||||
if(findtextEx(line,"#",1,2))
|
||||
continue
|
||||
in_character_filter += REGEX_QUOTE(line)
|
||||
|
||||
ic_filter_regex = in_character_filter.len ? regex("\\b([jointext(in_character_filter, "|")])\\b", "i") : null
|
||||
|
||||
syncChatRegexes()
|
||||
*/
|
||||
//Message admins when you can.
|
||||
/datum/controller/configuration/proc/DelayedMessageAdmins(text)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, /proc/message_admins, text), 0)
|
||||
|
||||
@@ -16,4 +16,4 @@
|
||||
|
||||
/datum/controller/proc/Recover()
|
||||
|
||||
/datum/controller/proc/stat_entry()
|
||||
/datum/controller/proc/stat_entry()
|
||||
|
||||
@@ -76,7 +76,11 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
// Highlander-style: there can only be one! Kill off the old and replace it with the new.
|
||||
|
||||
if(!random_seed)
|
||||
random_seed = (TEST_RUN_PARAMETER in world.params) ? 29051994 : rand(1, 1e9)
|
||||
#ifdef UNIT_TESTS
|
||||
random_seed = 29051994
|
||||
#else
|
||||
random_seed = rand(1, 1e9)
|
||||
#endif
|
||||
rand_seed(random_seed)
|
||||
|
||||
var/list/_subsystems = list()
|
||||
@@ -184,9 +188,6 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
if(delay)
|
||||
sleep(delay)
|
||||
|
||||
if(tgs_prime)
|
||||
world.TgsInitializationComplete()
|
||||
|
||||
if(init_sss)
|
||||
init_subtypes(/datum/controller/subsystem, subsystems)
|
||||
|
||||
@@ -219,6 +220,9 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
world.fps = CONFIG_GET(number/fps)
|
||||
var/initialized_tod = REALTIMEOFDAY
|
||||
|
||||
if(tgs_prime)
|
||||
world.TgsInitializationComplete()
|
||||
|
||||
if(sleep_offline_after_initializations)
|
||||
world.sleep_offline = TRUE
|
||||
sleep(1)
|
||||
@@ -643,3 +647,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
processing = CONFIG_GET(number/mc_tick_rate/base_mc_tick_rate)
|
||||
else if (client_count > CONFIG_GET(number/mc_tick_rate/high_pop_mc_mode_amount))
|
||||
processing = CONFIG_GET(number/mc_tick_rate/high_pop_mc_tick_rate)
|
||||
|
||||
/datum/controller/master/proc/OnConfigLoad()
|
||||
for (var/thing in subsystems)
|
||||
var/datum/controller/subsystem/SS = thing
|
||||
SS.OnConfigLoad()
|
||||
|
||||
@@ -1,39 +1,91 @@
|
||||
/**
|
||||
* # Subsystem base class
|
||||
*
|
||||
* Defines a subsystem to be managed by the [Master Controller][/datum/controller/master]
|
||||
*
|
||||
* Simply define a child of this subsystem, using the [SUBSYSTEM_DEF] macro, and the MC will handle registration.
|
||||
* Changing the name is required
|
||||
**/
|
||||
|
||||
/datum/controller/subsystem
|
||||
// Metadata; you should define these.
|
||||
name = "fire coderbus" //name of the subsystem
|
||||
var/init_order = INIT_ORDER_DEFAULT //order of initialization. Higher numbers are initialized first, lower numbers later. Use defines in __DEFINES/subsystems.dm for easy understanding of order.
|
||||
var/wait = 20 //time to wait (in deciseconds) between each call to fire(). Must be a positive integer.
|
||||
var/priority = FIRE_PRIORITY_DEFAULT //When mutiple subsystems need to run in the same tick, higher priority subsystems will run first and be given a higher share of the tick before MC_TICK_CHECK triggers a sleep
|
||||
|
||||
var/flags = 0 //see MC.dm in __DEFINES Most flags must be set on world start to take full effect. (You can also restart the mc to force them to process again)
|
||||
/// Name of the subsystem - you must change this
|
||||
name = "fire coderbus"
|
||||
|
||||
var/initialized = FALSE //set to TRUE after it has been initialized, will obviously never be set if the subsystem doesn't initialize
|
||||
/// Order of initialization. Higher numbers are initialized first, lower numbers later. Use or create defines such as [INIT_ORDER_DEFAULT] so we can see the order in one file.
|
||||
var/init_order = INIT_ORDER_DEFAULT
|
||||
|
||||
//set to 0 to prevent fire() calls, mostly for admin use or subsystems that may be resumed later
|
||||
// use the SS_NO_FIRE flag instead for systems that never fire to keep it from even being added to the list
|
||||
/// Time to wait (in deciseconds) between each call to fire(). Must be a positive integer.
|
||||
var/wait = 20
|
||||
|
||||
/// Priority Weight: When mutiple subsystems need to run in the same tick, higher priority subsystems will be given a higher share of the tick before MC_TICK_CHECK triggers a sleep, higher priority subsystems also run before lower priority subsystems
|
||||
var/priority = FIRE_PRIORITY_DEFAULT
|
||||
|
||||
/// [Subsystem Flags][SS_NO_INIT] to control binary behavior. Flags must be set at compile time or before preinit finishes to take full effect. (You can also restart the mc to force them to process again)
|
||||
var/flags = 0
|
||||
|
||||
/// This var is set to TRUE after the subsystem has been initialized.
|
||||
var/initialized = FALSE
|
||||
|
||||
/// Set to 0 to prevent fire() calls, mostly for admin use or subsystems that may be resumed later
|
||||
/// use the [SS_NO_FIRE] flag instead for systems that never fire to keep it from even being added to list that is checked every tick
|
||||
var/can_fire = TRUE
|
||||
|
||||
// Bookkeeping variables; probably shouldn't mess with these.
|
||||
var/last_fire = 0 //last world.time we called fire()
|
||||
var/next_fire = 0 //scheduled world.time for next fire()
|
||||
var/cost = 0 //average time to execute
|
||||
var/tick_usage = 0 //average tick usage
|
||||
var/tick_overrun = 0 //average tick overrun
|
||||
var/state = SS_IDLE //tracks the current state of the ss, running, paused, etc.
|
||||
var/paused_ticks = 0 //ticks this ss is taking to run right now.
|
||||
var/paused_tick_usage //total tick_usage of all of our runs while pausing this run
|
||||
var/ticks = 1 //how many ticks does this ss take to run on avg.
|
||||
var/times_fired = 0 //number of times we have called fire()
|
||||
var/queued_time = 0 //time we entered the queue, (for timing and priority reasons)
|
||||
var/queued_priority //we keep a running total to make the math easier, if priority changes mid-fire that would break our running total, so we store it here
|
||||
//linked list stuff for the queue
|
||||
var/datum/controller/subsystem/queue_next
|
||||
var/datum/controller/subsystem/queue_prev
|
||||
|
||||
///Bitmap of what game states can this subsystem fire at. See [RUNLEVELS_DEFAULT] for more details.
|
||||
var/runlevels = RUNLEVELS_DEFAULT //points of the game at which the SS can fire
|
||||
|
||||
var/static/list/failure_strikes //How many times we suspect a subsystem type has crashed the MC, 3 strikes and you're out!
|
||||
/*
|
||||
* The following variables are managed by the MC and should not be modified directly.
|
||||
*/
|
||||
|
||||
/// Last world.time the subsystem completed a run (as in wasn't paused by [MC_TICK_CHECK])
|
||||
var/last_fire = 0
|
||||
|
||||
/// Scheduled world.time for next fire()
|
||||
var/next_fire = 0
|
||||
|
||||
/// Running average of the amount of milliseconds it takes the subsystem to complete a run (including all resumes but not the time spent paused)
|
||||
var/cost = 0
|
||||
|
||||
/// Running average of the amount of tick usage in percents of a tick it takes the subsystem to complete a run
|
||||
var/tick_usage = 0
|
||||
|
||||
/// Running average of the amount of tick usage (in percents of a game tick) the subsystem has spent past its allocated time without pausing
|
||||
var/tick_overrun = 0
|
||||
|
||||
/// Tracks the current execution state of the subsystem. Used to handle subsystems that sleep in fire so the mc doesn't run them again while they are sleeping
|
||||
var/state = SS_IDLE
|
||||
|
||||
/// Tracks how many fires the subsystem has consecutively paused on in the current run
|
||||
var/paused_ticks = 0
|
||||
|
||||
/// Tracks how much of a tick the subsystem has consumed in the current run
|
||||
var/paused_tick_usage
|
||||
|
||||
/// Tracks how many fires the subsystem takes to complete a run on average.
|
||||
var/ticks = 1
|
||||
|
||||
/// Tracks the amount of completed runs for the subsystem
|
||||
var/times_fired = 0
|
||||
|
||||
/// Time the subsystem entered the queue, (for timing and priority reasons)
|
||||
var/queued_time = 0
|
||||
|
||||
/// Priority at the time the subsystem entered the queue. Needed to avoid changes in priority (by admins and the like) from breaking things.
|
||||
var/queued_priority
|
||||
|
||||
/// How many times we suspect a subsystem type has crashed the MC, 3 strikes and you're out!
|
||||
var/static/list/failure_strikes
|
||||
|
||||
/// Next subsystem in the queue of subsystems to run this tick
|
||||
var/datum/controller/subsystem/queue_next
|
||||
/// Previous subsystem in the queue of subsystems to run this tick
|
||||
var/datum/controller/subsystem/queue_prev
|
||||
|
||||
//Do not blindly add vars here to the bottom, put it where it goes above
|
||||
//If your var only has two values, put it in as a flag.
|
||||
|
||||
|
||||
//Do not override
|
||||
///datum/controller/subsystem/New()
|
||||
@@ -46,6 +98,7 @@
|
||||
|
||||
//This is used so the mc knows when the subsystem sleeps. do not override.
|
||||
/datum/controller/subsystem/proc/ignite(resumed = 0)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
set waitfor = 0
|
||||
. = SS_SLEEPING
|
||||
fire(resumed)
|
||||
@@ -87,7 +140,7 @@
|
||||
queue_node_flags = queue_node.flags
|
||||
|
||||
if (queue_node_flags & SS_TICKER)
|
||||
if (!(SS_flags & SS_TICKER))
|
||||
if ((SS_flags & (SS_TICKER|SS_BACKGROUND)) != SS_TICKER)
|
||||
continue
|
||||
if (queue_node_priority < SS_priority)
|
||||
break
|
||||
@@ -155,6 +208,9 @@
|
||||
if(SS_SLEEPING)
|
||||
state = SS_PAUSING
|
||||
|
||||
/// Called after the config has been loaded or reloaded.
|
||||
/datum/controller/subsystem/proc/OnConfigLoad()
|
||||
|
||||
/datum/controller/subsystem/proc/subsystem_log(msg)
|
||||
return log_subsystem(name, msg)
|
||||
|
||||
@@ -164,7 +220,7 @@
|
||||
var/time = (REALTIMEOFDAY - start_timeofday) / 10
|
||||
var/msg = "Initialized [name] subsystem within [time] second[time == 1 ? "" : "s"]!"
|
||||
to_chat(world, "<span class='boldannounce'>[msg]</span>")
|
||||
log_subsystem("INIT", msg)
|
||||
log_world(msg)
|
||||
return time
|
||||
|
||||
//hook for printing stats to the "MC" statuspanel for admins to see performance and related stats etc.
|
||||
|
||||
@@ -353,7 +353,6 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
dat = list("<tt>", header.Join(), body, "<br></tt>")
|
||||
var/datum/browser/popup = new(user, "id_com", src.name, 900, 620)
|
||||
popup.set_content(dat.Join())
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/card/Topic(href, href_list)
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
#define STATE_DEFAULT 1
|
||||
#define STATE_CALLSHUTTLE 2
|
||||
#define STATE_CANCELSHUTTLE 3
|
||||
#define STATE_MESSAGELIST 4
|
||||
#define STATE_VIEWMESSAGE 5
|
||||
#define STATE_DELMESSAGE 6
|
||||
#define STATE_STATUSDISPLAY 7
|
||||
#define STATE_ALERT_LEVEL 8
|
||||
#define STATE_CONFIRM_LEVEL 9
|
||||
#define STATE_TOGGLE_EMERGENCY 10
|
||||
#define STATE_PURCHASE 11
|
||||
|
||||
// The communications computer
|
||||
/obj/machinery/computer/communications
|
||||
name = "communications console"
|
||||
@@ -6,6 +18,7 @@
|
||||
icon_keyboard = "tech_key"
|
||||
req_access = list(ACCESS_HEADS)
|
||||
circuit = /obj/item/circuitboard/computer/communications
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
var/auth_id = "Unknown" //Who is currently logged in?
|
||||
var/list/datum/comm_message/messages = list()
|
||||
var/datum/comm_message/currmsg
|
||||
@@ -16,22 +29,10 @@
|
||||
var/ai_message_cooldown = 0
|
||||
var/tmp_alertlevel = 0
|
||||
var/static/security_level_cd // used to stop mass spam.
|
||||
var/const/STATE_DEFAULT = 1
|
||||
var/const/STATE_CALLSHUTTLE = 2
|
||||
var/const/STATE_CANCELSHUTTLE = 3
|
||||
var/const/STATE_MESSAGELIST = 4
|
||||
var/const/STATE_VIEWMESSAGE = 5
|
||||
var/const/STATE_DELMESSAGE = 6
|
||||
var/const/STATE_STATUSDISPLAY = 7
|
||||
var/const/STATE_ALERT_LEVEL = 8
|
||||
var/const/STATE_CONFIRM_LEVEL = 9
|
||||
var/const/STATE_TOGGLE_EMERGENCY = 10
|
||||
var/const/STATE_PURCHASE = 11
|
||||
|
||||
var/stat_msg1
|
||||
var/stat_msg2
|
||||
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
/obj/machinery/computer/communications/proc/checkCCcooldown()
|
||||
var/obj/item/circuitboard/computer/communications/CM = circuit
|
||||
@@ -46,7 +47,7 @@
|
||||
/obj/machinery/computer/communications/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(!usr.canUseTopic(src))
|
||||
if(!usr.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
if(!is_station_level(z) && !is_reserved_level(z)) //Can only use in transit and on SS13
|
||||
to_chat(usr, "<span class='boldannounce'>Unable to establish a connection</span>: \black You're too far away from the station!")
|
||||
@@ -132,15 +133,20 @@
|
||||
|
||||
if("crossserver")
|
||||
if(authenticated==2)
|
||||
var/dest = href_list["cross_dest"]
|
||||
if(!checkCCcooldown())
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
|
||||
return
|
||||
var/input = stripped_multiline_input(usr, "Please choose a message to transmit to allied stations. Please be aware that this process is very expensive, and abuse will lead to... termination.", "Send a message to an allied station.", "")
|
||||
var/warning = dest == "all" ? "Please choose a message to transmit to allied stations." : "Please choose a message to transmit to [dest] sector station."
|
||||
var/input = stripped_multiline_input(usr, "[warning] Please be aware that this process is very expensive, and abuse will lead to... termination.", "Send a message to an allied station.", "")
|
||||
if(!input || !(usr in view(1,src)) || !checkCCcooldown())
|
||||
return
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
send2otherserver("[station_name()]", input,"Comms_Console")
|
||||
if(dest == "all")
|
||||
send2otherserver("[station_name()]", input,"Comms_Console")
|
||||
else
|
||||
send2otherserver("[station_name()]", input,"Comms_Console", list(dest))
|
||||
minor_announce(input, title = "Outgoing message to allied station")
|
||||
usr.log_talk(input, LOG_SAY, tag="message to the other server")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] has sent a message to the other server.")
|
||||
@@ -156,12 +162,12 @@
|
||||
var/datum/map_template/shuttle/S = locate(href_list["chosen_shuttle"]) in shuttles
|
||||
if(S && istype(S))
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_RECALL && SSshuttle.emergency.mode != SHUTTLE_IDLE)
|
||||
to_chat(usr, "It's a bit late to buy a new shuttle, don't you think?")
|
||||
to_chat(usr, "<span class='alert'>It's a bit late to buy a new shuttle, don't you think?</span>")
|
||||
return
|
||||
if(SSshuttle.shuttle_purchased)
|
||||
to_chat(usr, "A replacement shuttle has already been purchased.")
|
||||
to_chat(usr, "<span class='alert'>A replacement shuttle has already been purchased.</span>")
|
||||
else if(!S.prerequisites_met())
|
||||
to_chat(usr, "You have not met the requirements for purchasing this shuttle.")
|
||||
to_chat(usr, "<span class='alert'>You have not met the requirements for purchasing this shuttle.</span>")
|
||||
else
|
||||
var/points_to_check
|
||||
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
||||
@@ -183,7 +189,7 @@
|
||||
|
||||
if("callshuttle")
|
||||
state = STATE_DEFAULT
|
||||
if(authenticated)
|
||||
if(authenticated && SSshuttle.canEvac(usr))
|
||||
state = STATE_CALLSHUTTLE
|
||||
if("callshuttle2")
|
||||
if(authenticated)
|
||||
@@ -284,12 +290,12 @@
|
||||
if("MessageCentCom")
|
||||
if(authenticated)
|
||||
if(!checkCCcooldown())
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
return
|
||||
var/input = stripped_input(usr, "Please choose a message to transmit to CentCom via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "Send a message to CentCom.", "")
|
||||
if(!input || !(usr in view(1,src)) || !checkCCcooldown())
|
||||
return
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
CentCom_announce(input, usr)
|
||||
to_chat(usr, "<span class='notice'>Message transmitted to Central Command.</span>")
|
||||
for(var/client/X in GLOB.admins)
|
||||
@@ -302,7 +308,7 @@
|
||||
|
||||
// OMG SYNDICATE ...LETTERHEAD
|
||||
if("MessageSyndicate")
|
||||
if((authenticated==2) && (obj_flags & EMAGGED))
|
||||
if((authenticated) && (obj_flags & EMAGGED))
|
||||
if(!checkCCcooldown())
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
|
||||
@@ -332,7 +338,7 @@
|
||||
if(!checkCCcooldown())
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
return
|
||||
var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self Destruct Code Request.","")
|
||||
var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self-Destruct Code Request.","")
|
||||
if(!input || !(usr in view(1,src)) || !checkCCcooldown())
|
||||
return
|
||||
Nuke_request(input, usr)
|
||||
@@ -347,7 +353,9 @@
|
||||
aicurrmsg = null
|
||||
aistate = STATE_DEFAULT
|
||||
if("ai-callshuttle")
|
||||
aistate = STATE_CALLSHUTTLE
|
||||
aistate = STATE_DEFAULT
|
||||
if(SSshuttle.canEvac(usr))
|
||||
aistate = STATE_CALLSHUTTLE
|
||||
if("ai-callshuttle2")
|
||||
SSshuttle.requestEvac(usr, href_list["call"])
|
||||
aistate = STATE_DEFAULT
|
||||
@@ -461,7 +469,7 @@
|
||||
|
||||
var/datum/browser/popup = new(user, "communications", "Communications Console", 400, 500)
|
||||
|
||||
if(issilicon(user) || (hasSiliconAccessInArea(user) && !in_range(user,src)))
|
||||
if(issilicon(user))
|
||||
var/dat2 = interact_ai(user) // give the AI a different interact proc to limit its access
|
||||
if(dat2)
|
||||
dat += dat2
|
||||
@@ -492,9 +500,15 @@
|
||||
if (authenticated==2)
|
||||
dat += "<BR><BR><B>Captain Functions</B>"
|
||||
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=announce'>Make a Captain's Announcement</A> \]"
|
||||
var/cross_servers_count = length(CONFIG_GET(keyed_list/cross_server))
|
||||
if(cross_servers_count)
|
||||
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=crossserver'>Send a message to [cross_servers_count == 1 ? "an " : ""]allied station[cross_servers_count > 1 ? "s" : ""]</A> \]"
|
||||
var/list/cross_servers = CONFIG_GET(keyed_list/cross_server)
|
||||
var/our_id = CONFIG_GET(string/cross_comms_name)
|
||||
if(cross_servers.len)
|
||||
for(var/server in cross_servers)
|
||||
if(server == our_id)
|
||||
continue
|
||||
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=crossserver=all;cross_dest=[server]'>Send a message to station in [server] sector.</A> \]"
|
||||
if(cross_servers.len > 2)
|
||||
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=crossserver;cross_dest=all'>Send a message to all allied stations</A> \]"
|
||||
if(SSmapping.config.allow_custom_shuttles)
|
||||
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=purchase_menu'>Purchase Shuttle</A> \]"
|
||||
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=changeseclevel'>Change Alert Level</A> \]"
|
||||
@@ -720,8 +734,13 @@
|
||||
to_chat(user, "<span class='alert'>Intercomms recharging. Please stand by.</span>")
|
||||
return
|
||||
var/input = stripped_input(user, "Please choose a message to announce to the station crew.", "What?")
|
||||
if(!input || !user.canUseTopic(src))
|
||||
if(!input || !user.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
if(!(user.can_speak())) //No more cheating, mime/random mute guy!
|
||||
input = "..."
|
||||
to_chat(user, "<span class='warning'>You find yourself unable to speak.</span>")
|
||||
else
|
||||
input = user.treat_message(input) //Adds slurs and so on. Someone should make this use languages too.
|
||||
SScommunications.make_announcement(user, is_silicon, input)
|
||||
deadchat_broadcast("<span class='deadsay'><span class='name'>[user.real_name]</span> made an priority announcement from <span class='name'>[get_area_name(usr, TRUE)]</span>.</span>", user)
|
||||
|
||||
@@ -770,3 +789,15 @@
|
||||
content = new_content
|
||||
if(new_possible_answers)
|
||||
possible_answers = new_possible_answers
|
||||
|
||||
#undef STATE_DEFAULT
|
||||
#undef STATE_CALLSHUTTLE
|
||||
#undef STATE_CANCELSHUTTLE
|
||||
#undef STATE_MESSAGELIST
|
||||
#undef STATE_VIEWMESSAGE
|
||||
#undef STATE_DELMESSAGE
|
||||
#undef STATE_STATUSDISPLAY
|
||||
#undef STATE_ALERT_LEVEL
|
||||
#undef STATE_CONFIRM_LEVEL
|
||||
#undef STATE_TOGGLE_EMERGENCY
|
||||
#undef STATE_PURCHASE
|
||||
|
||||
@@ -234,7 +234,6 @@ RLD
|
||||
|
||||
var/datum/browser/popup = new(user, "rcd_access", "Access Control", 900, 500, src)
|
||||
popup.set_content(t1)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/item/construction/rcd/Topic(href, href_list)
|
||||
|
||||
@@ -334,8 +334,7 @@
|
||||
to_chat(C, "<span class='big warning'> You feel an overwhelming desire to [message]")
|
||||
if(2)
|
||||
visible_message("<b>[src]</b> waves their arms around, <span class='spooky'>\"If only you had a better upbringing, your ears are now full of my singing!\"</span>")
|
||||
var/client/C2 = C.client
|
||||
C.tgui_panel?.play_music("https://puu.sh/ExBbv.mp4")
|
||||
C.client.tgui_panel?.play_music("https://puu.sh/ExBbv.mp4")
|
||||
if(3)
|
||||
visible_message("<b>[src]</b> waves their arms around, <span class='spooky'>\"You're cute little bumpkin, On your head is a pumpkin!\"</span>")
|
||||
if(C.head)
|
||||
|
||||
@@ -82,7 +82,6 @@
|
||||
|
||||
var/datum/browser/popup = new(user, "instrument", parent?.name || "instrument", 700, 500)
|
||||
popup.set_content(dat.Join(""))
|
||||
popup.set_title_image(user.browse_rsc_icon(parent.icon, parent.icon_state))
|
||||
popup.open()
|
||||
|
||||
/datum/song/proc/ParseSong(text)
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
/mob/living/carbon/human/movement_delay()
|
||||
. = ..()
|
||||
if(CHECK_MOBILITY(src, MOBILITY_STAND) && m_intent == MOVE_INTENT_RUN && (combat_flags & COMBAT_FLAG_SPRINT_ACTIVE))
|
||||
var/static/datum/config_entry/number/movedelay/sprint_speed_increase/SSI
|
||||
var/static/SSI
|
||||
if(!SSI)
|
||||
SSI = CONFIG_GET_ENTRY(number/movedelay/sprint_speed_increase)
|
||||
. -= SSI.config_entry_value
|
||||
SSI = CONFIG_GET(number/movedelay/sprint_speed_increase)
|
||||
. -= SSI //but WHY
|
||||
if (m_intent == MOVE_INTENT_WALK && HAS_TRAIT(src, TRAIT_SPEEDY_STEP))
|
||||
. -= 1.5
|
||||
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
/* Photocopiers!
|
||||
* Contains:
|
||||
* Photocopier
|
||||
* Toner Cartridge
|
||||
*/
|
||||
|
||||
/*
|
||||
* Photocopier
|
||||
*/
|
||||
/// For use with the `color_mode` var. Photos will be printed in greyscale while the var has this value.
|
||||
#define PHOTO_GREYSCALE "Greyscale"
|
||||
/// For use with the `color_mode` var. Photos will be printed in full color while the var has this value.
|
||||
#define PHOTO_COLOR "Color"
|
||||
|
||||
/// How much toner is used for making a copy of a paper.
|
||||
#define PAPER_TONER_USE 0.125
|
||||
/// How much toner is used for making a copy of a photo.
|
||||
#define PHOTO_TONER_USE 0.625
|
||||
/// How much toner is used for making a copy of a document.
|
||||
#define DOCUMENT_TONER_USE 0.75
|
||||
/// How much toner is used for making a copy of an ass.
|
||||
#define ASS_TONER_USE 0.625
|
||||
/// The maximum amount of copies you can make with one press of the copy button.
|
||||
#define MAX_COPIES_AT_ONCE 10
|
||||
|
||||
/obj/machinery/photocopier
|
||||
name = "photocopier"
|
||||
desc = "Used to copy important documents and anatomy studies."
|
||||
@@ -19,183 +27,314 @@
|
||||
power_channel = EQUIP
|
||||
max_integrity = 300
|
||||
integrity_failure = 0.33
|
||||
var/obj/item/paper/copy = null //what's in the copier!
|
||||
var/obj/item/photo/photocopy = null
|
||||
var/obj/item/documents/doccopy = null
|
||||
var/copies = 1 //how many copies to print!
|
||||
var/toner = 40 //how much toner is left! woooooo~
|
||||
var/maxcopies = 10 //how many copies can be copied at once- idea shamelessly stolen from bs12's copier!
|
||||
var/greytoggle = "Greyscale"
|
||||
var/mob/living/ass //i can't believe i didn't write a stupid-ass comment about this var when i first coded asscopy.
|
||||
/// A reference to an `/obj/item/paper` inside the copier, if one is inserted. Otherwise null.
|
||||
var/obj/item/paper/paper_copy
|
||||
/// A reference to an `/obj/item/photo` inside the copier, if one is inserted. Otherwise null.
|
||||
var/obj/item/photo/photo_copy
|
||||
/// A reference to an `/obj/item/documents` inside the copier, if one is inserted. Otherwise null.
|
||||
var/obj/item/documents/document_copy
|
||||
/// A reference to a mob on top of the photocopier trying to copy their ass. Null if there is no mob.
|
||||
var/mob/living/ass
|
||||
/// A reference to the toner cartridge that's inserted into the copier. Null if there is no cartridge.
|
||||
var/obj/item/toner/toner_cartridge
|
||||
/// How many copies will be printed with one click of the "copy" button.
|
||||
var/num_copies = 1
|
||||
/// Used with photos. Determines if the copied photo will be in greyscale or color.
|
||||
var/color_mode = PHOTO_COLOR
|
||||
/// Indicates whether the printer is currently busy copying or not.
|
||||
var/busy = FALSE
|
||||
|
||||
/obj/machinery/photocopier/ui_interact(mob/user)
|
||||
/obj/machinery/photocopier/Initialize()
|
||||
. = ..()
|
||||
var/list/dat = list("Photocopier<BR><BR>")
|
||||
if(copy || photocopy || doccopy || (ass && (ass.loc == src.loc)))
|
||||
dat += "<a href='byond://?src=[REF(src)];remove=1'>Remove Paper</a><BR>"
|
||||
if(toner)
|
||||
dat += "<a href='byond://?src=[REF(src)];copy=1'>Copy</a><BR>"
|
||||
dat += "Printing: [copies] copies."
|
||||
dat += "<a href='byond://?src=[REF(src)];min=1'>-</a> "
|
||||
dat += "<a href='byond://?src=[REF(src)];add=1'>+</a><BR><BR>"
|
||||
if(photocopy)
|
||||
dat += "Printing in <a href='byond://?src=[REF(src)];colortoggle=1'>[greytoggle]</a><BR><BR>"
|
||||
else if(toner)
|
||||
dat += "Please insert paper to copy.<BR><BR>"
|
||||
if(isAI(user))
|
||||
dat += "<a href='byond://?src=[REF(src)];aipic=1'>Print photo from database</a><BR><BR>"
|
||||
dat += "Current toner level: [toner]"
|
||||
if(!toner)
|
||||
dat +="<BR>Please insert a new toner cartridge!"
|
||||
user << browse(dat.Join(""), "window=copier")
|
||||
onclose(user, "copier")
|
||||
//AddComponent(/datum/component/payment, 5, SSeconomy.get_dep_account(ACCOUNT_CIV), PAYMENT_CLINICAL)
|
||||
toner_cartridge = new(src)
|
||||
|
||||
/obj/machinery/photocopier/Topic(href, href_list)
|
||||
/obj/machinery/photocopier/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "Photocopier")
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/photocopier/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["has_item"] = !copier_empty()
|
||||
data["num_copies"] = num_copies
|
||||
|
||||
if(photo_copy)
|
||||
data["is_photo"] = TRUE
|
||||
data["color_mode"] = color_mode
|
||||
|
||||
if(isAI(user))
|
||||
data["isAI"] = TRUE
|
||||
data["can_AI_print"] = toner_cartridge ? toner_cartridge.charges >= PHOTO_TONER_USE : FALSE
|
||||
else
|
||||
data["isAI"] = FALSE
|
||||
|
||||
if(toner_cartridge)
|
||||
data["has_toner"] = TRUE
|
||||
data["current_toner"] = toner_cartridge.charges
|
||||
data["max_toner"] = toner_cartridge.max_charges
|
||||
data["has_enough_toner"] = has_enough_toner()
|
||||
else
|
||||
data["has_toner"] = FALSE
|
||||
data["has_enough_toner"] = FALSE
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/photocopier/ui_act(action, list/params)
|
||||
if(..())
|
||||
return
|
||||
if(href_list["copy"])
|
||||
if(copy)
|
||||
for(var/i = 0, i < copies, i++)
|
||||
if(toner > 0 && !busy && copy)
|
||||
var/copy_as_paper = 1
|
||||
if(istype(copy, /obj/item/paper/contract/employment))
|
||||
var/obj/item/paper/contract/employment/E = copy
|
||||
var/obj/item/paper/contract/employment/C = new /obj/item/paper/contract/employment (loc, E.target.current)
|
||||
if(C)
|
||||
copy_as_paper = 0
|
||||
if(copy_as_paper)
|
||||
var/obj/item/paper/c = new /obj/item/paper (loc)
|
||||
if(length(copy.info) > 0) //Only print and add content if the copied doc has words on it
|
||||
if(toner > 10) //lots of toner, make it dark
|
||||
c.info = "<font color = #101010>"
|
||||
else //no toner? shitty copies for you!
|
||||
c.info = "<font color = #808080>"
|
||||
var/copied = copy.info
|
||||
copied = replacetext(copied, "<font face=\"[PEN_FONT]\" color=", "<font face=\"[PEN_FONT]\" nocolor=") //state of the art techniques in action
|
||||
copied = replacetext(copied, "<font face=\"[CRAYON_FONT]\" color=", "<font face=\"[CRAYON_FONT]\" nocolor=") //This basically just breaks the existing color tag, which we need to do because the innermost tag takes priority.
|
||||
c.info += copied
|
||||
c.info += "</font>"
|
||||
c.name = copy.name
|
||||
c.update_icon()
|
||||
c.stamps = copy.stamps
|
||||
if(copy.stamped)
|
||||
c.stamped = copy.stamped.Copy()
|
||||
c.copy_overlays(copy, TRUE)
|
||||
toner--
|
||||
busy = TRUE
|
||||
addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS)
|
||||
else
|
||||
break
|
||||
updateUsrDialog()
|
||||
else if(photocopy)
|
||||
for(var/i = 0, i < copies, i++)
|
||||
if(toner >= 5 && !busy && photocopy) //Was set to = 0, but if there was say 3 toner left and this ran, you would get -2 which would be weird for ink
|
||||
new /obj/item/photo (loc, photocopy.picture.Copy(greytoggle == "Greyscale"? TRUE : FALSE))
|
||||
busy = TRUE
|
||||
addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS)
|
||||
else
|
||||
break
|
||||
else if(doccopy)
|
||||
for(var/i = 0, i < copies, i++)
|
||||
if(toner > 5 && !busy && doccopy)
|
||||
new /obj/item/documents/photocopy(loc, doccopy)
|
||||
toner-= 6 // the sprite shows 6 papers, yes I checked
|
||||
busy = TRUE
|
||||
addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS)
|
||||
else
|
||||
break
|
||||
updateUsrDialog()
|
||||
else if(ass) //ASS COPY. By Miauw
|
||||
for(var/i = 0, i < copies, i++)
|
||||
var/icon/temp_img
|
||||
if(ishuman(ass) && (ass.get_item_by_slot(ITEM_SLOT_ICLOTHING) || ass.get_item_by_slot(ITEM_SLOT_OCLOTHING)))
|
||||
to_chat(usr, "<span class='notice'>You feel kind of silly, copying [ass == usr ? "your" : ass][ass == usr ? "" : "\'s"] ass with [ass == usr ? "your" : "[ass.p_their()]"] clothes on.</span>" )
|
||||
break
|
||||
else if(toner >= 5 && !busy && check_ass()) //You have to be sitting on the copier and either be a xeno or a human without clothes on.
|
||||
if(isalienadult(ass) || istype(ass, /mob/living/simple_animal/hostile/alien)) //Xenos have their own asses, thanks to Pybro.
|
||||
temp_img = icon('icons/ass/assalien.png')
|
||||
else if(ishuman(ass)) //Suit checks are in check_ass
|
||||
temp_img = icon(ass.gender == FEMALE ? 'icons/ass/assfemale.png' : 'icons/ass/assmale.png')
|
||||
else if(isdrone(ass)) //Drones are hot
|
||||
temp_img = icon('icons/ass/assdrone.png')
|
||||
else
|
||||
break
|
||||
busy = TRUE
|
||||
sleep(15)
|
||||
var/obj/item/photo/p = new /obj/item/photo (loc)
|
||||
var/datum/picture/toEmbed = new(name = "[ass]'s Ass", desc = "You see [ass]'s ass on the photo.", image = temp_img)
|
||||
p.pixel_x = rand(-10, 10)
|
||||
p.pixel_y = rand(-10, 10)
|
||||
toEmbed.psize_x = 128
|
||||
toEmbed.psize_y = 128
|
||||
p.set_picture(toEmbed, TRUE, TRUE)
|
||||
toner -= 5
|
||||
busy = FALSE
|
||||
else
|
||||
break
|
||||
updateUsrDialog()
|
||||
else if(href_list["remove"])
|
||||
if(copy)
|
||||
remove_photocopy(copy, usr)
|
||||
copy = null
|
||||
else if(photocopy)
|
||||
remove_photocopy(photocopy, usr)
|
||||
photocopy = null
|
||||
else if(doccopy)
|
||||
remove_photocopy(doccopy, usr)
|
||||
doccopy = null
|
||||
else if(check_ass())
|
||||
to_chat(ass, "<span class='notice'>You feel a slight pressure on your ass.</span>")
|
||||
updateUsrDialog()
|
||||
else if(href_list["min"])
|
||||
if(copies > 1)
|
||||
copies--
|
||||
updateUsrDialog()
|
||||
else if(href_list["add"])
|
||||
if(copies < maxcopies)
|
||||
copies++
|
||||
updateUsrDialog()
|
||||
else if(href_list["aipic"])
|
||||
if(!isAI(usr))
|
||||
return
|
||||
if(toner >= 5 && !busy)
|
||||
|
||||
switch(action)
|
||||
// Copying paper, photos, documents and asses.
|
||||
if("make_copy")
|
||||
if(busy)
|
||||
to_chat(usr, "<span class='warning'>[src] is currently busy copying something. Please wait until it is finished.</span>")
|
||||
return FALSE
|
||||
if(paper_copy)
|
||||
if(!length(paper_copy.info))
|
||||
to_chat(usr, "<span class='warning'>An error message flashes across [src]'s screen: \"The supplied paper is blank. Aborting.\"</span>")
|
||||
return FALSE
|
||||
// Basic paper
|
||||
if(istype(paper_copy, /obj/item/paper))
|
||||
do_copy_loop(CALLBACK(src, .proc/make_paper_copy), usr)
|
||||
return TRUE
|
||||
// Devil contract paper.
|
||||
if(istype(paper_copy, /obj/item/paper/contract/employment))
|
||||
do_copy_loop(CALLBACK(src, .proc/make_devil_paper_copy), usr)
|
||||
return TRUE
|
||||
// Copying photo.
|
||||
if(photo_copy)
|
||||
do_copy_loop(CALLBACK(src, .proc/make_photo_copy), usr)
|
||||
return TRUE
|
||||
// Copying Documents.
|
||||
if(document_copy)
|
||||
do_copy_loop(CALLBACK(src, .proc/make_document_copy), usr)
|
||||
return TRUE
|
||||
// ASS COPY. By Miauw
|
||||
if(ass)
|
||||
do_copy_loop(CALLBACK(src, .proc/make_ass_copy), usr)
|
||||
return TRUE
|
||||
|
||||
// Remove the paper/photo/document from the photocopier.
|
||||
if("remove")
|
||||
if(paper_copy)
|
||||
remove_photocopy(paper_copy, usr)
|
||||
paper_copy = null
|
||||
else if(photo_copy)
|
||||
remove_photocopy(photo_copy, usr)
|
||||
photo_copy = null
|
||||
else if(document_copy)
|
||||
remove_photocopy(document_copy, usr)
|
||||
document_copy = null
|
||||
else if(check_ass())
|
||||
to_chat(ass, "<span class='notice'>You feel a slight pressure on your ass.</span>")
|
||||
return TRUE
|
||||
|
||||
// AI printing photos from their saved images.
|
||||
if("ai_photo")
|
||||
if(busy)
|
||||
to_chat(usr, "<span class='warning'>[src] is currently busy copying something. Please wait until it is finished.</span>")
|
||||
return FALSE
|
||||
var/mob/living/silicon/ai/tempAI = usr
|
||||
if(tempAI.aicamera.stored.len == 0)
|
||||
to_chat(usr, "<span class='boldannounce'>No images saved</span>")
|
||||
if(!length(tempAI.aicamera.stored))
|
||||
to_chat(usr, "<span class='boldannounce'>No images saved.</span>")
|
||||
return
|
||||
var/datum/picture/selection = tempAI.aicamera.selectpicture(usr)
|
||||
var/obj/item/photo/photo = new(loc, selection)
|
||||
photo.pixel_x = rand(-10, 10)
|
||||
photo.pixel_y = rand(-10, 10)
|
||||
toner -= 5 //AI prints color pictures only, thus they can do it more efficiently
|
||||
busy = TRUE
|
||||
addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS)
|
||||
updateUsrDialog()
|
||||
else if(href_list["colortoggle"])
|
||||
if(greytoggle == "Greyscale")
|
||||
greytoggle = "Color"
|
||||
else
|
||||
greytoggle = "Greyscale"
|
||||
updateUsrDialog()
|
||||
var/obj/item/photo/photo = new(loc, selection) // AI prints color photos only.
|
||||
give_pixel_offset(photo)
|
||||
toner_cartridge.charges -= PHOTO_TONER_USE
|
||||
return TRUE
|
||||
|
||||
// Switch between greyscale and color photos
|
||||
if("color_mode")
|
||||
if(params["mode"] in list(PHOTO_GREYSCALE, PHOTO_COLOR))
|
||||
color_mode = params["mode"]
|
||||
return TRUE
|
||||
|
||||
// Remove the toner cartridge from the copier.
|
||||
if("remove_toner")
|
||||
if(issilicon(usr) || (ishuman(usr) && !usr.put_in_hands(toner_cartridge)))
|
||||
toner_cartridge.forceMove(drop_location())
|
||||
toner_cartridge = null
|
||||
return TRUE
|
||||
|
||||
// Set the number of copies to be printed with 1 click of the "copy" button.
|
||||
if("set_copies")
|
||||
num_copies = clamp(text2num(params["num_copies"]), 1, MAX_COPIES_AT_ONCE)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Determines if the photocopier has enough toner to create `num_copies` amount of copies of the currently inserted item.
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/has_enough_toner()
|
||||
if(paper_copy)
|
||||
return toner_cartridge.charges >= (PAPER_TONER_USE * num_copies)
|
||||
else if(document_copy)
|
||||
return toner_cartridge.charges >= (DOCUMENT_TONER_USE * num_copies)
|
||||
else if(photo_copy)
|
||||
return toner_cartridge.charges >= (PHOTO_TONER_USE * num_copies)
|
||||
else if(ass)
|
||||
return toner_cartridge.charges >= (ASS_TONER_USE * num_copies)
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Will invoke the passed in `copy_cb` callback in 1 second intervals, and charge the user 5 credits for each copy made.
|
||||
*
|
||||
* Arguments:
|
||||
* * copy_cb - a callback for which proc to call. Should only be one of the `make_x_copy()` procs, such as `make_paper_copy()`.
|
||||
* * user - the mob who clicked copy.
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/do_copy_loop(datum/callback/copy_cb, mob/user)
|
||||
busy = TRUE
|
||||
var/i
|
||||
for(i in 1 to num_copies)
|
||||
//if(attempt_charge(src, user) & COMPONENT_OBJ_CANCEL_CHARGE)
|
||||
// break
|
||||
addtimer(copy_cb, i SECONDS)
|
||||
addtimer(CALLBACK(src, .proc/reset_busy), i SECONDS)
|
||||
|
||||
/**
|
||||
* Sets busy to `FALSE`. Created as a proc so it can be used in callbacks.
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/reset_busy()
|
||||
busy = FALSE
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/photocopier/proc/do_insertion(obj/item/O, mob/user)
|
||||
O.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You insert [O] into [src].</span>")
|
||||
/**
|
||||
* Gives items a random x and y pixel offset, between -10 and 10 for each.
|
||||
*
|
||||
* This is done that when someone prints multiple papers, we dont have them all appear to be stacked in the same exact location.
|
||||
*
|
||||
* Arguments:
|
||||
* * copied_item - The paper, document, or photo that was just spawned on top of the printer.
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/give_pixel_offset(obj/item/copied_item)
|
||||
copied_item.pixel_x = rand(-10, 10)
|
||||
copied_item.pixel_y = rand(-10, 10)
|
||||
|
||||
/**
|
||||
* Handles the copying of devil contract paper. Transfers all the text, stamps and so on from the old paper, to the copy.
|
||||
*
|
||||
* Checks first if `paper_copy` exists. Since this proc is called from a timer, it's possible that it was removed.
|
||||
* Does not check if it has enough toner because devil contracts cost no toner to print.
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/make_devil_paper_copy()
|
||||
if(!paper_copy)
|
||||
return
|
||||
var/obj/item/paper/contract/employment/E = paper_copy
|
||||
var/obj/item/paper/contract/employment/C = new(loc, E.target.current)
|
||||
give_pixel_offset(C)
|
||||
|
||||
/**
|
||||
* Handles the copying of paper. Transfers all the text, stamps and so on from the old paper, to the copy.
|
||||
*
|
||||
* Checks first if `paper_copy` exists. Since this proc is called from a timer, it's possible that it was removed.
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/make_paper_copy()
|
||||
if(!paper_copy)
|
||||
return
|
||||
var/obj/item/paper/copied_paper = new(loc)
|
||||
give_pixel_offset(copied_paper)
|
||||
if(toner_cartridge.charges > 10) // Lots of toner, make it dark.
|
||||
copied_paper.info = "<font color = #101010>"
|
||||
else // No toner? shitty copies for you!
|
||||
copied_paper.info = "<font color = #808080>"
|
||||
|
||||
var/copied_info = paper_copy.info
|
||||
copied_info = replacetext(copied_info, "<font face=\"[PEN_FONT]\" color=", "<font face=\"[PEN_FONT]\" nocolor=") //state of the art techniques in action
|
||||
copied_info = replacetext(copied_info, "<font face=\"[CRAYON_FONT]\" color=", "<font face=\"[CRAYON_FONT]\" nocolor=") //This basically just breaks the existing color tag, which we need to do because the innermost tag takes priority.
|
||||
copied_paper.info += copied_info
|
||||
copied_paper.info += "</font>"
|
||||
copied_paper.name = paper_copy.name
|
||||
copied_paper.update_icon()
|
||||
copied_paper.stamps = paper_copy.stamps
|
||||
if(paper_copy.stamped)
|
||||
copied_paper.stamped = paper_copy.stamped.Copy()
|
||||
copied_paper.copy_overlays(paper_copy, TRUE)
|
||||
toner_cartridge.charges -= PAPER_TONER_USE
|
||||
|
||||
/**
|
||||
* Handles the copying of photos, which can be printed in either color or greyscale.
|
||||
*
|
||||
* Checks first if `photo_copy` exists. Since this proc is called from a timer, it's possible that it was removed.
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/make_photo_copy()
|
||||
if(!photo_copy)
|
||||
return
|
||||
var/obj/item/photo/copied_pic = new(loc, photo_copy.picture.Copy(color_mode == PHOTO_GREYSCALE ? TRUE : FALSE))
|
||||
give_pixel_offset(copied_pic)
|
||||
toner_cartridge.charges -= PHOTO_TONER_USE
|
||||
|
||||
/**
|
||||
* Handles the copying of documents.
|
||||
*
|
||||
* Checks first if `document_copy` exists. Since this proc is called from a timer, it's possible that it was removed.
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/make_document_copy()
|
||||
if(!document_copy)
|
||||
return
|
||||
var/obj/item/documents/photocopy/copied_doc = new(loc, document_copy)
|
||||
give_pixel_offset(copied_doc)
|
||||
toner_cartridge.charges -= DOCUMENT_TONER_USE
|
||||
|
||||
/**
|
||||
* Handles the copying of an ass photo.
|
||||
*
|
||||
* Calls `check_ass()` first to make sure that `ass` exists, among other conditions. Since this proc is called from a timer, it's possible that it was removed.
|
||||
* Additionally checks that the mob has their clothes off.
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/make_ass_copy()
|
||||
if(!check_ass())
|
||||
return
|
||||
if(ishuman(ass) && (ass.get_item_by_slot(ITEM_SLOT_ICLOTHING) || ass.get_item_by_slot(ITEM_SLOT_OCLOTHING)))
|
||||
to_chat(usr, "<span class='notice'>You feel kind of silly, copying [ass == usr ? "your" : ass][ass == usr ? "" : "\'s"] ass with [ass == usr ? "your" : "[ass.p_their()]"] clothes on.</span>" )
|
||||
return
|
||||
|
||||
var/icon/temp_img
|
||||
if(isalienadult(ass) || istype(ass, /mob/living/simple_animal/hostile/alien)) //Xenos have their own asses, thanks to Pybro.
|
||||
temp_img = icon('icons/ass/assalien.png')
|
||||
else if(ishuman(ass)) //Suit checks are in check_ass
|
||||
temp_img = icon(ass.gender == FEMALE ? 'icons/ass/assfemale.png' : 'icons/ass/assmale.png')
|
||||
else if(isdrone(ass)) //Drones are hot
|
||||
temp_img = icon('icons/ass/assdrone.png')
|
||||
|
||||
var/obj/item/photo/copied_ass = new /obj/item/photo(loc)
|
||||
var/datum/picture/toEmbed = new(name = "[ass]'s Ass", desc = "You see [ass]'s ass on the photo.", image = temp_img)
|
||||
give_pixel_offset(copied_ass)
|
||||
toEmbed.psize_x = 128
|
||||
toEmbed.psize_y = 128
|
||||
copied_ass.set_picture(toEmbed, TRUE, TRUE)
|
||||
toner_cartridge.charges -= ASS_TONER_USE
|
||||
|
||||
/**
|
||||
* Inserts the item into the copier. Called in `attackby()` after a human mob clicked on the copier with a paper, photo, or document.
|
||||
*
|
||||
* Arugments:
|
||||
* * object - the object that got inserted.
|
||||
* * user - the mob that inserted the object.
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/do_insertion(obj/item/object, mob/user)
|
||||
object.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You insert [object] into [src].</span>")
|
||||
flick("photocopier1", src)
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/photocopier/proc/remove_photocopy(obj/item/O, mob/user)
|
||||
/**
|
||||
* Called when someone hits the "remove item" button on the copier UI.
|
||||
*
|
||||
* If the user is a silicon, it drops the object at the location of the copier. If the user is not a silicon, it tries to put the object in their hands first.
|
||||
* Sets `busy` to `FALSE` because if the inserted item is removed, the copier should halt copying.
|
||||
*
|
||||
* Arguments:
|
||||
* * object - the item we're trying to remove.
|
||||
* * user - the user removing the item.
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/remove_photocopy(obj/item/object, mob/user)
|
||||
if(!issilicon(user)) //surprised this check didn't exist before, putting stuff in AI's hand is bad
|
||||
O.forceMove(user.loc)
|
||||
user.put_in_hands(O)
|
||||
object.forceMove(user.loc)
|
||||
user.put_in_hands(object)
|
||||
else
|
||||
O.forceMove(drop_location())
|
||||
to_chat(user, "<span class='notice'>You take [O] out of [src].</span>")
|
||||
object.forceMove(drop_location())
|
||||
to_chat(user, "<span class='notice'>You take [object] out of [src]. [busy ? "The [src] comes to a halt." : ""]</span>")
|
||||
|
||||
/obj/machinery/photocopier/attackby(obj/item/O, mob/user, params)
|
||||
if(default_unfasten_wrench(user, O))
|
||||
@@ -210,7 +349,7 @@
|
||||
else
|
||||
if(!user.temporarilyRemoveItemFromInventory(O))
|
||||
return
|
||||
copy = O
|
||||
paper_copy = O
|
||||
do_insertion(O, user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There is already something in [src]!</span>")
|
||||
@@ -219,7 +358,7 @@
|
||||
if(copier_empty())
|
||||
if(!user.temporarilyRemoveItemFromInventory(O))
|
||||
return
|
||||
photocopy = O
|
||||
photo_copy = O
|
||||
do_insertion(O, user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There is already something in [src]!</span>")
|
||||
@@ -228,38 +367,35 @@
|
||||
if(copier_empty())
|
||||
if(!user.temporarilyRemoveItemFromInventory(O))
|
||||
return
|
||||
doccopy = O
|
||||
document_copy = O
|
||||
do_insertion(O, user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There is already something in [src]!</span>")
|
||||
|
||||
else if(istype(O, /obj/item/toner))
|
||||
if(toner <= 0)
|
||||
if(!user.temporarilyRemoveItemFromInventory(O))
|
||||
return
|
||||
qdel(O)
|
||||
toner = 40
|
||||
to_chat(user, "<span class='notice'>You insert [O] into [src].</span>")
|
||||
updateUsrDialog()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>This cartridge is not yet ready for replacement! Use up the rest of the toner.</span>")
|
||||
if(toner_cartridge)
|
||||
to_chat(user, "<span class='warning'>[src] already has a toner cartridge inserted. Remove that one first.</span>")
|
||||
return
|
||||
O.forceMove(src)
|
||||
toner_cartridge = O
|
||||
to_chat(user, "<span class='notice'>You insert [O] into [src].</span>")
|
||||
|
||||
else if(istype(O, /obj/item/areaeditor/blueprints))
|
||||
to_chat(user, "<span class='warning'>The Blueprint is too large to put into the copier. You need to find something else to record the document</span>")
|
||||
to_chat(user, "<span class='warning'>The Blueprint is too large to put into the copier. You need to find something else to record the document.</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/photocopier/obj_break(damage_flag)
|
||||
. = ..()
|
||||
if(. && toner > 0)
|
||||
if(. && toner_cartridge.charges)
|
||||
new /obj/effect/decal/cleanable/oil(get_turf(src))
|
||||
toner = 0
|
||||
toner_cartridge.charges = 0
|
||||
|
||||
/obj/machinery/photocopier/MouseDrop_T(mob/target, mob/user)
|
||||
check_ass() //Just to make sure that you can re-drag somebody onto it after they moved off.
|
||||
if (!istype(target) || target.anchored || target.buckled || !Adjacent(target) || !user.canUseTopic(src, BE_CLOSE) || target == ass || copier_blocked())
|
||||
if(!istype(target) || target.anchored || target.buckled || !Adjacent(target) || !user.canUseTopic(src, BE_CLOSE) || target == ass || copier_blocked())
|
||||
return
|
||||
src.add_fingerprint(user)
|
||||
add_fingerprint(user)
|
||||
if(target == user)
|
||||
user.visible_message("<span class='notice'>[user] starts climbing onto the photocopier!</span>", "<span class='notice'>You start climbing onto the photocopier...</span>")
|
||||
else
|
||||
@@ -277,49 +413,63 @@
|
||||
target.forceMove(drop_location())
|
||||
ass = target
|
||||
|
||||
if(photocopy)
|
||||
photocopy.forceMove(drop_location())
|
||||
visible_message("<span class='warning'>[photocopy] is shoved out of the way by [ass]!</span>")
|
||||
photocopy = null
|
||||
if(photo_copy)
|
||||
photo_copy.forceMove(drop_location())
|
||||
visible_message("<span class='warning'>[photo_copy] is shoved out of the way by [ass]!</span>")
|
||||
photo_copy = null
|
||||
|
||||
else if(copy)
|
||||
copy.forceMove(drop_location())
|
||||
visible_message("<span class='warning'>[copy] is shoved out of the way by [ass]!</span>")
|
||||
copy = null
|
||||
updateUsrDialog()
|
||||
else if(paper_copy)
|
||||
paper_copy.forceMove(drop_location())
|
||||
visible_message("<span class='warning'>[paper_copy] is shoved out of the way by [ass]!</span>")
|
||||
paper_copy = null
|
||||
|
||||
else if(document_copy)
|
||||
document_copy.forceMove(drop_location())
|
||||
visible_message("<span class='warning'>[document_copy] is shoved out of the way by [ass]!</span>")
|
||||
document_copy = null
|
||||
|
||||
/obj/machinery/photocopier/Exited(atom/movable/AM, atom/newloc)
|
||||
check_ass() // There was potentially a person sitting on the copier, check if they're still there.
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Checks the living mob `ass` exists and its location is the same as the photocopier.
|
||||
*
|
||||
* Returns FALSE if `ass` doesn't exist or is not at the copier's location. Returns TRUE otherwise.
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/check_ass() //I'm not sure wether I made this proc because it's good form or because of the name.
|
||||
if(!ass)
|
||||
return 0
|
||||
if(ass.loc != src.loc)
|
||||
return FALSE
|
||||
if(ass.loc != loc)
|
||||
ass = null
|
||||
updateUsrDialog()
|
||||
return 0
|
||||
else if(ishuman(ass))
|
||||
if(!ass.get_item_by_slot(ITEM_SLOT_ICLOTHING) && !ass.get_item_by_slot(ITEM_SLOT_OCLOTHING))
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Checks if the copier is deleted, or has something dense at its location. Called in `MouseDrop_T()`
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/copier_blocked()
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(loc.density)
|
||||
return 1
|
||||
return TRUE
|
||||
for(var/atom/movable/AM in loc)
|
||||
if(AM == src)
|
||||
continue
|
||||
if(AM.density)
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Checks if there is an item inserted into the copier or a mob sitting on top of it.
|
||||
*
|
||||
* Return `FALSE` is the copier has something inside of it. Returns `TRUE` if it doesn't.
|
||||
*/
|
||||
/obj/machinery/photocopier/proc/copier_empty()
|
||||
if(copy || photocopy || check_ass())
|
||||
return 0
|
||||
if(paper_copy || photo_copy || document_copy || check_ass())
|
||||
return FALSE
|
||||
else
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/*
|
||||
* Toner cartridge
|
||||
@@ -343,3 +493,11 @@
|
||||
desc = "Why would ANYONE need THIS MUCH TONER?"
|
||||
charges = 200
|
||||
max_charges = 200
|
||||
|
||||
#undef PHOTO_GREYSCALE
|
||||
#undef PHOTO_COLOR
|
||||
#undef PAPER_TONER_USE
|
||||
#undef PHOTO_TONER_USE
|
||||
#undef DOCUMENT_TONER_USE
|
||||
#undef ASS_TONER_USE
|
||||
#undef MAX_COPIES_AT_ONCE
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
|
||||
var/datum/browser/popup = new(user, "computer", M ? M.name : "shuttle", 300, 200)
|
||||
popup.set_content("<center>[dat]</center>")
|
||||
popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/shuttle/Topic(href, href_list)
|
||||
|
||||
1
config/policy.json
Normal file
1
config/policy.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -3399,6 +3399,7 @@
|
||||
#include "code\modules\tgui\states\always.dm"
|
||||
#include "code\modules\tgui\states\conscious.dm"
|
||||
#include "code\modules\tgui\states\contained.dm"
|
||||
#include "code\modules\tgui\states\debug.dm"
|
||||
#include "code\modules\tgui\states\deep_inventory.dm"
|
||||
#include "code\modules\tgui\states\default.dm"
|
||||
#include "code\modules\tgui\states\hands.dm"
|
||||
|
||||
Reference in New Issue
Block a user