Merge remote-tracking branch 'refs/remotes/origin/master' into custom_roundstart_items
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
|
||||
@@ -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.")
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
diff a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm (rejected hunks)
|
||||
@@ -67,7 +67,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
for(var/I in l2b)
|
||||
var/datum/admin_help/AH = I
|
||||
dat += "<span class='adminnotice'><span class='adminhelp'>Ticket #[AH.id]</span>: <A HREF='?_src_=holder;ahelp=\ref[AH];ahelp_action=ticket'>[AH.initiator_key_name]: [AH.name]</A></span><br>"
|
||||
-
|
||||
+
|
||||
usr << browse(dat.Join(), "window=ahelp_list[state];size=600x480")
|
||||
|
||||
//Tickets statpanel
|
||||
@@ -253,7 +253,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
if(state == AHELP_ACTIVE)
|
||||
to_chat(usr, "<span class='warning'>This ticket is already open.</span>")
|
||||
return
|
||||
-
|
||||
+
|
||||
if(GLOB.ahelp_tickets.CKey2ActiveTicket(initiator_ckey))
|
||||
to_chat(usr, "<span class='warning'>This user already has an active ticket, cannot reopen this one.</span>")
|
||||
return
|
||||
@@ -310,7 +310,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
RemoveActive()
|
||||
state = AHELP_RESOLVED
|
||||
GLOB.ahelp_tickets.ListInsert(src)
|
||||
-
|
||||
+
|
||||
if(initiator)
|
||||
initiator.giveadminhelpverb()
|
||||
|
||||
@@ -325,7 +325,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
/datum/admin_help/proc/Reject(key_name = key_name_admin(usr))
|
||||
if(state != AHELP_ACTIVE)
|
||||
return
|
||||
-
|
||||
+
|
||||
if(initiator)
|
||||
initiator.giveadminhelpverb()
|
||||
|
||||
@@ -494,7 +494,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
|
||||
if(!check_rights(R_ADMIN, TRUE))
|
||||
return
|
||||
-
|
||||
+
|
||||
var/browse_to
|
||||
|
||||
switch(input("Display which ticket list?") as null|anything in list("Active Tickets", "Closed Tickets", "Resolved Tickets"))
|
||||
@@ -506,7 +506,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
browse_to = AHELP_RESOLVED
|
||||
else
|
||||
return
|
||||
-
|
||||
+
|
||||
GLOB.ahelp_tickets.BrowseTickets(browse_to)
|
||||
|
||||
//
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
@@ -700,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
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
diff a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm (rejected hunks)
|
||||
@@ -108,8 +108,8 @@
|
||||
for(var/mob/M in view(range,A))
|
||||
to_chat(M, msg)
|
||||
|
||||
- log_admin("LocalNarrate: [key_name(usr)] at ([get_area(A)]): [msg]")
|
||||
- message_admins("<span class='adminnotice'><b> LocalNarrate: [key_name_admin(usr)] at (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[A.x];Y=[A.y];Z=[A.z]'>[get_area(A)]</a>):</b> [msg]<BR></span>")
|
||||
+ log_admin("LocalNarrate: [key_name(usr)] at [get_area(A)][COORD(A)]: [msg]")
|
||||
+ 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)
|
||||
@@ -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"])
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell
|
||||
name = "cryo cell"
|
||||
icon = 'icons/obj/cryogenics.dmi'
|
||||
icon_state = "pod0"
|
||||
icon_state = "cell-off"
|
||||
density = 1
|
||||
anchored = 1
|
||||
obj_integrity = 350
|
||||
@@ -12,7 +12,6 @@
|
||||
state_open = FALSE
|
||||
var/autoeject = FALSE
|
||||
var/volume = 100
|
||||
var/running_bob_animation = FALSE
|
||||
|
||||
var/efficiency = 1
|
||||
var/sleep_factor = 750
|
||||
@@ -88,59 +87,17 @@
|
||||
beaker = null
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/update_icon()
|
||||
handle_update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/proc/handle_update_icon() //making another proc to avoid spam in update_icon
|
||||
overlays.Cut() //empty the overlay proc, just in case
|
||||
|
||||
if(panel_open)
|
||||
icon_state = "pod0-o"
|
||||
icon_state = "cell-o"
|
||||
else if(state_open)
|
||||
icon_state = "pod0"
|
||||
icon_state = "cell-open"
|
||||
else if(on && is_operational())
|
||||
if(occupant)
|
||||
var/image/pickle = image(occupant.icon, occupant.icon_state)
|
||||
pickle.overlays = occupant.overlays
|
||||
pickle.pixel_y = 22
|
||||
overlays += pickle
|
||||
icon_state = "pod1"
|
||||
var/up = 0 //used to see if we are going up or down, 1 is down, 2 is up
|
||||
spawn(0) // Without this, the icon update will block. The new thread will die once the occupant leaves.
|
||||
running_bob_animation = TRUE
|
||||
while(occupant)
|
||||
overlays -= "lid1" //have to remove the overlays first, to force an update- remove cloning pod overlay
|
||||
overlays -= pickle //remove mob overlay
|
||||
|
||||
switch(pickle.pixel_y) //this looks messy as fuck but it works, switch won't call itself twice
|
||||
|
||||
if(23) //inbetween state, for smoothness
|
||||
switch(up) //this is set later in the switch, to keep track of where the mob is supposed to go
|
||||
if(2) //2 is up
|
||||
pickle.pixel_y = 24 //set to highest
|
||||
|
||||
if(1) //1 is down
|
||||
pickle.pixel_y = 22 //set to lowest
|
||||
|
||||
if(22) //mob is at it's lowest
|
||||
pickle.pixel_y = 23 //set to inbetween
|
||||
up = 2 //have to go up
|
||||
|
||||
if(24) //mob is at it's highest
|
||||
pickle.pixel_y = 23 //set to inbetween
|
||||
up = 1 //have to go down
|
||||
|
||||
overlays += pickle //re-add the mob to the icon
|
||||
overlays += "lid1" //re-add the overlay of the pod, they are inside it, not floating
|
||||
|
||||
sleep(7) //don't want to jiggle violently, just slowly bob
|
||||
return
|
||||
running_bob_animation = FALSE
|
||||
icon_state = "cell-occupied"
|
||||
else
|
||||
icon_state = "pod1"
|
||||
overlays += "lid0" //have to remove the overlays first, to force an update- remove cloning pod overlay
|
||||
icon_state = "cell-on"
|
||||
else
|
||||
icon_state = "pod0"
|
||||
overlays += "lid0" //if no occupant, just put the lid overlay on, and ignore the rest
|
||||
icon_state = "cell-off"
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/process()
|
||||
..()
|
||||
@@ -153,25 +110,26 @@
|
||||
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.
|
||||
@@ -191,20 +149,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.
|
||||
|
||||
@@ -242,7 +201,7 @@
|
||||
..()
|
||||
if(occupant)
|
||||
if(on)
|
||||
to_chat(user, "[occupant] is inside [src]!")
|
||||
to_chat(user, "Someone's inside [src]!")
|
||||
else
|
||||
to_chat(user, "You can barely make out a form floating in [src].")
|
||||
else
|
||||
@@ -265,9 +224,11 @@
|
||||
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))
|
||||
if(default_deconstruction_screwdriver(user, "cell-o", "cell-off", I))
|
||||
return
|
||||
if(exchange_parts(user, I))
|
||||
return
|
||||
@@ -294,17 +255,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
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
diff a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm (rejected hunks)
|
||||
@@ -110,8 +110,8 @@
|
||||
return
|
||||
var/datum/gas_mixture/air1 = AIR1
|
||||
var/turf/T = get_turf(src)
|
||||
- if(isliving(occupant))
|
||||
- var/mob/living/mob_occupant
|
||||
+ if(occupant)
|
||||
+ var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant.health >= 100) // Don't bother with fully healed people.
|
||||
on = FALSE
|
||||
update_icon()
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -1688,15 +1688,6 @@
|
||||
/obj/item/toy/crayon/rainbow)
|
||||
crate_name = "art supply crate"
|
||||
|
||||
/datum/supply_pack/misc/soapstone
|
||||
name = "Curator Engraving/Scribbling Crate"
|
||||
crate_name = "curator 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")
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
diff a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm (rejected hunks)
|
||||
@@ -266,17 +266,11 @@ GLOBAL_LIST(external_rsc_urls)
|
||||
if((global.comms_key == "default_pwd" || length(global.comms_key) <= 6) && global.comms_allowed) //It's the default value or less than 6 characters long, but it somehow didn't disable comms.
|
||||
to_chat(src, "<span class='danger'>The server's API key is either too short or is the default value! Consider changing it immediately!</span>")
|
||||
|
||||
- add_verbs_from_config()
|
||||
+ add_verbs_from_config(tdata)
|
||||
set_client_age_from_db()
|
||||
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()
|
||||
-
|
||||
- sync_client_with_db(tdata)
|
||||
-
|
||||
-
|
||||
+ player_age = 0
|
||||
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")
|
||||
@@ -295,7 +289,14 @@ GLOBAL_LIST(external_rsc_urls)
|
||||
send2irc_adminless_only("New-user", "[key_name(src)] is connecting for the first time!")
|
||||
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 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 day[(account_age==1?"":"s")] old, created on [account_join_date].")
|
||||
+ else //We failed to get an age for this user, let admins know they need to keep an eye on them
|
||||
+ message_admins("Failed to get BYOND account age for [key_name_admin(src)]")
|
||||
get_message_output("watchlist entry", ckey)
|
||||
check_ip_intel()
|
||||
|
||||
@@ -340,7 +341,7 @@ GLOBAL_LIST(external_rsc_urls)
|
||||
adminGreet(1)
|
||||
holder.owner = null
|
||||
GLOB.admins -= src
|
||||
-
|
||||
+
|
||||
GLOB.ahelp_tickets.ClientLogout(src)
|
||||
GLOB.directory -= ckey
|
||||
GLOB.clients -= src
|
||||
@@ -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]")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -128,7 +129,7 @@ Curator
|
||||
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/curator
|
||||
name = "Curator"
|
||||
|
||||
@@ -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,9 +80,10 @@
|
||||
|
||||
/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.
|
||||
@@ -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
|
||||
|
||||
@@ -212,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,49 +1,51 @@
|
||||
//Dead mobs can exist whenever. This is needful
|
||||
|
||||
INITIALIZE_IMMEDIATE(/mob/dead)
|
||||
|
||||
/mob/dead/Initialize()
|
||||
if(initialized)
|
||||
stack_trace("Warning: [src]([type]) initialized multiple times!")
|
||||
tag = "mob_[next_mob_id++]"
|
||||
GLOB.mob_list += src
|
||||
|
||||
INITIALIZE_IMMEDIATE(/mob/dead)
|
||||
prepare_huds()
|
||||
|
||||
|
||||
/mob/dead/Initialize()
|
||||
|
||||
if(initialized)
|
||||
|
||||
stack_trace("Warning: [src]([type]) initialized multiple times!")
|
||||
if(config.cross_allowed)
|
||||
verbs += /mob/dead/proc/server_hop
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
|
||||
initialized = TRUE
|
||||
/mob/dead/dust() //ghosts can't be vaporised.
|
||||
return
|
||||
|
||||
/mob/dead/gib() //ghosts can't be gibbed.
|
||||
return
|
||||
|
||||
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/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/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!"
|
||||
@@ -0,0 +1,9 @@
|
||||
diff a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm (rejected hunks)
|
||||
@@ -5,6 +5,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
|
||||
/mob/dead/Initialize()
|
||||
if(initialized)
|
||||
stack_trace("Warning: [src]([type]) initialized multiple times!")
|
||||
+ initialized = TRUE
|
||||
tag = "mob_[next_mob_id++]"
|
||||
GLOB.mob_list += src
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -788,13 +788,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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -71,6 +71,9 @@
|
||||
//Ears
|
||||
var/obj/item/organ/ears/mutantears = /obj/item/organ/ears
|
||||
|
||||
//Hands
|
||||
var/obj/item/mutanthands = null
|
||||
|
||||
//Citadel snowflake
|
||||
var/fixed_mut_color2 = ""
|
||||
var/fixed_mut_color3 = ""
|
||||
@@ -145,15 +148,16 @@
|
||||
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((!(NOBREATH in species_traits)) && !lungs)
|
||||
if(mutantlungs)
|
||||
@@ -175,6 +179,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
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
diff a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm (rejected hunks)
|
||||
@@ -173,14 +173,18 @@
|
||||
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))
|
||||
- if(C.dropItemToGround(I))
|
||||
- C.put_in_hands(new mutanthands())
|
||||
+ 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())
|
||||
|
||||
@@ -189,10 +193,6 @@
|
||||
C.dna.blood_type = random_blood_type()
|
||||
if(DIGITIGRADE in species_traits)
|
||||
C.Digitigrade_Leg_Swap(TRUE)
|
||||
- if(mutanthands)
|
||||
- for(var/obj/item/I in C.held_items)
|
||||
- if(istype(I, mutanthands))
|
||||
- qdel(I)
|
||||
|
||||
/datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour)
|
||||
H.remove_overlay(HAIR_LAYER)
|
||||
@@ -13,9 +13,11 @@
|
||||
name = "Infectious Zombie"
|
||||
id = "memezombies"
|
||||
limbs_id = "zombie"
|
||||
mutanthands = /obj/item/zombie_hand
|
||||
no_equip = list(slot_wear_mask, slot_head)
|
||||
armor = 20 // 120 damage to KO a zombie, which kills it
|
||||
speedmod = 2
|
||||
mutanteyes = /obj/item/organ/eyes/night_vision/zombie
|
||||
|
||||
/datum/species/zombie/infectious/spec_life(mob/living/carbon/C)
|
||||
. = ..()
|
||||
@@ -27,29 +29,15 @@
|
||||
|
||||
/datum/species/zombie/infectious/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
. = ..()
|
||||
// Drop items in hands
|
||||
// If you're a zombie 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))
|
||||
if(C.dropItemToGround(I))
|
||||
var/obj/item/zombie_hand/zh = new /obj/item/zombie_hand()
|
||||
C.put_in_hands(zh)
|
||||
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
|
||||
var/obj/item/zombie_hand/zh = new /obj/item/zombie_hand()
|
||||
C.put_in_hands(zh)
|
||||
|
||||
// Next, deal with the source of this zombie corruption
|
||||
// Deal with the source of this zombie corruption
|
||||
// Infection organ needs to be handled separately from mutant_organs
|
||||
// because it persists through species transitions
|
||||
var/obj/item/organ/zombie_infection/infection
|
||||
infection = C.getorganslot("zombie_infection")
|
||||
if(!infection)
|
||||
infection = new(C)
|
||||
|
||||
/datum/species/zombie/infectious/on_species_loss(mob/living/carbon/C)
|
||||
. = ..()
|
||||
for(var/obj/item/I in C.held_items)
|
||||
if(istype(I, /obj/item/zombie_hand))
|
||||
qdel(I)
|
||||
infection = new()
|
||||
infection.Insert(C)
|
||||
|
||||
|
||||
// Your skin falls off
|
||||
|
||||
@@ -450,7 +450,7 @@
|
||||
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1)//separated from our puller and not in the middle of a diagonal move.
|
||||
pulledby.stop_pulling()
|
||||
|
||||
if (s_active && !(s_active.ClickAccessible(src, depth=STORAGE_VIEW_DEPTH) || s_active.Adjacent(src)))
|
||||
if (s_active && !(CanReach(s_active,view_only = TRUE)))
|
||||
s_active.close(src)
|
||||
|
||||
/mob/living/movement_delay(ignorewalk = 0)
|
||||
|
||||
@@ -1143,7 +1143,7 @@
|
||||
M.visible_message("<span class='boldwarning'>Unfortunately, [M] just can't seem to hold onto [src]!</span>")
|
||||
return
|
||||
if(iscarbon(M) && (!riding_datum.equip_buckle_inhands(M, 1)))
|
||||
M.visible_message("<span class='boldwarning'>[M] can't climb onto [src] because his hands are full!</span>")
|
||||
M.visible_message("<span class='boldwarning'>[M] can't climb onto [src] because [M.p_their()] hands are full!</span>")
|
||||
return
|
||||
. = ..(M, force, check_loc)
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
if(change)
|
||||
if(change > 0)
|
||||
if(M && stat != DEAD)
|
||||
flick_overlay(image('icons/mob/animal.dmi', src, "heart-ani2", ABOVE_MOB_LAYER), list(M.client), 20)
|
||||
new /obj/effect/overlay/temp/heart(loc)
|
||||
emote("me", 1, "purrs!")
|
||||
else
|
||||
if(M && stat != DEAD)
|
||||
|
||||
@@ -553,7 +553,7 @@
|
||||
if(change)
|
||||
if(change > 0)
|
||||
if(M && stat != DEAD) // Added check to see if this mob (the dog) is dead to fix issue 2454
|
||||
flick_overlay(image('icons/mob/animal.dmi',src,"heart-ani2",ABOVE_MOB_LAYER), list(M.client), 20)
|
||||
new /obj/effect/overlay/temp/heart(loc)
|
||||
emote("me", 1, "yaps happily!")
|
||||
else
|
||||
if(M && stat != DEAD) // Same check here, even though emote checks it as well (poor form to check it only in the help case)
|
||||
|
||||
@@ -51,14 +51,12 @@
|
||||
src.visible_message("<span class='notice'>[src] calms down.</span>")
|
||||
if(stat == CONSCIOUS)
|
||||
udder.generateMilk()
|
||||
var/obj/structure/spacevine/SV = locate(/obj/structure/spacevine) in loc
|
||||
if(SV)
|
||||
SV.eat(src)
|
||||
eat_plants()
|
||||
if(!pulledby)
|
||||
for(var/direction in shuffle(list(1,2,4,8,5,6,9,10)))
|
||||
var/step = get_step(src, direction)
|
||||
if(step)
|
||||
if(locate(/obj/structure/spacevine) in step)
|
||||
if(locate(/obj/structure/spacevine) in step || locate(/obj/structure/glowshroom) in step)
|
||||
Move(step, get_dir(src, step))
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/Retaliate()
|
||||
@@ -68,9 +66,22 @@
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/Move()
|
||||
..()
|
||||
if(!stat)
|
||||
var/obj/structure/spacevine/SV = locate(/obj/structure/spacevine) in loc
|
||||
if(SV)
|
||||
SV.eat(src)
|
||||
eat_plants()
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/proc/eat_plants()
|
||||
var/eaten = FALSE
|
||||
var/obj/structure/spacevine/SV = locate(/obj/structure/spacevine) in loc
|
||||
if(SV)
|
||||
SV.eat(src)
|
||||
eaten = TRUE
|
||||
|
||||
var/obj/structure/glowshroom/GS = locate(/obj/structure/glowshroom) in loc
|
||||
if(GS)
|
||||
qdel(GS)
|
||||
eaten = TRUE
|
||||
|
||||
if(eaten && prob(10))
|
||||
say("Nom")
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/attackby(obj/item/O, mob/user, params)
|
||||
if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass))
|
||||
@@ -300,8 +311,7 @@
|
||||
name = "udder"
|
||||
|
||||
/obj/item/udder/Initialize()
|
||||
reagents = new(50)
|
||||
reagents.my_atom = src
|
||||
create_reagents(50)
|
||||
reagents.add_reagent("milk", 20)
|
||||
..()
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@
|
||||
loc = BB
|
||||
target = null
|
||||
wanted_objects -= typecacheof(/obj/structure/beebox) //so we don't attack beeboxes when not going home
|
||||
return //no don't attack the goddamm box
|
||||
else
|
||||
. = ..()
|
||||
if(. && beegent && isliving(target))
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/ghost/Initialize()
|
||||
. = ..()
|
||||
set_light(1, 2)
|
||||
if(!random)
|
||||
give_hair()
|
||||
else
|
||||
@@ -60,4 +61,4 @@
|
||||
ghost_facial_hair = mutable_appearance('icons/mob/human_face.dmi', "facial_[ghost_facial_hair_style]", -HAIR_LAYER)
|
||||
ghost_facial_hair.alpha = 200
|
||||
ghost_facial_hair.color = ghost_facial_hair_color
|
||||
add_overlay(ghost_facial_hair)
|
||||
add_overlay(ghost_facial_hair)
|
||||
|
||||
@@ -578,6 +578,7 @@
|
||||
var/datum/map_config/cached = SSmapping.next_map_config
|
||||
if(cached)
|
||||
stat(null, "Next Map: [cached.map_name]")
|
||||
stat("Round ID:", "[GLOB.round_id ? GLOB.round_id : "NULL"]")
|
||||
stat(null, "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]")
|
||||
stat(null, "Station Time: [worldtime2text()]")
|
||||
stat(null, "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)")
|
||||
|
||||
@@ -12,16 +12,20 @@
|
||||
slot_flags = SLOT_BELT
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
/obj/item/weapon/clipboard/New()
|
||||
/obj/item/weapon/clipboard/Initialize()
|
||||
update_icon()
|
||||
..()
|
||||
. = ..()
|
||||
|
||||
/obj/item/weapon/clipboard/Destroy()
|
||||
QDEL_NULL(haspen)
|
||||
QDEL_NULL(toppaper) //let movable/Destroy handle the rest
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/clipboard/update_icon()
|
||||
cut_overlays()
|
||||
if(toppaper)
|
||||
add_overlay(toppaper.icon_state)
|
||||
add_overlay(toppaper.overlays)
|
||||
copy_overlays(toppaper)
|
||||
if(haspen)
|
||||
add_overlay("clipboard_pen")
|
||||
add_overlay("clipboard_over")
|
||||
@@ -115,4 +119,4 @@
|
||||
|
||||
//Update everything
|
||||
attack_self(usr)
|
||||
update_icon()
|
||||
update_icon()
|
||||
|
||||
@@ -98,7 +98,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne
|
||||
//
|
||||
|
||||
/obj/machinery/gravity_generator/main/station/Initialize()
|
||||
. = ..()
|
||||
. = ..()
|
||||
setup_parts()
|
||||
middle.add_overlay("activated")
|
||||
update_list()
|
||||
@@ -303,17 +303,17 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne
|
||||
use_power = on ? 2 : 1
|
||||
// Sound the alert if gravity was just enabled or disabled.
|
||||
var/alert = 0
|
||||
var/area/area = get_area(src)
|
||||
if(on && SSticker.IsRoundInProgress()) // If we turned on and the game is live.
|
||||
var/area/A = get_area(src)
|
||||
if(on && SSticker.IsRoundInProgress()) // If we turned on and the game is live.
|
||||
if(gravity_in_level() == 0)
|
||||
alert = 1
|
||||
investigate_log("was brought online and is now producing gravity for this level.", "gravity")
|
||||
message_admins("The gravity generator was brought online. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>[area.name]</a>)")
|
||||
message_admins("The gravity generator was brought online [A][ADMIN_COORDJMP(src)]")
|
||||
else
|
||||
if(gravity_in_level() == 1)
|
||||
alert = 1
|
||||
investigate_log("was brought offline and there is now no gravity for this level.", "gravity")
|
||||
message_admins("The gravity generator was brought offline with no backup generator. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>[area.name]</a>)")
|
||||
message_admins("The gravity generator was brought offline with no backup generator. [A][ADMIN_COORDJMP(src)]")
|
||||
|
||||
update_icon()
|
||||
update_list()
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
diff a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm (rejected hunks)
|
||||
@@ -303,17 +303,17 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne
|
||||
use_power = on ? 2 : 1
|
||||
// Sound the alert if gravity was just enabled or disabled.
|
||||
var/alert = 0
|
||||
- var/area/area = get_area(src)
|
||||
+ var/area/A = get_area(src)
|
||||
if(on && SSticker.IsRoundInProgress()) // If we turned on and the game is live.
|
||||
if(gravity_in_level() == 0)
|
||||
alert = 1
|
||||
investigate_log("was brought online and is now producing gravity for this level.", "gravity")
|
||||
- message_admins("The gravity generator was brought online. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>[area.name]</a>)")
|
||||
+ message_admins("The gravity generator was brought online [A][ADMIN_COORDJMP(src)]")
|
||||
else
|
||||
if(gravity_in_level() == 1)
|
||||
alert = 1
|
||||
investigate_log("was brought offline and there is now no gravity for this level.", "gravity")
|
||||
- message_admins("The gravity generator was brought offline with no backup generator. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>[area.name]</a>)")
|
||||
+ message_admins("The gravity generator was brought offline with no backup generator. [A][ADMIN_COORDJMP(src)]")
|
||||
|
||||
update_icon()
|
||||
update_list()
|
||||
@@ -93,7 +93,7 @@
|
||||
connect_to_network()
|
||||
|
||||
sparks = new
|
||||
sparks.attach(src)
|
||||
sparks.attach(src)
|
||||
sparks.set_up(5, TRUE, src)
|
||||
|
||||
/obj/machinery/power/emitter/Destroy()
|
||||
@@ -121,8 +121,8 @@
|
||||
if(src.active==1)
|
||||
src.active = 0
|
||||
to_chat(user, "<span class='notice'>You turn off \the [src].</span>")
|
||||
message_admins("Emitter turned off by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
log_game("Emitter turned off by [key_name(user)] in ([x],[y],[z])")
|
||||
message_admins("Emitter turned off by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(src)]",0,1)
|
||||
log_game("Emitter turned off by [key_name(user)] in [COORD(src)]")
|
||||
investigate_log("turned <font color='red'>off</font> by [key_name(user)] at [get_area(src)]","singulo")
|
||||
else
|
||||
src.active = 1
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
diff a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm (rejected hunks)
|
||||
@@ -98,9 +98,10 @@
|
||||
|
||||
/obj/machinery/power/emitter/Destroy()
|
||||
if(SSticker && SSticker.IsRoundInProgress())
|
||||
- message_admins("Emitter deleted at ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
- log_game("Emitter deleted at ([x],[y],[z])")
|
||||
- investigate_log("<font color='red'>deleted</font> at ([x],[y],[z]) at [get_area(src)]","singulo")
|
||||
+ var/turf/T = get_turf(src)
|
||||
+ message_admins("Emitter deleted at [ADMIN_COORDJMP(T)]",0,1)
|
||||
+ log_game("Emitter deleted at [COORD(T)]")
|
||||
+ investigate_log("<font color='red'>deleted</font> at [get_area(src)] [COORD(T)]","singulo")
|
||||
QDEL_NULL(sparks)
|
||||
return ..()
|
||||
|
||||
@@ -117,8 +117,8 @@
|
||||
strength++
|
||||
strength_change()
|
||||
|
||||
message_admins("PA Control Computer increased to [strength] by [key_name_admin(usr)](<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
log_game("PA Control Computer increased to [strength] by [key_name(usr)] in ([x],[y],[z])")
|
||||
message_admins("PA Control Computer increased to [strength] by [ADMIN_LOOKUPFLW(usr)] in [ADMIN_COORDJMP(src)]",0,1)
|
||||
log_game("PA Control Computer increased to [strength] by [key_name(usr)] in [COORD(src)]")
|
||||
investigate_log("increased to <font color='red'>[strength]</font> by [key_name(usr)]","singulo")
|
||||
|
||||
|
||||
@@ -127,8 +127,8 @@
|
||||
strength--
|
||||
strength_change()
|
||||
|
||||
message_admins("PA Control Computer decreased to [strength] by [key_name_admin(usr)](<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
log_game("PA Control Computer decreased to [strength] by [key_name(usr)] in ([x],[y],[z])")
|
||||
message_admins("PA Control Computer decreased to [strength] by [ADMIN_LOOKUPFLW(usr)] in [ADMIN_COORDJMP(src)]",0,1)
|
||||
log_game("PA Control Computer decreased to [strength] by [key_name(usr)] in [COORD(src)]")
|
||||
investigate_log("decreased to <font color='green'>[strength]</font> by [key_name(usr)]","singulo")
|
||||
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@
|
||||
//crowbarring it !
|
||||
var/turf/T = get_turf(src)
|
||||
if(default_deconstruction_crowbar(I))
|
||||
message_admins("[src] has been deconstructed by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([T.x],[T.y],[T.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>JMP</a>)",0,1)
|
||||
message_admins("[src] has been deconstructed by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(T)]",0,1)
|
||||
log_game("[src] has been deconstructed by [key_name(user)]")
|
||||
investigate_log("SMES deconstructed by [key_name(user)]","singulo")
|
||||
return
|
||||
@@ -256,9 +256,9 @@
|
||||
input_available = terminal.surplus()
|
||||
|
||||
if(inputting)
|
||||
if(input_available > 0 && input_available >= input_level) // if there's power available, try to charge
|
||||
if(input_available > 0) // if there's power available, try to charge
|
||||
|
||||
var/load = min((capacity-charge)/SMESRATE, input_level) // charge at set rate, limited to spare capacity
|
||||
var/load = min(min((capacity-charge)/SMESRATE, input_level), input_available) // charge at set rate, limited to spare capacity
|
||||
|
||||
charge += load * SMESRATE // increase the charge
|
||||
|
||||
@@ -268,7 +268,7 @@
|
||||
inputting = 0 // stop inputting
|
||||
|
||||
else
|
||||
if(input_attempt && input_available > 0 && input_available >= input_level)
|
||||
if(input_attempt && input_available > 0)
|
||||
inputting = 1
|
||||
else
|
||||
inputting = 0
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
diff a/code/modules/power/smes.dm b/code/modules/power/smes.dm (rejected hunks)
|
||||
@@ -192,10 +192,11 @@
|
||||
|
||||
/obj/machinery/power/smes/Destroy()
|
||||
if(SSticker && SSticker.IsRoundInProgress())
|
||||
- var/area/area = get_area(src)
|
||||
- message_admins("SMES deleted at (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>[area.name]</a>)")
|
||||
- log_game("SMES deleted at ([area.name])")
|
||||
- investigate_log("<font color='red'>deleted</font> at ([area.name])","singulo")
|
||||
+ var/area/A = get_area(src)
|
||||
+ var/turf/T = get_turf(src)
|
||||
+ message_admins("SMES deleted at [A][ADMIN_JMP(T)]")
|
||||
+ log_game("SMES deleted at [A][COORD(T)]")
|
||||
+ investigate_log("<font color='red'>deleted</font> at [A][COORD(T)]","singulo")
|
||||
if(terminal)
|
||||
disconnect_terminal()
|
||||
return ..()
|
||||
@@ -344,7 +344,7 @@
|
||||
lastwarning = REALTIMEOFDAY
|
||||
if(!has_reached_emergency)
|
||||
investigate_log("has reached the emergency point for the first time.", "supermatter")
|
||||
message_admins("[src] has reached the emergency point <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>(JMP)</a>.")
|
||||
message_admins("[src] has reached the emergency point [ADMIN_JMP(src)].")
|
||||
has_reached_emergency = 1
|
||||
else if(damage >= damage_archived) // The damage is still going up
|
||||
SPEAK("[warning_alert] Instability: [stability]%")
|
||||
@@ -391,7 +391,7 @@
|
||||
power += Proj.damage * config_bullet_energy
|
||||
if(!has_been_powered)
|
||||
investigate_log("has been powered for the first time.", "supermatter")
|
||||
message_admins("[src] has been powered for the first time <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>(JMP)</a>.")
|
||||
message_admins("[src] has been powered for the first time [ADMIN_JMP(src)].")
|
||||
has_been_powered = 1
|
||||
else if(takes_damage)
|
||||
damage += Proj.damage * config_bullet_energy
|
||||
@@ -490,7 +490,7 @@
|
||||
/obj/machinery/power/supermatter_shard/proc/Consume(atom/movable/AM)
|
||||
if(isliving(AM))
|
||||
var/mob/living/user = AM
|
||||
message_admins("[src] has consumed [key_name_admin(user)]<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>(JMP)</a>.")
|
||||
message_admins("[src] has consumed [key_name_admin(user)] [ADMIN_JMP(src)].")
|
||||
investigate_log("has consumed [key_name(user)].", "supermatter")
|
||||
user.dust()
|
||||
matter_power += 200
|
||||
|
||||
@@ -19,15 +19,12 @@
|
||||
/obj/item/weapon/gun/energy/pulse/prize/New()
|
||||
. = ..()
|
||||
GLOB.poi_list |= src
|
||||
var/msg = "A pulse rifle prize has been created at ([x],[y],[z] - (\
|
||||
<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>\
|
||||
JMP</a>)"
|
||||
var/msg = "A pulse rifle prize has been created at [ADMIN_COORDJMP(src)]"
|
||||
|
||||
message_admins(msg)
|
||||
log_game(msg)
|
||||
|
||||
notify_ghosts("Someone won a pulse rifle as a prize!", source = src,
|
||||
action = NOTIFY_ORBIT)
|
||||
notify_ghosts("Someone won a pulse rifle as a prize!", source = src, action = NOTIFY_ORBIT)
|
||||
|
||||
/obj/item/weapon/gun/energy/pulse/prize/Destroy()
|
||||
GLOB.poi_list -= src
|
||||
|
||||
@@ -367,3 +367,9 @@
|
||||
desc = "Creates and dispenses mutagen."
|
||||
dispensable_reagents = list("mutagen")
|
||||
emagged_reagents = list("plasma")
|
||||
|
||||
|
||||
/obj/machinery/chem_dispenser/mutagensaltpeter
|
||||
name = "mutagen and saltpeter dispenser"
|
||||
desc = "Creates and dispenses mutagen and even saltpeter."
|
||||
dispensable_reagents = list("mutagen", "saltpetre")
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
active_power_usage = 100
|
||||
pass_flags = PASSTABLE
|
||||
resistance_flags = ACID_PROOF
|
||||
var/operating = 0
|
||||
var/operating = FALSE
|
||||
var/obj/item/weapon/reagent_containers/beaker = null
|
||||
var/limit = 10
|
||||
var/list/blend_items = list (
|
||||
@@ -220,9 +220,12 @@
|
||||
[processing_chamber]<br>
|
||||
[beaker_contents]<hr>
|
||||
"}
|
||||
if (is_beaker_ready && !is_chamber_empty && !(stat & (NOPOWER|BROKEN)))
|
||||
dat += "<A href='?src=\ref[src];action=grind'>Grind the reagents</a><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=juice'>Juice the reagents</a><BR><BR>"
|
||||
if (is_beaker_ready)
|
||||
if(!is_chamber_empty && !(stat & (NOPOWER|BROKEN)))
|
||||
dat += "<A href='?src=\ref[src];action=grind'>Grind the reagents</a><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=juice'>Juice the reagents</a><BR><BR>"
|
||||
else if (beaker.reagents.total_volume)
|
||||
dat += "<A href='?src=\ref[src];action=mix'>Mix the reagents</a><BR><BR>"
|
||||
if(holdingitems && holdingitems.len > 0)
|
||||
dat += "<A href='?src=\ref[src];action=eject'>Eject the reagents</a><BR>"
|
||||
if (beaker)
|
||||
@@ -248,6 +251,8 @@
|
||||
grind()
|
||||
if("juice")
|
||||
juice()
|
||||
if("mix")
|
||||
mix()
|
||||
if("eject")
|
||||
eject()
|
||||
if ("detach")
|
||||
@@ -327,11 +332,11 @@
|
||||
playsound(src.loc, 'sound/machines/juicer.ogg', 20, 1)
|
||||
var/offset = prob(50) ? -2 : 2
|
||||
animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 250) //start shaking
|
||||
operating = 1
|
||||
operating = TRUE
|
||||
updateUsrDialog()
|
||||
spawn(50)
|
||||
pixel_x = initial(pixel_x) //return to its spot after shaking
|
||||
operating = 0
|
||||
operating = FALSE
|
||||
updateUsrDialog()
|
||||
|
||||
//Snacks
|
||||
@@ -365,11 +370,11 @@
|
||||
playsound(src.loc, 'sound/machines/blender.ogg', 50, 1)
|
||||
var/offset = prob(50) ? -2 : 2
|
||||
animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 250) //start shaking
|
||||
operating = 1
|
||||
operating = TRUE
|
||||
updateUsrDialog()
|
||||
spawn(60)
|
||||
pixel_x = initial(pixel_x) //return to its spot after shaking
|
||||
operating = 0
|
||||
operating = FALSE
|
||||
updateUsrDialog()
|
||||
|
||||
//Snacks and Plants
|
||||
@@ -467,3 +472,33 @@
|
||||
break
|
||||
beaker.reagents.add_reagent(r_id, min(O.reagent_contents[r_id], space))
|
||||
remove_object(O)
|
||||
|
||||
/obj/machinery/reagentgrinder/proc/mix()
|
||||
|
||||
//For butter and other things that would change upon shaking or mixing
|
||||
power_change()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
if (!beaker)
|
||||
return
|
||||
playsound(src.loc, 'sound/machines/juicer.ogg', 20, 1)
|
||||
var/offset = prob(50) ? -2 : 2
|
||||
animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 250) //start shaking
|
||||
operating = TRUE
|
||||
updateUsrDialog()
|
||||
addtimer(CALLBACK(src, /obj/machinery/reagentgrinder/proc/mix_complete), 50)
|
||||
|
||||
/obj/machinery/reagentgrinder/proc/mix_complete()
|
||||
pixel_x = initial(pixel_x) //return to its spot after shaking
|
||||
operating = FALSE
|
||||
updateUsrDialog()
|
||||
if (beaker.reagents.total_volume)
|
||||
//Recipe to make Butter
|
||||
while(beaker.reagents.get_reagent_amount("milk") >= 15)
|
||||
beaker.reagents.remove_reagent("milk", 15)
|
||||
new /obj/item/weapon/reagent_containers/food/snacks/butter(src.loc)
|
||||
//Recipe to make Mayonnaise
|
||||
if (beaker.reagents.has_reagent("eggyolk"))
|
||||
var/amount = beaker.reagents.get_reagent_amount("eggyolk")
|
||||
beaker.reagents.remove_reagent("eggyolk", amount)
|
||||
beaker.reagents.add_reagent("mayonnaise", amount)
|
||||
Regular → Executable
+13
-3
@@ -516,17 +516,27 @@
|
||||
/datum/reagent/consumable/honey
|
||||
name = "honey"
|
||||
id = "honey"
|
||||
description = "Sweet sweet honey, decays into sugar."
|
||||
description = "Sweet sweet honey, decays into sugar and has natural healing properties."
|
||||
color = "#d3a308"
|
||||
nutriment_factor = 15 * REAGENTS_METABOLISM
|
||||
metabolization_rate = 1 * REAGENTS_METABOLISM
|
||||
taste_description = "sweetness"
|
||||
|
||||
/datum/reagent/consumable/honey/on_mob_life(mob/living/M)
|
||||
M.reagents.add_reagent("sugar",3)
|
||||
if(prob(20))
|
||||
M.heal_bodypart_damage(3,1)
|
||||
if(prob(55))
|
||||
M.adjustBruteLoss(-1*REM, 0)
|
||||
M.adjustFireLoss(-1*REM, 0)
|
||||
M.adjustOxyLoss(-1*REM, 0)
|
||||
M.adjustToxLoss(-1*REM, 0)
|
||||
..()
|
||||
|
||||
/datum/reagent/consumable/mayonnaise
|
||||
name = "Mayonnaise"
|
||||
id = "mayonnaise"
|
||||
description = "An white and oily mixture of mixed egg yolks."
|
||||
color = "#DFDFDF"
|
||||
taste_description = "mayonnaise"
|
||||
|
||||
////Lavaland Flora Reagents////
|
||||
|
||||
|
||||
@@ -1110,8 +1110,9 @@
|
||||
id = "nitrous_oxide"
|
||||
description = "A potent oxidizer used as fuel in rockets and as an anaesthetic during surgery."
|
||||
reagent_state = LIQUID
|
||||
metabolization_rate = 1.5 * REAGENTS_METABOLISM
|
||||
color = "#808080"
|
||||
taste_description = "numbness"
|
||||
taste_description = "sweetness"
|
||||
|
||||
/datum/reagent/nitrous_oxide/reaction_obj(obj/O, reac_volume)
|
||||
if((!O) || (!reac_volume))
|
||||
@@ -1122,7 +1123,19 @@
|
||||
if(istype(T))
|
||||
T.atmos_spawn_air("n2o=[reac_volume/5];TEMP=[T20C]")
|
||||
|
||||
|
||||
/datum/reagent/nitrous_oxide/reaction_mob(mob/M, method=TOUCH, reac_volume)
|
||||
if(method == VAPOR)
|
||||
M.drowsyness += max(round(reac_volume, 1), 2)
|
||||
|
||||
/datum/reagent/nitrous_oxide/on_mob_life(mob/living/M)
|
||||
M.drowsyness += 2
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
H.blood_volume = max(H.blood_volume - 2.5, 0)
|
||||
if(prob(20))
|
||||
M.losebreath += 2
|
||||
M.confused = min(M.confused + 2, 5)
|
||||
..()
|
||||
|
||||
/////////////////////////Coloured Crayon Powder////////////////////////////
|
||||
//For colouring in /proc/mix_color_from_reagents
|
||||
@@ -1533,7 +1546,9 @@
|
||||
|
||||
/datum/reagent/romerol/on_mob_life(mob/living/carbon/human/H)
|
||||
// Silently add the zombie infection organ to be activated upon death
|
||||
new /obj/item/organ/zombie_infection(H)
|
||||
if(!H.getorganslot("zombie_infection"))
|
||||
var/obj/item/organ/zombie_infection/ZI = new()
|
||||
ZI.Insert(H)
|
||||
..()
|
||||
|
||||
/datum/reagent/growthserum
|
||||
|
||||
@@ -36,12 +36,12 @@
|
||||
var/atom/A = holder.my_atom
|
||||
var/turf/T = get_turf(A)
|
||||
var/area/my_area = get_area(T)
|
||||
var/message = "A [reaction_name] reaction has occurred in [my_area.name]. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>JMP</A>)"
|
||||
var/message = "A [reaction_name] reaction has occurred in [my_area.name] [ADMIN_COORDJMP(T)]"
|
||||
message += " (<A HREF='?_src_=vars;Vars=\ref[A]'>VV</A>)"
|
||||
|
||||
var/mob/M = get(A, /mob)
|
||||
if(M)
|
||||
message += " - Carried By: [key_name_admin(M)](<A HREF='?_src_=holder;adminmoreinfo=\ref[M]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[M]'>FLW</A>)"
|
||||
message += " - Carried By: [ADMIN_LOOKUPFLW(M)]"
|
||||
else
|
||||
message += " - Last Fingerprint: [(A.fingerprintslast ? A.fingerprintslast : "N/A")]"
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
/datum/chemical_reaction/reagent_explosion/on_reaction(datum/reagents/holder, created_volume)
|
||||
var/turf/T = get_turf(holder.my_atom)
|
||||
var/area/A = get_area(T)
|
||||
var/inside_msg
|
||||
if(ismob(holder.my_atom))
|
||||
var/mob/M = holder.my_atom
|
||||
@@ -14,9 +15,9 @@
|
||||
var/touch_msg = "N/A"
|
||||
if(lastkey)
|
||||
var/mob/toucher = get_mob_by_key(lastkey)
|
||||
touch_msg = "[key_name_admin(lastkey)]<A HREF='?_src_=holder;adminmoreinfo=\ref[toucher]'>?</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[toucher]'>FLW</A>)"
|
||||
message_admins("Reagent explosion reaction occurred at <a href='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>[T.loc.name] (JMP)</a>[inside_msg]. Last Fingerprint: [touch_msg].")
|
||||
log_game("Reagent explosion reaction occurred at [T.loc.name] ([T.x],[T.y],[T.z]). Last Fingerprint: [lastkey ? lastkey : "N/A"]." )
|
||||
touch_msg = "[ADMIN_LOOKUPFLW(toucher)]"
|
||||
message_admins("Reagent explosion reaction occurred at [A] [ADMIN_COORDJMP(T)][inside_msg]. Last Fingerprint: [touch_msg].")
|
||||
log_game("Reagent explosion reaction occurred at [A] [COORD(T)]. Last Fingerprint: [lastkey ? lastkey : "N/A"]." )
|
||||
var/datum/effect_system/reagents_explosion/e = new()
|
||||
e.set_up(modifier + round(created_volume/strengthdiv, 1), T, 0, 0)
|
||||
e.start()
|
||||
|
||||
@@ -437,13 +437,14 @@
|
||||
|
||||
/datum/chemical_reaction/slime/slimeexplosion/on_reaction(datum/reagents/holder)
|
||||
var/turf/T = get_turf(holder.my_atom)
|
||||
var/area/A = get_area(T)
|
||||
var/lastkey = holder.my_atom.fingerprintslast
|
||||
var/touch_msg = "N/A"
|
||||
if(lastkey)
|
||||
var/mob/toucher = get_mob_by_key(lastkey)
|
||||
touch_msg = "[key_name_admin(lastkey)]<A HREF='?_src_=holder;adminmoreinfo=\ref[toucher]'>?</A>(<A HREF='?_src_=holder;adminplayerobservefollow=\ref[toucher]'>FLW</A>)."
|
||||
message_admins("Slime Explosion reaction started at <a href='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>[T.loc.name] (JMP)</a>. Last Fingerprint: [touch_msg]")
|
||||
log_game("Slime Explosion reaction started at [T.loc.name] ([T.x],[T.y],[T.z]). Last Fingerprint: [lastkey ? lastkey : "N/A"].")
|
||||
touch_msg = "[ADMIN_LOOKUPFLW(toucher)]."
|
||||
message_admins("Slime Explosion reaction started at [A] [ADMIN_COORDJMP(T)]. Last Fingerprint: [touch_msg]")
|
||||
log_game("Slime Explosion reaction started at [A] [COORD(T)]. Last Fingerprint: [lastkey ? lastkey : "N/A"].")
|
||||
T.visible_message("<span class='danger'>The slime extract begins to vibrate violently !</span>")
|
||||
addtimer(CALLBACK(src, .proc/boom, holder), 50)
|
||||
var/obj/item/slime_extract/M = holder.my_atom
|
||||
|
||||
Regular → Executable
+6
@@ -155,6 +155,12 @@
|
||||
filling.color = mix_color_from_reagents(reagents.reagent_list)
|
||||
add_overlay(filling)
|
||||
|
||||
/obj/item/weapon/reagent_containers/glass/beaker/jar
|
||||
name = "honey jar"
|
||||
desc = "A jar for honey. It can hold up to 50 units of sweet delight."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "vapour"
|
||||
|
||||
/obj/item/weapon/reagent_containers/glass/beaker/large
|
||||
name = "large beaker"
|
||||
desc = "A large beaker. Can hold up to 100 units."
|
||||
|
||||
@@ -48,15 +48,16 @@
|
||||
user.changeNext_move(CLICK_CD_RANGE*2)
|
||||
user.newtonian_move(get_dir(A, user))
|
||||
var/turf/T = get_turf(src)
|
||||
var/area/area = get_area(src)
|
||||
if(reagents.has_reagent("sacid"))
|
||||
message_admins("[key_name_admin(user)] fired sulphuric acid from \a [src] at (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>[get_area(src)] ([T.x], [T.y], [T.z])</a>).")
|
||||
log_game("[key_name(user)] fired sulphuric acid from \a [src] at [get_area(src)] ([T.x], [T.y], [T.z]).")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] fired sulphuric acid from \a [src] at [area] [ADMIN_COORDJMP(T)].")
|
||||
log_game("[key_name(user)] fired sulphuric acid from \a [src] at [area] ([T.x], [T.y], [T.z]).")
|
||||
if(reagents.has_reagent("facid"))
|
||||
message_admins("[key_name_admin(user)] fired Fluacid from \a [src] at (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>[get_area(src)] ([T.x], [T.y], [T.z])</a>).")
|
||||
log_game("[key_name(user)] fired Fluacid from \a [src] at [get_area(src)] ([T.x], [T.y], [T.z]).")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] fired Fluacid from \a [src] at [area] [ADMIN_COORDJMP(T)].")
|
||||
log_game("[key_name(user)] fired Fluacid from \a [src] at [area] [COORD(T)].")
|
||||
if(reagents.has_reagent("lube"))
|
||||
message_admins("[key_name_admin(user)] fired Space lube from \a [src] at (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>[get_area(src)] ([T.x], [T.y], [T.z])</a>).")
|
||||
log_game("[key_name(user)] fired Space lube from \a [src] at [get_area(src)] ([T.x], [T.y], [T.z]).")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] fired Space lube from \a [src] at [area] [ADMIN_COORDJMP(T)].")
|
||||
log_game("[key_name(user)] fired Space lube from \a [src] at [area] [COORD(T)].")
|
||||
return
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user