Merge remote-tracking branch 'refs/remotes/origin/master' into custom_roundstart_items

This commit is contained in:
kevinz000
2017-05-14 20:54:47 -07:00
270 changed files with 12488 additions and 5920 deletions
+4 -2
View File
@@ -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)
+5 -8
View File
@@ -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
+1 -1
View File
@@ -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 = ""
+6 -1
View File
@@ -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(
+11 -40
View File
@@ -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")
+2 -2
View File
@@ -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
+2 -36
View File
@@ -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"
+11
View File
@@ -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
+7 -26
View File
@@ -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
+1 -1
View File
@@ -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.")
+55
View File
@@ -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)
//
+6 -65
View File
@@ -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
+2 -1
View File
@@ -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)
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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)
-9
View File
@@ -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
+5 -2
View File
@@ -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
+97 -67
View File
@@ -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")
+46
View File
@@ -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
+4 -1
View File
@@ -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())
+14 -29
View File
@@ -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
+216 -156
View File
@@ -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]")
+1 -1
View File
@@ -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)
+5
View File
@@ -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'
+2 -1
View File
@@ -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
+1 -1
View File
@@ -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
+3 -4
View File
@@ -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
-2
View File
@@ -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)
+1
View File
@@ -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
+1 -1
View File
@@ -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()
+2 -2
View File
@@ -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)
+8 -3
View File
@@ -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
+18 -27
View File
@@ -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!
+2 -1
View File
@@ -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)
+1 -1
View File
@@ -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)
+3 -2
View File
@@ -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"
+26 -54
View File
@@ -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))
+3 -5
View File
@@ -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
+15 -9
View File
@@ -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)
+1 -1
View File
@@ -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
+159 -124
View File
@@ -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
+7 -1
View File
@@ -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)
+3 -3
View File
@@ -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
+1 -2
View File
@@ -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)
+2 -2
View File
@@ -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)
+6 -6
View File
@@ -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)
+42 -40
View File
@@ -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!"
+9
View File
@@ -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
+14 -2
View File
@@ -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
+2 -5
View File
@@ -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
+1 -1
View File
@@ -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)
+1
View File
@@ -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)]%)")
+8 -4
View File
@@ -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()
+5 -5
View File
@@ -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()
+3 -3
View File
@@ -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")
+4 -4
View File
@@ -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
+17
View File
@@ -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)
+13 -3
View File
@@ -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
+2 -2
View File
@@ -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
+6
View File
@@ -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