Merge branch 'master' into upstream-merge-26425

This commit is contained in:
LetterJay
2017-05-12 00:08:32 -04:00
committed by GitHub
335 changed files with 4038 additions and 1990 deletions
+2 -2
View File
@@ -79,8 +79,8 @@
validckey = 1
if(!validckey)
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 = ""
+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
-10
View File
@@ -1,10 +0,0 @@
diff a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm (rejected hunks)
@@ -8,7 +8,7 @@
if(href_list["ahelp"])
if(!check_rights(R_ADMIN))
return
-
+
var/ahelp_ref = href_list["ahelp"]
var/datum/admin_help/AH = locate(ahelp_ref)
if(AH)
+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
View File
@@ -103,6 +103,7 @@
if(!recipient)
if(holder)
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
to_chat(src, msg)
else
current_ticket.MessageNoRecipient(msg)
return
+1 -1
View File
@@ -19,7 +19,7 @@
if (!msg)
return
var/nicknames = world.file2list("config/admin_nicknames.txt")
var/static/nicknames = world.file2list("config/admin_nicknames.txt")
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>ADMIN([src.holder.fakekey ? pick(nicknames) : src.key])</span> says, <span class='message'>\"[msg]\"</span></span>"
+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
+1 -1
View File
@@ -21,7 +21,7 @@
var/res = alert(usr, "Show the title of this song to the players?",, "No", "Yes", "Cancel")
switch(res)
if("Yes")
to_chat(world, "An admin played: [S]")
to_chat(world, "<span class='boldannounce'>An admin played: [S]</span>")
if("Cancel")
return
-1
View File
@@ -350,7 +350,6 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(G_found.mind && !G_found.mind.active)
G_found.mind.transfer_to(new_character) //be careful when doing stuff like this! I've already checked the mind isn't in use
new_character.mind.special_verbs = list()
else
new_character.mind_initialize()
if(!new_character.mind.assigned_role)
@@ -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"
+1 -1
View File
@@ -227,7 +227,7 @@ GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation)
if(check_exile_implant(C))
say("Rejecting [AM]: Exile implant detected in contained lifeform.")
return
if(AM.buckled_mobs.len)
if(AM.has_buckled_mobs())
for(var/mob/living/carbon/C in AM.buckled_mobs)
if(check_exile_implant(C))
say("Rejecting [AM]: Exile implant detected in close proximity lifeform.")
@@ -64,17 +64,18 @@
next_check = world.time + cooldown
/obj/structure/academy_wizard_spawner/proc/give_control()
set waitfor = FALSE
if(!current_wizard)
return
spawn(0)
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as Wizard Academy Defender?", "wizard", null, ROLE_WIZARD, current_wizard)
var/mob/dead/observer/chosen = null
if(candidates.len)
chosen = pick(candidates)
message_admins("[key_name_admin(chosen)] was spawned as Wizard Academy Defender")
current_wizard.ghostize() // on the off chance braindead defender gets back in
current_wizard.key = chosen.key
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as Wizard Academy Defender?", "wizard", null, be_special_flag = ROLE_WIZARD, M = current_wizard)
var/mob/dead/observer/chosen = null
if(candidates.len)
chosen = pick(candidates)
message_admins("[key_name_admin(chosen)] was spawned as Wizard Academy Defender")
current_wizard.ghostize() // on the off chance braindead defender gets back in
current_wizard.key = chosen.key
/obj/structure/academy_wizard_spawner/proc/summon_wizard()
var/turf/T = src.loc
+1 -6
View File
@@ -50,11 +50,6 @@
material_id = MAT_PLASMA
message = "cm3 of plasma"
/datum/export/material/plasma/get_cost(obj/O, contr = 0, emag = 0)
. = ..()
if(emag) // Syndicate pays you more for the plasma.
. = round(. * 1.5)
// Uranium. Still useful for both power generation and nuclear annihilation.
/datum/export/material/uranium
cost = 400
@@ -98,4 +93,4 @@
message = "cm3 of glass"
material_id = MAT_GLASS
export_types = list(/obj/item/stack/sheet/glass, /obj/item/weapon/ore,
/obj/item/weapon/shard)
/obj/item/weapon/shard)
+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)
+12 -4
View File
@@ -182,14 +182,14 @@
/datum/supply_pack/emergency/syndicate
name = "NULL_ENTRY"
hidden = TRUE
cost = 14000
cost = 20000
contains = list()
crate_name = "emergency crate"
crate_type = /obj/structure/closet/crate/internals
dangerous = TRUE
/datum/supply_pack/emergency/syndicate/fill(obj/structure/closet/crate/C)
var/crate_value = 50
var/crate_value = 30
var/list/uplink_items = get_uplink_items(SSticker.mode)
while(crate_value)
var/category = pick(uplink_items)
@@ -828,6 +828,14 @@
/obj/item/weapon/defibrillator/loaded)
crate_name = "defibrillator crate"
/datum/supply_pack/medical/vending
name = "Medical Vending Crate"
cost = 2000
contains = list(/obj/item/weapon/vending_refill/medical,
/obj/item/weapon/vending_refill/medical,
/obj/item/weapon/vending_refill/medical)
crate_name = "medical vending crate"
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Science /////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -1681,8 +1689,8 @@
crate_name = "art supply crate"
/datum/supply_pack/misc/soapstone
name = "Librarian Engraving/Scribbling Crate"
crate_name = "librarian engraving/scribbling crate"
name = "Curator Engraving/Scribbling Crate"
crate_name = "curator engraving/scribbling crate"
cost = 3000
contains = list(/obj/item/soapstone)
access = GLOB.access_library
+22 -2
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"])
@@ -361,6 +360,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//
//////////////
+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]")
+2 -2
View File
@@ -13,8 +13,8 @@
return
if(confirm == "Yes")
suiciding = 1
log_game("[key_name(src)] (job: [job ? "[job]" : "None"]) commited suicide at [get_area(src)].")
message_admins("[key_name(src)] (job: [job ? "[job]" : "None"]) commited suicide at [get_area(src)].")
log_game("[key_name(src)] (job: [job ? "[job]" : "None"]) committed suicide at [get_area(src)].")
message_admins("[key_name(src)] (job: [job ? "[job]" : "None"]) committed suicide at [get_area(src)].")
var/obj/item/held_item = get_active_held_item()
if(held_item)
var/damagetype = held_item.suicide_act(src)
+3 -1
View File
@@ -161,7 +161,9 @@
/obj/item/clothing/obj_break(damage_flag)
if(!damaged_clothes)
update_clothes_damaged_state(TRUE)
to_chat(usr, "<span class='notice'>Your [src] starts to fall apart!")
if(ismob(loc)) //It's not important enough to warrant a message if nobody's wearing it
var/mob/M = loc
M.visible_message("<span class='warning'>[M]'s [name] starts to fall apart!", "<span class='warning'>Your [name] starts to fall apart!")
/obj/item/clothing/proc/update_clothes_damaged_state(damaging = TRUE)
var/index = "\ref[initial(icon)]-[initial(icon_state)]"
@@ -18,6 +18,7 @@
vision_flags = 0
darkness_view = 2
invis_view = SEE_INVISIBLE_LIVING
lighting_alpha = null
to_chat(user, "<span class='notice'>You toggle the goggles' scanning mode to \[T-Ray].</span>")
else
STOP_PROCESSING(SSobj, src)
+1 -1
View File
@@ -30,7 +30,7 @@
/obj/item/clothing/head/collectable/paper
name = "collectable paper hat"
desc = "What looks like an ordinary paper hat is actually a rare and valuable collector's edition paper hat. Keep away from water, fire, and Librarians."
desc = "What looks like an ordinary paper hat is actually a rare and valuable collector's edition paper hat. Keep away from water, fire, and Curators."
icon_state = "paper"
dog_fashion = /datum/dog_fashion/head
+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
+9 -19
View File
@@ -326,9 +326,6 @@
disable_flight(1)
if(!suit)
disable_flight(1)
if(!resync)
addtimer(CALLBACK(src, .proc/resync), 600)
resync = 1
if(!wearer) //Oh god our user fell off!
disable_flight(1)
if(!pressure && brake)
@@ -340,12 +337,6 @@
stabilizer = FALSE
usermessage("Warning: Sensor data is not being recieved from flight shoes. Stabilizers and airbrake modules OFFLINE!", 2)
//Resync the suit
/obj/item/device/flightpack/proc/resync()
resync = FALSE
suit.resync()
//How fast should the wearer be?
/obj/item/device/flightpack/proc/update_slowdown()
if(!flight)
suit.slowdown = slowdown_ground
@@ -356,20 +347,11 @@
/obj/item/device/flightpack/process()
if(!suit || (processing_mode == FLIGHTSUIT_PROCESSING_NONE))
return FALSE
update_slowdown()
update_icon()
check_conditions()
calculate_momentum_speed()
momentum_drift()
handle_boost()
handle_damage()
handle_flight()
/obj/item/device/flightpack/proc/handle_flight()
if(!flight)
return FALSE
if(wearer)
wearer.float(TRUE)
/obj/item/device/flightpack/proc/handle_damage()
if(crash_damage)
@@ -424,7 +406,6 @@
if(boost_charge < boost_maxcharge)
boost_charge = Clamp(boost_charge+boost_chargerate, 0, boost_maxcharge)
/obj/item/device/flightpack/proc/cycle_power()
if(powersetting < powersetting_high)
powersetting++
@@ -654,6 +635,8 @@
wearer.movement_type |= FLYING
wearer.pass_flags |= flight_passflags
usermessage("ENGAGING FLIGHT ENGINES.")
update_slowdown()
wearer.floating = TRUE
wearer.visible_message("<font color='blue' size='2'>[wearer]'s flight engines activate as they lift into the air!</font>")
//I DONT HAVE SOUND EFFECTS YET playsound(
flight = TRUE
@@ -670,6 +653,8 @@
momentum_x = 0
momentum_y = 0
usermessage("DISENGAGING FLIGHT ENGINES.")
update_slowdown()
wearer.floating = FALSE
wearer.visible_message("<font color='blue' size='2'>[wearer] drops to the ground as their flight engines cut out!</font>")
//NO SOUND YET playsound(
ion_trail.stop()
@@ -678,6 +663,9 @@
flight = FALSE
if(suit.shoes)
suit.shoes.toggle(FALSE)
if(isturf(wearer.loc))
var/turf/T = wearer.loc
T.Entered(src)
else
if(override_safe)
disable_flight(TRUE)
@@ -749,11 +737,13 @@
wearer.visible_message("<span class='notice'>[wearer.name]'s flightpack engines flare in intensity as they are rocketed forward by the immense thrust!</span>")
boost = TRUE
update_slowdown()
update_icon()
/obj/item/device/flightpack/proc/deactivate_booster()
usermessage("Boosters disengaged!")
boost = FALSE
update_slowdown()
update_icon()
/obj/item/device/flightpack/proc/enable_airbrake()
if(wearer)
+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
+2 -2
View File
@@ -137,7 +137,7 @@
can_adjust = 1
alt_covers_chest = 1
/obj/item/clothing/under/rank/librarian
/obj/item/clothing/under/rank/curator
name = "sensible suit"
desc = "It's very... sensible."
icon_state = "red_suit"
@@ -145,7 +145,7 @@
item_color = "red_suit"
can_adjust = 0
/obj/item/clothing/under/rank/librarian/curator
/obj/item/clothing/under/rank/curator/treasure_hunter
name = "treasure hunter uniform"
desc = "A rugged uniform suitable for treasure hunting."
icon_state = "curator"
+4 -4
View File
@@ -13,6 +13,8 @@
var/scanning = 0
var/list/log = list()
origin_tech = "engineering=4;biotech=2;programming=5"
var/range = 8
var/view_check = TRUE
/obj/item/device/detective_scanner/attack_self(mob/user)
if(log.len && !scanning)
@@ -43,7 +45,7 @@
log = list()
scanning = 0
/obj/item/device/detective_scanner/pre_attackby(atom/A, mob/user, params)
/obj/item/device/detective_scanner/afterattack(atom/A, mob/user, params)
scan(A, user)
return FALSE
@@ -51,9 +53,7 @@
set waitfor = 0
if(!scanning)
// Can remotely scan objects and mobs.
if(!in_range(A, user) && !(A in view(world.view, user)))
return
if(loc != user)
if((get_dist(A, user) > range) || (!(A in view(range, user)) && view_check) || (loc != user))
return
scanning = 1
+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
@@ -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!
@@ -468,3 +468,11 @@
list_reagents = list("nutriment" = 3, "vitamin" = 2, "sodiumchloride" = 5)
bonus_reagents = list("sodiumchloride" = 10)
tastes = list("bran" = 4, "raisins" = 3, "salt" = 1)
/obj/item/weapon/reagent_containers/food/snacks/butter
name = "stick of butter"
desc = "A stick of delicious, golden, fatty goodness."
icon_state = "butter"
list_reagents = list("nutriment" = 5)
filling_color = "#FFD700"
tastes = list("butter" = 1)
@@ -13,8 +13,8 @@
filling_color = "#D2691E"
tastes = list("donut" = 1)
/obj/item/weapon/reagent_containers/food/snacks/donut/New()
..()
/obj/item/weapon/reagent_containers/food/snacks/donut/Initialize()
. = ..()
if(prob(30))
icon_state = "donut2"
name = "frosted donut"
@@ -28,8 +28,8 @@
bitesize = 10
tastes = list("donut" = 3, "chaos" = 1)
/obj/item/weapon/reagent_containers/food/snacks/donut/chaos/New()
..()
/obj/item/weapon/reagent_containers/food/snacks/donut/chaos/Initialize()
. = ..()
extra_reagent = pick("nutriment", "capsaicin", "frostoil", "krokodil", "plasma", "cocoa", "slimejelly", "banana", "berryjuice", "omnizine")
reagents.add_reagent("[extra_reagent]", 3)
bonus_reagents = list("[extra_reagent]" = 3, "sugar" = 1)
@@ -48,8 +48,8 @@
extra_reagent = "berryjuice"
tastes = list("jelly" = 1, "donut" = 3)
/obj/item/weapon/reagent_containers/food/snacks/donut/jelly/New()
..()
/obj/item/weapon/reagent_containers/food/snacks/donut/jelly/Initialize()
. = ..()
if(extra_reagent)
reagents.add_reagent("[extra_reagent]", 3)
if(prob(30))
@@ -210,13 +210,13 @@
filling_color = "#F0E68C"
tastes = list("mushroom" = 1, "biscuit" = 1)
/obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit/New()
/obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit/Initialize()
var/fey = prob(10)
if(fey)
name = "exceptional plump helmet biscuit"
desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump helmet biscuit!"
bonus_reagents = list("omnizine" = 5, "nutriment" = 1, "vitamin" = 1)
..()
. = ..()
if(fey)
reagents.add_reagent("omnizine", 5)
@@ -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)
+1
View File
@@ -111,6 +111,7 @@
for(var/datum/plant_gene/trait/trait in seed.genes)
trait.on_squash(src, target)
reagents.reaction(T)
for(var/A in T)
reagents.reaction(A)
+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
+1 -1
View File
@@ -459,7 +459,7 @@ GLOBAL_VAR_CONST(access_away_generic4, 208)
/proc/get_all_jobs()
return list("Assistant", "Captain", "Head of Personnel", "Bartender", "Cook", "Botanist", "Quartermaster", "Cargo Technician",
"Shaft Miner", "Clown", "Mime", "Janitor", "Librarian", "Lawyer", "Chaplain", "Chief Engineer", "Station Engineer",
"Shaft Miner", "Clown", "Mime", "Janitor", "Curator", "Lawyer", "Chaplain", "Chief Engineer", "Station Engineer",
"Atmospheric Technician", "Chief Medical Officer", "Medical Doctor", "Chemist", "Geneticist", "Virologist",
"Research Director", "Scientist", "Roboticist", "Head of Security", "Warden", "Detective", "Security Officer")
+24 -22
View File
@@ -112,11 +112,11 @@ Mime
H.mind.miming = 1
/*
Librarian
Curator
*/
/datum/job/librarian
title = "Librarian"
flag = LIBRARIAN
/datum/job/curator
title = "Curator"
flag = CURATOR
department_head = list("Head of Personnel")
department_flag = CIVILIAN
faction = "Station"
@@ -125,33 +125,35 @@ Librarian
supervisors = "the head of personnel"
selection_color = "#dddddd"
outfit = /datum/outfit/job/librarian
outfit = /datum/outfit/job/curator
access = list(GLOB.access_library)
minimal_access = list(GLOB.access_library)
minimal_access = list(GLOB.access_library, GLOB.access_construction,GLOB.access_mining_station)
/datum/outfit/job/librarian
name = "Librarian"
jobtype = /datum/job/librarian
/datum/outfit/job/curator
name = "Curator"
jobtype = /datum/job/curator
belt = /obj/item/device/pda/librarian
uniform = /obj/item/clothing/under/rank/librarian
belt = /obj/item/device/pda/curator
uniform = /obj/item/clothing/under/rank/curator
l_hand = /obj/item/weapon/storage/bag/books
r_pocket = /obj/item/weapon/barcodescanner
r_pocket = /obj/item/key/displaycase
l_pocket = /obj/item/device/laser_pointer
backpack_contents = list(
/obj/item/soapstone = 1
/obj/item/weapon/melee/curator_whip = 1,
/obj/item/soapstone = 1,
/obj/item/weapon/barcodescanner = 1
)
/datum/outfit/job/librarian/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
..()
if(visualsOnly)
return
H.grant_all_languages(omnitongue=TRUE)
/datum/outfit/job/curator/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
..()
if(visualsOnly)
return
H.grant_all_languages(omnitongue=TRUE)
/*
Lawyer
*/
+1 -1
View File
@@ -39,7 +39,7 @@ GLOBAL_LIST_INIT(civilian_positions, list(
"Botanist",
"Cook",
"Janitor",
"Librarian",
"Curator",
"Lawyer",
"Chaplain",
"Clown",
+1 -1
View File
@@ -32,7 +32,7 @@
var/speed = 300
var/correctness = 85
var/willpower = 98
if(U.job in list("Librarian")) // the librarian is both faster, and more accurate than normal crew members at research
if(U.job in list("Curator")) // the curator is both faster, and more accurate than normal crew members at research
speed = 45
correctness = 100
willpower = 100
+4 -4
View File
@@ -22,7 +22,7 @@
------------
A place for the crew to go, relax, and enjoy a good book.
Aspiring authors can even self publish and, if they're lucky
convince the on-staff Librarian to submit it to the Archives
convince the on-staff Curator to submit it to the Archives
to be chronicled in history forever - some say even persisting
through alternate dimensions.
@@ -49,12 +49,12 @@
// Ideas for the future
// ---------------------
// - Visitor's computer should be able to search the current in-round library inventory (that the Librarian has stocked and checked in)
// - Visitor's computer should be able to search the current in-round library inventory (that the Curator has stocked and checked in)
// -- Give computer other features like an Instant Messenger application, or the ability to edit, save, and print documents.
// - Admin interface directly tied to the Archive DB. Right now there's no way to delete uploaded books in-game.
// -- If this gets implemented, allow Librarians to "tag" or "suggest" books to be deleted. The DB ID of the tagged books gets saved to a text file (or another table in the DB maybe?).
// -- If this gets implemented, allow Curators to "tag" or "suggest" books to be deleted. The DB ID of the tagged books gets saved to a text file (or another table in the DB maybe?).
// The admin interface would automatically take these IDs and SELECT them all from the DB to be displayed along with a Delete link to drop the row from the table.
// - When the game sets up and the round begins, have it automatically pick random books from the DB to populate the library with. Even if the Librarian is a useless fuck there are at least a few books around.
// - When the game sets up and the round begins, have it automatically pick random books from the DB to populate the library with. Even if the Curator is a useless fuck there are at least a few books around.
// - Allow books to be "hollowed out" like the Chaplain's Bible, allowing you to store one pocket-sized item inside.
// - Make books/book cases burn when exposed to flame.
// - Make book binder hackable.
+1 -1
View File
@@ -115,7 +115,7 @@
as instructions and/or memes for the next generation of spessmen.
Limited in location to station_z only. Can be smashed out or exploded,
but only permamently removed with the librarian's soapstone.
but only permamently removed with the curator's soapstone.
*/
/obj/item/soapstone/infinite
+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)
@@ -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
+11 -2
View File
@@ -84,7 +84,7 @@
if(D.make_reagents.len)
return 0
var/build_amount = 1
var/build_amount = 0
for(var/mat_id in D.materials)
var/M = D.materials[mat_id]
@@ -93,7 +93,15 @@
if(!M || !redemption_mat)
return 0
build_amount = min(build_amount, round(redemption_mat.amount / M))
var/smeltable_sheets = round(redemption_mat.amount / M)
if(!smeltable_sheets)
return 0
if(!build_amount)
build_amount = smeltable_sheets
build_amount = min(build_amount, smeltable_sheets)
return build_amount
@@ -152,6 +160,7 @@
if(exchange_parts(user, W))
return
if(default_pry_open(W))
materials.retrieve_all()
return
if(default_unfasten_wrench(user, W))
return
+1 -3
View File
@@ -193,9 +193,7 @@
qdel(voucher)
/obj/machinery/mineral/equipment_vendor/ex_act(severity, target)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start()
do_sparks(5, TRUE, src)
if(prob(50 / severity) && severity < 3)
qdel(src)
+8 -1
View File
@@ -3,9 +3,16 @@
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
prepare_huds()
if(config.cross_allowed)
verbs += /mob/dead/proc/server_hop
return INITIALIZE_HINT_NORMAL
/mob/dead/dust() //ghosts can't be vaporised.
return
@@ -16,12 +16,6 @@
var/mob/living/new_character //for instant transfer once the round is set up
/mob/dead/new_player/Initialize()
if(initialized)
stack_trace("Warning: [src]([type]) initialized multiple times!")
initialized = TRUE
tag = "mob_[next_mob_id++]"
GLOB.mob_list += src
if(client && SSticker.state == GAME_STATE_STARTUP)
var/obj/screen/splash/S = new(client, TRUE, TRUE)
S.Fade(TRUE)
@@ -30,7 +24,10 @@
loc = pick(GLOB.newplayer_start)
else
loc = locate(1,1,1)
return INITIALIZE_HINT_NORMAL
. = ..()
/mob/dead/new_player/prepare_huds()
return
/mob/dead/new_player/proc/new_player_panel()
+15 -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
@@ -118,6 +118,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
animate(src, pixel_y = 2, time = 10, loop = -1)
grant_all_languages()
GLOB.dead_mob_list += src
..()
/mob/dead/observer/narsie_act()
@@ -787,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
+3 -4
View File
@@ -35,22 +35,21 @@
blood_volume += 0.1 // regenerate blood VERY slowly
//Effects of bloodloss
var/word = pick("dizzy","woozy","faint")
switch(blood_volume)
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
if(prob(5))
to_chat(src, "<span class='warning'>You feel [pick("dizzy","woozy","faint")].</span>")
to_chat(src, "<span class='warning'>You feel [word].</span>")
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1))
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
if(prob(5))
blur_eyes(6)
var/word = pick("dizzy","woozy","faint")
to_chat(src, "<span class='warning'>You feel very [word].</span>")
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
adjustOxyLoss(5)
if(prob(15))
Paralyse(rand(1,3))
var/word = pick("dizzy","woozy","faint")
to_chat(src, "<span class='warning'>You feel extremely [word].</span>")
if(0 to BLOOD_VOLUME_SURVIVE)
death()
@@ -70,7 +69,7 @@
bleed_rate = max(bleed_rate - 0.5, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases
if(bleed_rate && !bleedsuppress)
if(bleed_rate && !bleedsuppress && !(status_flags & FAKEDEATH))
bleed(bleed_rate)
//Makes a blood drop, leaking amt units of blood from the mob
@@ -87,6 +87,8 @@
owner.adjustFireLoss(-heal_amt)
owner.adjustOxyLoss(-heal_amt)
owner.adjustCloneLoss(-heal_amt)
else
owner.adjustPlasma(plasma_rate * 0.1)
/obj/item/organ/alien/plasmavessel/Insert(mob/living/carbon/M, special = 0)
..()
+1 -1
View File
@@ -1,4 +1,4 @@
/mob/living/proc/alien_talk(message, shown_name = name)
/mob/living/proc/alien_talk(message, shown_name = real_name)
log_say("[key_name(src)] : [message]")
message = trim(message)
if(!message) return
+11 -1
View File
@@ -484,7 +484,7 @@
adjustBruteLoss(3)
else
if(T)
T.add_vomit_floor(src, 0)//toxic barf looks different
T.add_vomit_floor(src, toxic)//toxic barf looks different
nutrition -= lost_nutrition
adjustToxLoss(-3)
T = get_step(T, dir)
@@ -492,6 +492,16 @@
break
return 1
/mob/living/carbon/proc/spew_organ(power = 5)
if(!internal_organs.len)
return //Guess we're out of organs
var/obj/item/organ/guts = pick(internal_organs)
var/turf/T = get_turf(src)
guts.Remove(src)
guts.forceMove(T)
var/atom/throw_target = get_edge_target_turf(guts, dir)
guts.throw_at(throw_target, power, 4, src)
/mob/living/carbon/fully_replace_character_name(oldname,newname)
..()
@@ -119,9 +119,7 @@
visible_message("<span class='danger'>The [M.name] has shocked [src]!</span>", \
"<span class='userdanger'>The [M.name] has shocked [src]!</span>")
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start()
do_sparks(5, TRUE, src)
var/power = M.powerlevel + rand(0,3)
Weaken(power)
if(stuttering < power)
+11
View File
@@ -68,6 +68,17 @@
if(!isnum(text2num(params)))
return message
/datum/emote/sound/carbon/snap
key = "snap"
key_third_person = "snaps"
message = "snaps their fingers."
muzzle_ignore = TRUE
restraint_check = TRUE
emote_type = EMOTE_AUDIBLE
sound = 'sound/effects/snap01.ogg'
mob_type_allowed_typecache = list(/mob/living/carbon/)
/datum/emote/living/carbon/sign/signal
key = "signal"
key_third_person = "signals"
@@ -1,10 +0,0 @@
diff a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm (rejected hunks)
@@ -32,7 +32,7 @@
dna.species.spec_death(gibbed, src)
- if(SSticker && SSticker.mode)
+ if(SSticker.HasRoundStarted())
SSblackbox.ReportDeath(src)
if(mind && mind.devilinfo)
INVOKE_ASYNC(mind.devilinfo, /datum/devilinfo.proc/beginResurrectionCheck, src)
@@ -171,5 +171,8 @@
dna.species.mutant_bodyparts -= "wingsopen"
dna.species.mutant_bodyparts |= "wings"
update_body()
if(isturf(loc))
var/turf/T = loc
T.Entered(src)
//Ayy lmao
@@ -134,7 +134,7 @@
if(stat == DEAD || (status_flags & FAKEDEATH))
appears_dead = 1
if(suiciding)
msg += "<span class='warning'>[t_He] appear[p_s()] to have commited suicide... there is no hope of recovery.</span>\n"
msg += "<span class='warning'>[t_He] appear[p_s()] to have committed suicide... there is no hope of recovery.</span>\n"
if(hellbound)
msg += "<span class='warning'>[t_His] soul seems to have been ripped out of [t_his] body. Revival is impossible.</span>\n"
msg += "<span class='deadsay'>[t_He] [t_is] limp and unresponsive; there are no signs of life"
@@ -119,6 +119,8 @@
var/obj/item/thing = C.get_item_by_slot(slot_id)
if(thing && (!thing.species_exception || !is_type_in_list(src,thing.species_exception)))
C.dropItemToGround(thing)
if(C.hud_used)
C.hud_used.update_locked_slots()
// this needs to be FIRST because qdel calls update_body which checks if we have DIGITIGRADE legs or not and if not then removes DIGITIGRADE from species_traits
if(("legs" in C.dna.species.mutant_bodyparts) && C.dna.features["legs"] == "Digitigrade Legs")
@@ -352,7 +354,7 @@
var/datum/sprite_accessory/undershirt/undershirt = GLOB.undershirt_list[H.undershirt]
if(undershirt)
if(H.dna.species.sexes && H.gender == FEMALE)
standing += wear_female_version(undershirt.icon_state, undershirt.icon, -BODY_LAYER)
standing += wear_female_version(undershirt.icon_state, undershirt.icon, BODY_LAYER)
else
standing += mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER)
@@ -9,7 +9,7 @@
punchdamagelow = 5
punchdamagehigh = 14
punchstunthreshold = 11 //about 40% chance to stun
no_equip = list(slot_wear_mask, slot_wear_suit, slot_gloves, slot_shoes, slot_w_uniform)
no_equip = list(slot_wear_mask, slot_wear_suit, slot_gloves, slot_shoes, slot_w_uniform, slot_s_store)
nojumpsuit = 1
sexes = 1
damage_overlay_type = ""
@@ -20,6 +20,7 @@
dangerous_existence = TRUE
limbs_id = "golem"
fixed_mut_color = "aaa"
mutant_organs = list(/obj/item/organ/adamantine_resonator)
var/info_text = "As an <span class='danger'>Iron Golem</span>, you don't have any special traits."
var/prefix = "Iron"
@@ -54,8 +55,9 @@
name = "Adamantine Golem"
id = "adamantine golem"
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/golem/adamantine
mutant_organs = list(/obj/item/organ/adamantine_resonator, /obj/item/organ/vocal_cords/adamantine)
fixed_mut_color = "4ed"
info_text = "As an <span class='danger'>Adamantine Golem</span>, you don't have any special traits."
info_text = "As an <span class='danger'>Adamantine Golem</span>, you possess special vocal cords allowing you to \"resonate\" messages to all golems."
prefix = "Adamantine"
//Explodes on death
@@ -71,14 +73,14 @@
prefix = "Plasma"
special_names = list("Flood","Fire","Bar","Man")
/datum/species/golem/plasma/spec_life(mob/living/carbon/human/H)
if(H.bodytemperature > 900 && H.on_fire)
explosion(get_turf(H),1,2,4,flame_range = 5)
if(H)
H.gib()
if(H.fire_stacks < 2) //flammable
H.adjust_fire_stacks(1)
..()
/datum/species/golem/plasma/spec_life(mob/living/carbon/human/H)
if(H.bodytemperature > 900 && H.on_fire)
explosion(get_turf(H),1,2,4,flame_range = 5)
if(H)
H.gib()
if(H.fire_stacks < 2) //flammable
H.adjust_fire_stacks(1)
..()
//Harder to hurt
/datum/species/golem/diamond
@@ -505,7 +507,7 @@
sexes = FALSE
info_text = "As a <span class='danger'>Runic Golem</span>, you possess eldritch powers granted by the Elder God Nar'Sie."
species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOFIRE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER) //no mutcolors
prefix = "Runic"
prefix = "Runic"
var/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/golem/phase_shift
var/obj/effect/proc_holder/spell/targeted/abyssal_gaze/abyssal_gaze
@@ -643,4 +645,19 @@
if(P.is_hot())
visible_message("<span class='danger'>[src] bursts into flames!</span>")
fire_act()
fire_act()
/datum/species/golem/plastic
name = "Plastic"
id = "plastic golem"
prefix = "Plastic"
fixed_mut_color = "fff"
info_text = "As a <span class='danger'>Plastic Golem</span>, you are capable of ventcrawling, and passing through plastic flaps."
/datum/species/golem/plastic/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
C.ventcrawler = VENTCRAWLER_NUDE
/datum/species/golem/plastic/on_species_loss(mob/living/carbon/C)
. = ..()
C.ventcrawler = initial(C.ventcrawler)
@@ -28,7 +28,7 @@
//Holopad
if(istype(ai.current, /obj/machinery/holopad))
var/obj/machinery/holopad/H = ai.current
H.move_hologram(ai)
H.move_hologram(ai, T)
/mob/camera/aiEye/Move()
return 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)
@@ -287,17 +287,13 @@
to_chat(user, "<span class='warning'>The welder must be on for this task!</span>")
else
if(W.force) //if force is non-zero
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start()
do_sparks(5, TRUE, src)
..()
/mob/living/simple_animal/bot/bullet_act(obj/item/projectile/Proj)
if(Proj && (Proj.damage_type == BRUTE || Proj.damage_type == BURN))
if(prob(75) && Proj.damage > 0)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start()
do_sparks(5, TRUE, src)
return ..()
/mob/living/simple_animal/bot/emp_act(severity)
@@ -259,9 +259,7 @@
if(prob(50))
new /obj/item/bodypart/l_arm/robot(Tsec)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
do_sparks(3, TRUE, src)
..()
/obj/machinery/bot_core/cleanbot
@@ -390,9 +390,7 @@ Auto Patrol[]"},
if(lasercolor == "r")
new /obj/item/clothing/suit/redtag(Tsec)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
do_sparks(3, TRUE, src)
new /obj/effect/decal/cleanable/oil(loc)
..()
@@ -381,9 +381,7 @@
var/obj/item/stack/tile/plasteel/T = new (Tsec)
T.amount = 1
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
do_sparks(3, TRUE, src)
..()
/obj/machinery/bot_core/floorbot
@@ -530,9 +530,7 @@
if(emagged && prob(25))
playsound(loc, 'sound/voice/minsult.ogg', 50, 0)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
do_sparks(3, TRUE, src)
..()
/mob/living/simple_animal/bot/medbot/proc/declare(crit_patient)
@@ -719,9 +719,7 @@
cell.update_icon()
cell = null
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
do_sparks(3, TRUE, src)
new /obj/effect/decal/cleanable/oil(loc)
..()
@@ -397,9 +397,7 @@ Auto Patrol: []"},
if(prob(50))
new /obj/item/bodypart/l_arm/robot(Tsec)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
do_sparks(3, TRUE, src)
new /obj/effect/decal/cleanable/oil(loc)
..()
@@ -20,6 +20,7 @@
var/obj/item/inventory_head
var/obj/item/inventory_mask
gold_core_spawnable = 2
devourable = TRUE
/mob/living/simple_animal/crab/Life()
..()
@@ -16,6 +16,7 @@
speed = 0
maxHealth = 25
health = 25
devourable = TRUE
harm_intent_damage = 8
obj_damage = 50
@@ -53,7 +53,5 @@
ranged = 1
/mob/living/simple_animal/hostile/hivebot/death(gibbed)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
do_sparks(3, TRUE, src)
..(1)
@@ -0,0 +1,85 @@
/mob/living/simple_animal/hostile/jungle
vision_range = 5
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
faction = list("jungle")
weather_immunities = list("acid")
obj_damage = 30
environment_smash = 2
minbodytemp = 0
maxbodytemp = 450
response_help = "pokes"
response_disarm = "shoves"
response_harm = "strikes"
status_flags = 0
a_intent = INTENT_HARM
see_in_dark = 4
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
mob_size = MOB_SIZE_LARGE
//Mega arachnid
/mob/living/simple_animal/hostile/jungle/mega_arachnid
name = "mega arachnid"
desc = "Though physically imposing, it prefers to ambush its prey, and it will only engage with an already crippled opponent."
melee_damage_lower = 30
melee_damage_upper = 30
maxHealth = 300
health = 300
speed = 1
ranged = 1
pixel_x = -16
move_to_delay = 10
aggro_vision_range = 9
speak_emote = list("chitters")
attack_sound = 'sound/weapons/bladeslice.ogg'
ranged_cooldown_time = 60
projectiletype = /obj/item/projectile/mega_arachnid
projectilesound = 'sound/weapons/pierce.ogg'
icon = 'icons/mob/jungle/arachnid.dmi'
icon_state = "arachnid"
icon_living = "arachnid"
icon_dead = "dead_purple"
alpha = 50
/mob/living/simple_animal/hostile/jungle/mega_arachnid/Life()
..()
if(target && ranged_cooldown > world.time && iscarbon(target))
var/mob/living/carbon/C = target
if(!C.legcuffed && C.health < 50)
retreat_distance = 9
minimum_distance = 9
alpha = 125
return
retreat_distance = 0
minimum_distance = 0
alpha = 255
/mob/living/simple_animal/hostile/jungle/mega_arachnid/Aggro()
..()
alpha = 255
/mob/living/simple_animal/hostile/jungle/mega_arachnid/LoseAggro()
..()
alpha = 50
/obj/item/projectile/mega_arachnid
name = "flesh snare"
nodamage = 1
damage = 0
icon_state = "tentacle_end"
/obj/item/projectile/mega_arachnid/on_hit(atom/target, blocked = 0)
if(iscarbon(target) && blocked < 100)
var/obj/item/weapon/restraints/legcuffs/beartrap/mega_arachnid/B = new /obj/item/weapon/restraints/legcuffs/beartrap/mega_arachnid(get_turf(target))
B.Crossed(target)
..()
/obj/item/weapon/restraints/legcuffs/beartrap/mega_arachnid
name = "fleshy restraints"
desc = "Used by mega arachnids to immobilize their prey."
flags = DROPDEL
icon_state = "tentacle_end"
icon = 'icons/obj/projectiles.dmi'
@@ -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)
@@ -16,7 +16,7 @@
response_disarm = "shoos"
response_harm = "stomps on"
emote_see = list("jiggles", "bounces in place")
speak_emote = list("telepathically chirps")
speak_emote = list("blorbles")
bubble_icon = "slime"
initial_languages = list(/datum/language/common, /datum/language/slime)
@@ -31,10 +31,10 @@
see_in_dark = 8
verb_say = "telepathically chirps"
verb_ask = "telepathically asks"
verb_exclaim = "telepathically cries"
verb_yell = "telephatically cries"
verb_say = "blorbles"
verb_ask = "inquisitively blorbles"
verb_exclaim = "loudly blorbles"
verb_yell = "loudly blorbles"
// canstun and canweaken don't affect slimes because they ignore stun and weakened variables
// for the sake of cleanliness, though, here they are.
+2
View File
@@ -351,6 +351,8 @@
/mob/proc/spin(spintime, speed)
set waitfor = 0
var/D = dir
if((spintime < 1)||(speed < 1)||!spintime||!speed)
return
while(spintime >= speed)
sleep(speed)
switch(D)
+2 -6
View File
@@ -497,9 +497,7 @@
var/turf/T = get_turf(src)
var/obj/structure/cable/N = T.get_cable_node()
if (prob(50) && electrocute_mob(usr, N, N, 1, TRUE))
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start()
do_sparks(5, TRUE, src)
return
C.use(10)
to_chat(user, "<span class='notice'>You add cables to the APC frame.</span>")
@@ -1181,9 +1179,7 @@
/obj/machinery/power/apc/proc/shock(mob/user, prb)
if(!prob(prb))
return 0
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start()
do_sparks(5, TRUE, src)
if(isalien(user))
return 0
if(electrocute_mob(user, src, src, 1, TRUE))
+1 -3
View File
@@ -156,9 +156,7 @@ By design, d1 is the smallest direction and d2 is the highest
if(!prob(prb))
return 0
if (electrocute_mob(user, powernet, src, siemens_coeff))
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start()
do_sparks(5, TRUE, src)
return 1
else
return 0
+30 -13
View File
@@ -28,11 +28,12 @@
/obj/machinery/power/generator/Initialize(mapload)
. = ..()
. = ..()
var/obj/machinery/atmospherics/components/binary/circulator/circpath = /obj/machinery/atmospherics/components/binary/circulator
cold_circ = locate(circpath) in get_step(src, cold_dir)
hot_circ = locate(circpath) in get_step(src, hot_dir)
connect_to_network()
SSair.atmos_machinery += src
if(cold_circ)
switch(cold_dir)
@@ -55,6 +56,9 @@
update_icon()
/obj/machinery/power/generator/Destroy()
SSair.atmos_machinery -= src
return ..()
/obj/machinery/power/generator/update_icon()
@@ -63,21 +67,20 @@
else
cut_overlays()
if(lastgenlev != 0)
add_overlay("teg-op[lastgenlev]")
var/L = min(round(lastgenlev/100000),11)
if(L != 0)
add_overlay(image('icons/obj/power.dmi', "teg-op[L]"))
add_overlay("teg-oc[lastcirc]")
add_overlay("teg-oc[lastcirc]")
#define GENRATE 800 // generator output coefficient from Q
/obj/machinery/power/generator/process()
/obj/machinery/power/generator/process_atmos()
if(!cold_circ || !hot_circ)
return
lastgen = 0
if(powernet)
//to_chat(world, "cold_circ and hot_circ pass")
@@ -104,7 +107,7 @@
var/energy_transfer = delta_temperature*hot_air_heat_capacity*cold_air_heat_capacity/(hot_air_heat_capacity+cold_air_heat_capacity)
var/heat = energy_transfer*(1-efficiency)
lastgen = energy_transfer*efficiency
lastgen += energy_transfer*efficiency
//to_chat(world, "lastgen = [lastgen]; heat = [heat]; delta_temperature = [delta_temperature]; hot_air_heat_capacity = [hot_air_heat_capacity]; cold_air_heat_capacity = [cold_air_heat_capacity];")
@@ -113,7 +116,7 @@
//to_chat(world, "POWER: [lastgen] W generated at [efficiency*100]% efficiency and sinks sizes [cold_air_heat_capacity], [hot_air_heat_capacity]")
add_avail(lastgen)
//add_avail(lastgen) This is done in process now
// update icon overlays only if displayed level has changed
if(hot_air)
@@ -124,15 +127,23 @@
var/datum/gas_mixture/cold_circ_air1 = cold_circ.AIR1
cold_circ_air1.merge(cold_air)
var/genlev = max(0, min( round(11*lastgen / 100000), 11))
update_icon()
var/circ = "[cold_circ && cold_circ.last_pressure_delta > 0 ? "1" : "0"][hot_circ && hot_circ.last_pressure_delta > 0 ? "1" : "0"]"
if((genlev != lastgenlev) || (circ != lastcirc))
lastgenlev = genlev
if(circ != lastcirc)
lastcirc = circ
update_icon()
src.updateDialog()
/obj/machinery/power/generator/process()
//Setting this number higher just makes the change in power output slower, it doesnt actualy reduce power output cause **math**
var/power_output = round(lastgen / 10)
add_avail(power_output)
lastgenlev = power_output
lastgen -= power_output
..()
/obj/machinery/power/generator/attack_hand(mob/user)
if(..())
user << browse(null, "window=teg")
@@ -151,7 +162,13 @@
t += "<div class='statusDisplay'>"
t += "Output: [round(lastgen)] W"
var/displaygen = lastgenlev
if(displaygen < 1000000) //less than a MW
displaygen /= 1000
t += "Output: [round(displaygen,0.01)] kW"
else
displaygen /= 1000000
t += "Output: [round(displaygen,0.01)] MW"
t += "<BR>"
+3 -2
View File
@@ -14,6 +14,7 @@
light_power = 0.7
light_range = 15
light_color = rgb(255, 0, 0)
gender = FEMALE
var/clashing = FALSE //If Nar-Sie is fighting Ratvar
/obj/singularity/narsie/large
@@ -26,8 +27,8 @@
grav_pull = 10
consume_range = 12 //How many tiles out do we eat
/obj/singularity/narsie/large/New()
..()
/obj/singularity/narsie/large/Initialize()
. = ..()
send_to_playing_players("<span class='narsie'>NAR-SIE HAS RISEN</span>")
send_to_playing_players(pick('sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg'))
@@ -29,12 +29,12 @@
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
dangerous_possession = TRUE
/obj/singularity/New(loc, var/starting_energy = 50, var/temp = 0)
/obj/singularity/Initialize(mapload, starting_energy = 50)
//CARN: admin-alert for chuckle-fuckery.
admin_investigate_setup()
src.energy = starting_energy
..()
. = ..()
START_PROCESSING(SSobj, src)
GLOB.poi_list |= src
GLOB.singularities |= src
@@ -129,6 +129,7 @@
/obj/machinery/power/supermatter_shard/Initialize()
. = ..()
SSair.atmos_machinery += src
countdown = new(src)
countdown.start()
GLOB.poi_list |= src
@@ -139,6 +140,7 @@
/obj/machinery/power/supermatter_shard/Destroy()
investigate_log("has been destroyed.", "supermatter")
SSair.atmos_machinery -= src
QDEL_NULL(radio)
GLOB.poi_list -= src
QDEL_NULL(countdown)
@@ -181,7 +183,7 @@
E.energy = power
qdel(src)
/obj/machinery/power/supermatter_shard/process()
/obj/machinery/power/supermatter_shard/process_atmos()
var/turf/T = loc
if(isnull(T)) // We have a null turf...something is wrong, stop processing this entity.
@@ -296,6 +298,7 @@
if(produces_gas)
env.merge(removed)
air_update_turf()
for(var/mob/living/carbon/human/l in view(src, HALLUCINATION_RANGE(power))) // If they can see it without mesons on. Bad on them.
if(!istype(l.glasses, /obj/item/clothing/glasses/meson))
+11 -1
View File
@@ -40,6 +40,11 @@ GLOBAL_LIST_INIT(blacklisted_tesla_types, typecacheof(list(/obj/machinery/atmosp
var/energy_to_raise = 32
var/energy_to_lower = -20
/obj/singularity/energy_ball/Initialize(mapload, starting_energy = 50, is_miniball = FALSE)
. = ..()
if(!is_miniball)
set_light(10, 7, "#EEEEFF")
/obj/singularity/energy_ball/ex_act(severity, target)
return
@@ -54,6 +59,11 @@ GLOBAL_LIST_INIT(blacklisted_tesla_types, typecacheof(list(/obj/machinery/atmosp
. = ..()
/obj/singularity/energy_ball/admin_investigate_setup()
if(istype(loc, /obj/singularity/energy_ball))
return
..()
/obj/singularity/energy_ball/process()
if(!orbiting)
handle_energy()
@@ -117,7 +127,7 @@ GLOBAL_LIST_INIT(blacklisted_tesla_types, typecacheof(list(/obj/machinery/atmosp
/obj/singularity/energy_ball/proc/new_mini_ball()
if(!loc)
return
var/obj/singularity/energy_ball/EB = new(loc)
var/obj/singularity/energy_ball/EB = new(loc, 0, TRUE)
EB.transform *= pick(0.3, 0.4, 0.5, 0.6, 0.7)
var/icon/I = icon(icon,icon_state,dir)
@@ -191,7 +191,7 @@
fire_sound = 'sound/magic/lightningbolt.ogg'
e_cost = 200
select_name = "stun"
projectile_type = /obj/item/projectile/energy/tesla_revolver
projectile_type = /obj/item/projectile/energy/tesla/revolver
/obj/item/ammo_casing/energy/gravityrepulse
projectile_type = /obj/item/projectile/gravityrepulse
+14 -9
View File
@@ -179,6 +179,8 @@
return
if(setAngle)
Angle = setAngle
var/old_pixel_x = pixel_x
var/old_pixel_y = pixel_y
if(!legacy) //new projectiles
set waitfor = 0
var/next_run = world.time
@@ -201,29 +203,30 @@
var/Pixel_x=round((sin(Angle)+16*sin(Angle)*2), 1) //round() is a floor operation when only one argument is supplied, we don't want that here
var/Pixel_y=round((cos(Angle)+16*cos(Angle)*2), 1)
var/pixel_x_offset = pixel_x + Pixel_x
var/pixel_y_offset = pixel_y + Pixel_y
var/pixel_x_offset = old_pixel_x + Pixel_x
var/pixel_y_offset = old_pixel_y + Pixel_y
var/new_x = x
var/new_y = y
while(pixel_x_offset > 16)
pixel_x_offset -= 32
pixel_x -= 32
old_pixel_x -= 32
new_x++// x++
while(pixel_x_offset < -16)
pixel_x_offset += 32
pixel_x += 32
old_pixel_x += 32
new_x--
while(pixel_y_offset > 16)
pixel_y_offset -= 32
pixel_y -= 32
old_pixel_y -= 32
new_y++
while(pixel_y_offset < -16)
pixel_y_offset += 32
pixel_y += 32
old_pixel_y += 32
new_y--
pixel_x = old_pixel_x
pixel_y = old_pixel_y
step_towards(src, locate(new_x, new_y, z))
next_run += max(world.tick_lag, speed)
var/delay = next_run - world.time
@@ -232,7 +235,9 @@
pixel_y = pixel_y_offset
else
animate(src, pixel_x = pixel_x_offset, pixel_y = pixel_y_offset, time = max(1, (delay <= 3 ? delay - 1 : delay)), flags = ANIMATION_END_NOW)
old_pixel_x = pixel_x_offset
old_pixel_y = pixel_y_offset
if(original && (original.layer>=2.75) || ismob(original))
if(loc == get_turf(original))
if(!(original in permutated))
+14 -24
View File
@@ -159,44 +159,34 @@
/obj/item/projectile/energy/bolt/large
damage = 20
/obj/item/projectile/energy/tesla_revolver
/obj/item/projectile/energy/tesla
name = "tesla bolt"
icon_state = "tesla_projectile"
impact_effect_type = /obj/effect/overlay/temp/impact_effect/blue_laser
var/chain
/obj/item/projectile/energy/tesla_revolver/fire(setAngle)
/obj/item/projectile/energy/tesla/fire(setAngle)
if(firer)
chain = firer.Beam(src, icon_state = "lightning[rand(1, 12)]", time = INFINITY, maxdistance = INFINITY)
..()
/obj/item/projectile/energy/tesla_revolver/on_hit(atom/target)
. = ..()
if(isliving(target))
tesla_zap(src, 3, 10000)
qdel(src)
/obj/item/projectile/energy/tesla_revolver/Destroy()
/obj/item/projectile/energy/tesla/Destroy()
qdel(chain)
return ..()
/obj/item/projectile/energy/tesla/revolver
name = "energy orb"
/obj/item/projectile/energy/tesla_cannon
name = "tesla bolt"
icon_state = "tesla_projectile"
impact_effect_type = /obj/effect/overlay/temp/impact_effect/blue_laser
var/chain
/obj/item/projectile/energy/tesla/revolver/on_hit(atom/target)
. = ..()
if(isliving(target))
tesla_zap(target, 3, 10000)
qdel(src)
/obj/item/projectile/energy/tesla_cannon/fire(setAngle)
if(firer)
chain = firer.Beam(src, icon_state = "lightning[rand(1, 12)]", time = INFINITY, maxdistance = INFINITY)
..()
/obj/item/projectile/energy/tesla/cannon
name = "tesla orb"
/obj/item/projectile/energy/tesla_cannon/on_hit(atom/target)
/obj/item/projectile/energy/tesla/cannon/on_hit(atom/target)
. = ..()
tesla_zap(src, 3, 10000, explosive = FALSE, stun_mobs = FALSE)
tesla_zap(target, 3, 10000, explosive = FALSE, stun_mobs = FALSE)
qdel(src)
/obj/item/projectile/energy/tesla_cannon/Destroy()
qdel(chain)
return ..()
@@ -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 (
@@ -38,7 +38,7 @@
/obj/item/weapon/reagent_containers/food/snacks/grown/wheat = list("flour" = -5),
/obj/item/weapon/reagent_containers/food/snacks/grown/oat = list("flour" = -5),
/obj/item/weapon/reagent_containers/food/snacks/grown/rice = list("rice" = -5),
/obj/item/weapon/reagent_containers/food/snacks/donut/New = list("sprinkles" = -2, "sugar" = 1),
/obj/item/weapon/reagent_containers/food/snacks/donut = list("sprinkles" = -2, "sugar" = 1),
/obj/item/weapon/reagent_containers/food/snacks/grown/cherries = list("cherryjelly" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/bluecherries = list("bluecherryjelly" = 0),
/obj/item/weapon/reagent_containers/food/snacks/egg = list("eggyolk" = -5),
@@ -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)
@@ -966,7 +966,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "Only for the experienced. You think you see sand floating in the glass."
/datum/reagent/consumable/ethanol/bananahonk
name = "Banana Mama"
name = "Banana Honk"
id = "bananahonk"
description = "A drink from Clown Heaven."
nutriment_factor = 1 * REAGENTS_METABOLISM
@@ -60,7 +60,10 @@
// data for nutriment is one or more (flavour -> ratio)
// where all the ratio values adds up to 1
var/list/taste_amounts = data.Copy()
var/list/taste_amounts = list()
if(data)
taste_amounts = data.Copy()
counterlist_scale(taste_amounts, volume)
var/list/other_taste_amounts = newdata.Copy()
@@ -524,6 +527,12 @@
M.heal_bodypart_damage(3,1)
..()
/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////
@@ -347,10 +347,9 @@
/datum/reagent/medicine/mine_salve/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
if(iscarbon(M) && M.stat != DEAD)
if(method in list(INGEST, VAPOR, INJECT))
M.Stun(4)
M.Weaken(4)
M.nutrition -= 5
if(show_message)
to_chat(M, "<span class='warning'>Your stomach agonizingly cramps!</span>")
to_chat(M, "<span class='warning'>Your stomach feels empty and cramps!</span>")
else
var/mob/living/carbon/C = M
for(var/s in C.surgeries)
@@ -962,8 +961,7 @@
/datum/reagent/medicine/antitoxin/on_mob_life(mob/living/M)
M.adjustToxLoss(-2*REM, 0)
for(var/datum/reagent/toxin/R in M.reagents.reagent_list)
if(R != src)
M.reagents.remove_reagent(R.id,1)
M.reagents.remove_reagent(R.id,1)
..()
. = 1
@@ -189,7 +189,7 @@
/datum/reagent/water/holywater/on_mob_life(mob/living/M)
if(!data) data = 1
data++
M.jitteriness = max(M.jitteriness-5,0)
M.jitteriness = min(M.jitteriness+4,10)
if(data >= 30) // 12 units, 54 seconds @ metabolism 0.4 units & tick rate 1.8 sec
if(!M.stuttering)
M.stuttering = 1
@@ -212,9 +212,9 @@
SSticker.mode.remove_cultist(M.mind, 1, 1)
else if(is_servant_of_ratvar(M))
remove_servant_of_ratvar(M)
holder.remove_reagent(id, volume) // maybe this is a little too perfect and a max() cap on the statuses would be better??
M.jitteriness = 0
M.stuttering = 0
holder.remove_reagent(id, volume) // maybe this is a little too perfect and a max() cap on the statuses would be better??
return
holder.remove_reagent(id, 0.4) //fixed consumption to prevent balancing going out of whack
@@ -658,7 +658,7 @@
taste_mult = 0 // apparently tasteless.
/datum/reagent/mercury/on_mob_life(mob/living/M)
if(M.canmove && isspaceturf(M.loc))
if(M.canmove && !isspaceturf(M.loc))
step(M, pick(GLOB.cardinal))
if(prob(5))
M.emote(pick("twitch","drool","moan"))
@@ -738,7 +738,7 @@
taste_description = "metal"
/datum/reagent/lithium/on_mob_life(mob/living/M)
if(M.canmove && isspaceturf(M.loc))
if(M.canmove && !isspaceturf(M.loc))
step(M, pick(GLOB.cardinal))
if(prob(5))
M.emote(pick("twitch","drool","moan"))
@@ -1568,6 +1568,13 @@
M.update_transform()
..()
/datum/reagent/plastic_polymers
name = "plastic polymers"
id = "plastic_polymers"
description = "the petroleum based components of plastic."
color = "#f7eded"
taste_description = "plastic"
/datum/reagent/glitter
name = "generic glitter"
id = "glitter"
@@ -648,6 +648,34 @@
M.losebreath += 5
return ..()
/datum/reagent/toxin/spewium
name = "Spewium"
id = "spewium"
description = "A powerful emetic, causes uncontrollable vomiting. May result in vomiting organs at high doses."
reagent_state = LIQUID
color = "#2f6617" //A sickly green color
metabolization_rate = REAGENTS_METABOLISM
overdose_threshold = 29
toxpwr = 0
taste_description = "vomit"
/datum/reagent/toxin/spewium/on_mob_life(mob/living/M)
.=..()
if(current_cycle >=11 && prob(min(50,current_cycle)) && ishuman(M))
var/mob/living/carbon/human/H = M
H.vomit(lost_nutrition = 10, blood = prob(10), stun = prob(50), distance = rand(0,4), message = TRUE, toxic = prob(30))
for(var/datum/reagent/toxin/R in M.reagents.reagent_list)
if(R != src)
H.reagents.remove_reagent(R.id,1)
/datum/reagent/toxin/spewium/overdose_process(mob/living/M)
. = ..()
if(current_cycle >=33 && prob(15) && ishuman(M))
var/mob/living/carbon/human/H = M
H.spew_organ()
H.vomit(lost_nutrition = 0, blood = 1, stun = 1, distance = 4)
to_chat(H, "<span class='userdanger'>You feel something lumpy come up as you vomit.</span>")
/datum/reagent/toxin/curare
name = "Curare"
id = "curare"
@@ -624,3 +624,14 @@
id = "laughter"
results = list("laughter" = 10) // Fuck it. I'm not touching this one.
required_reagents = list("sugar" = 1, "banana" = 1)
/datum/chemical_reaction/plastic_polymers
name = "plastic polymers"
id = "plastic_polymers"
required_reagents = list("oil" = 5, "sodiumchloride" = 2, "ash" = 3)
required_temp = 374 //lazily consistent with soap & other crafted objects generically created with heat.
/datum/chemical_reaction/plastic_polymers/on_reaction(datum/reagents/holder, created_volume)
var/location = get_turf(holder.my_atom)
for(var/i in 1 to 10)
new /obj/item/stack/sheet/plastic(location)

Some files were not shown because too many files have changed in this diff Show More