Merge branch 'master' into upstream-merge-26776
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
icon_state = "sleeper"
|
||||
state_open = TRUE
|
||||
anchored = TRUE
|
||||
occupant_typecache = list(/mob/living/carbon/human) // turned into typecache in Initialize
|
||||
var/you_die_in_the_game_you_die_for_real = FALSE
|
||||
var/datum/effect_system/spark_spread/sparks
|
||||
var/mob/living/carbon/human/virtual_reality/vr_human
|
||||
@@ -92,11 +93,12 @@
|
||||
return
|
||||
switch(action)
|
||||
if("vr_connect")
|
||||
if(ishuman(occupant) && occupant.mind)
|
||||
var/mob/living/carbon/human/human_occupant = occupant
|
||||
if(human_occupant && human_occupant.mind)
|
||||
to_chat(occupant, "<span class='warning'>Transfering to virtual reality...</span>")
|
||||
if(vr_human)
|
||||
vr_human.revert_to_reality(FALSE, FALSE)
|
||||
occupant.mind.transfer_to(vr_human)
|
||||
human_occupant.mind.transfer_to(vr_human)
|
||||
vr_human.real_me = occupant
|
||||
to_chat(vr_human, "<span class='notice'>Transfer successful! you are now playing as [vr_human] in VR!</span>")
|
||||
SStgui.close_user_uis(vr_human, src)
|
||||
|
||||
@@ -71,16 +71,13 @@
|
||||
computerid = bancid
|
||||
ip = banip
|
||||
|
||||
var/datum/DBQuery/query_add_ban_get_id = SSdbcore.NewQuery("SELECT id FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
|
||||
if(!query_add_ban_get_id.warn_execute())
|
||||
var/datum/DBQuery/query_add_ban_get_ckey = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
|
||||
if(!query_add_ban_get_ckey.warn_execute())
|
||||
return
|
||||
var/validckey = 0
|
||||
if(query_add_ban_get_id.NextRow())
|
||||
validckey = 1
|
||||
if(!validckey)
|
||||
if(!query_add_ban_get_ckey.NextRow())
|
||||
if(!banned_mob || (banned_mob && !IsGuestKey(banned_mob.key)))
|
||||
message_admins("<font color='red'>[key_name_admin(usr)] attempted to ban [ckey], but [ckey] has not been seen yet. Please only ban actual players.</font>",1)
|
||||
return
|
||||
if(alert(usr, "[ckey] has not been seen before, are you sure you want to create a ban for them?", "Unknown ckey", "Yes", "No", "Cancel") != "Yes")
|
||||
return
|
||||
|
||||
var/a_ckey
|
||||
var/a_computerid
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
if(!SSdbcore.Connect())
|
||||
log_world("Ban database connection failure. Key [ckeytext] not checked")
|
||||
GLOB.diary << "Ban database connection failure. Key [ckeytext] not checked"
|
||||
GLOB.world_game_log << "Ban database connection failure. Key [ckeytext] not checked"
|
||||
return
|
||||
|
||||
var/ipquery = ""
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
else
|
||||
body += " \[<A href='?_src_=holder;revive=\ref[M]'>Heal</A>\] "
|
||||
|
||||
if(M.client)
|
||||
body += "<br>\[<b>First Seen:</b> [M.client.player_join_date]\]\[<b>Byond account registered on:</b> [M.client.account_join_date]\]"
|
||||
|
||||
|
||||
|
||||
body += "<br><br>\[ "
|
||||
body += "<a href='?_src_=vars;Vars=\ref[M]'>VV</a> - "
|
||||
body += "<a href='?_src_=holder;traitor=\ref[M]'>TP</a> - "
|
||||
@@ -804,7 +809,7 @@
|
||||
return 1
|
||||
|
||||
/client/proc/adminGreet(logout)
|
||||
if(SSticker.HasRoundStarted())
|
||||
if(SSticker.HasRoundStarted())
|
||||
var/string
|
||||
if(logout && config && config.announce_admin_logout)
|
||||
string = pick(
|
||||
|
||||
@@ -1,50 +1,21 @@
|
||||
//By Carnwennan
|
||||
|
||||
//This system was made as an alternative to all the in-game lists and variables used to log stuff in-game.
|
||||
//lists and variables are great. However, they have several major flaws:
|
||||
//Firstly, they use memory. TGstation has one of the highest memory usage of all the ss13 branches.
|
||||
//Secondly, they are usually stored in an object. This means that they aren't centralised. It also means that
|
||||
//the data is lost when the object is deleted! This is especially annoying for things like the singulo engine!
|
||||
#define INVESTIGATE_DIR "data/investigate/"
|
||||
|
||||
//SYSTEM
|
||||
/proc/investigate_subject2file(subject)
|
||||
return file("[INVESTIGATE_DIR][subject].html")
|
||||
|
||||
/proc/investigate_reset()
|
||||
if(fdel(INVESTIGATE_DIR))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/atom/proc/investigate_log(message, subject)
|
||||
if(!message)
|
||||
return
|
||||
var/F = investigate_subject2file(subject)
|
||||
if(!F)
|
||||
atom/proc/investigate_log(message, subject)
|
||||
if(!message || !subject)
|
||||
return
|
||||
var/F = file("[GLOB.log_directory]/[subject].html")
|
||||
F << "<small>[time_stamp()] \ref[src] ([x],[y],[z])</small> || [src] [message]<br>"
|
||||
|
||||
//ADMINVERBS
|
||||
/client/proc/investigate_show( subject in list("hrefs","notes, memos, watchlist","singulo","wires","telesci", "gravity", "records", "cargo", "supermatter", "atmos", "experimentor", "botany") )
|
||||
|
||||
/client/proc/investigate_show( subject in list("hrefs","notes, memos, watchlist","singulo","wires","telesci", "gravity", "records", "cargo", "supermatter", "atmos", "experimentor", "botany") )
|
||||
set name = "Investigate"
|
||||
set category = "Admin"
|
||||
if(!holder)
|
||||
return
|
||||
switch(subject)
|
||||
if("singulo", "wires", "telesci", "gravity", "records", "cargo", "supermatter", "atmos", "botany") //general one-round-only stuff
|
||||
var/F = investigate_subject2file(subject)
|
||||
if(!F)
|
||||
to_chat(src, "<font color='red'>Error: admin_investigate: [INVESTIGATE_DIR][subject] is an invalid path or cannot be accessed.</font>")
|
||||
return
|
||||
src << browse(F,"window=investigate[subject];size=800x300")
|
||||
if("hrefs") //persistent logs and stuff
|
||||
if(GLOB.href_logfile)
|
||||
src << browse(GLOB.href_logfile,"window=investigate[subject];size=800x300")
|
||||
else if(!config.log_hrefs)
|
||||
to_chat(src, "<span class='danger'>Href logging is off and no logfile was found.</span>")
|
||||
return
|
||||
else
|
||||
to_chat(src, "<span class='danger'>No href logfile was found.</span>")
|
||||
return
|
||||
if("notes, memos, watchlist")
|
||||
browse_messages()
|
||||
else
|
||||
var/F = file("[GLOB.log_directory]/[subject].html")
|
||||
if(!fexists(F))
|
||||
to_chat(src, "<span class='danger'>No [subject] logfile was found.</span>")
|
||||
return
|
||||
src << browse(F,"window=investigate[subject];size=800x300")
|
||||
@@ -127,7 +127,7 @@ GLOBAL_PROTECT(admin_ranks)
|
||||
else
|
||||
if(!SSdbcore.Connect())
|
||||
log_world("Failed to connect to database in load_admin_ranks(). Reverting to legacy system.")
|
||||
GLOB.diary << "Failed to connect to database in load_admin_ranks(). Reverting to legacy system."
|
||||
GLOB.world_game_log << "Failed to connect to database in load_admin_ranks(). Reverting to legacy system."
|
||||
config.admin_legacy_system = 1
|
||||
load_admin_ranks()
|
||||
return
|
||||
@@ -202,7 +202,7 @@ GLOBAL_PROTECT(admin_ranks)
|
||||
else
|
||||
if(!SSdbcore.Connect())
|
||||
log_world("Failed to connect to database in load_admins(). Reverting to legacy system.")
|
||||
GLOB.diary << "Failed to connect to database in load_admins(). Reverting to legacy system."
|
||||
GLOB.world_game_log << "Failed to connect to database in load_admins(). Reverting to legacy system."
|
||||
config.admin_legacy_system = 1
|
||||
load_admins()
|
||||
return
|
||||
|
||||
@@ -4,18 +4,12 @@ GLOBAL_PROTECT(admin_verbs_default)
|
||||
GLOBAL_LIST_INIT(admin_verbs_default, world.AVerbsDefault())
|
||||
/world/proc/AVerbsDefault()
|
||||
return list(
|
||||
/client/proc/toggleadminhelpsound, /*toggles whether we hear a sound when adminhelps/PMs are used*/
|
||||
/client/proc/toggleannouncelogin, /*toggles if an admin's login is announced during a round*/
|
||||
/client/proc/deadmin, /*destroys our own admin datum so we can play as a regular player*/
|
||||
/client/proc/cmd_admin_say, /*admin-only ooc chat*/
|
||||
/client/proc/hide_verbs, /*hides all our adminverbs*/
|
||||
/client/proc/hide_most_verbs, /*hides all our hideable adminverbs*/
|
||||
/client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/
|
||||
/client/proc/deadchat, /*toggles deadchat on/off*/
|
||||
/client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/
|
||||
/client/proc/toggleprayers, /*toggles prayers on/off*/
|
||||
/client/verb/toggleprayersounds, /*Toggles prayer sounds (HALLELUJAH!)*/
|
||||
/client/proc/toggle_hear_radio, /*toggles whether we hear the radio*/
|
||||
/client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/
|
||||
/client/proc/secrets,
|
||||
/client/proc/restart_controller,
|
||||
@@ -32,7 +26,6 @@ GLOBAL_PROTECT(admin_verbs_admin)
|
||||
GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
|
||||
/world/proc/AVerbsAdmin()
|
||||
return list(
|
||||
/client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/
|
||||
/client/proc/invisimin, /*allows our mob to go invisible/visible*/
|
||||
// /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage
|
||||
/datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/
|
||||
@@ -46,16 +39,14 @@ GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
|
||||
/datum/admins/proc/set_admin_notice,/*announcement all clients see when joining the server.*/
|
||||
/client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/
|
||||
/client/proc/toggle_view_range, /*changes how far we can see*/
|
||||
/datum/admins/proc/view_txt_log, /*shows the server log (diary) for today*/
|
||||
/datum/admins/proc/view_txt_log, /*shows the server log (world_game_log) for today*/
|
||||
/datum/admins/proc/view_atk_log, /*shows the server combat-log, doesn't do anything presently*/
|
||||
/client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/
|
||||
/client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/
|
||||
/client/proc/cmd_admin_check_contents, /*displays the contents of an instance*/
|
||||
/client/proc/check_antagonists, /*shows all antags*/
|
||||
/datum/admins/proc/access_news_network, /*allows access of newscasters*/
|
||||
/client/proc/giveruntimelog, /*allows us to give access to runtime logs to somebody*/
|
||||
/client/proc/getruntimelog, /*allows us to access runtime logs to somebody*/
|
||||
/client/proc/getserverlog, /*allows us to fetch server logs (diary) for other days*/
|
||||
/client/proc/getserverlog, /*allows us to fetch server logs (world_game_log) for other days*/
|
||||
/client/proc/jumptocoord, /*we ghost and jump to a coordinate*/
|
||||
/client/proc/Getmob, /*teleports a mob to our location*/
|
||||
/client/proc/Getkey, /*teleports a mob with a certain ckey to our location*/
|
||||
@@ -116,7 +107,6 @@ GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer())
|
||||
/datum/admins/proc/end_round,
|
||||
/datum/admins/proc/delay,
|
||||
/datum/admins/proc/toggleaban,
|
||||
/client/proc/toggle_log_hrefs,
|
||||
/client/proc/everyone_random,
|
||||
/datum/admins/proc/toggleAI,
|
||||
/client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/
|
||||
@@ -182,9 +172,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
||||
/client/proc/set_ooc,
|
||||
/client/proc/reset_ooc,
|
||||
/client/proc/deadmin,
|
||||
/client/proc/deadchat,
|
||||
/client/proc/toggleprayers,
|
||||
/client/proc/toggle_hear_radio,
|
||||
/datum/admins/proc/show_traitor_panel,
|
||||
/datum/admins/proc/toggleenter,
|
||||
/datum/admins/proc/toggleguests,
|
||||
@@ -223,7 +210,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
||||
/datum/admins/proc/restart,
|
||||
/datum/admins/proc/delay,
|
||||
/datum/admins/proc/toggleaban,
|
||||
/client/proc/toggle_log_hrefs,
|
||||
/client/proc/everyone_random,
|
||||
/datum/admins/proc/toggleAI,
|
||||
/client/proc/restart_controller,
|
||||
@@ -398,13 +384,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
||||
mob.invisibility = INVISIBILITY_OBSERVER
|
||||
to_chat(mob, "<span class='adminnotice'><b>Invisimin on. You are now as invisible as a ghost.</b></span>")
|
||||
|
||||
/client/proc/player_panel_new()
|
||||
set name = "Player Panel"
|
||||
set category = "Admin"
|
||||
if(holder)
|
||||
holder.player_panel_new()
|
||||
SSblackbox.add_details("admin_verb","Player Panel New") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/check_antagonists()
|
||||
set name = "Check Antagonists"
|
||||
set category = "Admin"
|
||||
@@ -638,19 +617,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
||||
togglebuildmode(src.mob)
|
||||
SSblackbox.add_details("admin_verb","Toggle Build Mode") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/toggle_log_hrefs()
|
||||
set name = "Toggle href logging"
|
||||
set category = "Server"
|
||||
if(!holder)
|
||||
return
|
||||
if(config)
|
||||
if(config.log_hrefs)
|
||||
config.log_hrefs = 0
|
||||
to_chat(src, "<b>Stopped logging hrefs</b>")
|
||||
else
|
||||
config.log_hrefs = 1
|
||||
to_chat(src, "<b>Started logging hrefs</b>")
|
||||
|
||||
/client/proc/check_ai_laws()
|
||||
set name = "Check AI Laws"
|
||||
set category = "Admin"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/datum/menu/Admin/Generate_list(client/C)
|
||||
if (C.holder)
|
||||
. = ..()
|
||||
|
||||
/datum/menu/Admin/verb/playerpanel()
|
||||
set name = "Player Panel"
|
||||
set desc = "Player Panel"
|
||||
set category = "Admin"
|
||||
usr.client.holder.player_panel_new()
|
||||
SSblackbox.add_details("admin_verb","Player Panel New") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
@@ -1,10 +0,0 @@
|
||||
diff a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm (rejected hunks)
|
||||
@@ -8,7 +8,7 @@
|
||||
if(href_list["ahelp"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
-
|
||||
+
|
||||
var/ahelp_ref = href_list["ahelp"]
|
||||
var/datum/admin_help/AH = locate(ahelp_ref)
|
||||
if(AH)
|
||||
@@ -71,7 +71,7 @@
|
||||
if("select", "delete", "update")
|
||||
select_types = query_tree[query_tree[1]]
|
||||
|
||||
from_objs = SDQL_from_objs(query_tree["from"])
|
||||
from_objs = world.SDQL_from_objs(query_tree["from"])
|
||||
|
||||
var/list/objs = list()
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
if("call")
|
||||
for(var/datum/d in objs)
|
||||
try
|
||||
SDQL_var(d, query_tree["call"][1], source = d)
|
||||
world.SDQL_var(d, query_tree["call"][1], source = d)
|
||||
catch(var/exception/e)
|
||||
runtime_tracker += SDQL_parse_exception(e)
|
||||
runtimes++
|
||||
@@ -177,15 +177,6 @@
|
||||
returning += "Description: [E.desc]<BR>"
|
||||
return returning
|
||||
|
||||
/proc/SDQL_callproc_global(procname,args_list)
|
||||
set waitfor = FALSE
|
||||
WrapAdminProcCall(GLOBAL_PROC, procname, args_list)
|
||||
|
||||
/proc/SDQL_callproc(thing, procname, args_list)
|
||||
set waitfor = FALSE
|
||||
if(hascall(thing, procname))
|
||||
WrapAdminProcCall(thing, procname, args_list)
|
||||
|
||||
/proc/SDQL_parse(list/query_list)
|
||||
var/datum/SDQL_parser/parser = new()
|
||||
var/list/querys = list()
|
||||
@@ -249,15 +240,10 @@
|
||||
|
||||
|
||||
|
||||
/proc/SDQL_from_objs(list/tree)
|
||||
/world/proc/SDQL_from_objs(list/tree)
|
||||
if("world" in tree)
|
||||
if(IsAdminAdvancedProcCall())
|
||||
var/msg = "WARNING: Attempt to retrieve world reference made by [usr]!"
|
||||
log_admin(msg)
|
||||
message_admins(msg)
|
||||
return
|
||||
return world
|
||||
return SDQL_expression(world, tree)
|
||||
return src
|
||||
return SDQL_expression(src, tree)
|
||||
|
||||
/proc/SDQL_get_all(type, location)
|
||||
var/list/out = list()
|
||||
@@ -417,12 +403,12 @@
|
||||
result = dummy
|
||||
val += result
|
||||
else
|
||||
val = SDQL_var(object, expression, i, object)
|
||||
val = world.SDQL_var(object, expression, i, object)
|
||||
i = expression.len
|
||||
|
||||
return list("val" = val, "i" = i)
|
||||
|
||||
/proc/SDQL_var(datum/object, list/expression, start = 1, source)
|
||||
/world/proc/SDQL_var(datum/object, list/expression, start = 1, source)
|
||||
var/v
|
||||
var/long = start < expression.len
|
||||
if(object == world && long && expression[start + 1] == ".")
|
||||
@@ -456,11 +442,6 @@
|
||||
else
|
||||
return null
|
||||
if("world")
|
||||
if(IsAdminAdvancedProcCall())
|
||||
var/msg = "WARNING: Attempt to retrieve world reference made by [usr]!"
|
||||
log_admin(msg)
|
||||
message_admins(msg)
|
||||
return
|
||||
v = world
|
||||
if("global")
|
||||
v = GLOB
|
||||
|
||||
@@ -479,7 +479,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
current_ticket.MessageNoRecipient(msg)
|
||||
current_ticket.TimeoutVerb()
|
||||
return
|
||||
else
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Ticket not found, creating new one...</span>")
|
||||
else
|
||||
current_ticket.AddInteraction("[key_name_admin(usr)] opened a new ticket.")
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
if(!recipient)
|
||||
if(holder)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
|
||||
to_chat(src, msg)
|
||||
else
|
||||
current_ticket.MessageNoRecipient(msg)
|
||||
return
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
if (!msg)
|
||||
return
|
||||
var/nicknames = world.file2list("config/admin_nicknames.txt")
|
||||
var/static/nicknames = world.file2list("config/admin_nicknames.txt")
|
||||
|
||||
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>ADMIN([src.holder.fakekey ? pick(nicknames) : src.key])</span> says, <span class='message'>\"[msg]\"</span></span>"
|
||||
|
||||
|
||||
@@ -1,62 +1,3 @@
|
||||
/*
|
||||
HOW DO I LOG RUNTIMES?
|
||||
Firstly, start dreamdeamon if it isn't already running. Then select "world>Log Session" (or press the F3 key)
|
||||
navigate the popup window to the data/logs/runtimes/ folder from where your tgstation .dmb is located.
|
||||
(you may have to make this folder yourself)
|
||||
|
||||
OPTIONAL: you can select the little checkbox down the bottom to make dreamdeamon save the log everytime you
|
||||
start a world. Just remember to repeat these steps with a new name when you update to a new revision!
|
||||
|
||||
Save it with the name of the revision your server uses (e.g. r3459.txt).
|
||||
Game Masters will now be able to grant access any runtime logs you have archived this way!
|
||||
This will allow us to gather information on bugs across multiple servers and make maintaining the TG
|
||||
codebase for the entire /TG/station commuity a TONNE easier :3 Thanks for your help!
|
||||
*/
|
||||
|
||||
|
||||
//This proc allows Game Masters to grant a client access to the .getruntimelog verb
|
||||
//Permissions expire at the end of each round.
|
||||
//Runtimes can be used to meta or spot game-crashing exploits so it's advised to only grant coders that
|
||||
//you trust access. Also, it may be wise to ensure that they are not going to play in the current round.
|
||||
/client/proc/giveruntimelog()
|
||||
set name = ".giveruntimelog"
|
||||
set desc = "Give somebody access to any session logfiles saved to the /log/runtime/ folder."
|
||||
set category = null
|
||||
|
||||
if(!src.holder)
|
||||
to_chat(src, "<font color='red'>Only Admins may use this command.</font>")
|
||||
return
|
||||
|
||||
var/client/target = input(src,"Choose somebody to grant access to the server's runtime logs (permissions expire at the end of each round):","Grant Permissions",null) as null|anything in GLOB.clients
|
||||
if(!istype(target,/client))
|
||||
to_chat(src, "<font color='red'>Error: giveruntimelog(): Client not found.</font>")
|
||||
return
|
||||
|
||||
target.verbs |= /client/proc/getruntimelog
|
||||
to_chat(target, "<font color='red'>You have been granted access to runtime logs. Please use them responsibly or risk being banned.</font>")
|
||||
return
|
||||
|
||||
|
||||
//This proc allows download of runtime logs saved within the data/logs/ folder by dreamdeamon.
|
||||
//It works similarly to show-server-log.
|
||||
/client/proc/getruntimelog()
|
||||
set name = ".getruntimelog"
|
||||
set desc = "Retrieve any session logfiles saved by dreamdeamon."
|
||||
set category = null
|
||||
|
||||
var/path = browse_files("data/logs/runtimes/")
|
||||
if(!path)
|
||||
return
|
||||
|
||||
if(file_spam_check())
|
||||
return
|
||||
|
||||
message_admins("[key_name_admin(src)] accessed file: [path]")
|
||||
src << ftp(file(path))
|
||||
to_chat(src, "Attempting to send file, this may take a fair few minutes if the file is very large.")
|
||||
return
|
||||
|
||||
|
||||
//This proc allows download of past server logs saved within the data/logs/ folder.
|
||||
//It works similarly to show-server-log.
|
||||
/client/proc/getserverlog()
|
||||
@@ -83,10 +24,10 @@
|
||||
/datum/admins/proc/view_txt_log()
|
||||
set category = "Admin"
|
||||
set name = "Show Server Log"
|
||||
set desc = "Shows today's server log."
|
||||
set desc = "Shows server log for this round."
|
||||
|
||||
if(fexists("[GLOB.diary]"))
|
||||
src << ftp(GLOB.diary)
|
||||
if(fexists("[GLOB.world_game_log]"))
|
||||
src << ftp(GLOB.world_game_log)
|
||||
else
|
||||
to_chat(src, "<font color='red'>Server log not found, try using .getserverlog.</font>")
|
||||
return
|
||||
@@ -97,10 +38,10 @@
|
||||
/datum/admins/proc/view_atk_log()
|
||||
set category = "Admin"
|
||||
set name = "Show Server Attack Log"
|
||||
set desc = "Shows today's server attack log."
|
||||
set desc = "Shows server attack log for this round."
|
||||
|
||||
if(fexists("[GLOB.diaryofmeanpeople]"))
|
||||
src << ftp(GLOB.diaryofmeanpeople)
|
||||
if(fexists("[GLOB.world_attack_log]"))
|
||||
src << ftp(GLOB.world_attack_log)
|
||||
else
|
||||
to_chat(src, "<font color='red'>Server attack log not found, try using .getserverlog.</font>")
|
||||
return
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
usr.client.images += preview
|
||||
if(alert(usr,"Confirm location.","Template Confirm","Yes","No") == "Yes")
|
||||
if(template.load(T, centered = TRUE))
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has placed a map template ([template.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>(JMP)</a></span>")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has placed a map template ([template.name]) at [ADMIN_COORDJMP(T)]</span>")
|
||||
else
|
||||
to_chat(usr, "Failed to place map")
|
||||
usr.client.images -= preview
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
/datum/admins/proc/makeWizard()
|
||||
|
||||
var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for the position of a Wizard Foundation 'diplomat'?", "wizard", null)
|
||||
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for the position of a Wizard Foundation 'diplomat'?", "wizard", null)
|
||||
|
||||
var/mob/dead/observer/selected = pick_n_take(candidates)
|
||||
|
||||
@@ -215,7 +215,7 @@
|
||||
/datum/admins/proc/makeNukeTeam()
|
||||
|
||||
var/datum/game_mode/nuclear/temp = new
|
||||
var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for a nuke team being sent in?", "operative", temp)
|
||||
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for a nuke team being sent in?", "operative", temp)
|
||||
var/list/mob/dead/observer/chosen = list()
|
||||
var/mob/dead/observer/theghost = null
|
||||
|
||||
@@ -288,7 +288,7 @@
|
||||
// DEATH SQUADS
|
||||
/datum/admins/proc/makeDeathsquad()
|
||||
var/mission = input("Assign a mission to the deathsquad", "Assign Mission", "Leave no witnesses.")
|
||||
var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for an elite Nanotrasen Strike Team?", "deathsquad", null)
|
||||
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for an elite Nanotrasen Strike Team?", "deathsquad", null)
|
||||
var/squadSpawned = 0
|
||||
|
||||
if(candidates.len >= 2) //Minimum 2 to be considered a squad
|
||||
@@ -396,7 +396,7 @@
|
||||
|
||||
/datum/admins/proc/makeOfficial()
|
||||
var/mission = input("Assign a task for the official", "Assign Task", "Conduct a routine preformance review of [station_name()] and its Captain.")
|
||||
var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered to be a Centcom Official?", "deathsquad")
|
||||
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered to be a Centcom Official?", "deathsquad")
|
||||
|
||||
if(candidates.len)
|
||||
var/mob/dead/observer/chosen_candidate = pick(candidates)
|
||||
@@ -457,7 +457,7 @@
|
||||
var/mission = input("Assign a mission to the Emergency Response Team", "Assign Mission", "Assist the station.") as null|text
|
||||
if(!mission)
|
||||
return
|
||||
var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for a Code [alert] Nanotrasen Emergency Response Team?", "deathsquad", null)
|
||||
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for a Code [alert] Nanotrasen Emergency Response Team?", "deathsquad", null)
|
||||
var/teamSpawned = 0
|
||||
|
||||
if(candidates.len > 0)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
var/res = alert(usr, "Show the title of this song to the players?",, "No", "Yes", "Cancel")
|
||||
switch(res)
|
||||
if("Yes")
|
||||
to_chat(world, "An admin played: [S]")
|
||||
to_chat(world, "<span class='boldannounce'>An admin played: [S]</span>")
|
||||
if("Cancel")
|
||||
return
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
message_admins("<span class='adminnotice'><b> LocalNarrate: [key_name_admin(usr)] at [get_area(A)][ADMIN_JMP(A)]:</b> [msg]<BR></span>")
|
||||
SSblackbox.add_details("admin_verb","Local Narrate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
/client/proc/cmd_admin_godmode(mob/M in GLOB.mob_list)
|
||||
set category = "Special Verbs"
|
||||
set name = "Godmode"
|
||||
@@ -350,7 +351,6 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
|
||||
if(G_found.mind && !G_found.mind.active)
|
||||
G_found.mind.transfer_to(new_character) //be careful when doing stuff like this! I've already checked the mind isn't in use
|
||||
new_character.mind.special_verbs = list()
|
||||
else
|
||||
new_character.mind_initialize()
|
||||
if(!new_character.mind.assigned_role)
|
||||
@@ -701,7 +701,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
set name = "Make Everyone Random"
|
||||
set desc = "Make everyone have a random appearance. You can only use this before rounds!"
|
||||
|
||||
if(SSticker.HasRoundStarted())
|
||||
if(SSticker.HasRoundStarted())
|
||||
to_chat(usr, "Nope you can't do this, the game's already started. This only works before rounds!")
|
||||
return
|
||||
|
||||
|
||||
@@ -93,10 +93,10 @@
|
||||
if(href_list["time"])
|
||||
timing = text2num(href_list["time"])
|
||||
if(timing && istype(holder, /obj/item/device/transfer_valve))
|
||||
var/timer_message = "[key_name_admin(usr)](<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) activated [src] attachment on [holder]."
|
||||
var/timer_message = "[ADMIN_LOOKUPFLW(usr)] activated [src] attachment on [holder]."
|
||||
message_admins(timer_message)
|
||||
GLOB.bombers += timer_message
|
||||
log_game("[key_name(usr)] activated [src] attachment for [loc]")
|
||||
log_game("[key_name(usr)] activated [src] attachment on [holder]")
|
||||
update_icon()
|
||||
if(href_list["repeat"])
|
||||
loop = text2num(href_list["repeat"])
|
||||
|
||||
@@ -153,30 +153,31 @@
|
||||
return
|
||||
var/datum/gas_mixture/air1 = AIR1
|
||||
var/turf/T = get_turf(src)
|
||||
if(occupant)
|
||||
if(occupant.health >= 100) // Don't bother with fully healed people.
|
||||
if(isliving(occupant))
|
||||
var/mob/living/mob_occupant
|
||||
if(mob_occupant.health >= 100) // Don't bother with fully healed people.
|
||||
on = FALSE
|
||||
update_icon()
|
||||
playsound(T, 'sound/machines/cryo_warning.ogg', volume, 1) // Bug the doctors.
|
||||
radio.talk_into(src, "Patient fully restored", radio_channel)
|
||||
playsound(T, 'sound/machines/cryo_warning.ogg', volume) // Bug the doctors.
|
||||
radio.talk_into(src, "Patient fully restored", radio_channel, get_spans(), get_default_language())
|
||||
if(autoeject) // Eject if configured.
|
||||
radio.talk_into(src, "Auto ejecting patient now", radio_channel,get_spans(), get_default_language())
|
||||
radio.talk_into(src, "Auto ejecting patient now", radio_channel, get_spans(), get_default_language())
|
||||
open_machine()
|
||||
return
|
||||
else if(occupant.stat == DEAD) // We don't bother with dead people.
|
||||
else if(mob_occupant.stat == DEAD) // We don't bother with dead people.
|
||||
return
|
||||
if(autoeject) // Eject if configured.
|
||||
open_machine()
|
||||
return
|
||||
if(air1.gases.len)
|
||||
if(occupant.bodytemperature < T0C) // Sleepytime. Why? More cryo magic.
|
||||
occupant.Sleeping((occupant.bodytemperature / sleep_factor) * 100)
|
||||
occupant.Paralyse((occupant.bodytemperature / paralyze_factor) * 100)
|
||||
if(mob_occupant.bodytemperature < T0C) // Sleepytime. Why? More cryo magic.
|
||||
mob_occupant.Sleeping((mob_occupant.bodytemperature / sleep_factor) * 100)
|
||||
mob_occupant.Paralyse((mob_occupant.bodytemperature / paralyze_factor) * 100)
|
||||
|
||||
if(beaker)
|
||||
if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic.
|
||||
beaker.reagents.trans_to(occupant, 1, 10 * efficiency) // Transfer reagents, multiplied because cryo magic.
|
||||
beaker.reagents.reaction(occupant, VAPOR)
|
||||
beaker.reagents.trans_to(mob_occupant, 1, 10 * efficiency) // Transfer reagents, multiplied because cryo magic.
|
||||
beaker.reagents.reaction(mob_occupant, VAPOR)
|
||||
air1.gases["o2"][MOLES] -= 2 / efficiency // Lets use gas for this.
|
||||
if(++reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker).
|
||||
reagent_transfer = 0
|
||||
@@ -191,20 +192,21 @@
|
||||
on = FALSE
|
||||
update_icon()
|
||||
return
|
||||
if(occupant)
|
||||
if(isliving(occupant))
|
||||
var/mob/living/mob_occupant = occupant
|
||||
var/cold_protection = 0
|
||||
var/mob/living/carbon/human/H = occupant
|
||||
if(istype(H))
|
||||
cold_protection = H.get_cold_protection(air1.temperature)
|
||||
|
||||
var/temperature_delta = air1.temperature - occupant.bodytemperature // The only semi-realistic thing here: share temperature between the cell and the occupant.
|
||||
var/temperature_delta = air1.temperature - mob_occupant.bodytemperature // The only semi-realistic thing here: share temperature between the cell and the occupant.
|
||||
if(abs(temperature_delta) > 1)
|
||||
var/air_heat_capacity = air1.heat_capacity()
|
||||
var/heat = ((1 - cold_protection) / 10 + conduction_coefficient) \
|
||||
* temperature_delta * \
|
||||
(air_heat_capacity * heat_capacity / (air_heat_capacity + heat_capacity))
|
||||
air1.temperature = max(air1.temperature - heat / air_heat_capacity, TCMB)
|
||||
occupant.bodytemperature = max(occupant.bodytemperature + heat / heat_capacity, TCMB)
|
||||
mob_occupant.bodytemperature = max(mob_occupant.bodytemperature + heat / heat_capacity, TCMB)
|
||||
|
||||
air1.gases["o2"][MOLES] -= 0.5 / efficiency // Magically consume gas? Why not, we run on cryo magic.
|
||||
|
||||
@@ -265,6 +267,9 @@
|
||||
I.loc = src
|
||||
user.visible_message("[user] places [I] in [src].", \
|
||||
"<span class='notice'>You place [I] in [src].</span>")
|
||||
var/reagentlist = pretty_string_from_reagent_list(I.reagents.reagent_list)
|
||||
log_game("[key_name(user)] added an [I] to cyro containing [reagentlist]")
|
||||
|
||||
return
|
||||
if(!on && !occupant && !state_open)
|
||||
if(default_deconstruction_screwdriver(user, "pod0-o", "pod0", I))
|
||||
@@ -294,17 +299,18 @@
|
||||
data["autoEject"] = autoeject
|
||||
|
||||
var/list/occupantData = list()
|
||||
if(occupant)
|
||||
occupantData["name"] = occupant.name
|
||||
occupantData["stat"] = occupant.stat
|
||||
occupantData["health"] = occupant.health
|
||||
occupantData["maxHealth"] = occupant.maxHealth
|
||||
if(isliving(occupant))
|
||||
var/mob/living/mob_occupant = occupant
|
||||
occupantData["name"] = mob_occupant.name
|
||||
occupantData["stat"] = mob_occupant.stat
|
||||
occupantData["health"] = mob_occupant.health
|
||||
occupantData["maxHealth"] = mob_occupant.maxHealth
|
||||
occupantData["minHealth"] = HEALTH_THRESHOLD_DEAD
|
||||
occupantData["bruteLoss"] = occupant.getBruteLoss()
|
||||
occupantData["oxyLoss"] = occupant.getOxyLoss()
|
||||
occupantData["toxLoss"] = occupant.getToxLoss()
|
||||
occupantData["fireLoss"] = occupant.getFireLoss()
|
||||
occupantData["bodyTemperature"] = occupant.bodytemperature
|
||||
occupantData["bruteLoss"] = mob_occupant.getBruteLoss()
|
||||
occupantData["oxyLoss"] = mob_occupant.getOxyLoss()
|
||||
occupantData["toxLoss"] = mob_occupant.getToxLoss()
|
||||
occupantData["fireLoss"] = mob_occupant.getFireLoss()
|
||||
occupantData["bodyTemperature"] = mob_occupant.bodytemperature
|
||||
data["occupant"] = occupantData
|
||||
|
||||
|
||||
@@ -355,4 +361,4 @@
|
||||
return //can't ventcrawl in or out of cryo.
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/can_see_pipes()
|
||||
return 0 //you can't see the pipe network when inside a cryo cell.
|
||||
return 0 //you can't see the pipe network when inside a cryo cell.
|
||||
@@ -16,22 +16,17 @@
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 100, bomb = 0, bio = 100, rad = 100, fire = 40, acid = 0)
|
||||
|
||||
|
||||
/obj/machinery/meter/New()
|
||||
..()
|
||||
/obj/machinery/meter/Initialize(mapload)
|
||||
. = ..()
|
||||
SSair.atmos_machinery += src
|
||||
src.target = locate(/obj/machinery/atmospherics/pipe) in loc
|
||||
return 1
|
||||
if (mapload && !target)
|
||||
target = locate(/obj/machinery/atmospherics/pipe) in loc
|
||||
|
||||
/obj/machinery/meter/Destroy()
|
||||
SSair.atmos_machinery -= src
|
||||
src.target = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/meter/Initialize(mapload)
|
||||
..()
|
||||
if (mapload && !target)
|
||||
src.target = locate(/obj/machinery/atmospherics/pipe) in loc
|
||||
|
||||
/obj/machinery/meter/process_atmos()
|
||||
if(!target)
|
||||
icon_state = "meterX"
|
||||
|
||||
@@ -400,8 +400,8 @@
|
||||
var/bz = air_contents.gases["bz"]
|
||||
var/freon = air_contents.gases["freon"]
|
||||
if(n2o || plasma || bz || freon)
|
||||
message_admins("[key_name_admin(usr)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) opened a canister that contains the following: (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
|
||||
log_admin("[key_name(usr)] opened a canister that contains the following at [x], [y], [z]:")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] opened a canister that contains the following: [ADMIN_JMP(src)]")
|
||||
log_admin("[key_name(usr)] opened a canister that contains the following at [COORD(src)]:")
|
||||
if(plasma)
|
||||
log_admin("Plasma")
|
||||
message_admins("Plasma")
|
||||
|
||||
@@ -103,8 +103,9 @@
|
||||
var/plasma = air_contents.gases["plasma"]
|
||||
var/n2o = air_contents.gases["n2o"]
|
||||
if(n2o || plasma)
|
||||
message_admins("[key_name_admin(usr)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""]! (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
|
||||
log_admin("[key_name(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [x], [y], [z]")
|
||||
var/area/A = get_area(src)
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [A][ADMIN_JMP(src)]")
|
||||
log_admin("[key_name(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [A][COORD(src)]")
|
||||
. = TRUE
|
||||
if("direction")
|
||||
if(direction == PUMP_OUT)
|
||||
|
||||
@@ -227,7 +227,7 @@ GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation)
|
||||
if(check_exile_implant(C))
|
||||
say("Rejecting [AM]: Exile implant detected in contained lifeform.")
|
||||
return
|
||||
if(AM.buckled_mobs.len)
|
||||
if(AM.has_buckled_mobs())
|
||||
for(var/mob/living/carbon/C in AM.buckled_mobs)
|
||||
if(check_exile_implant(C))
|
||||
say("Rejecting [AM]: Exile implant detected in close proximity lifeform.")
|
||||
|
||||
@@ -64,17 +64,18 @@
|
||||
next_check = world.time + cooldown
|
||||
|
||||
/obj/structure/academy_wizard_spawner/proc/give_control()
|
||||
set waitfor = FALSE
|
||||
|
||||
if(!current_wizard)
|
||||
return
|
||||
spawn(0)
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as Wizard Academy Defender?", "wizard", null, ROLE_WIZARD, current_wizard)
|
||||
var/mob/dead/observer/chosen = null
|
||||
|
||||
if(candidates.len)
|
||||
chosen = pick(candidates)
|
||||
message_admins("[key_name_admin(chosen)] was spawned as Wizard Academy Defender")
|
||||
current_wizard.ghostize() // on the off chance braindead defender gets back in
|
||||
current_wizard.key = chosen.key
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as Wizard Academy Defender?", "wizard", null, be_special_flag = ROLE_WIZARD, M = current_wizard)
|
||||
var/mob/dead/observer/chosen = null
|
||||
|
||||
if(candidates.len)
|
||||
chosen = pick(candidates)
|
||||
message_admins("[key_name_admin(chosen)] was spawned as Wizard Academy Defender")
|
||||
current_wizard.ghostize() // on the off chance braindead defender gets back in
|
||||
current_wizard.key = chosen.key
|
||||
|
||||
/obj/structure/academy_wizard_spawner/proc/summon_wizard()
|
||||
var/turf/T = src.loc
|
||||
|
||||
@@ -50,11 +50,6 @@
|
||||
material_id = MAT_PLASMA
|
||||
message = "cm3 of plasma"
|
||||
|
||||
/datum/export/material/plasma/get_cost(obj/O, contr = 0, emag = 0)
|
||||
. = ..()
|
||||
if(emag) // Syndicate pays you more for the plasma.
|
||||
. = round(. * 1.5)
|
||||
|
||||
// Uranium. Still useful for both power generation and nuclear annihilation.
|
||||
/datum/export/material/uranium
|
||||
cost = 400
|
||||
@@ -98,4 +93,4 @@
|
||||
message = "cm3 of glass"
|
||||
material_id = MAT_GLASS
|
||||
export_types = list(/obj/item/stack/sheet/glass, /obj/item/weapon/ore,
|
||||
/obj/item/weapon/shard)
|
||||
/obj/item/weapon/shard)
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
|
||||
// Wood. Quite expensive in the grim and dark 26 century.
|
||||
/datum/export/stack/wood
|
||||
cost = 25
|
||||
cost = 50
|
||||
unit_name = "wood plank"
|
||||
export_types = list(/obj/item/stack/sheet/mineral/wood)
|
||||
|
||||
|
||||
+10
-11
@@ -182,14 +182,14 @@
|
||||
/datum/supply_pack/emergency/syndicate
|
||||
name = "NULL_ENTRY"
|
||||
hidden = TRUE
|
||||
cost = 14000
|
||||
cost = 20000
|
||||
contains = list()
|
||||
crate_name = "emergency crate"
|
||||
crate_type = /obj/structure/closet/crate/internals
|
||||
dangerous = TRUE
|
||||
|
||||
/datum/supply_pack/emergency/syndicate/fill(obj/structure/closet/crate/C)
|
||||
var/crate_value = 50
|
||||
var/crate_value = 30
|
||||
var/list/uplink_items = get_uplink_items(SSticker.mode)
|
||||
while(crate_value)
|
||||
var/category = pick(uplink_items)
|
||||
@@ -828,6 +828,14 @@
|
||||
/obj/item/weapon/defibrillator/loaded)
|
||||
crate_name = "defibrillator crate"
|
||||
|
||||
/datum/supply_pack/medical/vending
|
||||
name = "Medical Vending Crate"
|
||||
cost = 2000
|
||||
contains = list(/obj/item/weapon/vending_refill/medical,
|
||||
/obj/item/weapon/vending_refill/medical,
|
||||
/obj/item/weapon/vending_refill/medical)
|
||||
crate_name = "medical vending crate"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Science /////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1680,15 +1688,6 @@
|
||||
/obj/item/toy/crayon/rainbow)
|
||||
crate_name = "art supply crate"
|
||||
|
||||
/datum/supply_pack/misc/soapstone
|
||||
name = "Librarian Engraving/Scribbling Crate"
|
||||
crate_name = "librarian engraving/scribbling crate"
|
||||
cost = 3000
|
||||
contains = list(/obj/item/soapstone)
|
||||
access = GLOB.access_library
|
||||
crate_type = /obj/structure/closet/crate/secure
|
||||
|
||||
|
||||
/datum/supply_pack/misc/bsa
|
||||
name = "Bluespace Artillery Parts"
|
||||
cost = 15000
|
||||
|
||||
@@ -39,9 +39,12 @@
|
||||
////////////////////////////////////
|
||||
//things that require the database//
|
||||
////////////////////////////////////
|
||||
var/player_age = "Requires database" //So admins know why it isn't working - Used to determine how old the account is - in days.
|
||||
var/player_age = -1 //Used to determine how old the account is - in days.
|
||||
var/player_join_date = null //Date that this account was first seen in the server
|
||||
var/related_accounts_ip = "Requires database" //So admins know why it isn't working - Used to determine what other accounts previously logged in from this ip
|
||||
var/related_accounts_cid = "Requires database" //So admins know why it isn't working - Used to determine what other accounts previously logged in from this computer id
|
||||
var/account_join_date = null //Date of byond account creation in ISO 8601 format
|
||||
var/account_age = -1 //Age of byond account in days
|
||||
|
||||
preload_rsc = PRELOAD_RSC
|
||||
|
||||
@@ -62,4 +65,4 @@
|
||||
var/connection_timeofday //world.timeofday they connected
|
||||
|
||||
var/inprefs = FALSE
|
||||
var/list/topiclimiter
|
||||
var/list/topiclimiter
|
||||
|
||||
@@ -80,8 +80,7 @@
|
||||
*/
|
||||
|
||||
//Logs all hrefs
|
||||
if(config && config.log_hrefs && GLOB.href_logfile)
|
||||
GLOB.href_logfile << "<small>[time_stamp(show_ds = TRUE)] [src] (usr:[usr])</small> || [hsrc ? "[hsrc] " : ""][href]<br>"
|
||||
GLOB.world_href_log << "<small>[time_stamp(show_ds = TRUE)] [src] (usr:[usr])</small> || [hsrc ? "[hsrc] " : ""][href]<br>"
|
||||
|
||||
// Admin PM
|
||||
if(href_list["priv_msg"])
|
||||
@@ -289,16 +288,11 @@ GLOBAL_LIST(external_rsc_urls)
|
||||
mentor_memo_output("Show") */
|
||||
|
||||
add_verbs_from_config()
|
||||
set_client_age_from_db()
|
||||
set_client_age_from_db(tdata)
|
||||
var/cached_player_age = player_age //we have to cache this because other shit may change it and we need it's current value now down below.
|
||||
if (isnum(cached_player_age) && cached_player_age == -1) //first connection
|
||||
player_age = 0
|
||||
if(!IsGuestKey(key) && SSdbcore.IsConnected())
|
||||
findJoinDate()
|
||||
player_age = 0
|
||||
|
||||
sync_client_with_db(tdata)
|
||||
|
||||
|
||||
if (isnum(cached_player_age) && cached_player_age == -1) //first connection
|
||||
if (config.panic_bunker && !holder && !(ckey in GLOB.deadmins))
|
||||
log_access("Failed Login: [key] - New account attempting to connect during panic bunker")
|
||||
@@ -311,20 +305,19 @@ GLOBAL_LIST(external_rsc_urls)
|
||||
qdel(src)
|
||||
return 0
|
||||
|
||||
|
||||
if (config.notify_new_player_age >= 0)
|
||||
message_admins("New user: [key_name_admin(src)] is connecting here for the first time.")
|
||||
if (config.irc_first_connection_alert)
|
||||
send2irc_adminless_only("New-user", "[key_name(src)] is connecting for the first time!")
|
||||
|
||||
player_age = 0 // set it from -1 to 0 so the job selection code doesn't have a panic attack
|
||||
|
||||
else if (isnum(player_age) && player_age < config.notify_new_player_age)
|
||||
message_admins("New user: [key_name_admin(src)] just connected with an age of [player_age] day[(player_age==1?"":"s")]")
|
||||
|
||||
if(!IsGuestKey(key) && SSdbcore.IsConnected())
|
||||
findJoinDate()
|
||||
|
||||
sync_client_with_db(tdata)
|
||||
else if (isnum(cached_player_age) && cached_player_age < config.notify_new_player_age)
|
||||
message_admins("New user: [key_name_admin(src)] just connected with an age of [cached_player_age] day[(player_age==1?"":"s")]")
|
||||
if(config.use_account_age_for_jobs && account_age >= 0)
|
||||
player_age = account_age
|
||||
if(account_age >= 0 && account_age < config.notify_new_player_account_age)
|
||||
message_admins("[key_name_admin(src)] (IP: [address], ID: [computer_id]) is a new BYOND account [account_age] day[(account_age==1?"":"s")] old, created on [account_join_date].")
|
||||
if (config.irc_first_connection_alert)
|
||||
send2irc_adminless_only("new_byond_user", "[key_name(src)] (IP: [address], ID: [computer_id]) is a new BYOND account [account_age] day[(account_age==1?"":"s")] old, created on [account_join_date].")
|
||||
get_message_output("watchlist entry", ckey)
|
||||
check_ip_intel()
|
||||
|
||||
@@ -360,6 +353,27 @@ GLOBAL_LIST(external_rsc_urls)
|
||||
|
||||
hook_vr("client_new",list(src))
|
||||
|
||||
var/list/topmenus = GLOB.menulist[/datum/menu]
|
||||
for (var/thing in topmenus)
|
||||
var/datum/menu/topmenu = thing
|
||||
var/topmenuname = "[topmenu]"
|
||||
if (topmenuname == "[topmenu.type]")
|
||||
var/list/tree = splittext(topmenuname, "/")
|
||||
topmenuname = tree[tree.len]
|
||||
winset(src, "[topmenu.type]", "parent=menu;name=[url_encode(topmenuname)]")
|
||||
var/list/entries = topmenu.Generate_list(src)
|
||||
for (var/child in entries)
|
||||
winset(src, "[url_encode(child)]", "[entries[child]]")
|
||||
if (!ispath(child, /datum/menu))
|
||||
var/atom/verb/verbpath = child
|
||||
if (copytext(verbpath.name,1,2) != "@")
|
||||
new child(src)
|
||||
|
||||
for (var/thing in prefs.menuoptions)
|
||||
var/datum/menu/menuitem = GLOB.menulist[thing]
|
||||
if (menuitem)
|
||||
menuitem.Load_checked(src)
|
||||
|
||||
//////////////
|
||||
//DISCONNECT//
|
||||
//////////////
|
||||
@@ -370,8 +384,8 @@ GLOBAL_LIST(external_rsc_urls)
|
||||
adminGreet(1)
|
||||
holder.owner = null
|
||||
GLOB.admins -= src
|
||||
|
||||
if (!GLOB.admins.len && SSticker.current_state == GAME_STATE_PLAYING) //Only report this stuff if we are currently playing.
|
||||
|
||||
if (!GLOB.admins.len && SSticker.IsRoundInProgress()) //Only report this stuff if we are currently playing.
|
||||
if(!GLOB.admins.len) //Apparently the admin logging out is no longer an admin at this point, so we have to check this towards 0 and not towards 1. Awell.
|
||||
var/cheesy_message = pick(
|
||||
"I have no admins online!",\
|
||||
@@ -396,7 +410,7 @@ GLOBAL_LIST(external_rsc_urls)
|
||||
"Sometimes when I have sex, I think about putting an entire peanut butter and jelly sandwich in the VCR.",\
|
||||
"Forever alone :("\
|
||||
)
|
||||
|
||||
|
||||
send2irc("Server", "[cheesy_message] (No admins online)")
|
||||
|
||||
GLOB.ahelp_tickets.ClientLogout(src)
|
||||
@@ -410,70 +424,86 @@ GLOBAL_LIST(external_rsc_urls)
|
||||
/client/Destroy()
|
||||
return QDEL_HINT_HARDDEL_NOW
|
||||
|
||||
/client/proc/set_client_age_from_db()
|
||||
/client/proc/set_client_age_from_db(connectiontopic)
|
||||
if (IsGuestKey(src.key))
|
||||
return
|
||||
|
||||
if(!SSdbcore.Connect())
|
||||
return
|
||||
|
||||
var/sql_ckey = sanitizeSQL(src.ckey)
|
||||
|
||||
var/datum/DBQuery/query_get_client_age = SSdbcore.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'")
|
||||
if(!query_get_client_age.Execute())
|
||||
return
|
||||
|
||||
while(query_get_client_age.NextRow())
|
||||
player_age = text2num(query_get_client_age.item[2])
|
||||
return
|
||||
|
||||
//no match mark it as a first connection for use in client/New()
|
||||
player_age = -1
|
||||
|
||||
|
||||
/client/proc/sync_client_with_db(connectiontopic)
|
||||
if (IsGuestKey(src.key))
|
||||
return
|
||||
|
||||
if (!SSdbcore.Connect())
|
||||
return
|
||||
|
||||
var/sql_ckey = sanitizeSQL(ckey)
|
||||
|
||||
var/datum/DBQuery/query_get_ip = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ip = INET_ATON('[address]') AND ckey != '[sql_ckey]'")
|
||||
query_get_ip.Execute()
|
||||
var/datum/DBQuery/query_get_related_ip = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ip = INET_ATON('[address]') AND ckey != '[sql_ckey]'")
|
||||
query_get_related_ip.Execute()
|
||||
related_accounts_ip = ""
|
||||
while(query_get_ip.NextRow())
|
||||
related_accounts_ip += "[query_get_ip.item[1]], "
|
||||
|
||||
var/datum/DBQuery/query_get_cid = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE computerid = '[computer_id]' AND ckey != '[sql_ckey]'")
|
||||
if(!query_get_cid.Execute())
|
||||
while(query_get_related_ip.NextRow())
|
||||
related_accounts_ip += "[query_get_related_ip.item[1]], "
|
||||
var/datum/DBQuery/query_get_related_cid = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE computerid = '[computer_id]' AND ckey != '[sql_ckey]'")
|
||||
if(!query_get_related_cid.Execute())
|
||||
return
|
||||
related_accounts_cid = ""
|
||||
while (query_get_cid.NextRow())
|
||||
related_accounts_cid += "[query_get_cid.item[1]], "
|
||||
|
||||
while (query_get_related_cid.NextRow())
|
||||
related_accounts_cid += "[query_get_related_cid.item[1]], "
|
||||
var/admin_rank = "Player"
|
||||
if (src.holder && src.holder.rank)
|
||||
admin_rank = src.holder.rank.name
|
||||
else
|
||||
if (check_randomizer(connectiontopic))
|
||||
return
|
||||
|
||||
var/sql_ip = sanitizeSQL(src.address)
|
||||
var/sql_computerid = sanitizeSQL(src.computer_id)
|
||||
var/sql_ip = sanitizeSQL(address)
|
||||
var/sql_computerid = sanitizeSQL(computer_id)
|
||||
var/sql_admin_rank = sanitizeSQL(admin_rank)
|
||||
|
||||
|
||||
var/datum/DBQuery/query_log_player = SSdbcore.NewQuery("INSERT INTO [format_table_name("player")] (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[sql_ckey]', Now(), Now(), INET_ATON('[sql_ip]'), '[sql_computerid]', '[sql_admin_rank]') ON DUPLICATE KEY UPDATE lastseen = VALUES(lastseen), ip = VALUES(ip), computerid = VALUES(computerid), lastadminrank = VALUES(lastadminrank)")
|
||||
if(!query_log_player.Execute())
|
||||
var/new_player
|
||||
var/datum/DBQuery/query_client_in_db = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'")
|
||||
if(!query_client_in_db.Execute())
|
||||
return
|
||||
|
||||
//Logging player access
|
||||
|
||||
if(!query_client_in_db.NextRow())
|
||||
new_player = 1
|
||||
account_join_date = sanitizeSQL(findJoinDate())
|
||||
var/datum/DBQuery/query_add_player = SSdbcore.NewQuery("INSERT INTO [format_table_name("player")] (`ckey`, `firstseen`, `lastseen`, `ip`, `computerid`, `lastadminrank`, `accountjoindate`) VALUES ('[sql_ckey]', Now(), Now(), INET_ATON('[sql_ip]'), '[sql_computerid]', '[sql_admin_rank]', [account_join_date ? "'[account_join_date]'" : "NULL"])")
|
||||
if(!query_add_player.Execute())
|
||||
return
|
||||
if(!account_join_date)
|
||||
account_join_date = "Error"
|
||||
account_age = -1
|
||||
var/datum/DBQuery/query_get_client_age = SSdbcore.NewQuery("SELECT firstseen, DATEDIFF(Now(),firstseen), accountjoindate, DATEDIFF(Now(),accountjoindate) FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'")
|
||||
if(!query_get_client_age.Execute())
|
||||
return
|
||||
if(query_get_client_age.NextRow())
|
||||
player_join_date = query_get_client_age.item[1]
|
||||
player_age = text2num(query_get_client_age.item[2])
|
||||
if(!account_join_date)
|
||||
account_join_date = query_get_client_age.item[3]
|
||||
account_age = text2num(query_get_client_age.item[4])
|
||||
if(!account_age)
|
||||
account_join_date = sanitizeSQL(findJoinDate())
|
||||
if(!account_join_date)
|
||||
account_age = -1
|
||||
else
|
||||
var/datum/DBQuery/query_datediff = SSdbcore.NewQuery("SELECT DATEDIFF(Now(),[account_join_date])")
|
||||
if(!query_datediff.Execute())
|
||||
return
|
||||
if(query_datediff.NextRow())
|
||||
account_age = text2num(query_datediff.item[1])
|
||||
if(!new_player)
|
||||
var/datum/DBQuery/query_log_player = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET lastseen = Now(), ip = INET_ATON('[sql_ip]'), computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]', accountjoindate = [account_join_date ? "'[account_join_date]'" : "NULL"] WHERE ckey = '[sql_ckey]'")
|
||||
if(!query_log_player.Execute())
|
||||
return
|
||||
if(!account_join_date)
|
||||
account_join_date = "Error"
|
||||
var/datum/DBQuery/query_log_connection = SSdbcore.NewQuery("INSERT INTO `[format_table_name("connection_log")]` (`id`,`datetime`,`server_ip`,`server_port`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),INET_ATON('[world.internet_address]'),'[world.port]','[sql_ckey]',INET_ATON('[sql_ip]'),'[sql_computerid]')")
|
||||
query_log_connection.Execute()
|
||||
|
||||
/client/proc/findJoinDate()
|
||||
var/list/http = world.Export("http://byond.com/members/[ckey]?format=text")
|
||||
if(!http)
|
||||
log_world("Failed to connect to byond age check for [ckey]")
|
||||
return
|
||||
var/F = file2text(http["CONTENT"])
|
||||
if(F)
|
||||
var/regex/R = regex("joined = \"(\\d{4}-\\d{2}-\\d{2})\"")
|
||||
if(R.Find(F))
|
||||
. = R.group[1]
|
||||
else
|
||||
CRASH("Age check regex failed for [src.ckey]")
|
||||
|
||||
/client/proc/check_randomizer(topic)
|
||||
. = FALSE
|
||||
if (connection != "seeker")
|
||||
|
||||
@@ -168,6 +168,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
var/uplink_spawn_loc = UPLINK_PDA
|
||||
|
||||
var/list/menuoptions
|
||||
|
||||
//citadel code
|
||||
var/arousable = TRUE //Allows players to disable arousal from the character creation menu
|
||||
var/flavor_text = ""
|
||||
@@ -194,6 +196,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(!loaded_preferences_successfully)
|
||||
save_preferences()
|
||||
save_character() //let's save this new random character so it doesn't keep generating new ones.
|
||||
menuoptions = list()
|
||||
return
|
||||
|
||||
/datum/preferences/proc/ShowChoices(mob/user)
|
||||
@@ -790,7 +793,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(href_list["jobbancheck"])
|
||||
var/job = sanitizeSQL(href_list["jobbancheck"])
|
||||
var/sql_ckey = sanitizeSQL(user.ckey)
|
||||
var/datum/DBQuery/query_get_jobban = SSdbcore.NewQuery("SELECT reason, bantime, duration, expiration_time, a_ckey FROM [format_table_name("ban")] WHERE ckey = '[sql_ckey]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned) AND job = '[job]'")
|
||||
var/datum/DBQuery/query_get_jobban = SSdbcore.NewQuery("SELECT reason, bantime, duration, expiration_time, a_ckey FROM [format_table_name("ban")] WHERE ckey = '[sql_ckey]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned) AND job = '[job]'")
|
||||
if(!query_get_jobban.warn_execute())
|
||||
return
|
||||
if(query_get_jobban.NextRow())
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//This is the lowest supported version, anything below this is completely obsolete and the entire savefile will be wiped.
|
||||
#define SAVEFILE_VERSION_MIN 10
|
||||
#define SAVEFILE_VERSION_MIN 15
|
||||
|
||||
//This is the current version, anything below this will attempt to update (if it's not obsolete)
|
||||
#define SAVEFILE_VERSION_MAX 20
|
||||
@@ -88,15 +88,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
|
||||
/datum/preferences/proc/update_preferences(current_version, savefile/S)
|
||||
if(current_version < 10)
|
||||
toggles |= MEMBER_PUBLIC
|
||||
if(current_version < 11)
|
||||
chat_toggles = TOGGLES_DEFAULT_CHAT
|
||||
toggles = TOGGLES_DEFAULT
|
||||
if(current_version < 12)
|
||||
ignoring = list()
|
||||
if(current_version < 15)
|
||||
toggles |= SOUND_ANNOUNCEMENTS
|
||||
|
||||
|
||||
//should this proc get fairly long (say 3 versions long),
|
||||
@@ -106,16 +97,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
//It's only really meant to avoid annoying frequent players
|
||||
//if your savefile is 3 months out of date, then 'tough shit'.
|
||||
/datum/preferences/proc/update_character(current_version, savefile/S)
|
||||
if(pref_species && !(pref_species.id in GLOB.roundstart_species))
|
||||
var/rando_race = pick(config.roundstart_races)
|
||||
pref_species = new rando_race()
|
||||
|
||||
if(current_version < 13 || !istext(backbag))
|
||||
switch(backbag)
|
||||
if(2)
|
||||
backbag = DSATCHEL
|
||||
else
|
||||
backbag = DBACKPACK
|
||||
if(current_version < 16)
|
||||
var/berandom
|
||||
S["userandomjob"] >> berandom
|
||||
@@ -186,12 +167,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["tgui_fancy"] >> tgui_fancy
|
||||
S["tgui_lock"] >> tgui_lock
|
||||
S["windowflash"] >> windowflashing
|
||||
S["be_special"] >> be_special
|
||||
|
||||
if(islist(S["be_special"]))
|
||||
S["be_special"] >> be_special
|
||||
else //force update and store the old bitflag version of be_special
|
||||
needs_update = 12
|
||||
S["be_special"] >> old_be_special
|
||||
|
||||
S["default_slot"] >> default_slot
|
||||
S["chat_toggles"] >> chat_toggles
|
||||
@@ -207,6 +184,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["uses_glasses_colour"]>> uses_glasses_colour
|
||||
S["clientfps"] >> clientfps
|
||||
S["parallax"] >> parallax
|
||||
S["menuoptions"] >> menuoptions
|
||||
//citadel code
|
||||
S["arousable"] >> arousable
|
||||
|
||||
@@ -231,6 +209,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit))
|
||||
ghost_accs = sanitize_inlist(ghost_accs, GLOB.ghost_accs_options, GHOST_ACCS_DEFAULT_OPTION)
|
||||
ghost_others = sanitize_inlist(ghost_others, GLOB.ghost_others_options, GHOST_OTHERS_DEFAULT_OPTION)
|
||||
menuoptions = SANITIZE_LIST(menuoptions)
|
||||
be_special = SANITIZE_LIST(be_special)
|
||||
|
||||
|
||||
return 1
|
||||
|
||||
@@ -267,6 +248,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["uses_glasses_colour"]<< uses_glasses_colour
|
||||
S["clientfps"] << clientfps
|
||||
S["parallax"] << parallax
|
||||
S["menuoptions"] << menuoptions
|
||||
//citadel code
|
||||
S["arousable"] << arousable
|
||||
|
||||
@@ -299,9 +281,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
if(config.mutant_races && species_id && (species_id in GLOB.roundstart_species))
|
||||
var/newtype = GLOB.roundstart_species[species_id]
|
||||
pref_species = new newtype()
|
||||
else
|
||||
else if (config.roundstart_races.len)
|
||||
var/rando_race = pick(config.roundstart_races)
|
||||
pref_species = new rando_race()
|
||||
if (rando_race)
|
||||
pref_species = new rando_race()
|
||||
|
||||
if(!S["features["mcolor"]"] || S["features["mcolor"]"] == "#000")
|
||||
S["features["mcolor"]"] << "#FFF"
|
||||
@@ -565,7 +548,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
#undef SAVEFILE_VERSION_MAX
|
||||
#undef SAVEFILE_VERSION_MIN
|
||||
/*
|
||||
|
||||
#ifdef TESTING
|
||||
//DEBUG
|
||||
//Some crude tools for testing savefiles
|
||||
//path is the savefile path
|
||||
@@ -576,4 +560,5 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
/client/verb/savefile_import(path as text)
|
||||
var/savefile/S = new /savefile(path)
|
||||
S.ImportText("/",file("[path].txt"))
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -1,162 +1,249 @@
|
||||
//toggles
|
||||
/client/verb/toggle_ghost_ears()
|
||||
set name = "Show/Hide GhostEars"
|
||||
set category = "Preferences"
|
||||
set desc = ".Toggle Between seeing all mob speech, and only speech of nearby mobs"
|
||||
prefs.chat_toggles ^= CHAT_GHOSTEARS
|
||||
to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].")
|
||||
prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb","Toggle Ghost Ears|[prefs.chat_toggles & CHAT_GHOSTEARS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
//this works as is to create a single checked item, but has no back end code for toggleing the check yet
|
||||
#define TOGGLE_CHECKBOX(PARENT, CHILD) PARENT/CHILD/abstract = TRUE;PARENT/CHILD/checkbox = CHECKBOX_TOGGLE;PARENT/CHILD/verb/CHILD
|
||||
|
||||
/client/verb/toggle_ghost_sight()
|
||||
set name = "Show/Hide GhostSight"
|
||||
set category = "Preferences"
|
||||
set desc = ".Toggle Between seeing all mob emotes, and only emotes of nearby mobs"
|
||||
prefs.chat_toggles ^= CHAT_GHOSTSIGHT
|
||||
to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].")
|
||||
prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb","Toggle Ghost Sight|[prefs.chat_toggles & CHAT_GHOSTSIGHT]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
//Example usage TOGGLE_CHECKBOX(datum/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)()
|
||||
|
||||
/client/verb/toggle_ghost_whispers()
|
||||
set name = "Show/Hide GhostWhispers"
|
||||
set category = "Preferences"
|
||||
set desc = ".Toggle between hearing all whispers, and only whispers of nearby mobs"
|
||||
prefs.chat_toggles ^= CHAT_GHOSTWHISPER
|
||||
to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTWHISPER) ? "see all whispers in the world" : "only see whispers from nearby mobs"].")
|
||||
prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb","Toggle Ghost Whispers|[prefs.chat_toggles & CHAT_GHOSTWHISPER]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
//override because we don't want to save preferences twice.
|
||||
/datum/menu/Settings/Set_checked(client/C, verbpath)
|
||||
if (checkbox == CHECKBOX_GROUP)
|
||||
C.prefs.menuoptions[type] = verbpath
|
||||
else if (checkbox == CHECKBOX_TOGGLE)
|
||||
var/checked = Get_checked(C)
|
||||
C.prefs.menuoptions[type] = !checked
|
||||
winset(C, "[verbpath]", "is-checked = [!checked]")
|
||||
|
||||
/client/verb/toggle_ghost_radio()
|
||||
set name = "Show/Hide GhostRadio"
|
||||
/datum/menu/Settings/verb/setup_character()
|
||||
set name = "Game Preferences"
|
||||
set category = "Preferences"
|
||||
set desc = ".Enable or disable hearing radio chatter as a ghost"
|
||||
prefs.chat_toggles ^= CHAT_GHOSTRADIO
|
||||
to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTRADIO) ? "see radio chatter" : "not see radio chatter"].")
|
||||
prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb","Toggle Ghost Radio|[prefs.chat_toggles & CHAT_GHOSTRADIO]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! //social experiment, increase the generation whenever you copypaste this shamelessly GENERATION 1
|
||||
set desc = "Open Game Preferences Window"
|
||||
usr.client.prefs.current_tab = 1
|
||||
usr.client.prefs.ShowChoices(usr)
|
||||
|
||||
//toggles
|
||||
/datum/menu/Settings/Ghost/chatterbox
|
||||
name = "Chat Box Spam"
|
||||
|
||||
/client/verb/toggle_ghost_pda()
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)()
|
||||
set name = "Show/Hide GhostEars"
|
||||
set category = "Preferences"
|
||||
set desc = "See All Speech"
|
||||
usr.client.prefs.chat_toggles ^= CHAT_GHOSTEARS
|
||||
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].")
|
||||
usr.client.prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb","Toggle Ghost Ears|[usr.client.prefs.chat_toggles & CHAT_GHOSTEARS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_ears/Get_checked(client/C)
|
||||
return C.prefs.chat_toggles & CHAT_GHOSTEARS
|
||||
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_sight)()
|
||||
set name = "Show/Hide GhostSight"
|
||||
set category = "Preferences"
|
||||
set desc = "See All Emotes"
|
||||
usr.client.prefs.chat_toggles ^= CHAT_GHOSTSIGHT
|
||||
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].")
|
||||
usr.client.prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb","Toggle Ghost Sight|[usr.client.prefs.chat_toggles & CHAT_GHOSTSIGHT]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_sight/Get_checked(client/C)
|
||||
return C.prefs.chat_toggles & CHAT_GHOSTSIGHT
|
||||
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_whispers)()
|
||||
set name = "Show/Hide GhostWhispers"
|
||||
set category = "Preferences"
|
||||
set desc = "See All Whispers"
|
||||
usr.client.prefs.chat_toggles ^= CHAT_GHOSTWHISPER
|
||||
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTWHISPER) ? "see all whispers in the world" : "only see whispers from nearby mobs"].")
|
||||
usr.client.prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb","Toggle Ghost Whispers|[usr.client.prefs.chat_toggles & CHAT_GHOSTWHISPER]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_whispers/Get_checked(client/C)
|
||||
return C.prefs.chat_toggles & CHAT_GHOSTWHISPER
|
||||
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_radio)()
|
||||
set name = "Show/Hide GhostRadio"
|
||||
set category = "Preferences"
|
||||
set desc = "See All Radio Chatter"
|
||||
usr.client.prefs.chat_toggles ^= CHAT_GHOSTRADIO
|
||||
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTRADIO) ? "see radio chatter" : "not see radio chatter"].")
|
||||
usr.client.prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb","Toggle Ghost Radio|[usr.client.prefs.chat_toggles & CHAT_GHOSTRADIO]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! //social experiment, increase the generation whenever you copypaste this shamelessly GENERATION 1
|
||||
/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_radio/Get_checked(client/C)
|
||||
return C.prefs.chat_toggles & CHAT_GHOSTRADIO
|
||||
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_pda)()
|
||||
set name = "Show/Hide GhostPDA"
|
||||
set category = "Preferences"
|
||||
set desc = ".Toggle Between seeing all mob pda messages, and only pda messages of nearby mobs"
|
||||
prefs.chat_toggles ^= CHAT_GHOSTPDA
|
||||
to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTPDA) ? "see all pda messages in the world" : "only see pda messages from nearby mobs"].")
|
||||
prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb","Toggle Ghost PDA|[prefs.chat_toggles & CHAT_GHOSTPDA]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
set category = "Preferences"
|
||||
set desc = "See All PDA Messages"
|
||||
usr.client.prefs.chat_toggles ^= CHAT_GHOSTPDA
|
||||
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTPDA) ? "see all pda messages in the world" : "only see pda messages from nearby mobs"].")
|
||||
usr.client.prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb","Toggle Ghost PDA|[usr.client.prefs.chat_toggles & CHAT_GHOSTPDA]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_pda/Get_checked(client/C)
|
||||
return C.prefs.chat_toggles & CHAT_GHOSTPDA
|
||||
|
||||
/datum/menu/Settings/Ghost/chatterbox/Events
|
||||
name = "Events"
|
||||
|
||||
//please be aware that the following two verbs have inverted stat output, so that "Toggle Deathrattle|1" still means you activated it
|
||||
/client/verb/toggle_deathrattle()
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox/Events, toggle_deathrattle)()
|
||||
set name = "Toggle Deathrattle"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggle recieving a message in deadchat when sentient mobs die."
|
||||
prefs.toggles ^= DISABLE_DEATHRATTLE
|
||||
prefs.save_preferences()
|
||||
to_chat(usr, "You will [(prefs.toggles & DISABLE_DEATHRATTLE) ? "no longer" : "now"] get messages when a sentient mob dies.")
|
||||
SSblackbox.add_details("preferences_verb", "Toggle Deathrattle|[!(prefs.toggles & DISABLE_DEATHRATTLE)]") //If you are copy-pasting this, maybe you should spend some time reading the comments.
|
||||
|
||||
/client/verb/toggle_arrivalrattle()
|
||||
set category = "Preferences"
|
||||
set desc = "Death"
|
||||
usr.client.prefs.toggles ^= DISABLE_DEATHRATTLE
|
||||
usr.client.prefs.save_preferences()
|
||||
to_chat(usr, "You will [(usr.client.prefs.toggles & DISABLE_DEATHRATTLE) ? "no longer" : "now"] get messages when a sentient mob dies.")
|
||||
SSblackbox.add_details("preferences_verb", "Toggle Deathrattle|[!(usr.client.prefs.toggles & DISABLE_DEATHRATTLE)]") //If you are copy-pasting this, maybe you should spend some time reading the comments.
|
||||
/datum/menu/Settings/Ghost/chatterbox/Events/toggle_deathrattle/Get_checked(client/C)
|
||||
return !(C.prefs.toggles & DISABLE_DEATHRATTLE)
|
||||
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox/Events, toggle_arrivalrattle)()
|
||||
set name = "Toggle Arrivalrattle"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggle recieving a message in deadchat when someone joins the station."
|
||||
prefs.toggles ^= DISABLE_ARRIVALRATTLE
|
||||
to_chat(usr, "You will [(prefs.toggles & DISABLE_ARRIVALRATTLE) ? "no longer" : "now"] get messages when someone joins the station.")
|
||||
prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb", "Toggle Arrivalrattle|[!(prefs.toggles & DISABLE_ARRIVALRATTLE)]") //If you are copy-pasting this, maybe you should rethink where your life went so wrong.
|
||||
|
||||
/client/verb/togglemidroundantag()
|
||||
set category = "Preferences"
|
||||
set desc = "New Player Arrival"
|
||||
usr.client.prefs.toggles ^= DISABLE_ARRIVALRATTLE
|
||||
to_chat(usr, "You will [(usr.client.prefs.toggles & DISABLE_ARRIVALRATTLE) ? "no longer" : "now"] get messages when someone joins the station.")
|
||||
usr.client.prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb", "Toggle Arrivalrattle|[!(usr.client.prefs.toggles & DISABLE_ARRIVALRATTLE)]") //If you are copy-pasting this, maybe you should rethink where your life went so wrong.
|
||||
/datum/menu/Settings/Ghost/chatterbox/Events/toggle_arrivalrattle/Get_checked(client/C)
|
||||
return !(C.prefs.toggles & DISABLE_ARRIVALRATTLE)
|
||||
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost, togglemidroundantag)()
|
||||
set name = "Toggle Midround Antagonist"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggles whether or not you will be considered for antagonist status given during a round."
|
||||
prefs.toggles ^= MIDROUND_ANTAG
|
||||
prefs.save_preferences()
|
||||
to_chat(src, "You will [(prefs.toggles & MIDROUND_ANTAG) ? "now" : "no longer"] be considered for midround antagonist positions.")
|
||||
SSblackbox.add_details("preferences_verb","Toggle Midround Antag|[prefs.toggles & MIDROUND_ANTAG]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/verb/toggletitlemusic()
|
||||
set category = "Preferences"
|
||||
set desc = "Midround Antagonist"
|
||||
usr.client.prefs.toggles ^= MIDROUND_ANTAG
|
||||
usr.client.prefs.save_preferences()
|
||||
to_chat(usr, "You will [(usr.client.prefs.toggles & MIDROUND_ANTAG) ? "now" : "no longer"] be considered for midround antagonist positions.")
|
||||
SSblackbox.add_details("preferences_verb","Toggle Midround Antag|[usr.client.prefs.toggles & MIDROUND_ANTAG]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/datum/menu/Settings/Ghost/togglemidroundantag/Get_checked(client/C)
|
||||
return C.prefs.toggles & MIDROUND_ANTAG
|
||||
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggletitlemusic)()
|
||||
set name = "Hear/Silence LobbyMusic"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggles hearing the GameLobby music"
|
||||
prefs.toggles ^= SOUND_LOBBY
|
||||
prefs.save_preferences()
|
||||
if(prefs.toggles & SOUND_LOBBY)
|
||||
to_chat(src, "You will now hear music in the game lobby.")
|
||||
if(isnewplayer(mob))
|
||||
playtitlemusic()
|
||||
set desc = "Hear Music In Lobby"
|
||||
usr.client.prefs.toggles ^= SOUND_LOBBY
|
||||
usr.client.prefs.save_preferences()
|
||||
if(usr.client.prefs.toggles & SOUND_LOBBY)
|
||||
to_chat(usr, "You will now hear music in the game lobby.")
|
||||
if(isnewplayer(usr))
|
||||
usr.client.playtitlemusic()
|
||||
else
|
||||
to_chat(src, "You will no longer hear music in the game lobby.")
|
||||
mob.stop_sound_channel(CHANNEL_LOBBYMUSIC)
|
||||
SSblackbox.add_details("preferences_verb","Toggle Lobby Music|[prefs.toggles & SOUND_LOBBY]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
to_chat(usr, "You will no longer hear music in the game lobby.")
|
||||
usr.stop_sound_channel(CHANNEL_LOBBYMUSIC)
|
||||
SSblackbox.add_details("preferences_verb","Toggle Lobby Music|[usr.client.prefs.toggles & SOUND_LOBBY]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/datum/menu/Settings/Sound/toggletitlemusic/Get_checked(client/C)
|
||||
return C.prefs.toggles & SOUND_LOBBY
|
||||
|
||||
|
||||
/client/verb/togglemidis()
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, togglemidis)()
|
||||
set name = "Hear/Silence Midis"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggles hearing sounds uploaded by admins"
|
||||
prefs.toggles ^= SOUND_MIDI
|
||||
prefs.save_preferences()
|
||||
if(prefs.toggles & SOUND_MIDI)
|
||||
to_chat(src, "You will now hear any sounds uploaded by admins.")
|
||||
set desc = "Hear Admin Triggered Sounds (Midis)"
|
||||
usr.client.prefs.toggles ^= SOUND_MIDI
|
||||
usr.client.prefs.save_preferences()
|
||||
if(usr.client.prefs.toggles & SOUND_MIDI)
|
||||
to_chat(usr, "You will now hear any sounds uploaded by admins.")
|
||||
else
|
||||
to_chat(src, "You will no longer hear sounds uploaded by admins")
|
||||
mob.stop_sound_channel(CHANNEL_ADMIN)
|
||||
SSblackbox.add_details("preferences_verb","Toggle Hearing Midis|[prefs.toggles & SOUND_MIDI]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
to_chat(usr, "You will no longer hear sounds uploaded by admins")
|
||||
usr.stop_sound_channel(CHANNEL_ADMIN)
|
||||
SSblackbox.add_details("preferences_verb","Toggle Hearing Midis|[usr.client.prefs.toggles & SOUND_MIDI]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/datum/menu/Settings/Sound/togglemidis/Get_checked(client/C)
|
||||
return C.prefs.toggles & SOUND_MIDI
|
||||
|
||||
/client/verb/stop_client_sounds()
|
||||
set name = "Stop Sounds"
|
||||
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_instruments)()
|
||||
set name = "Hear/Silence Instruments"
|
||||
set category = "Preferences"
|
||||
set desc = "Kills all currently playing sounds, use if admin taste in midis a shite"
|
||||
src << sound(null)
|
||||
SSblackbox.add_details("preferences_verb","Stop Self Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
set desc = "Hear In-game Instruments"
|
||||
usr.client.prefs.toggles ^= SOUND_INSTRUMENTS
|
||||
usr.client.prefs.save_preferences()
|
||||
if(usr.client.prefs.toggles & SOUND_INSTRUMENTS)
|
||||
to_chat(usr, "You will now hear people playing musical instruments.")
|
||||
else
|
||||
to_chat(usr, "You will no longer hear musical instruments.")
|
||||
SSblackbox.add_details("preferences_verb","Toggle Instruments|[usr.client.prefs.toggles & SOUND_INSTRUMENTS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/datum/menu/Settings/Sound/toggle_instruments/Get_checked(client/C)
|
||||
return C.prefs.toggles & SOUND_INSTRUMENTS
|
||||
|
||||
|
||||
/client/verb/listen_ooc()
|
||||
set name = "Show/Hide OOC"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggles seeing OutOfCharacter chat"
|
||||
prefs.chat_toggles ^= CHAT_OOC
|
||||
prefs.save_preferences()
|
||||
to_chat(src, "You will [(prefs.chat_toggles & CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel.")
|
||||
SSblackbox.add_details("preferences_verb","Toggle Seeing OOC|[prefs.chat_toggles & CHAT_OOC]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/verb/Toggle_Soundscape() //All new ambience should be added here so it works with this verb until someone better at things comes up with a fix that isn't awful
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, Toggle_Soundscape)()
|
||||
set name = "Hear/Silence Ambience"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggles hearing ambient sound effects"
|
||||
prefs.toggles ^= SOUND_AMBIENCE
|
||||
prefs.save_preferences()
|
||||
if(prefs.toggles & SOUND_AMBIENCE)
|
||||
to_chat(src, "You will now hear ambient sounds.")
|
||||
set desc = "Hear Ambient Sound Effects"
|
||||
usr.client.prefs.toggles ^= SOUND_AMBIENCE
|
||||
usr.client.prefs.save_preferences()
|
||||
if(usr.client.prefs.toggles & SOUND_AMBIENCE)
|
||||
to_chat(usr, "You will now hear ambient sounds.")
|
||||
else
|
||||
to_chat(src, "You will no longer hear ambient sounds.")
|
||||
src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 1)
|
||||
src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2)
|
||||
SSblackbox.add_details("preferences_verb","Toggle Ambience|[prefs.toggles & SOUND_AMBIENCE]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
to_chat(usr, "You will no longer hear ambient sounds.")
|
||||
usr << sound(null, repeat = 0, wait = 0, volume = 0, channel = 1)
|
||||
usr << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2)
|
||||
SSblackbox.add_details("preferences_verb","Toggle Ambience|[usr.client.prefs.toggles & SOUND_AMBIENCE]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/datum/menu/Settings/Sound/Toggle_Soundscape/Get_checked(client/C)
|
||||
return C.prefs.toggles & SOUND_AMBIENCE
|
||||
|
||||
// This needs a toggle because you people are awful and spammed terrible music
|
||||
/client/verb/toggle_instruments()
|
||||
set name = "Hear/Silence Instruments"
|
||||
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_ship_ambience)()
|
||||
set name = "Hear/Silence Ship Ambience"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggles hearing musical instruments like the violin and piano"
|
||||
prefs.toggles ^= SOUND_INSTRUMENTS
|
||||
prefs.save_preferences()
|
||||
if(prefs.toggles & SOUND_INSTRUMENTS)
|
||||
to_chat(src, "You will now hear people playing musical instruments.")
|
||||
set desc = "Hear Ship Ambience Roar"
|
||||
usr.client.prefs.toggles ^= SOUND_SHIP_AMBIENCE
|
||||
usr.client.prefs.save_preferences()
|
||||
if(usr.client.prefs.toggles & SOUND_SHIP_AMBIENCE)
|
||||
to_chat(usr, "You will now hear ship ambience.")
|
||||
else
|
||||
to_chat(src, "You will no longer hear musical instruments.")
|
||||
SSblackbox.add_details("preferences_verb","Toggle Instruments|[prefs.toggles & SOUND_INSTRUMENTS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
to_chat(usr, "You will no longer hear ship ambience.")
|
||||
usr << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2)
|
||||
usr.client.ambience_playing = 0
|
||||
SSblackbox.add_details("preferences_verb", "Toggle Ship Ambience|[usr.client.prefs.toggles & SOUND_SHIP_AMBIENCE]") //If you are copy-pasting this, I bet you read this comment expecting to see the same thing :^)
|
||||
/datum/menu/Settings/Sound/toggle_ship_ambience/Get_checked(client/C)
|
||||
return C.prefs.toggles & SOUND_SHIP_AMBIENCE
|
||||
|
||||
//Lots of people get headaches from the normal ship ambience, this is to prevent that
|
||||
/client/verb/toggle_ship_ambience()
|
||||
set name = "Hear/Silence Ship Ambience"
|
||||
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_announcement_sound)()
|
||||
set name = "Hear/Silence Announcements"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggles hearing generalized ship ambience, no matter your area."
|
||||
prefs.toggles ^= SOUND_SHIP_AMBIENCE
|
||||
prefs.save_preferences()
|
||||
if(prefs.toggles & SOUND_SHIP_AMBIENCE)
|
||||
to_chat(src, "You will now hear ship ambience.")
|
||||
set desc = "Hear Announcement Sound"
|
||||
usr.client.prefs.toggles ^= SOUND_ANNOUNCEMENTS
|
||||
to_chat(usr, "You will now [(usr.client.prefs.toggles & SOUND_ANNOUNCEMENTS) ? "hear announcement sounds" : "no longer hear announcements"].")
|
||||
usr.client.prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb","Toggle Announcement Sound|[usr.client.prefs.toggles & SOUND_ANNOUNCEMENTS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/datum/menu/Settings/Sound/toggle_announcement_sound/Get_checked(client/C)
|
||||
return C.prefs.toggles & SOUND_ANNOUNCEMENTS
|
||||
|
||||
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggleprayersounds)()
|
||||
set name = "Hear/Silence Prayer Sounds"
|
||||
set category = "Preferences"
|
||||
set desc = "Hear Prayer Sounds"
|
||||
usr.client.prefs.toggles ^= SOUND_PRAYERS
|
||||
usr.client.prefs.save_preferences()
|
||||
if(usr.client.prefs.toggles & SOUND_PRAYERS)
|
||||
to_chat(usr, "You will now hear prayer sounds.")
|
||||
else
|
||||
to_chat(src, "You will no longer hear ship ambience.")
|
||||
src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2)
|
||||
src.ambience_playing = 0
|
||||
SSblackbox.add_details("preferences_verb", "Toggle Ship Ambience|[prefs.toggles & SOUND_SHIP_AMBIENCE]") //If you are copy-pasting this, I bet you read this comment expecting to see the same thing :^)
|
||||
to_chat(usr, "You will no longer prayer sounds.")
|
||||
SSblackbox.add_details("admin_toggle", "Toggle Prayer Sounds|[usr.client.prefs.toggles & SOUND_PRAYERS]")
|
||||
/datum/menu/Settings/Sound/toggleprayersounds/Get_checked(client/C)
|
||||
return C.prefs.toggles & SOUND_PRAYERS
|
||||
|
||||
|
||||
/datum/menu/Settings/Sound/verb/stop_client_sounds()
|
||||
set name = "Stop Sounds"
|
||||
set category = "Preferences"
|
||||
set desc = "Stop Current Sounds"
|
||||
usr << sound(null)
|
||||
SSblackbox.add_details("preferences_verb","Stop Self Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
TOGGLE_CHECKBOX(/datum/menu/Settings, listen_ooc)()
|
||||
set name = "Show/Hide OOC"
|
||||
set category = "Preferences"
|
||||
set desc = "Show OOC Chat"
|
||||
usr.client.prefs.chat_toggles ^= CHAT_OOC
|
||||
usr.client.prefs.save_preferences()
|
||||
to_chat(usr, "You will [(usr.client.prefs.chat_toggles & CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel.")
|
||||
SSblackbox.add_details("preferences_verb","Toggle Seeing OOC|[usr.client.prefs.chat_toggles & CHAT_OOC]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/datum/menu/Settings/listen_ooc/Get_checked(client/C)
|
||||
return C.prefs.chat_toggles & CHAT_OOC
|
||||
|
||||
|
||||
GLOBAL_LIST_INIT(ghost_forms, list("ghost","ghostking","ghostian2","skeleghost","ghost_red","ghost_black", \
|
||||
"ghost_blue","ghost_yellow","ghost_green","ghost_pink", \
|
||||
@@ -246,13 +333,6 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
|
||||
prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb","Toggle Intent Selection|[prefs.toggles & INTENT_STYLE]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/verb/setup_character()
|
||||
set name = "Game Preferences"
|
||||
set category = "Preferences"
|
||||
set desc = "Allows you to access the Setup Character screen. Changes to your character won't take effect until next round, but other changes will."
|
||||
prefs.current_tab = 1
|
||||
prefs.ShowChoices(usr)
|
||||
|
||||
/client/verb/toggle_ghost_hud_pref()
|
||||
set name = "Toggle Ghost HUD"
|
||||
set category = "Preferences"
|
||||
@@ -278,15 +358,6 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
|
||||
to_chat(src, "<span class='notice'>You will no longer examine things you click on.</span>")
|
||||
SSblackbox.add_details("preferences_verb","Toggle Ghost Inquisitiveness|[prefs.inquisitive_ghost]")
|
||||
|
||||
/client/verb/toggle_announcement_sound()
|
||||
set name = "Hear/Silence Announcements"
|
||||
set category = "Preferences"
|
||||
set desc = ".Toggles hearing Central Command, Captain, VOX, and other announcement sounds"
|
||||
prefs.toggles ^= SOUND_ANNOUNCEMENTS
|
||||
to_chat(src, "You will now [(prefs.toggles & SOUND_ANNOUNCEMENTS) ? "hear announcement sounds" : "no longer hear announcements"].")
|
||||
prefs.save_preferences()
|
||||
SSblackbox.add_details("preferences_verb","Toggle Announcement Sound|[prefs.toggles & SOUND_ANNOUNCEMENTS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
//Admin Preferences
|
||||
/client/proc/toggleadminhelpsound()
|
||||
set name = "Hear/Silence Adminhelps"
|
||||
@@ -338,14 +409,3 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
|
||||
to_chat(src, "You will [(prefs.chat_toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.")
|
||||
SSblackbox.add_details("admin_toggle","Toggle Prayer Visibility|[prefs.chat_toggles & CHAT_PRAYER]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/verb/toggleprayersounds()
|
||||
set name = "Hear/Silence Prayer Sounds"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggles hearing pray sounds."
|
||||
prefs.toggles ^= SOUND_PRAYERS
|
||||
prefs.save_preferences()
|
||||
if(prefs.toggles & SOUND_PRAYERS)
|
||||
to_chat(src, "You will now hear prayer sounds.")
|
||||
else
|
||||
to_chat(src, "You will no longer prayer sounds.")
|
||||
SSblackbox.add_details("admin_toggle", "Toggle Prayer Sounds|[prefs.toggles & SOUND_PRAYERS]")
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
return
|
||||
if(confirm == "Yes")
|
||||
suiciding = 1
|
||||
log_game("[key_name(src)] (job: [job ? "[job]" : "None"]) commited suicide at [get_area(src)].")
|
||||
message_admins("[key_name(src)] (job: [job ? "[job]" : "None"]) commited suicide at [get_area(src)].")
|
||||
log_game("[key_name(src)] (job: [job ? "[job]" : "None"]) committed suicide at [get_area(src)].")
|
||||
message_admins("[key_name(src)] (job: [job ? "[job]" : "None"]) committed suicide at [get_area(src)].")
|
||||
var/obj/item/held_item = get_active_held_item()
|
||||
if(held_item)
|
||||
var/damagetype = held_item.suicide_act(src)
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
entry += " - <font color='black'><b>DEAD</b></font>"
|
||||
if(is_special_character(C.mob))
|
||||
entry += " - <b><font color='red'>Antagonist</font></b>"
|
||||
entry += " (<A HREF='?_src_=holder;adminmoreinfo=\ref[C.mob]'>?</A>)"
|
||||
entry += " [ADMIN_QUE(C.mob)]"
|
||||
entry += " ([round(C.avgping, 1)]ms)"
|
||||
Lines += entry
|
||||
else//If they don't have +ADMIN, only show hidden admins
|
||||
|
||||
@@ -161,7 +161,9 @@
|
||||
/obj/item/clothing/obj_break(damage_flag)
|
||||
if(!damaged_clothes)
|
||||
update_clothes_damaged_state(TRUE)
|
||||
to_chat(usr, "<span class='notice'>Your [src] starts to fall apart!")
|
||||
if(ismob(loc)) //It's not important enough to warrant a message if nobody's wearing it
|
||||
var/mob/M = loc
|
||||
M.visible_message("<span class='warning'>[M]'s [name] starts to fall apart!", "<span class='warning'>Your [name] starts to fall apart!")
|
||||
|
||||
/obj/item/clothing/proc/update_clothes_damaged_state(damaging = TRUE)
|
||||
var/index = "\ref[initial(icon)]-[initial(icon_state)]"
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
vision_flags = 0
|
||||
darkness_view = 2
|
||||
invis_view = SEE_INVISIBLE_LIVING
|
||||
lighting_alpha = null
|
||||
to_chat(user, "<span class='notice'>You toggle the goggles' scanning mode to \[T-Ray].</span>")
|
||||
else
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/obj/item/clothing/head/hunter
|
||||
name = "hunter hat"
|
||||
desc = "It's a flimsy looking hat."
|
||||
icon_state = "hunter"
|
||||
icon = 'icons/obj/clothing/cit_hats.dmi'
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
/obj/item/clothing/head/collectable/paper
|
||||
name = "collectable paper hat"
|
||||
desc = "What looks like an ordinary paper hat is actually a rare and valuable collector's edition paper hat. Keep away from water, fire, and Librarians."
|
||||
desc = "What looks like an ordinary paper hat is actually a rare and valuable collector's edition paper hat. Keep away from water, fire, and Curators."
|
||||
icon_state = "paper"
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head
|
||||
|
||||
@@ -158,4 +158,5 @@
|
||||
name = "treasure hunter's fedora"
|
||||
desc = "You got red text today kid, but it doesn't mean you have to like it."
|
||||
icon_state = "curator"
|
||||
armor = list(melee = 25, bullet = 5, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0, fire = 30, acid = 50)
|
||||
armor = list(melee = 25, bullet = 5, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0, fire = 30, acid = 50)
|
||||
pockets = /obj/item/weapon/storage/internal/pocket/small
|
||||
@@ -326,9 +326,6 @@
|
||||
disable_flight(1)
|
||||
if(!suit)
|
||||
disable_flight(1)
|
||||
if(!resync)
|
||||
addtimer(CALLBACK(src, .proc/resync), 600)
|
||||
resync = 1
|
||||
if(!wearer) //Oh god our user fell off!
|
||||
disable_flight(1)
|
||||
if(!pressure && brake)
|
||||
@@ -340,12 +337,6 @@
|
||||
stabilizer = FALSE
|
||||
usermessage("Warning: Sensor data is not being recieved from flight shoes. Stabilizers and airbrake modules OFFLINE!", 2)
|
||||
|
||||
//Resync the suit
|
||||
/obj/item/device/flightpack/proc/resync()
|
||||
resync = FALSE
|
||||
suit.resync()
|
||||
|
||||
//How fast should the wearer be?
|
||||
/obj/item/device/flightpack/proc/update_slowdown()
|
||||
if(!flight)
|
||||
suit.slowdown = slowdown_ground
|
||||
@@ -356,20 +347,11 @@
|
||||
/obj/item/device/flightpack/process()
|
||||
if(!suit || (processing_mode == FLIGHTSUIT_PROCESSING_NONE))
|
||||
return FALSE
|
||||
update_slowdown()
|
||||
update_icon()
|
||||
check_conditions()
|
||||
calculate_momentum_speed()
|
||||
momentum_drift()
|
||||
handle_boost()
|
||||
handle_damage()
|
||||
handle_flight()
|
||||
|
||||
/obj/item/device/flightpack/proc/handle_flight()
|
||||
if(!flight)
|
||||
return FALSE
|
||||
if(wearer)
|
||||
wearer.float(TRUE)
|
||||
|
||||
/obj/item/device/flightpack/proc/handle_damage()
|
||||
if(crash_damage)
|
||||
@@ -424,7 +406,6 @@
|
||||
if(boost_charge < boost_maxcharge)
|
||||
boost_charge = Clamp(boost_charge+boost_chargerate, 0, boost_maxcharge)
|
||||
|
||||
|
||||
/obj/item/device/flightpack/proc/cycle_power()
|
||||
if(powersetting < powersetting_high)
|
||||
powersetting++
|
||||
@@ -654,6 +635,8 @@
|
||||
wearer.movement_type |= FLYING
|
||||
wearer.pass_flags |= flight_passflags
|
||||
usermessage("ENGAGING FLIGHT ENGINES.")
|
||||
update_slowdown()
|
||||
wearer.floating = TRUE
|
||||
wearer.visible_message("<font color='blue' size='2'>[wearer]'s flight engines activate as they lift into the air!</font>")
|
||||
//I DONT HAVE SOUND EFFECTS YET playsound(
|
||||
flight = TRUE
|
||||
@@ -670,6 +653,8 @@
|
||||
momentum_x = 0
|
||||
momentum_y = 0
|
||||
usermessage("DISENGAGING FLIGHT ENGINES.")
|
||||
update_slowdown()
|
||||
wearer.floating = FALSE
|
||||
wearer.visible_message("<font color='blue' size='2'>[wearer] drops to the ground as their flight engines cut out!</font>")
|
||||
//NO SOUND YET playsound(
|
||||
ion_trail.stop()
|
||||
@@ -678,6 +663,9 @@
|
||||
flight = FALSE
|
||||
if(suit.shoes)
|
||||
suit.shoes.toggle(FALSE)
|
||||
if(isturf(wearer.loc))
|
||||
var/turf/T = wearer.loc
|
||||
T.Entered(src)
|
||||
else
|
||||
if(override_safe)
|
||||
disable_flight(TRUE)
|
||||
@@ -749,11 +737,13 @@
|
||||
wearer.visible_message("<span class='notice'>[wearer.name]'s flightpack engines flare in intensity as they are rocketed forward by the immense thrust!</span>")
|
||||
boost = TRUE
|
||||
update_slowdown()
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/flightpack/proc/deactivate_booster()
|
||||
usermessage("Boosters disengaged!")
|
||||
boost = FALSE
|
||||
update_slowdown()
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/flightpack/proc/enable_airbrake()
|
||||
if(wearer)
|
||||
|
||||
@@ -182,7 +182,7 @@
|
||||
item_state = "curator"
|
||||
blood_overlay_type = "coat"
|
||||
body_parts_covered = CHEST|ARMS
|
||||
allowed = list(/obj/item/weapon/tank/internals/emergency_oxygen, /obj/item/weapon/melee/curator_whip)
|
||||
allowed = list(/obj/item/weapon/tank/internals, /obj/item/weapon/melee/curator_whip)
|
||||
armor = list(melee = 25, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 45)
|
||||
cold_protection = CHEST|ARMS
|
||||
heat_protection = CHEST|ARMS
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
can_adjust = 1
|
||||
alt_covers_chest = 1
|
||||
|
||||
/obj/item/clothing/under/rank/librarian
|
||||
/obj/item/clothing/under/rank/curator
|
||||
name = "sensible suit"
|
||||
desc = "It's very... sensible."
|
||||
icon_state = "red_suit"
|
||||
@@ -145,7 +145,7 @@
|
||||
item_color = "red_suit"
|
||||
can_adjust = 0
|
||||
|
||||
/obj/item/clothing/under/rank/librarian/curator
|
||||
/obj/item/clothing/under/rank/curator/treasure_hunter
|
||||
name = "treasure hunter uniform"
|
||||
desc = "A rugged uniform suitable for treasure hunting."
|
||||
icon_state = "curator"
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
var/scanning = 0
|
||||
var/list/log = list()
|
||||
origin_tech = "engineering=4;biotech=2;programming=5"
|
||||
var/range = 8
|
||||
var/view_check = TRUE
|
||||
|
||||
/obj/item/device/detective_scanner/attack_self(mob/user)
|
||||
if(log.len && !scanning)
|
||||
@@ -43,7 +45,7 @@
|
||||
log = list()
|
||||
scanning = 0
|
||||
|
||||
/obj/item/device/detective_scanner/pre_attackby(atom/A, mob/user, params)
|
||||
/obj/item/device/detective_scanner/afterattack(atom/A, mob/user, params)
|
||||
scan(A, user)
|
||||
return FALSE
|
||||
|
||||
@@ -51,9 +53,7 @@
|
||||
set waitfor = 0
|
||||
if(!scanning)
|
||||
// Can remotely scan objects and mobs.
|
||||
if(!in_range(A, user) && !(A in view(world.view, user)))
|
||||
return
|
||||
if(loc != user)
|
||||
if((get_dist(A, user) > range) || (!(A in view(range, user)) && view_check) || (loc != user))
|
||||
return
|
||||
|
||||
scanning = 1
|
||||
|
||||
@@ -6,7 +6,7 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
|
||||
if(!istype(E)) //Something threw an unusual exception
|
||||
log_world("\[[time_stamp()]] Uncaught exception: [E]")
|
||||
return ..()
|
||||
|
||||
|
||||
var/static/list/error_last_seen = list()
|
||||
var/static/list/error_cooldown = list() /* Error_cooldown items will either be positive(cooldown time) or negative(silenced error)
|
||||
If negative, starts at -1, and goes down by 1 each time that error gets skipped*/
|
||||
@@ -107,9 +107,8 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
|
||||
if (split[i] != "")
|
||||
split[i] = "\[[time2text(world.timeofday,"hh:mm:ss")]\][split[i]]"
|
||||
E.desc = jointext(split, "\n")
|
||||
if(config && config.log_runtimes)
|
||||
world.log = GLOB.runtime_diary
|
||||
..(E)
|
||||
world.log = GLOB.world_runtime_log
|
||||
..(E)
|
||||
|
||||
world.log = null
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
var/list/mob/dead/observer/regular_candidates
|
||||
// don't get their hopes up
|
||||
if(priority_candidates.len < minimum_required)
|
||||
regular_candidates = pollCandidates("Do you wish to be considered for the special role of '[role_name]'?", jobban, gametypecheck, be_special)
|
||||
regular_candidates = pollGhostCandidates("Do you wish to be considered for the special role of '[role_name]'?", jobban, gametypecheck, be_special)
|
||||
else
|
||||
regular_candidates = list()
|
||||
|
||||
|
||||
@@ -362,8 +362,6 @@
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
override += SM.on_eat(src, eater)
|
||||
if(!override)
|
||||
if(prob(10))
|
||||
eater.say("Nom")
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/spacevine/attackby(obj/item/weapon/W, mob/user, params)
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
"sodiumchloride" = list("saltshakersmall", "salt shaker", "Salt. From space oceans, presumably"),
|
||||
"blackpepper" = list("peppermillsmall", "pepper mill", "Often used to flavor food or make people sneeze"),
|
||||
"cornoil" = list("oliveoil", "corn oil bottle", "A delicious oil used in cooking. Made from corn"),
|
||||
"sugar" = list("emptycondiment", "sugar bottle", "Tasty spacey sugar!"))
|
||||
"sugar" = list("emptycondiment", "sugar bottle", "Tasty spacey sugar!"),
|
||||
"mayonnaise" = list("mayonnaise", "mayonnaise jar", "An oily condiment made from egg yolks."))
|
||||
var/originalname = "condiment" //Can't use initial(name) for this. This stores the name set by condimasters.
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/condiment/attack(mob/M, mob/user, def_zone)
|
||||
@@ -207,6 +208,13 @@
|
||||
list_reagents = list("soysauce" = 50)
|
||||
possible_states = list()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/condiment/mayonnaise
|
||||
name = "mayonnaise"
|
||||
desc = "An oily condiment made from egg yolks."
|
||||
icon_state = "mayonnaise"
|
||||
list_reagents = list("mayonnaise" = 50)
|
||||
possible_states = list()
|
||||
|
||||
|
||||
|
||||
//Food packs. To easily apply deadly toxi... delicious sauces to your food!
|
||||
|
||||
@@ -164,3 +164,24 @@
|
||||
icon = 'icons/obj/food/food.dmi'
|
||||
icon_state = ""
|
||||
bitesize = 2
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/butteredtoast
|
||||
name = "buttered toast"
|
||||
desc = "Butter lightly spread over a piece of toast."
|
||||
icon = 'icons/obj/food/food.dmi'
|
||||
icon_state = "butteredtoast"
|
||||
bitesize = 3
|
||||
filling_color = "#FFA500"
|
||||
list_reagents = list("nutriment" = 4)
|
||||
bonus_reagents = list("nutriment" = 1, "vitamin" = 1)
|
||||
tastes = list("butter" = 1, "toast" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/butterbiscuit
|
||||
name = "butter biscuit"
|
||||
desc = "Well butter my biscuit!"
|
||||
icon = 'icons/obj/food/food.dmi'
|
||||
icon_state = "butterbiscuit"
|
||||
filling_color = "#F0E68C"
|
||||
list_reagents = list("nutriment" = 5)
|
||||
bonus_reagents = list("nutriment" = 1, "vitamin" = 1)
|
||||
tastes = list("butter" = 1, "biscuit" = 1)
|
||||
@@ -236,3 +236,12 @@
|
||||
var/shape = pick("lump", "star", "lizard", "corgi")
|
||||
desc = "A 'chicken' nugget vaguely shaped like a [shape]."
|
||||
icon_state = "nugget_[shape]"
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/pigblanket
|
||||
name = "pig in a blanket"
|
||||
desc = "A tiny sausage wrapped in a flakey, buttery roll. Free this pig from its blanket prison by eating it."
|
||||
icon_state = "pigblanket"
|
||||
list_reagents = list("nutriment" = 6, "vitamin" = 1)
|
||||
bonus_reagents = list("nutriment" = 1, "vitamin" = 1)
|
||||
filling_color = "#800000"
|
||||
tastes = list("meat" = 1, "butter" = 1)
|
||||
|
||||
@@ -468,3 +468,11 @@
|
||||
list_reagents = list("nutriment" = 3, "vitamin" = 2, "sodiumchloride" = 5)
|
||||
bonus_reagents = list("sodiumchloride" = 10)
|
||||
tastes = list("bran" = 4, "raisins" = 3, "salt" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/butter
|
||||
name = "stick of butter"
|
||||
desc = "A stick of delicious, golden, fatty goodness."
|
||||
icon_state = "butter"
|
||||
list_reagents = list("nutriment" = 5)
|
||||
filling_color = "#FFD700"
|
||||
tastes = list("butter" = 1)
|
||||
@@ -13,8 +13,8 @@
|
||||
filling_color = "#D2691E"
|
||||
tastes = list("donut" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/donut/New()
|
||||
..()
|
||||
/obj/item/weapon/reagent_containers/food/snacks/donut/Initialize()
|
||||
. = ..()
|
||||
if(prob(30))
|
||||
icon_state = "donut2"
|
||||
name = "frosted donut"
|
||||
@@ -28,8 +28,8 @@
|
||||
bitesize = 10
|
||||
tastes = list("donut" = 3, "chaos" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/donut/chaos/New()
|
||||
..()
|
||||
/obj/item/weapon/reagent_containers/food/snacks/donut/chaos/Initialize()
|
||||
. = ..()
|
||||
extra_reagent = pick("nutriment", "capsaicin", "frostoil", "krokodil", "plasma", "cocoa", "slimejelly", "banana", "berryjuice", "omnizine")
|
||||
reagents.add_reagent("[extra_reagent]", 3)
|
||||
bonus_reagents = list("[extra_reagent]" = 3, "sugar" = 1)
|
||||
@@ -48,8 +48,8 @@
|
||||
extra_reagent = "berryjuice"
|
||||
tastes = list("jelly" = 1, "donut" = 3)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/donut/jelly/New()
|
||||
..()
|
||||
/obj/item/weapon/reagent_containers/food/snacks/donut/jelly/Initialize()
|
||||
. = ..()
|
||||
if(extra_reagent)
|
||||
reagents.add_reagent("[extra_reagent]", 3)
|
||||
if(prob(30))
|
||||
@@ -210,13 +210,13 @@
|
||||
filling_color = "#F0E68C"
|
||||
tastes = list("mushroom" = 1, "biscuit" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit/New()
|
||||
/obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit/Initialize()
|
||||
var/fey = prob(10)
|
||||
if(fey)
|
||||
name = "exceptional plump helmet biscuit"
|
||||
desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump helmet biscuit!"
|
||||
bonus_reagents = list("omnizine" = 5, "nutriment" = 1, "vitamin" = 1)
|
||||
..()
|
||||
. = ..()
|
||||
if(fey)
|
||||
reagents.add_reagent("omnizine", 5)
|
||||
|
||||
|
||||
@@ -85,3 +85,12 @@
|
||||
trash = /obj/item/weapon/reagent_containers/glass/bowl
|
||||
bonus_reagents = list("nutriment" = 5, "vitamin" = 6, "liquidgibs" = 3)
|
||||
tastes = list("noodle" = 1, "meat" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/butternoodles
|
||||
name = "butter noodles"
|
||||
desc = "Noodles covered in savory butter. Simple and slippery, but delicious."
|
||||
icon = 'icons/obj/food/pizzaspaghetti.dmi'
|
||||
icon_state = "butternoodles"
|
||||
trash = /obj/item/trash/plate
|
||||
bonus_reagents = list("nutriment" = 8, "vitamin" = 1)
|
||||
tastes = list("noodle" = 1, "butter" = 1)
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
break
|
||||
|
||||
if(!input_plate)
|
||||
GLOB.diary << "a [src] didn't find an input plate."
|
||||
GLOB.world_game_log << "a [src] didn't find an input plate."
|
||||
return
|
||||
|
||||
/obj/machinery/gibber/autogibber/Bumped(atom/A)
|
||||
@@ -168,13 +168,14 @@
|
||||
|
||||
var/offset = prob(50) ? -2 : 2
|
||||
animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 200) //start shaking
|
||||
var/sourcename = src.occupant.real_name
|
||||
var/mob/living/mob_occupant = occupant
|
||||
var/sourcename = mob_occupant.real_name
|
||||
var/sourcejob
|
||||
if(ishuman(occupant))
|
||||
var/mob/living/carbon/human/gibee = occupant
|
||||
sourcejob = gibee.job
|
||||
var/sourcenutriment = src.occupant.nutrition / 15
|
||||
var/sourcetotalreagents = src.occupant.reagents.total_volume
|
||||
var/sourcenutriment = mob_occupant.nutrition / 15
|
||||
var/sourcetotalreagents = mob_occupant.reagents.total_volume
|
||||
var/gibtype = /obj/effect/decal/cleanable/blood/gibs
|
||||
var/typeofmeat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human
|
||||
var/typeofskin = /obj/item/stack/sheet/animalhide/human
|
||||
@@ -212,8 +213,8 @@
|
||||
allskin = newskin
|
||||
|
||||
add_logs(user, occupant, "gibbed")
|
||||
src.occupant.death(1)
|
||||
src.occupant.ghostize()
|
||||
mob_occupant.death(1)
|
||||
mob_occupant.ghostize()
|
||||
qdel(src.occupant)
|
||||
spawn(src.gibtime)
|
||||
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
var/mutable_appearance/bomb_overlay = mutable_appearance(bomb.icon, bomb.icon_state)
|
||||
bomb_overlay.pixel_y = 5
|
||||
add_overlay(bomb_overlay)
|
||||
else
|
||||
icon_state = "pizzabox[boxes.len + 1]"
|
||||
var/obj/item/pizzabox/box = boxes.len ? boxes[boxes.len] : src
|
||||
if(box.boxtag != "")
|
||||
|
||||
@@ -74,3 +74,22 @@
|
||||
)
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/store/bread/mimana
|
||||
category = CAT_BREAD
|
||||
|
||||
/datum/crafting_recipe/food/butteredtoast
|
||||
name = "Buttered Toast"
|
||||
reqs = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/breadslice/plain = 1,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/butter = 1
|
||||
)
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/butteredtoast
|
||||
category = CAT_BREAD
|
||||
|
||||
/datum/crafting_recipe/food/butterbiscuit
|
||||
name = "Butter Biscuit"
|
||||
reqs = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/bun = 1,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/butter = 1
|
||||
)
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/butterbiscuit
|
||||
category = CAT_BREAD
|
||||
|
||||
|
||||
@@ -160,3 +160,13 @@
|
||||
)
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/rawkhinkali
|
||||
category = CAT_MEAT
|
||||
|
||||
/datum/crafting_recipe/food/pigblanket
|
||||
name = "Pig in a Blanket"
|
||||
reqs = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/bun = 1,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/butter = 1,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat/cutlet = 1
|
||||
)
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/pigblanket
|
||||
category = CAT_MEAT
|
||||
|
||||
@@ -59,3 +59,12 @@
|
||||
)
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/chowmein
|
||||
category = CAT_SPAGHETTI
|
||||
|
||||
/datum/crafting_recipe/food/butternoodles
|
||||
name = "Butter Noodles"
|
||||
reqs = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/boiledspaghetti = 1,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/butter = 1
|
||||
)
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/butternoodles
|
||||
category = CAT_SPAGHETTI
|
||||
@@ -111,6 +111,7 @@
|
||||
for(var/datum/plant_gene/trait/trait in seed.genes)
|
||||
trait.on_squash(src, target)
|
||||
|
||||
reagents.reaction(T)
|
||||
for(var/A in T)
|
||||
reagents.reaction(A)
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
species = "ambrosia_gaia"
|
||||
plantname = "Ambrosia Gaia"
|
||||
product = /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosia/gaia
|
||||
mutatelist = list()
|
||||
mutatelist = list(/obj/item/seeds/ambrosia/deus)
|
||||
reagents_add = list("earthsblood" = 0.05, "nutriment" = 0.06, "vitamin" = 0.05)
|
||||
rarity = 30 //These are some pretty good plants right here
|
||||
genes = list()
|
||||
|
||||
@@ -123,8 +123,8 @@
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown/cherry_bomb/attack_self(mob/living/user)
|
||||
var/area/A = get_area(user)
|
||||
user.visible_message("<span class='warning'>[user] plucks the stem from [src]!</span>", "<span class='userdanger'>You pluck the stem from [src], which begins to hiss loudly!</span>")
|
||||
message_admins("[user] ([user.key ? user.key : "no key"]) primed a cherry bomb for detonation at [A] ([user.x], [user.y], [user.z]) <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>(JMP)</a>")
|
||||
log_game("[user] ([user.key ? user.key : "no key"]) primed a cherry bomb for detonation at [A] ([user.x],[user.y],[user.z]).")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] primed a cherry bomb for detonation at [A] [ADMIN_COORDJMP(user)]")
|
||||
log_game("[key_name(user)] primed a cherry bomb for detonation at [A] [COORD(user)].")
|
||||
prime()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown/cherry_bomb/deconstruct(disassembled = TRUE)
|
||||
|
||||
@@ -50,17 +50,22 @@
|
||||
/obj/item/weapon/grown/nettle/pickup(mob/living/user)
|
||||
..()
|
||||
if(!iscarbon(user))
|
||||
return 0
|
||||
return FALSE
|
||||
var/mob/living/carbon/C = user
|
||||
if(C.gloves)
|
||||
return 0
|
||||
return FALSE
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(H.dna && H.dna.species)
|
||||
if(PIERCEIMMUNE in H.dna.species.species_traits)
|
||||
return FALSE
|
||||
var/hit_zone = (C.held_index_to_dir(C.active_hand_index) == "l" ? "l_":"r_") + "arm"
|
||||
var/obj/item/bodypart/affecting = C.get_bodypart(hit_zone)
|
||||
if(affecting)
|
||||
if(affecting.receive_damage(0, force))
|
||||
C.update_damage_overlays()
|
||||
to_chat(C, "<span class='userdanger'>The nettle burns your bare hand!</span>")
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/item/weapon/grown/nettle/afterattack(atom/A as mob|obj, mob/user,proximity)
|
||||
if(!proximity) return
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
var/unwrenchable = 1
|
||||
var/recent_bee_visit = FALSE //Have we been visited by a bee recently, so bees dont overpollinate one plant
|
||||
var/using_irrigation = FALSE //If the tray is connected to other trays via irrigation hoses
|
||||
var/self_sufficiency_req = 20 //Required total dose to make a self-sufficient hydro tray. 1:1 with earthsblood.
|
||||
var/self_sufficiency_progress = 0
|
||||
var/self_sustaining = FALSE //If the tray generates nutrients and water on its own
|
||||
|
||||
|
||||
@@ -329,6 +331,9 @@
|
||||
if(!self_sustaining)
|
||||
to_chat(user, "<span class='info'>Water: [waterlevel]/[maxwater]</span>")
|
||||
to_chat(user, "<span class='info'>Nutrient: [nutrilevel]/[maxnutri]</span>")
|
||||
if(self_sufficiency_progress > 0)
|
||||
var/percent_progress = round(self_sufficiency_progress * 100 / self_sufficiency_req)
|
||||
to_chat(user, "<span class='info'>Treatment for self-sustenance are [percent_progress]% complete.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='info'>It doesn't require any water or nutrients.</span>")
|
||||
|
||||
@@ -504,6 +509,14 @@
|
||||
yieldmod = 1.3
|
||||
mutmod = 0
|
||||
adjustNutri(round(S.get_reagent_amount("robustharvestnutriment") *1 ))
|
||||
|
||||
// Ambrosia Gaia produces earthsblood.
|
||||
if(S.has_reagent("earthsblood"))
|
||||
self_sufficiency_progress += S.get_reagent_amount("earthsblood")
|
||||
if(self_sufficiency_progress >= self_sufficiency_req)
|
||||
become_self_sufficient()
|
||||
else if(!self_sustaining)
|
||||
to_chat(user, "<span class='notice'>[src] warms as it might on a spring day under a genuine Sun.</span>")
|
||||
|
||||
// Antitoxin binds shit pretty well. So the tox goes significantly down
|
||||
if(S.has_reagent("charcoal", 1))
|
||||
@@ -675,33 +688,7 @@
|
||||
|
||||
/obj/machinery/hydroponics/attackby(obj/item/O, mob/user, params)
|
||||
//Called when mob user "attacks" it with object O
|
||||
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosia/gaia)) //Checked early on so it doesn't have to deal with composting checks
|
||||
if(self_sustaining)
|
||||
to_chat(user, "<span class='warning'>This [name] is already self-sustaining!</span>")
|
||||
return
|
||||
if(myseed || weedlevel)
|
||||
to_chat(user, "<span class='warning'>[src] needs to be clear of plants and weeds!</span>")
|
||||
return
|
||||
if(alert(user, "This will make [src] self-sustaining but consume [O] forever. Are you sure?", "[name]", "I'm Sure", "Abort") == "Abort" || !user)
|
||||
return
|
||||
if(!O || QDELETED(O))
|
||||
return
|
||||
if(!Adjacent(user))
|
||||
return
|
||||
if(self_sustaining)
|
||||
to_chat(user, "<span class='warning'>This [name] is already self-sustaining!</span>")
|
||||
return
|
||||
if(myseed || weedlevel)
|
||||
to_chat(user, "<span class='warning'>[src] needs to be clear of plants and weeds!</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] gently pulls open the soil for [O] and places it inside.</span>", "<span class='notice'>You tenderly root [O] into [src].</span>")
|
||||
user.drop_item()
|
||||
qdel(O)
|
||||
visible_message("<span class='boldnotice'>[src] begins to glow with a beautiful light!</span>")
|
||||
self_sustaining = TRUE
|
||||
update_icon()
|
||||
|
||||
else if(istype(O, /obj/item/weapon/reagent_containers) ) // Syringe stuff (and other reagent containers now too)
|
||||
if(istype(O, /obj/item/weapon/reagent_containers) ) // Syringe stuff (and other reagent containers now too)
|
||||
var/obj/item/weapon/reagent_containers/reagent_source = O
|
||||
|
||||
if(istype(reagent_source, /obj/item/weapon/reagent_containers/syringe))
|
||||
@@ -930,6 +917,10 @@
|
||||
var/mob/living/simple_animal/hostile/C = new chosen
|
||||
C.faction = list("plants")
|
||||
|
||||
/obj/machinery/hydroponics/proc/become_self_sufficient() // Ambrosia Gaia effect
|
||||
visible_message("<span class='boldnotice'>[src] begins to glow with a beautiful light!</span>")
|
||||
self_sustaining = TRUE
|
||||
update_icon()
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/obj/machinery/hydroponics/soil //Not actually hydroponics at all! Honk!
|
||||
|
||||
@@ -268,7 +268,7 @@
|
||||
rate = 0.03
|
||||
examine_line = "<span class='info'>It emits a soft glow.</span>"
|
||||
trait_id = "glow"
|
||||
var/glow_color = "#AAD84B"
|
||||
var/glow_color = "#C3E381"
|
||||
|
||||
/datum/plant_gene/trait/glow/proc/glow_range(obj/item/seeds/S)
|
||||
return 1.4 + S.potency*rate
|
||||
@@ -285,6 +285,7 @@
|
||||
//adds -potency*(rate*0.05) light power to products
|
||||
name = "Shadow Emission"
|
||||
rate = 0.04
|
||||
glow_color = "#AAD84B"
|
||||
|
||||
/datum/plant_gene/trait/glow/shadow/glow_power(obj/item/seeds/S)
|
||||
return -max(S.potency*(rate*0.05), 0.075)
|
||||
|
||||
@@ -459,7 +459,7 @@ GLOBAL_VAR_CONST(access_away_generic4, 208)
|
||||
|
||||
/proc/get_all_jobs()
|
||||
return list("Assistant", "Captain", "Head of Personnel", "Bartender", "Cook", "Botanist", "Quartermaster", "Cargo Technician",
|
||||
"Shaft Miner", "Clown", "Mime", "Janitor", "Librarian", "Lawyer", "Chaplain", "Chief Engineer", "Station Engineer",
|
||||
"Shaft Miner", "Clown", "Mime", "Janitor", "Curator", "Lawyer", "Chaplain", "Chief Engineer", "Station Engineer",
|
||||
"Atmospheric Technician", "Chief Medical Officer", "Medical Doctor", "Chemist", "Geneticist", "Virologist",
|
||||
"Research Director", "Scientist", "Roboticist", "Head of Security", "Warden", "Detective", "Security Officer")
|
||||
|
||||
|
||||
@@ -277,4 +277,4 @@ Janitor
|
||||
belt = /obj/item/device/pda/janitor
|
||||
ears = /obj/item/device/radio/headset/headset_srv
|
||||
uniform = /obj/item/clothing/under/rank/janitor
|
||||
backpack_contents = list(/obj/item/device/modular_computer/tablet/preset/advanced=1, /obj/item/soapstone/empty=1)
|
||||
backpack_contents = list(/obj/item/device/modular_computer/tablet/preset/advanced=1)
|
||||
|
||||
@@ -35,7 +35,8 @@ Clown
|
||||
/obj/item/weapon/reagent_containers/spray/waterflower = 1,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown/banana = 1,
|
||||
/obj/item/device/megaphone/clown = 1,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/canned_laughter = 1
|
||||
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/canned_laughter = 1,
|
||||
/obj/item/weapon/pneumatic_cannon/pie = 1
|
||||
)
|
||||
|
||||
implants = list(/obj/item/weapon/implant/sad_trombone)
|
||||
@@ -112,11 +113,11 @@ Mime
|
||||
H.mind.miming = 1
|
||||
|
||||
/*
|
||||
Librarian
|
||||
Curator
|
||||
*/
|
||||
/datum/job/librarian
|
||||
title = "Librarian"
|
||||
flag = LIBRARIAN
|
||||
/datum/job/curator
|
||||
title = "Curator"
|
||||
flag = CURATOR
|
||||
department_head = list("Head of Personnel")
|
||||
department_flag = CIVILIAN
|
||||
faction = "Station"
|
||||
@@ -125,33 +126,35 @@ Librarian
|
||||
supervisors = "the head of personnel"
|
||||
selection_color = "#dddddd"
|
||||
|
||||
outfit = /datum/outfit/job/librarian
|
||||
outfit = /datum/outfit/job/curator
|
||||
|
||||
access = list(GLOB.access_library)
|
||||
minimal_access = list(GLOB.access_library)
|
||||
minimal_access = list(GLOB.access_library, GLOB.access_construction,GLOB.access_mining_station)
|
||||
|
||||
/datum/outfit/job/librarian
|
||||
name = "Librarian"
|
||||
jobtype = /datum/job/librarian
|
||||
/datum/outfit/job/curator
|
||||
name = "Curator"
|
||||
jobtype = /datum/job/curator
|
||||
|
||||
belt = /obj/item/device/pda/librarian
|
||||
uniform = /obj/item/clothing/under/rank/librarian
|
||||
belt = /obj/item/device/pda/curator
|
||||
uniform = /obj/item/clothing/under/rank/curator
|
||||
l_hand = /obj/item/weapon/storage/bag/books
|
||||
r_pocket = /obj/item/weapon/barcodescanner
|
||||
r_pocket = /obj/item/key/displaycase
|
||||
l_pocket = /obj/item/device/laser_pointer
|
||||
backpack_contents = list(
|
||||
/obj/item/soapstone = 1
|
||||
/obj/item/weapon/melee/curator_whip = 1,
|
||||
/obj/item/soapstone = 1,
|
||||
/obj/item/weapon/barcodescanner = 1
|
||||
)
|
||||
|
||||
|
||||
/datum/outfit/job/librarian/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
..()
|
||||
|
||||
if(visualsOnly)
|
||||
return
|
||||
|
||||
H.grant_all_languages(omnitongue=TRUE)
|
||||
|
||||
|
||||
/datum/outfit/job/curator/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
..()
|
||||
|
||||
if(visualsOnly)
|
||||
return
|
||||
|
||||
H.grant_all_languages(omnitongue=TRUE)
|
||||
|
||||
/*
|
||||
Lawyer
|
||||
*/
|
||||
|
||||
@@ -39,7 +39,7 @@ GLOBAL_LIST_INIT(civilian_positions, list(
|
||||
"Botanist",
|
||||
"Cook",
|
||||
"Janitor",
|
||||
"Librarian",
|
||||
"Curator",
|
||||
"Lawyer",
|
||||
"Chaplain",
|
||||
"Clown",
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
var/speed = 300
|
||||
var/correctness = 85
|
||||
var/willpower = 98
|
||||
if(U.job in list("Librarian")) // the librarian is both faster, and more accurate than normal crew members at research
|
||||
if(U.job in list("Curator")) // the curator is both faster, and more accurate than normal crew members at research
|
||||
speed = 45
|
||||
correctness = 100
|
||||
willpower = 100
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
------------
|
||||
A place for the crew to go, relax, and enjoy a good book.
|
||||
Aspiring authors can even self publish and, if they're lucky
|
||||
convince the on-staff Librarian to submit it to the Archives
|
||||
convince the on-staff Curator to submit it to the Archives
|
||||
to be chronicled in history forever - some say even persisting
|
||||
through alternate dimensions.
|
||||
|
||||
@@ -49,12 +49,12 @@
|
||||
|
||||
// Ideas for the future
|
||||
// ---------------------
|
||||
// - Visitor's computer should be able to search the current in-round library inventory (that the Librarian has stocked and checked in)
|
||||
// - Visitor's computer should be able to search the current in-round library inventory (that the Curator has stocked and checked in)
|
||||
// -- Give computer other features like an Instant Messenger application, or the ability to edit, save, and print documents.
|
||||
// - Admin interface directly tied to the Archive DB. Right now there's no way to delete uploaded books in-game.
|
||||
// -- If this gets implemented, allow Librarians to "tag" or "suggest" books to be deleted. The DB ID of the tagged books gets saved to a text file (or another table in the DB maybe?).
|
||||
// -- If this gets implemented, allow Curators to "tag" or "suggest" books to be deleted. The DB ID of the tagged books gets saved to a text file (or another table in the DB maybe?).
|
||||
// The admin interface would automatically take these IDs and SELECT them all from the DB to be displayed along with a Delete link to drop the row from the table.
|
||||
// - When the game sets up and the round begins, have it automatically pick random books from the DB to populate the library with. Even if the Librarian is a useless fuck there are at least a few books around.
|
||||
// - When the game sets up and the round begins, have it automatically pick random books from the DB to populate the library with. Even if the Curator is a useless fuck there are at least a few books around.
|
||||
// - Allow books to be "hollowed out" like the Chaplain's Bible, allowing you to store one pocket-sized item inside.
|
||||
// - Make books/book cases burn when exposed to flame.
|
||||
// - Make book binder hackable.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/obj/item/soapstone
|
||||
name = "chisel"
|
||||
name = "soapstone"
|
||||
desc = "Leave informative messages for the crew, including the crew of future shifts!\nEven if out of uses, it can still be used to remove messages.\n(Not suitable for engraving on shuttles, off station or on cats. Side effects may include beatings, bannings and orbital bombardment.)"
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "soapstone"
|
||||
@@ -9,36 +9,9 @@
|
||||
var/tool_speed = 50
|
||||
var/remaining_uses = 3
|
||||
|
||||
var/non_dull_name
|
||||
var/w_engrave = "engrave"
|
||||
var/w_engraving = "engraving"
|
||||
var/w_chipping = "chipping"
|
||||
var/w_dull = "dull"
|
||||
|
||||
/obj/item/soapstone/New()
|
||||
/obj/item/soapstone/Initialize(mapload)
|
||||
. = ..()
|
||||
random_name()
|
||||
check_name() // could start empty
|
||||
|
||||
/obj/item/soapstone/proc/random_name()
|
||||
name = pick("soapstone", "chisel", "chalk", "magic marker")
|
||||
non_dull_name = name
|
||||
if(name == "chalk" || name == "magic marker")
|
||||
desc = replacetext(desc, "engraving", "scribbling")
|
||||
w_engrave = "scribble"
|
||||
w_engraving = "scribbling"
|
||||
w_chipping = "sketching"
|
||||
if(name == "chalk")
|
||||
w_dull = "used"
|
||||
if(name == "magic marker")
|
||||
w_dull = "empty"
|
||||
|
||||
if(name == "soapstone" || name == "chisel")
|
||||
desc = replacetext(desc, "scribbling", "engraving")
|
||||
w_engrave = initial(w_engrave)
|
||||
w_engraving = initial(w_engraving)
|
||||
w_chipping = initial(w_chipping)
|
||||
w_dull = "dull"
|
||||
check_name()
|
||||
|
||||
/obj/item/soapstone/examine(mob/user)
|
||||
. = ..()
|
||||
@@ -57,11 +30,11 @@
|
||||
return
|
||||
|
||||
if(!good_chisel_message_location(T))
|
||||
to_chat(user, "<span class='warning'>It's not appropriate to [w_engrave] on [T].</span>")
|
||||
to_chat(user, "<span class='warning'>It's not appropriate to engrave on [T].</span>")
|
||||
return
|
||||
|
||||
if(existing_message)
|
||||
user.visible_message("<span class='notice'>[user] starts erasing [existing_message].</span>", "<span class='notice'>You start erasing [existing_message].</span>", "<span class='italics'>You hear a [w_chipping] sound.</span>")
|
||||
user.visible_message("<span class='notice'>[user] starts erasing [existing_message].</span>", "<span class='notice'>You start erasing [existing_message].</span>", "<span class='italics'>You hear a chipping sound.</span>")
|
||||
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
|
||||
if(do_after(user, tool_speed, target = existing_message))
|
||||
user.visible_message("<span class='notice'>[user] erases [existing_message].</span>", "<span class='notice'>You erase [existing_message][existing_message.creator_key == user.ckey ? ", refunding a use" : ""].</span>")
|
||||
@@ -72,19 +45,19 @@
|
||||
refund_use()
|
||||
return
|
||||
|
||||
var/message = stripped_input(user, "What would you like to [w_engrave]?", "Leave a message")
|
||||
var/message = stripped_input(user, "What would you like to engrave?", "Leave a message")
|
||||
if(!message)
|
||||
to_chat(user, "<span class='notice'>You decide not to [w_engrave] anything.</span>")
|
||||
to_chat(user, "<span class='notice'>You decide not to engrave anything.</span>")
|
||||
return
|
||||
|
||||
if(!target.Adjacent(user) && locate(/obj/structure/chisel_message) in T)
|
||||
to_chat(user, "<span class='warning'>Someone wrote here before you chose! Find another spot.</span>")
|
||||
return
|
||||
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
|
||||
user.visible_message("<span class='notice'>[user] starts [w_engraving] a message into [T]...</span>", "<span class='notice'>You start [w_engraving] a message into [T]...</span>", "<span class='italics'>You hear a [w_chipping] sound.</span>")
|
||||
user.visible_message("<span class='notice'>[user] starts engraving a message into [T]...</span>", "<span class='notice'>You start engraving a message into [T]...</span>", "<span class='italics'>You hear a chipping sound.</span>")
|
||||
if(can_use() && do_after(user, tool_speed, target = T) && can_use()) //This looks messy but it's actually really clever!
|
||||
if(!locate(/obj/structure/chisel_message in T))
|
||||
user.visible_message("<span class='notice'>[user] leaves a message for future spacemen!</span>", "<span class='notice'>You [w_engrave] a message into [T]!</span>", "<span class='italics'>You hear a [w_chipping] sound.</span>")
|
||||
user.visible_message("<span class='notice'>[user] leaves a message for future spacemen!</span>", "<span class='notice'>You engrave a message into [T]!</span>", "<span class='italics'>You hear a chipping sound.</span>")
|
||||
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
|
||||
var/obj/structure/chisel_message/M = new(T)
|
||||
M.register(user, message)
|
||||
@@ -107,15 +80,16 @@
|
||||
|
||||
/obj/item/soapstone/proc/check_name()
|
||||
if(remaining_uses)
|
||||
name = non_dull_name
|
||||
// This will mess up RPG loot names, but w/e
|
||||
name = initial(name)
|
||||
else
|
||||
name = "[w_dull] [name]"
|
||||
name = "dull [initial(name)]"
|
||||
|
||||
/* Persistent engraved messages, etched onto the station turfs to serve
|
||||
as instructions and/or memes for the next generation of spessmen.
|
||||
|
||||
Limited in location to station_z only. Can be smashed out or exploded,
|
||||
but only permamently removed with the librarian's soapstone.
|
||||
but only permamently removed with the curator's soapstone.
|
||||
*/
|
||||
|
||||
/obj/item/soapstone/infinite
|
||||
@@ -127,10 +101,6 @@
|
||||
/proc/good_chisel_message_location(turf/T)
|
||||
if(!T)
|
||||
. = FALSE
|
||||
else if(T.z != ZLEVEL_STATION)
|
||||
. = FALSE
|
||||
else if(istype(get_area(T), /area/shuttle))
|
||||
. = FALSE
|
||||
else if(!(isfloorturf(T) || iswallturf(T)))
|
||||
. = FALSE
|
||||
else
|
||||
@@ -142,9 +112,8 @@
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "soapstone_message"
|
||||
layer = HIGH_OBJ_LAYER
|
||||
density = 0
|
||||
anchored = 1
|
||||
luminosity = 1
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
obj_integrity = 30
|
||||
max_integrity = 30
|
||||
|
||||
@@ -157,17 +126,18 @@
|
||||
var/list/like_keys = list()
|
||||
var/list/dislike_keys = list()
|
||||
|
||||
/obj/structure/chisel_message/New(newloc)
|
||||
..()
|
||||
var/turf/original_turf
|
||||
|
||||
/obj/structure/chisel_message/Initialize(mapload)
|
||||
. = ..()
|
||||
SSpersistence.chisel_messages += src
|
||||
var/turf/T = get_turf(src)
|
||||
original_turf = T
|
||||
|
||||
if(!good_chisel_message_location(T))
|
||||
persists = FALSE
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/chisel_message/singularity_pull()
|
||||
return
|
||||
|
||||
/obj/structure/chisel_message/proc/register(mob/user, newmessage)
|
||||
hidden_message = newmessage
|
||||
creator_name = user.real_name
|
||||
@@ -181,6 +151,8 @@
|
||||
var/hash = md5(hidden_message)
|
||||
var/newcolor = copytext(hash, 1, 7)
|
||||
add_atom_colour("#[newcolor]", FIXED_COLOUR_PRIORITY)
|
||||
light_color = "#[newcolor]"
|
||||
set_light(1)
|
||||
|
||||
/obj/structure/chisel_message/proc/pack()
|
||||
var/list/data = list()
|
||||
@@ -189,12 +161,12 @@
|
||||
data["creator_key"] = creator_key
|
||||
data["realdate"] = realdate
|
||||
data["map"] = SSmapping.config.map_name
|
||||
var/turf/T = get_turf(src)
|
||||
data["x"] = T.x
|
||||
data["y"] = T.y
|
||||
data["z"] = T.z
|
||||
data["x"] = original_turf.x
|
||||
data["y"] = original_turf.y
|
||||
data["z"] = original_turf.z
|
||||
data["like_keys"] = like_keys
|
||||
data["dislike_keys"] = dislike_keys
|
||||
return data
|
||||
|
||||
/obj/structure/chisel_message/proc/unpack(list/data)
|
||||
if(!islist(data))
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, NORTHWEST))
|
||||
|
||||
/datum/lighting_corner
|
||||
var/list/turf/masters = list()
|
||||
var/list/datum/light_source/affecting = list() // Light sources affecting us.
|
||||
var/list/turf/masters
|
||||
var/list/datum/light_source/affecting // Light sources affecting us.
|
||||
var/active = FALSE // TRUE if one of our masters has dynamic lighting.
|
||||
|
||||
var/x = 0
|
||||
@@ -25,11 +25,9 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST,
|
||||
var/cache_b = LIGHTING_SOFT_THRESHOLD
|
||||
var/cache_mx = 0
|
||||
|
||||
var/update_gen = 0
|
||||
|
||||
/datum/lighting_corner/New(var/turf/new_turf, var/diagonal)
|
||||
. = ..()
|
||||
|
||||
masters = list()
|
||||
masters[new_turf] = turn(diagonal, 180)
|
||||
z = new_turf.z
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ GLOBAL_LIST_EMPTY(all_lighting_objects) // Global list of lighting objects.
|
||||
anchored = TRUE
|
||||
|
||||
icon = LIGHTING_ICON
|
||||
icon_state = "transparent"
|
||||
color = LIGHTING_BASE_MATRIX
|
||||
plane = LIGHTING_PLANE
|
||||
mouse_opacity = 0
|
||||
@@ -16,7 +17,7 @@ GLOBAL_LIST_EMPTY(all_lighting_objects) // Global list of lighting objects.
|
||||
|
||||
var/needs_update = FALSE
|
||||
|
||||
/atom/movable/lighting_object/Initialize(mapload, var/no_update = FALSE)
|
||||
/atom/movable/lighting_object/Initialize(mapload)
|
||||
. = ..()
|
||||
verbs.Cut()
|
||||
GLOB.all_lighting_objects += src
|
||||
@@ -28,10 +29,8 @@ GLOBAL_LIST_EMPTY(all_lighting_objects) // Global list of lighting objects.
|
||||
for(var/turf/open/space/S in RANGE_TURFS(1, src)) //RANGE_TURFS is in code\__HELPERS\game.dm
|
||||
S.update_starlight()
|
||||
|
||||
if (no_update)
|
||||
return
|
||||
|
||||
update()
|
||||
needs_update = TRUE
|
||||
GLOB.lighting_update_objects += src
|
||||
|
||||
/atom/movable/lighting_object/Destroy(var/force)
|
||||
if (force)
|
||||
@@ -69,10 +68,17 @@ GLOBAL_LIST_EMPTY(all_lighting_objects) // Global list of lighting objects.
|
||||
|
||||
// See LIGHTING_CORNER_DIAGONAL in lighting_corner.dm for why these values are what they are.
|
||||
var/static/datum/lighting_corner/dummy/dummy_lighting_corner = new
|
||||
var/datum/lighting_corner/cr = T.corners[3] || dummy_lighting_corner
|
||||
var/datum/lighting_corner/cg = T.corners[2] || dummy_lighting_corner
|
||||
var/datum/lighting_corner/cb = T.corners[4] || dummy_lighting_corner
|
||||
var/datum/lighting_corner/ca = T.corners[1] || dummy_lighting_corner
|
||||
|
||||
var/list/corners = T.corners
|
||||
var/datum/lighting_corner/cr = dummy_lighting_corner
|
||||
var/datum/lighting_corner/cg = dummy_lighting_corner
|
||||
var/datum/lighting_corner/cb = dummy_lighting_corner
|
||||
var/datum/lighting_corner/ca = dummy_lighting_corner
|
||||
if (corners) //done this way for speed
|
||||
cr = corners[3] || dummy_lighting_corner
|
||||
cg = corners[2] || dummy_lighting_corner
|
||||
cb = corners[4] || dummy_lighting_corner
|
||||
ca = corners[1] || dummy_lighting_corner
|
||||
|
||||
var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx)
|
||||
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
if(!IS_DYNAMIC_LIGHTING(T))
|
||||
continue
|
||||
|
||||
new/atom/movable/lighting_object(T, TRUE)
|
||||
new/atom/movable/lighting_object(T)
|
||||
CHECK_TICK
|
||||
CHECK_TICK
|
||||
|
||||
@@ -26,22 +26,15 @@
|
||||
|
||||
var/applied = FALSE // Whether we have applied our light yet or not.
|
||||
|
||||
var/vis_update // Whether we should smartly recalculate visibility. and then only update tiles that became (in)visible to us.
|
||||
var/needs_update // Whether we are queued for an update.
|
||||
var/force_update
|
||||
var/needs_update = LIGHTING_NO_UPDATE // Whether we are queued for an update.
|
||||
|
||||
|
||||
/datum/light_source/New(var/atom/owner, var/atom/top)
|
||||
source_atom = owner // Set our new owner.
|
||||
if (!source_atom.light_sources)
|
||||
source_atom.light_sources = list()
|
||||
|
||||
source_atom.light_sources += src // Add us to the lights of our owner.
|
||||
LAZYADD(source_atom.light_sources, src)
|
||||
top_atom = top
|
||||
if (top_atom != source_atom)
|
||||
if (!top.light_sources)
|
||||
top.light_sources = list()
|
||||
|
||||
top_atom.light_sources += src
|
||||
LAZYADD(top_atom.light_sources, src)
|
||||
|
||||
source_turf = top_atom
|
||||
pixel_turf = get_turf_pixel(top_atom) || source_turf
|
||||
@@ -52,20 +45,18 @@
|
||||
|
||||
parse_light_color()
|
||||
|
||||
effect_str = list()
|
||||
affecting_turfs = list()
|
||||
|
||||
update()
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/light_source/Destroy(force)
|
||||
force_update()
|
||||
remove_lum()
|
||||
if (source_atom)
|
||||
source_atom.light_sources -= src
|
||||
LAZYREMOVE(source_atom.light_sources, src)
|
||||
|
||||
if (top_atom)
|
||||
top_atom.light_sources -= src
|
||||
LAZYREMOVE(top_atom.light_sources, src)
|
||||
|
||||
. = ..()
|
||||
if(!force)
|
||||
return QDEL_HINT_IWILLGC
|
||||
@@ -73,79 +64,34 @@
|
||||
// Yes this doesn't align correctly on anything other than 4 width tabs.
|
||||
// If you want it to go switch everybody to elastic tab stops.
|
||||
// Actually that'd be great if you could!
|
||||
#define EFFECT_UPDATE \
|
||||
if (!needs_update) \
|
||||
{ \
|
||||
GLOB.lighting_update_lights += src; \
|
||||
needs_update = TRUE; \
|
||||
}
|
||||
#define EFFECT_UPDATE(level) \
|
||||
if (needs_update == LIGHTING_NO_UPDATE) \
|
||||
GLOB.lighting_update_lights += src; \
|
||||
if (needs_update < level) \
|
||||
needs_update = level; \
|
||||
|
||||
|
||||
// This proc will cause the light source to update the top atom, and add itself to the update queue.
|
||||
/datum/light_source/proc/update(var/atom/new_top_atom)
|
||||
// This top atom is different.
|
||||
if (new_top_atom && new_top_atom != top_atom)
|
||||
if(top_atom != source_atom && top_atom.light_sources) // Remove ourselves from the light sources of that top atom.
|
||||
top_atom.light_sources -= src
|
||||
LAZYREMOVE(top_atom.light_sources, src)
|
||||
|
||||
top_atom = new_top_atom
|
||||
|
||||
if (top_atom != source_atom)
|
||||
LAZYADD(top_atom.light_sources, src) // Add ourselves to the light sources of our new top atom.
|
||||
|
||||
EFFECT_UPDATE
|
||||
EFFECT_UPDATE(LIGHTING_CHECK_UPDATE)
|
||||
|
||||
// Will force an update without checking if it's actually needed.
|
||||
/datum/light_source/proc/force_update()
|
||||
force_update = 1
|
||||
|
||||
EFFECT_UPDATE
|
||||
EFFECT_UPDATE(LIGHTING_FORCE_UPDATE)
|
||||
|
||||
// Will cause the light source to recalculate turfs that were removed or added to visibility only.
|
||||
/datum/light_source/proc/vis_update()
|
||||
vis_update = 1
|
||||
|
||||
EFFECT_UPDATE
|
||||
|
||||
// Will check if we actually need to update, and update any variables that may need to be updated.
|
||||
/datum/light_source/proc/check()
|
||||
if (!source_atom || !light_range || !light_power)
|
||||
qdel(src)
|
||||
return 1
|
||||
|
||||
if (!top_atom)
|
||||
top_atom = source_atom
|
||||
. = 1
|
||||
|
||||
if (isturf(top_atom))
|
||||
if (source_turf != top_atom)
|
||||
source_turf = top_atom
|
||||
pixel_turf = source_turf
|
||||
. = 1
|
||||
else if (top_atom.loc != source_turf)
|
||||
source_turf = top_atom.loc
|
||||
pixel_turf = get_turf_pixel(top_atom)
|
||||
. = 1
|
||||
else
|
||||
var/P = get_turf_pixel(top_atom)
|
||||
if (P != pixel_turf)
|
||||
. = 1
|
||||
pixel_turf = get_turf_pixel(top_atom)
|
||||
|
||||
if (source_atom.light_power != light_power)
|
||||
light_power = source_atom.light_power
|
||||
. = 1
|
||||
|
||||
if (source_atom.light_range != light_range)
|
||||
light_range = source_atom.light_range
|
||||
. = 1
|
||||
|
||||
if (light_range && light_power && !applied)
|
||||
. = 1
|
||||
|
||||
if (source_atom.light_color != light_color)
|
||||
light_color = source_atom.light_color
|
||||
parse_light_color()
|
||||
. = 1
|
||||
EFFECT_UPDATE(LIGHTING_VIS_UPDATE)
|
||||
|
||||
// Decompile the hexadecimal colour into lumcounts of each perspective.
|
||||
/datum/light_source/proc/parse_light_color()
|
||||
@@ -164,48 +110,47 @@
|
||||
// As such this all gets counted as a single line.
|
||||
// The braces and semicolons are there to be able to do this on a single line.
|
||||
#define LUM_FALLOFF(C, T) (1 - CLAMP01(sqrt((C.x - T.x) ** 2 + (C.y - T.y) ** 2 + LIGHTING_HEIGHT) / max(1, light_range)))
|
||||
#define APPLY_CORNER(C) \
|
||||
. = LUM_FALLOFF(C, pixel_turf); \
|
||||
\
|
||||
. *= light_power; \
|
||||
\
|
||||
effect_str[C] = .; \
|
||||
\
|
||||
C.update_lumcount \
|
||||
( \
|
||||
. * applied_lum_r, \
|
||||
. * applied_lum_g, \
|
||||
. * applied_lum_b \
|
||||
|
||||
#define APPLY_CORNER(C) \
|
||||
. = LUM_FALLOFF(C, pixel_turf); \
|
||||
. *= light_power; \
|
||||
var/OLD = effect_str[C]; \
|
||||
\
|
||||
effect_str[C] = .; \
|
||||
\
|
||||
C.update_lumcount \
|
||||
( \
|
||||
(. * lum_r) - (OLD * applied_lum_r), \
|
||||
(. * lum_g) - (OLD * applied_lum_g), \
|
||||
(. * lum_b) - (OLD * applied_lum_b) \
|
||||
);
|
||||
|
||||
// I don't need to explain what this does, do I?
|
||||
#define REMOVE_CORNER(C) \
|
||||
. = -effect_str[C]; \
|
||||
C.update_lumcount \
|
||||
( \
|
||||
. * applied_lum_r, \
|
||||
. * applied_lum_g, \
|
||||
. * applied_lum_b \
|
||||
|
||||
#define REMOVE_CORNER(C) \
|
||||
. = -effect_str[C]; \
|
||||
C.update_lumcount \
|
||||
( \
|
||||
. * applied_lum_r, \
|
||||
. * applied_lum_g, \
|
||||
. * applied_lum_b \
|
||||
);
|
||||
|
||||
// This is the define used to calculate falloff.
|
||||
|
||||
|
||||
/*
|
||||
/datum/light_source/proc/apply_lum()
|
||||
var/static/update_gen = 1
|
||||
applied = 1
|
||||
|
||||
// Keep track of the last applied lum values so that the lighting can be reversed
|
||||
applied_lum_r = lum_r
|
||||
applied_lum_g = lum_g
|
||||
applied_lum_b = lum_b
|
||||
var/thing
|
||||
var/datum/lighting_corner/C
|
||||
var/corners = list()
|
||||
LAZYINITLIST(effect_str)
|
||||
FOR_DVIEW(var/turf/T, light_range+1, source_turf, INVISIBILITY_LIGHTING)
|
||||
if (!T.lighting_corners_initialised)
|
||||
T.generate_missing_corners()
|
||||
var/list/turf_corners = T.get_corners()
|
||||
|
||||
for (thing in T.get_corners())
|
||||
for (thing in turf_corners)
|
||||
C = thing
|
||||
if (C.update_gen == update_gen)
|
||||
continue
|
||||
@@ -220,9 +165,13 @@
|
||||
APPLY_CORNER(C)
|
||||
|
||||
LAZYADD(T.affecting_lights, src)
|
||||
affecting_turfs += T
|
||||
LAZYADD(affecting_turfs, T)
|
||||
FOR_DVIEW_END
|
||||
update_gen++
|
||||
applied_lum_r = lum_r
|
||||
applied_lum_g = lum_g
|
||||
applied_lum_b = lum_b
|
||||
*/
|
||||
|
||||
/datum/light_source/proc/remove_lum()
|
||||
applied = FALSE
|
||||
@@ -231,7 +180,7 @@
|
||||
var/turf/T = thing
|
||||
LAZYREMOVE(T.affecting_lights, src)
|
||||
|
||||
affecting_turfs.Cut()
|
||||
affecting_turfs = null
|
||||
|
||||
var/datum/lighting_corner/C
|
||||
for (thing in effect_str)
|
||||
@@ -240,30 +189,93 @@
|
||||
|
||||
LAZYREMOVE(C.affecting, src)
|
||||
|
||||
effect_str.Cut()
|
||||
effect_str = null
|
||||
|
||||
/datum/light_source/proc/recalc_corner(var/datum/lighting_corner/C)
|
||||
if (effect_str.Find(C)) // Already have one.
|
||||
LAZYINITLIST(effect_str)
|
||||
if (effect_str[C]) // Already have one.
|
||||
REMOVE_CORNER(C)
|
||||
effect_str[C] = 0
|
||||
|
||||
APPLY_CORNER(C)
|
||||
UNSETEMPTY(effect_str)
|
||||
|
||||
/datum/light_source/proc/update_corners()
|
||||
var/update = FALSE
|
||||
|
||||
if (!source_atom || QDELETED(source_atom))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if (source_atom.light_power != light_power)
|
||||
light_power = source_atom.light_power
|
||||
update = TRUE
|
||||
|
||||
if (source_atom.light_range != light_range)
|
||||
light_range = source_atom.light_range
|
||||
update = TRUE
|
||||
|
||||
if (!top_atom)
|
||||
top_atom = source_atom
|
||||
update = TRUE
|
||||
|
||||
if (!light_range || !light_power)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if (isturf(top_atom))
|
||||
if (source_turf != top_atom)
|
||||
source_turf = top_atom
|
||||
pixel_turf = source_turf
|
||||
update = TRUE
|
||||
else if (top_atom.loc != source_turf)
|
||||
source_turf = top_atom.loc
|
||||
pixel_turf = get_turf_pixel(top_atom)
|
||||
update = TRUE
|
||||
else
|
||||
var/P = get_turf_pixel(top_atom)
|
||||
if (P != pixel_turf)
|
||||
pixel_turf = P
|
||||
update = TRUE
|
||||
|
||||
if (!isturf(source_turf))
|
||||
if (applied)
|
||||
remove_lum()
|
||||
return
|
||||
|
||||
if (light_range && light_power && !applied)
|
||||
update = TRUE
|
||||
|
||||
if (source_atom.light_color != light_color)
|
||||
light_color = source_atom.light_color
|
||||
parse_light_color()
|
||||
update = TRUE
|
||||
|
||||
else if (applied_lum_r != lum_r || applied_lum_g != lum_g || applied_lum_b != lum_b)
|
||||
update = TRUE
|
||||
|
||||
if (update)
|
||||
needs_update = LIGHTING_CHECK_UPDATE
|
||||
applied = TRUE
|
||||
else if (needs_update == LIGHTING_CHECK_UPDATE)
|
||||
return //nothing's changed
|
||||
|
||||
/datum/light_source/proc/smart_vis_update()
|
||||
var/list/datum/lighting_corner/corners = list()
|
||||
var/list/turf/turfs = list()
|
||||
var/thing
|
||||
var/datum/lighting_corner/C
|
||||
var/turf/T
|
||||
if (source_turf)
|
||||
var/oldlum = source_turf.luminosity
|
||||
source_turf.luminosity = Ceiling(light_range)
|
||||
for(T in view(Ceiling(light_range), source_turf))
|
||||
for (thing in T.get_corners(source_turf))
|
||||
C = thing
|
||||
corners[C] = 0
|
||||
turfs += T
|
||||
source_turf.luminosity = oldlum
|
||||
|
||||
FOR_DVIEW(T, light_range+1, source_turf, 0)
|
||||
if (!T.lighting_corners_initialised)
|
||||
T.generate_missing_corners()
|
||||
for (thing in T.get_corners(source_turf))
|
||||
C = thing
|
||||
corners[C] = 0
|
||||
turfs += T
|
||||
FOR_DVIEW_END
|
||||
|
||||
LAZYINITLIST(affecting_turfs)
|
||||
var/list/L = turfs - affecting_turfs // New turfs, add us to the affecting lights of them.
|
||||
affecting_turfs += L
|
||||
for (thing in L)
|
||||
@@ -276,22 +288,45 @@
|
||||
T = thing
|
||||
LAZYREMOVE(T.affecting_lights, src)
|
||||
|
||||
LAZYINITLIST(effect_str)
|
||||
if (needs_update == LIGHTING_VIS_UPDATE)
|
||||
for (thing in corners - effect_str) // New corners
|
||||
C = thing
|
||||
LAZYADD(C.affecting, src)
|
||||
if (!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
APPLY_CORNER(C)
|
||||
else
|
||||
L = corners - effect_str
|
||||
for (thing in L) // New corners
|
||||
C = thing
|
||||
LAZYADD(C.affecting, src)
|
||||
if (!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
APPLY_CORNER(C)
|
||||
|
||||
for (thing in corners - L) // Existing corners
|
||||
C = thing
|
||||
if (!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
APPLY_CORNER(C)
|
||||
|
||||
for (thing in corners - effect_str) // New corners
|
||||
C = thing
|
||||
LAZYADD(C.affecting, src)
|
||||
if (!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
|
||||
APPLY_CORNER(C)
|
||||
|
||||
for (thing in effect_str - corners) // Old, now gone, corners.
|
||||
L = effect_str - corners
|
||||
for (thing in L) // Old, now gone, corners.
|
||||
C = thing
|
||||
REMOVE_CORNER(C)
|
||||
LAZYREMOVE(C.affecting, src)
|
||||
effect_str -= C
|
||||
effect_str -= L
|
||||
|
||||
applied_lum_r = lum_r
|
||||
applied_lum_g = lum_g
|
||||
applied_lum_b = lum_b
|
||||
|
||||
UNSETEMPTY(effect_str)
|
||||
UNSETEMPTY(affecting_turfs)
|
||||
|
||||
#undef EFFECT_UPDATE
|
||||
#undef LUM_FALLOFF
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
return
|
||||
|
||||
var/area/A = loc
|
||||
if (!IS_DYNAMIC_LIGHTING(A))
|
||||
if (!IS_DYNAMIC_LIGHTING(A) && !light_sources)
|
||||
return
|
||||
|
||||
if (!lighting_corners_initialised)
|
||||
@@ -113,12 +113,18 @@
|
||||
lighting_clear_overlay()
|
||||
|
||||
/turf/proc/get_corners()
|
||||
if (!IS_DYNAMIC_LIGHTING(src) && !light_sources)
|
||||
return null
|
||||
if (!lighting_corners_initialised)
|
||||
generate_missing_corners()
|
||||
if (has_opaque_atom)
|
||||
return null // Since this proc gets used in a for loop, null won't be looped though.
|
||||
|
||||
return corners
|
||||
|
||||
/turf/proc/generate_missing_corners()
|
||||
if (!IS_DYNAMIC_LIGHTING(src) && !light_sources)
|
||||
return
|
||||
lighting_corners_initialised = TRUE
|
||||
if (!corners)
|
||||
corners = list(null, null, null, null)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
if(ruins && ruins.len)
|
||||
ruin = ruins[pick(ruins)]
|
||||
else
|
||||
world.log << "Ruin loader had no ruins to pick from with [budget] left to spend."
|
||||
log_world("Ruin loader had no ruins to pick from with [budget] left to spend.")
|
||||
break
|
||||
// Can we afford it
|
||||
if(ruin.cost > budget)
|
||||
@@ -47,7 +47,7 @@
|
||||
if(!valid)
|
||||
continue
|
||||
|
||||
world.log << "Ruin \"[ruin.name]\" placed at ([T.x], [T.y], [T.z])"
|
||||
log_world("Ruin \"[ruin.name]\" placed at ([T.x], [T.y], [T.z])")
|
||||
|
||||
var/obj/effect/ruin_loader/R = new /obj/effect/ruin_loader(T)
|
||||
R.Load(ruins,ruin)
|
||||
@@ -57,7 +57,7 @@
|
||||
break
|
||||
|
||||
if(!overall_sanity)
|
||||
world.log << "Ruin loader gave up with [budget] left to spend."
|
||||
log_world("Ruin loader gave up with [budget] left to spend.")
|
||||
|
||||
|
||||
/obj/effect/ruin_loader
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
desc = "It's watching you suspiciously."
|
||||
|
||||
/obj/structure/closet/crate/necropolis/tendril/PopulateContents()
|
||||
var/loot = rand(1,25)
|
||||
var/loot = rand(1,26)
|
||||
switch(loot)
|
||||
if(1)
|
||||
new /obj/item/device/shared_storage/red(src)
|
||||
@@ -33,7 +33,7 @@
|
||||
if(9)
|
||||
new /obj/item/organ/brain/alien(src)
|
||||
if(10)
|
||||
new /obj/item/organ/heart/cursed(src)
|
||||
new /obj/item/organ/heart/cursed/wizard(src)
|
||||
if(11)
|
||||
new /obj/item/ship_in_a_bottle(src)
|
||||
if(12)
|
||||
@@ -65,6 +65,8 @@
|
||||
new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor(src)
|
||||
if(25)
|
||||
new /obj/item/weapon/spellbook/oneuse/summonitem(src)
|
||||
if(26)
|
||||
new /obj/item/book_of_babel(src)
|
||||
|
||||
|
||||
|
||||
@@ -343,6 +345,24 @@
|
||||
add_fingerprint(usr)
|
||||
|
||||
|
||||
|
||||
|
||||
//Book of Babel
|
||||
|
||||
/obj/item/book_of_babel
|
||||
name = "Book of Babel"
|
||||
desc = "An ancient tome written in countless tongues."
|
||||
icon = 'icons/obj/library.dmi'
|
||||
icon_state = "book1"
|
||||
w_class = 2
|
||||
|
||||
/obj/item/book_of_babel/attack_self(mob/user)
|
||||
to_chat(user, "You flip through the pages of the book, quickly and conveniently learning every language in existence. Somewhat less conveniently, the aging book crumbles to dust in the process. Whoops.")
|
||||
user.grant_all_languages(omnitongue=TRUE)
|
||||
new /obj/effect/decal/cleanable/ash(get_turf(user))
|
||||
qdel(src)
|
||||
|
||||
|
||||
//Boat
|
||||
|
||||
/obj/vehicle/lavaboat
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
if(D.make_reagents.len)
|
||||
return 0
|
||||
|
||||
var/build_amount = 1
|
||||
var/build_amount = 0
|
||||
|
||||
for(var/mat_id in D.materials)
|
||||
var/M = D.materials[mat_id]
|
||||
@@ -93,7 +93,15 @@
|
||||
if(!M || !redemption_mat)
|
||||
return 0
|
||||
|
||||
build_amount = min(build_amount, round(redemption_mat.amount / M))
|
||||
var/smeltable_sheets = round(redemption_mat.amount / M)
|
||||
|
||||
if(!smeltable_sheets)
|
||||
return 0
|
||||
|
||||
if(!build_amount)
|
||||
build_amount = smeltable_sheets
|
||||
|
||||
build_amount = min(build_amount, smeltable_sheets)
|
||||
|
||||
return build_amount
|
||||
|
||||
@@ -152,6 +160,7 @@
|
||||
if(exchange_parts(user, W))
|
||||
return
|
||||
if(default_pry_open(W))
|
||||
materials.retrieve_all()
|
||||
return
|
||||
if(default_unfasten_wrench(user, W))
|
||||
return
|
||||
|
||||
@@ -193,9 +193,7 @@
|
||||
qdel(voucher)
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/ex_act(severity, target)
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(5, 1, src)
|
||||
s.start()
|
||||
do_sparks(5, TRUE, src)
|
||||
if(prob(50 / severity) && severity < 3)
|
||||
qdel(src)
|
||||
|
||||
@@ -214,11 +212,10 @@
|
||||
new /datum/data/mining_equipment("Monkey Cube", /obj/item/weapon/reagent_containers/food/snacks/monkeycube, 300),
|
||||
new /datum/data/mining_equipment("Toolbelt", /obj/item/weapon/storage/belt/utility, 350),
|
||||
new /datum/data/mining_equipment("Sulphuric Acid", /obj/item/weapon/reagent_containers/glass/beaker/sulphuric, 500),
|
||||
new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/weapon/storage/firstaid/brute, 600),
|
||||
new /datum/data/mining_equipment("Grey Slime Extract", /obj/item/slime_extract/grey, 1000),
|
||||
new /datum/data/mining_equipment("Modification Kit", /obj/item/borg/upgrade/modkit/trigger_guard, 1700),
|
||||
new /datum/data/mining_equipment("The Liberator's Legacy", /obj/item/weapon/storage/box/rndboards, 2000),
|
||||
|
||||
new /datum/data/mining_equipment("Royal Cape of the Liberator", /obj/item/weapon/bedsheet/rd/royal_cape, 500)
|
||||
)
|
||||
|
||||
var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/mining_equipment_vendor/golem(null)
|
||||
|
||||
@@ -278,8 +278,8 @@
|
||||
|
||||
var/turf/T = deploy_location
|
||||
if(T.z != ZLEVEL_MINING && T.z != ZLEVEL_LAVALAND)//only report capsules away from the mining/lavaland level
|
||||
message_admins("[key_name_admin(usr)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) activated a bluespace capsule away from the mining level! (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>JMP</a>)")
|
||||
log_admin("[key_name(usr)] activated a bluespace capsule away from the mining level at [T.x], [T.y], [T.z]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] activated a bluespace capsule away from the mining level! [ADMIN_JMP(T)]")
|
||||
log_admin("[key_name(usr)] activated a bluespace capsule away from the mining level at [get_area(T)][COORD(T)]")
|
||||
template.load(deploy_location, centered = TRUE)
|
||||
new /obj/effect/particle_effect/smoke(get_turf(src))
|
||||
qdel(src)
|
||||
|
||||
@@ -248,18 +248,18 @@
|
||||
|
||||
if(notify_admins)
|
||||
if(triggered_by == 1)
|
||||
message_admins("An explosion has triggered a [name] to detonate at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name] (JMP)</a>.")
|
||||
message_admins("An explosion has triggered a [name] to detonate at [ADMIN_COORDJMP(bombturf)].")
|
||||
else if(triggered_by == 2)
|
||||
message_admins("A signal has triggered a [name] to detonate at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name] (JMP)</a>. Igniter attacher: [key_name_admin(attacher)]<A HREF='?_src_=holder;adminmoreinfo=\ref[attacher]'>?</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[attacher]'>FLW</A>)")
|
||||
message_admins("A signal has triggered a [name] to detonate at [ADMIN_COORDJMP(bombturf)]. Igniter attacher: [ADMIN_LOOKUPFLW(attacher)]")
|
||||
else
|
||||
message_admins("[key_name_admin(user)]<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) has triggered a [name] to detonate at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name] (JMP)</a>.")
|
||||
message_admins("[ADMIN_LOOKUPFLW(attacher)] has triggered a [name] to detonate at [ADMIN_COORDJMP(bombturf)].")
|
||||
if(triggered_by == 1)
|
||||
log_game("An explosion has primed a [name] for detonation at [A.name]([bombturf.x],[bombturf.y],[bombturf.z])")
|
||||
log_game("An explosion has primed a [name] for detonation at [A][COORD(bombturf)]")
|
||||
else if(triggered_by == 2)
|
||||
log_game("A signal has primed a [name] for detonation at [A.name]([bombturf.x],[bombturf.y],[bombturf.z]). Igniter attacher: [key_name(attacher)].")
|
||||
log_game("A signal has primed a [name] for detonation at [A][COORD(bombturf)]. Igniter attacher: [key_name(attacher)].")
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] strikes \the [src], causing a chain reaction!</span>", "<span class='danger'>You strike \the [src], causing a chain reaction.</span>")
|
||||
log_game("[key_name(user)] has primed a [name] for detonation at [A.name]([bombturf.x],[bombturf.y],[bombturf.z])")
|
||||
log_game("[key_name(user)] has primed a [name] for detonation at [A][COORD(bombturf)]")
|
||||
spawn(det_time)
|
||||
if(primed)
|
||||
if(quality == 3)
|
||||
|
||||
@@ -1,42 +1,51 @@
|
||||
//Dead mobs can exist whenever. This is needful
|
||||
|
||||
INITIALIZE_IMMEDIATE(/mob/dead)
|
||||
|
||||
/mob/dead/Initialize()
|
||||
. = ..()
|
||||
if(config.cross_allowed)
|
||||
verbs += /mob/dead/proc/server_hop
|
||||
INITIALIZE_IMMEDIATE(/mob/dead)
|
||||
|
||||
/mob/dead/dust() //ghosts can't be vaporised.
|
||||
return
|
||||
|
||||
/mob/dead/gib() //ghosts can't be gibbed.
|
||||
return
|
||||
/mob/dead/Initialize()
|
||||
if(initialized)
|
||||
stack_trace("Warning: [src]([type]) initialized multiple times!")
|
||||
initialized = TRUE
|
||||
tag = "mob_[next_mob_id++]"
|
||||
GLOB.mob_list += src
|
||||
|
||||
/mob/dead/ConveyorMove() //lol
|
||||
return
|
||||
prepare_huds()
|
||||
|
||||
if(config.cross_allowed)
|
||||
verbs += /mob/dead/proc/server_hop
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
|
||||
/mob/dead/dust() //ghosts can't be vaporised.
|
||||
return
|
||||
|
||||
/mob/dead/gib() //ghosts can't be gibbed.
|
||||
return
|
||||
|
||||
/mob/dead/ConveyorMove() //lol
|
||||
return
|
||||
|
||||
|
||||
|
||||
/mob/dead/proc/server_hop()
|
||||
set category = "OOC"
|
||||
set name = "Server Hop!"
|
||||
set desc= "Jump to the other server"
|
||||
if(notransform)
|
||||
return
|
||||
if(!config.cross_allowed)
|
||||
verbs -= /mob/dead/proc/server_hop
|
||||
to_chat(src, "<span class='notice'>Server Hop has been disabled.</span>")
|
||||
return
|
||||
if (alert(src, "Jump to server running at [config.cross_address]?", "Server Hop", "Yes", "No") != "Yes")
|
||||
return 0
|
||||
if (client && config.cross_allowed)
|
||||
to_chat(src, "<span class='notice'>Sending you to [config.cross_address].</span>")
|
||||
new /obj/screen/splash(client)
|
||||
notransform = TRUE
|
||||
sleep(29) //let the animation play
|
||||
notransform = FALSE
|
||||
winset(src, null, "command=.options") //other wise the user never knows if byond is downloading resources
|
||||
client << link(config.cross_address + "?server_hop=[key]")
|
||||
else
|
||||
to_chat(src, "<span class='error'>There is no other server configured!</span>")
|
||||
/mob/dead/proc/server_hop()
|
||||
set category = "OOC"
|
||||
set name = "Server Hop!"
|
||||
set desc= "Jump to the other server"
|
||||
if(notransform)
|
||||
return
|
||||
if(!config.cross_allowed)
|
||||
verbs -= /mob/dead/proc/server_hop
|
||||
to_chat(src, "<span class='notice'>Server Hop has been disabled.</span>")
|
||||
return
|
||||
if (alert(src, "Jump to server running at [config.cross_address]?", "Server Hop", "Yes", "No") != "Yes")
|
||||
return 0
|
||||
if (client && config.cross_allowed)
|
||||
to_chat(src, "<span class='notice'>Sending you to [config.cross_address].</span>")
|
||||
new /obj/screen/splash(client)
|
||||
notransform = TRUE
|
||||
sleep(29) //let the animation play
|
||||
notransform = FALSE
|
||||
winset(src, null, "command=.options") //other wise the user never knows if byond is downloading resources
|
||||
client << link(config.cross_address + "?server_hop=[key]")
|
||||
else
|
||||
to_chat(src, "<span class='error'>There is no other server configured!</span>")
|
||||
|
||||
@@ -16,12 +16,6 @@
|
||||
var/mob/living/new_character //for instant transfer once the round is set up
|
||||
|
||||
/mob/dead/new_player/Initialize()
|
||||
if(initialized)
|
||||
stack_trace("Warning: [src]([type]) initialized multiple times!")
|
||||
initialized = TRUE
|
||||
tag = "mob_[next_mob_id++]"
|
||||
GLOB.mob_list += src
|
||||
|
||||
if(client && SSticker.state == GAME_STATE_STARTUP)
|
||||
var/obj/screen/splash/S = new(client, TRUE, TRUE)
|
||||
S.Fade(TRUE)
|
||||
@@ -30,7 +24,10 @@
|
||||
loc = pick(GLOB.newplayer_start)
|
||||
else
|
||||
loc = locate(1,1,1)
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
. = ..()
|
||||
|
||||
/mob/dead/new_player/prepare_huds()
|
||||
return
|
||||
|
||||
/mob/dead/new_player/proc/new_player_panel()
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
|
||||
var/deadchat_name
|
||||
|
||||
/mob/dead/observer/Initialize()
|
||||
invisibility = GLOB.observer_default_invisibility
|
||||
set_invisibility(GLOB.observer_default_invisibility)
|
||||
|
||||
verbs += /mob/dead/observer/proc/dead_tele
|
||||
|
||||
@@ -117,6 +117,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
|
||||
|
||||
animate(src, pixel_y = 2, time = 10, loop = -1)
|
||||
|
||||
|
||||
GLOB.dead_mob_list += src
|
||||
|
||||
..()
|
||||
@@ -786,13 +787,25 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if(!invisibility)
|
||||
to_chat(user, "It seems extremely obvious.")
|
||||
|
||||
/mob/dead/observer/proc/set_invisibility(value)
|
||||
invisibility = value
|
||||
if(!value)
|
||||
set_light(1, 2)
|
||||
else
|
||||
set_light(0, 0)
|
||||
|
||||
// Ghosts have no momentum, being massless ectoplasm
|
||||
/mob/dead/observer/Process_Spacemove(movement_dir)
|
||||
return 1
|
||||
|
||||
/mob/dead/observer/vv_edit_var(var_name, var_value)
|
||||
. = ..()
|
||||
if(var_name == "invisibility")
|
||||
set_invisibility(invisibility) // updates light
|
||||
|
||||
/proc/set_observer_default_invisibility(amount, message=null)
|
||||
for(var/mob/dead/observer/G in GLOB.player_list)
|
||||
G.invisibility = amount
|
||||
G.set_invisibility(amount)
|
||||
if(message)
|
||||
to_chat(G, message)
|
||||
GLOB.observer_default_invisibility = amount
|
||||
|
||||
@@ -35,22 +35,21 @@
|
||||
blood_volume += 0.1 // regenerate blood VERY slowly
|
||||
|
||||
//Effects of bloodloss
|
||||
var/word = pick("dizzy","woozy","faint")
|
||||
switch(blood_volume)
|
||||
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
|
||||
if(prob(5))
|
||||
to_chat(src, "<span class='warning'>You feel [pick("dizzy","woozy","faint")].</span>")
|
||||
to_chat(src, "<span class='warning'>You feel [word].</span>")
|
||||
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1))
|
||||
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
|
||||
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
|
||||
if(prob(5))
|
||||
blur_eyes(6)
|
||||
var/word = pick("dizzy","woozy","faint")
|
||||
to_chat(src, "<span class='warning'>You feel very [word].</span>")
|
||||
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
|
||||
adjustOxyLoss(5)
|
||||
if(prob(15))
|
||||
Paralyse(rand(1,3))
|
||||
var/word = pick("dizzy","woozy","faint")
|
||||
to_chat(src, "<span class='warning'>You feel extremely [word].</span>")
|
||||
if(0 to BLOOD_VOLUME_SURVIVE)
|
||||
death()
|
||||
@@ -70,7 +69,7 @@
|
||||
|
||||
bleed_rate = max(bleed_rate - 0.5, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases
|
||||
|
||||
if(bleed_rate && !bleedsuppress)
|
||||
if(bleed_rate && !bleedsuppress && !(status_flags & FAKEDEATH))
|
||||
bleed(bleed_rate)
|
||||
|
||||
//Makes a blood drop, leaking amt units of blood from the mob
|
||||
|
||||
@@ -31,13 +31,10 @@
|
||||
else
|
||||
icon_state = "mmi_empty"
|
||||
|
||||
/obj/item/device/mmi/New()
|
||||
..()
|
||||
/obj/item/device/mmi/Initialize()
|
||||
. = ..()
|
||||
radio = new(src) //Spawns a radio inside the MMI.
|
||||
radio.broadcasting = 0 //researching radio mmis turned the robofabs into radios because this didnt start as 0.
|
||||
|
||||
/obj/item/device/mmi/Initialize()
|
||||
..()
|
||||
laws.set_laws_config()
|
||||
|
||||
/obj/item/device/mmi/attackby(obj/item/O, mob/user, params)
|
||||
|
||||
@@ -87,6 +87,8 @@
|
||||
owner.adjustFireLoss(-heal_amt)
|
||||
owner.adjustOxyLoss(-heal_amt)
|
||||
owner.adjustCloneLoss(-heal_amt)
|
||||
else
|
||||
owner.adjustPlasma(plasma_rate * 0.1)
|
||||
|
||||
/obj/item/organ/alien/plasmavessel/Insert(mob/living/carbon/M, special = 0)
|
||||
..()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/living/proc/alien_talk(message, shown_name = name)
|
||||
/mob/living/proc/alien_talk(message, shown_name = real_name)
|
||||
log_say("[key_name(src)] : [message]")
|
||||
message = trim(message)
|
||||
if(!message) return
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
|
||||
bursting = TRUE
|
||||
|
||||
var/list/candidates = pollCandidates("Do you want to play as an alien larva that will burst out of [owner]?", ROLE_ALIEN, null, ROLE_ALIEN, 100, POLL_IGNORE_ALIEN_LARVA)
|
||||
var/list/candidates = pollGhostCandidates("Do you want to play as an alien larva that will burst out of [owner]?", ROLE_ALIEN, null, ROLE_ALIEN, 100, POLL_IGNORE_ALIEN_LARVA)
|
||||
|
||||
if(QDELETED(src) || QDELETED(owner))
|
||||
return
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
var/mob/dead/observer/ghost = pick(candidates)
|
||||
|
||||
var/mutable_appearance/overlay = mutable_appearance('icons/mob/alien.dmi', "burst_lie")
|
||||
var/mutable_appearance/overlay = mutable_appearance('icons/mob/alien.dmi', "burst_lie")
|
||||
owner.add_overlay(overlay)
|
||||
|
||||
var/atom/xeno_loc = get_turf(owner)
|
||||
|
||||
@@ -484,7 +484,7 @@
|
||||
adjustBruteLoss(3)
|
||||
else
|
||||
if(T)
|
||||
T.add_vomit_floor(src, 0)//toxic barf looks different
|
||||
T.add_vomit_floor(src, toxic)//toxic barf looks different
|
||||
nutrition -= lost_nutrition
|
||||
adjustToxLoss(-3)
|
||||
T = get_step(T, dir)
|
||||
@@ -492,6 +492,16 @@
|
||||
break
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/proc/spew_organ(power = 5)
|
||||
if(!internal_organs.len)
|
||||
return //Guess we're out of organs
|
||||
var/obj/item/organ/guts = pick(internal_organs)
|
||||
var/turf/T = get_turf(src)
|
||||
guts.Remove(src)
|
||||
guts.forceMove(T)
|
||||
var/atom/throw_target = get_edge_target_turf(guts, dir)
|
||||
guts.throw_at(throw_target, power, 4, src)
|
||||
|
||||
|
||||
/mob/living/carbon/fully_replace_character_name(oldname,newname)
|
||||
..()
|
||||
|
||||
@@ -119,9 +119,7 @@
|
||||
visible_message("<span class='danger'>The [M.name] has shocked [src]!</span>", \
|
||||
"<span class='userdanger'>The [M.name] has shocked [src]!</span>")
|
||||
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(5, 1, src)
|
||||
s.start()
|
||||
do_sparks(5, TRUE, src)
|
||||
var/power = M.powerlevel + rand(0,3)
|
||||
Weaken(power)
|
||||
if(stuttering < power)
|
||||
|
||||
@@ -68,6 +68,17 @@
|
||||
if(!isnum(text2num(params)))
|
||||
return message
|
||||
|
||||
/datum/emote/sound/carbon/snap
|
||||
key = "snap"
|
||||
key_third_person = "snaps"
|
||||
message = "snaps their fingers."
|
||||
muzzle_ignore = TRUE
|
||||
restraint_check = TRUE
|
||||
emote_type = EMOTE_AUDIBLE
|
||||
sound = 'sound/effects/snap01.ogg'
|
||||
mob_type_allowed_typecache = list(/mob/living/carbon/)
|
||||
|
||||
|
||||
/datum/emote/living/carbon/sign/signal
|
||||
key = "signal"
|
||||
key_third_person = "signals"
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
diff a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm (rejected hunks)
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
dna.species.spec_death(gibbed, src)
|
||||
|
||||
- if(SSticker && SSticker.mode)
|
||||
+ if(SSticker.HasRoundStarted())
|
||||
SSblackbox.ReportDeath(src)
|
||||
if(mind && mind.devilinfo)
|
||||
INVOKE_ASYNC(mind.devilinfo, /datum/devilinfo.proc/beginResurrectionCheck, src)
|
||||
@@ -171,5 +171,8 @@
|
||||
dna.species.mutant_bodyparts -= "wingsopen"
|
||||
dna.species.mutant_bodyparts |= "wings"
|
||||
update_body()
|
||||
if(isturf(loc))
|
||||
var/turf/T = loc
|
||||
T.Entered(src)
|
||||
|
||||
//Ayy lmao
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
if(stat == DEAD || (status_flags & FAKEDEATH))
|
||||
appears_dead = 1
|
||||
if(suiciding)
|
||||
msg += "<span class='warning'>[t_He] appear[p_s()] to have commited suicide... there is no hope of recovery.</span>\n"
|
||||
msg += "<span class='warning'>[t_He] appear[p_s()] to have committed suicide... there is no hope of recovery.</span>\n"
|
||||
if(hellbound)
|
||||
msg += "<span class='warning'>[t_His] soul seems to have been ripped out of [t_his] body. Revival is impossible.</span>\n"
|
||||
msg += "<span class='deadsay'>[t_He] [t_is] limp and unresponsive; there are no signs of life"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
diff a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm (rejected hunks)
|
||||
@@ -58,8 +58,9 @@
|
||||
if(!(NOBLOOD in dna.species.species_traits))
|
||||
internal_organs += new /obj/item/organ/heart
|
||||
|
||||
- internal_organs += new dna.species.mutanteyes()
|
||||
+ internal_organs += new dna.species.mutanteyes
|
||||
internal_organs += new dna.species.mutantears
|
||||
+ internal_organs += new dna.species.mutanttongue
|
||||
internal_organs += new /obj/item/organ/brain
|
||||
..()
|
||||
|
||||
@@ -142,10 +142,12 @@
|
||||
return not_handled //For future deeper overrides
|
||||
|
||||
/mob/living/carbon/human/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE)
|
||||
var/index = get_held_index_of_item(I)
|
||||
. = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should.
|
||||
if(!. || !I)
|
||||
return
|
||||
|
||||
if(index && dna.species.mutanthands)
|
||||
put_in_hand(new dna.species.mutanthands(), index)
|
||||
if(I == wear_suit)
|
||||
if(s_store && invdrop)
|
||||
dropItemToGround(s_store, TRUE) //It makes no sense for your suit storage to stay on you if you drop your suit.
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
var/say_mod = "says" // affects the speech message
|
||||
var/list/default_features = list() // Default mutant bodyparts for this species. Don't forget to set one for every mutant bodypart you allow this species to have.
|
||||
var/list/mutant_bodyparts = list() // Parts of the body that are diferent enough from the standard human model that they cause clipping with some equipment
|
||||
var/list/mutant_organs = list(/obj/item/organ/tongue) //Internal organs that are unique to this race.
|
||||
var/list/mutant_organs = list() //Internal organs that are unique to this race.
|
||||
var/speedmod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster
|
||||
var/armor = 0 // overall defense for the race... or less defense, if it's negative.
|
||||
var/brutemod = 1 // multiplier for brute damage
|
||||
@@ -65,11 +65,12 @@
|
||||
//Flight and floating
|
||||
var/override_float = 0
|
||||
|
||||
//Eyes
|
||||
var/obj/item/organ/eyes/mutanteyes = /obj/item/organ/eyes
|
||||
|
||||
//Ears
|
||||
var/obj/item/organ/ears/mutantears = /obj/item/organ/ears
|
||||
var/obj/item/organ/tongue/mutanttongue = /obj/item/organ/tongue
|
||||
|
||||
//Hands
|
||||
var/obj/item/mutanthands = null
|
||||
|
||||
//Citadel snowflake
|
||||
var/fixed_mut_color2 = ""
|
||||
@@ -119,6 +120,8 @@
|
||||
var/obj/item/thing = C.get_item_by_slot(slot_id)
|
||||
if(thing && (!thing.species_exception || !is_type_in_list(src,thing.species_exception)))
|
||||
C.dropItemToGround(thing)
|
||||
if(C.hud_used)
|
||||
C.hud_used.update_locked_slots()
|
||||
|
||||
// this needs to be FIRST because qdel calls update_body which checks if we have DIGITIGRADE legs or not and if not then removes DIGITIGRADE from species_traits
|
||||
if(("legs" in C.dna.species.mutant_bodyparts) && C.dna.features["legs"] == "Digitigrade Legs")
|
||||
@@ -131,6 +134,7 @@
|
||||
var/obj/item/organ/appendix/appendix = C.getorganslot("appendix")
|
||||
var/obj/item/organ/eyes/eyes = C.getorganslot("eye_sight")
|
||||
var/obj/item/organ/ears/ears = C.getorganslot("ears")
|
||||
var/obj/item/organ/tongue/tongue = C.getorganslot("tongue")
|
||||
|
||||
if((NOBLOOD in species_traits) && heart)
|
||||
heart.Remove(C)
|
||||
@@ -143,15 +147,21 @@
|
||||
qdel(lungs)
|
||||
lungs = null
|
||||
|
||||
if(eyes)
|
||||
qdel(eyes)
|
||||
eyes = new mutanteyes
|
||||
eyes.Insert(C)
|
||||
if(C.get_bodypart("head"))
|
||||
if(eyes)
|
||||
qdel(eyes)
|
||||
eyes = new mutanteyes
|
||||
eyes.Insert(C)
|
||||
|
||||
if(ears)
|
||||
qdel(ears)
|
||||
ears = new mutantears
|
||||
ears.Insert(C)
|
||||
if(ears)
|
||||
qdel(ears)
|
||||
ears = new mutantears
|
||||
ears.Insert(C)
|
||||
|
||||
if(tongue)
|
||||
qdel(tongue)
|
||||
tongue = new mutanttongue
|
||||
tongue.Insert(C)
|
||||
|
||||
if((!(NOBREATH in species_traits)) && !lungs)
|
||||
if(mutantlungs)
|
||||
@@ -173,6 +183,21 @@
|
||||
if(exotic_bloodtype && C.dna.blood_type != exotic_bloodtype)
|
||||
C.dna.blood_type = exotic_bloodtype
|
||||
|
||||
if(old_species.mutanthands)
|
||||
for(var/obj/item/I in C.held_items)
|
||||
if(istype(I, old_species.mutanthands))
|
||||
qdel(I)
|
||||
|
||||
if(mutanthands)
|
||||
// Drop items in hands
|
||||
// If you're lucky enough to have a NODROP item, then it stays.
|
||||
for(var/V in C.held_items)
|
||||
var/obj/item/I = V
|
||||
if(istype(I))
|
||||
C.dropItemToGround(I)
|
||||
else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand
|
||||
C.put_in_hands(new mutanthands())
|
||||
|
||||
if(NOAROUSAL in species_traits)
|
||||
C.canbearoused = FALSE
|
||||
else
|
||||
@@ -352,7 +377,7 @@
|
||||
var/datum/sprite_accessory/undershirt/undershirt = GLOB.undershirt_list[H.undershirt]
|
||||
if(undershirt)
|
||||
if(H.dna.species.sexes && H.gender == FEMALE)
|
||||
standing += wear_female_version(undershirt.icon_state, undershirt.icon, -BODY_LAYER)
|
||||
standing += wear_female_version(undershirt.icon_state, undershirt.icon, BODY_LAYER)
|
||||
else
|
||||
standing += mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user