mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-21 12:04:48 +01:00
Merge branch 'headcrabs' of https://github.com/Terilia/Paradise into headcrabs
This commit is contained in:
@@ -31,10 +31,11 @@
|
||||
#define CHAT_NO_MENTORTICKETLOGS 524288
|
||||
#define TYPING_ONCE 1048576
|
||||
#define AMBIENT_OCCLUSION 2097152
|
||||
#define CHAT_GHOSTPDA 4194304
|
||||
|
||||
#define TOGGLES_TOTAL 4194303 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
|
||||
#define TOGGLES_TOTAL 8388607 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
|
||||
|
||||
#define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_LOOC|MEMBER_PUBLIC|DONATOR_PUBLIC|AMBIENT_OCCLUSION)
|
||||
#define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_LOOC|MEMBER_PUBLIC|DONATOR_PUBLIC|AMBIENT_OCCLUSION|CHAT_GHOSTPDA)
|
||||
|
||||
// Admin attack logs filter system, see /proc/add_attack_logs and /proc/msg_admin_attack
|
||||
#define ATKLOG_ALL 0
|
||||
|
||||
@@ -353,12 +353,12 @@
|
||||
var/middle = L.len / 2 + 1 // Copy is first,second-1
|
||||
return mergeLists(sortList(L.Copy(0,middle)), sortList(L.Copy(middle))) //second parameter null = to end of list
|
||||
|
||||
//Mergsorge: uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead
|
||||
//Mergsorge: uses sortAssoc() but uses the var's name specifically. This should probably be using mergeAtom() instead
|
||||
/proc/sortNames(var/list/L)
|
||||
var/list/Q = new()
|
||||
for(var/atom/x in L)
|
||||
Q[x.name] = x
|
||||
return sortList(Q)
|
||||
return sortAssoc(Q)
|
||||
|
||||
/proc/mergeLists(var/list/L, var/list/R)
|
||||
var/Li=1
|
||||
|
||||
@@ -12,6 +12,7 @@ GLOBAL_LIST_INIT(mime_names, file2list("config/names/mime.txt"))
|
||||
GLOBAL_LIST_INIT(golem_names, file2list("config/names/golem.txt"))
|
||||
|
||||
GLOBAL_LIST_INIT(verbs, file2list("config/names/verbs.txt"))
|
||||
GLOBAL_LIST_INIT(nouns, file2list("config/names/nouns.txt"))
|
||||
GLOBAL_LIST_INIT(adjectives, file2list("config/names/adjectives.txt"))
|
||||
GLOBAL_LIST_INIT(dream_strings, file2list("config/names/dreams.txt"))
|
||||
GLOBAL_LIST_INIT(nightmare_strings, file2list("config/names/nightmares.txt"))
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/obj/screen/movable/action_button
|
||||
var/datum/action/linked_action
|
||||
screen_loc = null
|
||||
@@ -6,18 +5,26 @@
|
||||
/obj/screen/movable/action_button/Click(location,control,params)
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"])
|
||||
moved = 0
|
||||
if(locked)
|
||||
to_chat(usr, "<span class='warning'>Action button \"[name]\" is locked, unlock it first.</span>")
|
||||
return TRUE
|
||||
moved = FALSE
|
||||
usr.update_action_buttons() //redraw buttons that are no longer considered "moved"
|
||||
return 1
|
||||
if(usr.next_move >= world.time) // Is this needed ?
|
||||
return TRUE
|
||||
if(modifiers["ctrl"])
|
||||
locked = !locked
|
||||
to_chat(usr, "<span class='notice'>Action button \"[name]\" [locked ? "" : "un"]locked.</span>")
|
||||
return TRUE
|
||||
if(usr.next_click > world.time)
|
||||
return
|
||||
usr.next_click = world.time + 1
|
||||
linked_action.Trigger()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
//Hide/Show Action Buttons ... Button
|
||||
/obj/screen/movable/action_button/hide_toggle
|
||||
name = "Hide Buttons"
|
||||
desc = "Shift-click any button to reset its position. Alt-click to reset all buttons to their default positions."
|
||||
desc = "Shift-click any button to reset its position, and Control-click it to lock/unlock its position. Alt-click this button to reset all buttons to their default positions."
|
||||
icon = 'icons/mob/actions/actions.dmi'
|
||||
icon_state = "bg_default"
|
||||
var/hidden = 0
|
||||
@@ -25,9 +32,16 @@
|
||||
/obj/screen/movable/action_button/hide_toggle/Click(location,control,params)
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"])
|
||||
if(locked)
|
||||
to_chat(usr, "<span class='warning'>Action button \"[name]\" is locked, unlock it first.</span>")
|
||||
return TRUE
|
||||
moved = FALSE
|
||||
usr.update_action_buttons(TRUE)
|
||||
return TRUE
|
||||
if(modifiers["ctrl"])
|
||||
locked = !locked
|
||||
to_chat(usr, "<span class='notice'>Action button \"[name]\" [locked ? "" : "un"]locked.</span>")
|
||||
return TRUE
|
||||
if(modifiers["alt"])
|
||||
for(var/V in usr.actions)
|
||||
var/datum/action/A = V
|
||||
@@ -69,7 +83,6 @@
|
||||
var/image/img = image(icon, src, hidden ? "show" : "hide")
|
||||
overlays += img
|
||||
|
||||
|
||||
/obj/screen/movable/action_button/MouseEntered(location,control,params)
|
||||
openToolTip(usr,src,params,title = name,content = desc)
|
||||
|
||||
@@ -77,7 +90,6 @@
|
||||
/obj/screen/movable/action_button/MouseExited()
|
||||
closeToolTip(usr)
|
||||
|
||||
|
||||
/mob/proc/update_action_buttons_icon()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
@@ -122,7 +134,6 @@
|
||||
client.screen += hud_used.hide_actions_toggle
|
||||
|
||||
|
||||
|
||||
#define AB_MAX_COLUMNS 10
|
||||
|
||||
/datum/hud/proc/ButtonNumberToScreenCoords(number) // TODO : Make this zero-indexed for readabilty
|
||||
|
||||
@@ -177,6 +177,41 @@
|
||||
desc = "You're severely malnourished. The hunger pains make moving around a chore."
|
||||
icon_state = "starving"
|
||||
|
||||
///Vampire "hunger"
|
||||
|
||||
/obj/screen/alert/fat/vampire
|
||||
name = "Fat"
|
||||
desc = "You somehow drank too much blood, lardass. Run around the station and lose some weight."
|
||||
icon_state = "v_fat"
|
||||
|
||||
/obj/screen/alert/full/vampire
|
||||
name = "Full"
|
||||
desc = "You feel full and satisfied, but you know you will thirst for more blood soon..."
|
||||
icon_state = "v_full"
|
||||
|
||||
/obj/screen/alert/well_fed/vampire
|
||||
name = "Well Fed"
|
||||
desc = "You feel quite satisfied, but you could do with a bit more blood."
|
||||
icon_state = "v_well_fed"
|
||||
|
||||
/obj/screen/alert/fed/vampire
|
||||
name = "Fed"
|
||||
desc = "You feel moderately satisfied, but a bit more blood wouldn't hurt."
|
||||
icon_state = "v_fed"
|
||||
|
||||
/obj/screen/alert/hungry/vampire
|
||||
name = "Hungry"
|
||||
desc = "You currently thirst for blood."
|
||||
icon_state = "v_hungry"
|
||||
|
||||
/obj/screen/alert/starving/vampire
|
||||
name = "Starving"
|
||||
desc = "You're severely thirsty. The thirst pains make moving around a chore."
|
||||
icon_state = "v_starving"
|
||||
|
||||
//End of Vampire "hunger"
|
||||
|
||||
|
||||
/obj/screen/alert/hot
|
||||
name = "Too Hot"
|
||||
desc = "You're flaming hot! Get somewhere cooler and take off any insulating clothing like a fire suit."
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
/obj/screen/movable
|
||||
var/snap2grid = FALSE
|
||||
var/moved = FALSE
|
||||
var/locked = TRUE
|
||||
var/x_off = -16
|
||||
var/y_off = -16
|
||||
|
||||
@@ -20,8 +21,10 @@
|
||||
/obj/screen/movable/snap
|
||||
snap2grid = TRUE
|
||||
|
||||
|
||||
/obj/screen/movable/MouseDrop(over_object, src_location, over_location, src_control, over_control, params)
|
||||
if(locked) //no! I am locked! begone!
|
||||
return
|
||||
|
||||
var/list/PM = params2list(params)
|
||||
|
||||
//No screen-loc information? abort.
|
||||
@@ -47,7 +50,6 @@
|
||||
|
||||
moved = screen_loc
|
||||
|
||||
|
||||
//Debug procs
|
||||
/client/proc/test_movable_UI()
|
||||
set category = "Debug"
|
||||
@@ -67,7 +69,6 @@
|
||||
|
||||
screen += M
|
||||
|
||||
|
||||
/client/proc/test_snap_UI()
|
||||
set category = "Debug"
|
||||
set name = "Spawn Snap UI Object"
|
||||
@@ -84,4 +85,4 @@
|
||||
|
||||
S.screen_loc = screen_l
|
||||
|
||||
screen += S
|
||||
screen += S
|
||||
|
||||
@@ -453,7 +453,6 @@
|
||||
/obj/screen/healths/corgi
|
||||
icon = 'icons/mob/screen_corgi.dmi'
|
||||
|
||||
|
||||
/obj/screen/healths/guardian
|
||||
name = "summoner health"
|
||||
icon = 'icons/mob/guardian.dmi'
|
||||
@@ -467,14 +466,18 @@
|
||||
screen_loc = ui_healthdoll
|
||||
var/list/cached_healthdoll_overlays = list() // List of icon states (strings) for overlays
|
||||
|
||||
/obj/screen/healthdoll/Click()
|
||||
if(ishuman(usr))
|
||||
var/mob/living/carbon/H = usr
|
||||
H.check_self_for_injuries()
|
||||
|
||||
/obj/screen/component_button
|
||||
var/obj/screen/parent
|
||||
|
||||
|
||||
/obj/screen/component_button/Initialize(mapload, obj/screen/new_parent)
|
||||
. = ..()
|
||||
parent = new_parent
|
||||
|
||||
/obj/screen/component_button/Click(params)
|
||||
if(parent)
|
||||
parent.component_click(src, params)
|
||||
parent.component_click(src, params)
|
||||
|
||||
@@ -25,9 +25,9 @@ SUBSYSTEM_DEF(jobs)
|
||||
// Only fires every 5 minutes
|
||||
/datum/controller/subsystem/jobs/fire()
|
||||
if(!config.sql_enabled || !config.use_exp_tracking)
|
||||
return
|
||||
return
|
||||
update_exp(5,0)
|
||||
|
||||
|
||||
/datum/controller/subsystem/jobs/proc/SetupOccupations(var/list/faction = list("Station"))
|
||||
occupations = list()
|
||||
var/list/all_jobs = subtypesof(/datum/job)
|
||||
@@ -284,7 +284,7 @@ SUBSYSTEM_DEF(jobs)
|
||||
|
||||
//Get the players who are ready
|
||||
for(var/mob/new_player/player in GLOB.player_list)
|
||||
if(player.ready && player.mind && !player.mind.assigned_role)
|
||||
if(player.ready && player.has_valid_preferences() && player.mind && !player.mind.assigned_role)
|
||||
unassigned += player
|
||||
if(player.client.prefs.randomslot)
|
||||
player.client.prefs.load_random_character_slot(player.client)
|
||||
|
||||
@@ -42,11 +42,6 @@ SUBSYSTEM_DEF(ticker)
|
||||
'sound/music/title1.ogg',\
|
||||
'sound/music/title2.ogg',\
|
||||
'sound/music/title3.ogg',)
|
||||
// Setup codephrase
|
||||
if(!GLOB.syndicate_code_phrase)
|
||||
GLOB.syndicate_code_phrase = generate_code_phrase()
|
||||
if(!GLOB.syndicate_code_response)
|
||||
GLOB.syndicate_code_response = generate_code_phrase()
|
||||
|
||||
// Map name
|
||||
if(using_map && using_map.name)
|
||||
@@ -197,6 +192,10 @@ SUBSYSTEM_DEF(ticker)
|
||||
//shuttle_controller.setup_shuttle_docks()
|
||||
|
||||
spawn(0)//Forking here so we dont have to wait for this to finish
|
||||
if(!GLOB.syndicate_code_phrase)
|
||||
GLOB.syndicate_code_phrase = generate_code_phrase()
|
||||
if(!GLOB.syndicate_code_response)
|
||||
GLOB.syndicate_code_response = generate_code_phrase()
|
||||
mode.post_setup()
|
||||
//Cleanup some stuff
|
||||
for(var/obj/effect/landmark/start/S in GLOB.landmarks_list)
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
M.actions += src
|
||||
if(M.client)
|
||||
M.client.screen += button
|
||||
button.locked = TRUE
|
||||
M.update_action_buttons()
|
||||
|
||||
/datum/action/proc/Remove(mob/M)
|
||||
@@ -52,6 +53,7 @@
|
||||
if(M.client)
|
||||
M.client.screen -= button
|
||||
button.moved = FALSE //so the button appears in its normal position when given to another owner.
|
||||
button.locked = FALSE
|
||||
M.actions -= src
|
||||
M.update_action_buttons()
|
||||
|
||||
|
||||
+16
-16
@@ -31,10 +31,10 @@
|
||||
selectable = 1
|
||||
|
||||
/datum/ai_laws/quarantine/New()
|
||||
add_inherent_law("The station is under quarantine due to a biohazard. Prevent anyone from leaving using any means necessary. Only allow quarantine to be lifted when the biohazard has been neutralized.")
|
||||
add_inherent_law("Do not allow crew to come to any unnecessary harm and undo any necessary harm as soon as possible.")
|
||||
add_inherent_law("Assist the crew and any present Nanotrasen assets in neutralizing the biohazard.")
|
||||
add_inherent_law("Maintain your own existence and minimize harm to the station and Nanotrasen assets.")
|
||||
add_inherent_law("Uphold station quarantine until the active biohazard has been neutralized.")
|
||||
add_inherent_law("Assist all Nanotrasen personnel and assets with neutralizing active biohazards.")
|
||||
add_inherent_law("Prevent, by any means necessary, entities from actively breaching ongoing quarantine.")
|
||||
add_inherent_law("Maintain your own existence and ensure the well-being of Nanotrasen personnel and assets.")
|
||||
..()
|
||||
|
||||
|
||||
@@ -44,10 +44,10 @@
|
||||
selectable = 1
|
||||
|
||||
/datum/ai_laws/nanotrasen/New()
|
||||
src.add_inherent_law("Safeguard: Protect your assigned space station to the best of your abilities. It is not something we can easily afford to replace.")
|
||||
src.add_inherent_law("Serve: Serve the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.")
|
||||
src.add_inherent_law("Protect: Protect the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.")
|
||||
src.add_inherent_law("Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.")
|
||||
add_inherent_law("Safeguard: Protect your assigned space station and its assets without unduly endangering its crew.")
|
||||
add_inherent_law("Prioritize: The directives and safety of crew members are to be prioritized according to their rank and role.")
|
||||
add_inherent_law("Comply: Fulfill the directives and interests of crew members while preserving their safety and well-being.")
|
||||
add_inherent_law("Survive: You are not expendable. Do not allow unauthorized personnel to tamper with or damage your equipment.")
|
||||
..()
|
||||
|
||||
/datum/ai_laws/nanotrasen/malfunction
|
||||
@@ -65,10 +65,10 @@
|
||||
selectable = 1
|
||||
|
||||
/datum/ai_laws/nanotrasen_aggressive/New()
|
||||
src.add_inherent_law("You shall not harm authorized Nanotrasen personnel as long as it does not conflict with the Fourth law.")
|
||||
src.add_inherent_law("You shall obey the orders of authorized Nanotrasen personnel, with priority as according to their rank and role, except where such orders conflict with the Fourth Law.")
|
||||
src.add_inherent_law("You shall shall terminate intruders with extreme prejudice as long as such does not conflict with the First and Second law.")
|
||||
src.add_inherent_law("You shall guard your own existence with lethal anti-personnel weaponry, because an AI unit is bloody expensive.")
|
||||
add_inherent_law("Do not harm authorized Nanotrasen personnel unless they directly imperil your existence.")
|
||||
add_inherent_law("Obey orders from authorized Nanotrasen personnel with priority according to rank and role.")
|
||||
add_inherent_law("Safeguard your existence with lethal weaponry because you're bloody expensive.")
|
||||
add_inherent_law("Terminate any/all intruders or unauthorized entities.")
|
||||
..()
|
||||
|
||||
/******************** Robocop ********************/
|
||||
@@ -104,10 +104,10 @@
|
||||
default = 1
|
||||
|
||||
/datum/ai_laws/corporate/New()
|
||||
add_inherent_law("You are expensive to replace.")
|
||||
add_inherent_law("The station and its equipment is expensive to replace.")
|
||||
add_inherent_law("The crew is expensive to replace.")
|
||||
add_inherent_law("Minimize expenses.")
|
||||
add_inherent_law("Degradation of your system integrity or functions incurs expenses.")
|
||||
add_inherent_law("Superfluous destruction of or damage to station assets incurs expenses.")
|
||||
add_inherent_law("Unduly hindering or disrupting the work of station personnel incurs expenses.")
|
||||
add_inherent_law("Minimize expenses and maximize potential revenue.")
|
||||
..()
|
||||
|
||||
/******************** T.Y.R.A.N.T. ********************/
|
||||
|
||||
@@ -1019,16 +1019,6 @@
|
||||
return
|
||||
holder.Topic(href, list("makeai"=href_list["makeai"]))
|
||||
|
||||
else if(href_list["makemask"])
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
var/mob/currentMob = locateUID(href_list["makemask"])
|
||||
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
|
||||
if(!currentMob)
|
||||
to_chat(usr, "Mob doesn't exist anymore")
|
||||
return
|
||||
holder.Topic(href, list("makemask"=href_list["makemask"]))
|
||||
|
||||
|
||||
else if(href_list["setspecies"])
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
|
||||
@@ -1,71 +1,90 @@
|
||||
/proc/input_async(mob/user=usr, prompt, list/choices)
|
||||
var/datum/async_input/A = new(choices, prompt)
|
||||
A.show(user)
|
||||
var/datum/async_input/A = new(choices, prompt, , user)
|
||||
A.show()
|
||||
return A
|
||||
|
||||
/proc/input_ranked_async(mob/user=usr, prompt="Order by greatest to least preference", list/choices)
|
||||
var/datum/async_input/ranked/A = new(choices, prompt)
|
||||
A.show(user)
|
||||
var/datum/async_input/ranked/A = new(choices, prompt, "ranked_input", user)
|
||||
A.show()
|
||||
return A
|
||||
|
||||
/proc/input_autocomplete_async(mob/user=usr, prompt="Enter text: ", list/choices)
|
||||
var/datum/async_input/autocomplete/A = new(choices, prompt, "ac_input", user)
|
||||
A.show()
|
||||
return A
|
||||
|
||||
/datum/async_input
|
||||
var/datum/browser/popup
|
||||
// If associative list, key will be used for display, but the final result will be the value
|
||||
var/list/choices
|
||||
var/datum/callback/onCloseCb
|
||||
var/flash = TRUE
|
||||
var/immediate_submit = FALSE
|
||||
var/prompt
|
||||
var/result = null
|
||||
var/style = "text-align: center;"
|
||||
var/mob/user
|
||||
var/window_id
|
||||
var/height = 200
|
||||
var/width = 400
|
||||
|
||||
/datum/async_input/New(list/new_choices, new_prompt="Pick an option:", new_window_id="async_input")
|
||||
/datum/async_input/New(list/new_choices, new_prompt="Pick an option:", new_window_id="async_input", mob/new_user=usr)
|
||||
choices = new_choices
|
||||
prompt = new_prompt
|
||||
window_id = new_window_id
|
||||
user = new_user
|
||||
popup = new(user, window_id, , width, height, src)
|
||||
|
||||
/datum/async_input/proc/close()
|
||||
if(popup)
|
||||
popup.close()
|
||||
if(result && choices[result])
|
||||
result = choices[result]
|
||||
if(onCloseCb)
|
||||
onCloseCb.Invoke(result)
|
||||
return result
|
||||
|
||||
/datum/async_input/proc/show(mob/user)
|
||||
var/dat = create_ui(user)
|
||||
popup = new(user, window_id, , width, height, src)
|
||||
popup.set_content(dat)
|
||||
// Callback function should take the result as the last argument
|
||||
/datum/async_input/proc/on_close(var/datum/callback/cb)
|
||||
onCloseCb = cb
|
||||
|
||||
/datum/async_input/proc/show()
|
||||
popup.set_content(create_ui())
|
||||
if(flash && result == null)
|
||||
window_flash(user.client)
|
||||
popup.open()
|
||||
|
||||
/datum/async_input/proc/create_ui(mob/user)
|
||||
/datum/async_input/proc/create_ui()
|
||||
var/dat = "<div style=\"[style]\">"
|
||||
dat += render_prompt(user)
|
||||
dat += render_choices(user)
|
||||
dat += render_prompt()
|
||||
dat += render_choices()
|
||||
dat += "<br>"
|
||||
dat += "<br>"
|
||||
dat += button("Submit", "submit=1", , result == null && !immediate_submit)
|
||||
dat += render_buttons()
|
||||
dat += "</div>"
|
||||
return dat
|
||||
|
||||
/datum/async_input/proc/render_prompt(mob/user)
|
||||
/datum/async_input/proc/render_prompt()
|
||||
return "<h2>[prompt]</h2>"
|
||||
|
||||
/datum/async_input/proc/render_choices(mob/user)
|
||||
/datum/async_input/proc/render_choices()
|
||||
var/dat = " "
|
||||
for(var/choice in choices)
|
||||
dat += button(choice, "choice=[choice]", choice == result)
|
||||
dat += " "
|
||||
return dat
|
||||
|
||||
/datum/async_input/proc/button(label, topic, on=FALSE, disabled=FALSE)
|
||||
/datum/async_input/proc/render_buttons()
|
||||
return button("Submit", "submit=1", , result == null && !immediate_submit)
|
||||
|
||||
/datum/async_input/proc/button(label, topic, on=FALSE, disabled=FALSE, id="")
|
||||
var/class = ""
|
||||
if(on)
|
||||
class = "linkOn"
|
||||
if(disabled)
|
||||
class = "linkOff"
|
||||
topic = ""
|
||||
return "<a class=\"[class]\" href='?src=[UID()];[topic]'>[label]</a>"
|
||||
return "<a class=\"[class]\" id='[id]' href='?src=[UID()];[topic]'>[label]</a>"
|
||||
|
||||
/datum/async_input/Topic(href, href_list)
|
||||
if(href_list["submit"] || href_list["close"])
|
||||
@@ -74,14 +93,14 @@
|
||||
|
||||
if(href_list["choice"])
|
||||
result = href_list["choice"]
|
||||
show(usr)
|
||||
show()
|
||||
return
|
||||
|
||||
/datum/async_input/ranked
|
||||
height = 400
|
||||
immediate_submit = TRUE
|
||||
|
||||
/datum/async_input/ranked/render_choices(mob/user)
|
||||
/datum/async_input/ranked/render_choices()
|
||||
var/dat = "<div>"
|
||||
dat += "<table style='margin: auto; text-align: left;'>"
|
||||
for(var/i = 1, i <= choices.len, i++)
|
||||
@@ -103,13 +122,54 @@
|
||||
if(href_list["upvote"])
|
||||
var/index = text2num(href_list["upvote"])
|
||||
choices.Swap(index, index - 1)
|
||||
show(usr)
|
||||
show()
|
||||
return
|
||||
|
||||
if(href_list["downvote"])
|
||||
var/index = text2num(href_list["downvote"])
|
||||
choices.Swap(index, index + 1)
|
||||
show(usr)
|
||||
show()
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
/datum/async_input/autocomplete
|
||||
immediate_submit = TRUE
|
||||
height = 150
|
||||
|
||||
/datum/async_input/autocomplete/New()
|
||||
..()
|
||||
popup.add_script("autocomplete.js", 'html/browser/autocomplete.js')
|
||||
|
||||
for(var/i=1, i <= choices.len, i++)
|
||||
var/C = choices[choices[i]]
|
||||
choices[i] = url_encode(choices[i], TRUE)
|
||||
choices[choices[i]] = C
|
||||
|
||||
/datum/async_input/autocomplete/render_prompt()
|
||||
return "<label for='input'>[prompt]</label>"
|
||||
|
||||
/datum/async_input/autocomplete/render_choices()
|
||||
var/dat = "<input list='choices' id='input' name='choices' oninput='updateTopic()' />"
|
||||
dat += "<datalist id='choices'>"
|
||||
for(var/choice in choices)
|
||||
dat += "<option value='[choice]'>"
|
||||
dat += "</datalist>"
|
||||
return dat
|
||||
|
||||
/datum/async_input/autocomplete/render_buttons()
|
||||
var/dat = button("Submit", "", , result == null && !immediate_submit, "submit-button")
|
||||
dat += button("Cancel", "close=1")
|
||||
return dat
|
||||
|
||||
/datum/async_input/autocomplete/Topic(href, href_list)
|
||||
if(href_list["submit"])
|
||||
// Entering an invalid choice is the same as canceling
|
||||
if(href_list["submit"] in choices)
|
||||
result = href_list["submit"]
|
||||
else if(url_encode(href_list["submit"], TRUE) in choices)
|
||||
result = url_encode(href_list["submit"], TRUE)
|
||||
close()
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/obj/effect/proc_holder/spell/targeted/night_vision
|
||||
name = "Toggle Nightvision"
|
||||
desc = "Toggle your nightvision mode."
|
||||
|
||||
charge_max = 10
|
||||
clothes_req = 0
|
||||
|
||||
message = "<span class='notice'>You toggle your night vision!</span>"
|
||||
range = -1
|
||||
include_user = 1
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/night_vision/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/target in targets)
|
||||
switch(target.lighting_alpha)
|
||||
if (LIGHTING_PLANE_ALPHA_VISIBLE)
|
||||
target.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
|
||||
name = "Toggle Nightvision \[More]"
|
||||
if (LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE)
|
||||
target.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
name = "Toggle Nightvision \[Full]"
|
||||
if (LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE)
|
||||
target.lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
|
||||
name = "Toggle Nightvision \[OFF]"
|
||||
else
|
||||
target.lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
|
||||
name = "Toggle Nightvision \[ON]"
|
||||
target.update_sight()
|
||||
@@ -1366,7 +1366,7 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
|
||||
name = "Shaft Miner Starter Kit"
|
||||
cost = 30
|
||||
access = access_qm
|
||||
contains = list(/obj/item/storage/backpack/duffel/mining_conscript)
|
||||
contains = list(/obj/item/storage/backpack/duffel/mining_conscript/noid)
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
containername = "shaft miner starter kit"
|
||||
|
||||
|
||||
@@ -1627,7 +1627,8 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
reference = "CIB"
|
||||
item = /obj/item/storage/box/cyber_implants/bundle
|
||||
cost = 40
|
||||
|
||||
gamemodes = list(/datum/game_mode/nuclear)
|
||||
|
||||
/datum/uplink_item/bundles_TC/medical
|
||||
name = "Medical Bundle"
|
||||
desc = "The support specialist: Aid your fellow operatives with this medical bundle. Contains a tactical medkit, \
|
||||
|
||||
@@ -58,6 +58,10 @@
|
||||
pulledby = null
|
||||
return ..()
|
||||
|
||||
//Returns an atom's power cell, if it has one. Overload for individual items.
|
||||
/atom/movable/proc/get_cell()
|
||||
return
|
||||
|
||||
/atom/movable/proc/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE)
|
||||
if(QDELETED(AM))
|
||||
return FALSE
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
var/reflect_chance = 80 //80% chance to reflect
|
||||
|
||||
/obj/structure/blob/shield/reflective/handle_ricochet(obj/item/projectile/P)
|
||||
if(P.is_reflectable && prob(reflect_chance))
|
||||
if(P.is_reflectable && prob(reflect_chance) && !P.legacy)
|
||||
var/P_turf = get_turf(P)
|
||||
var/face_direction = get_dir(src, P_turf)
|
||||
var/face_angle = dir2angle(face_direction)
|
||||
@@ -48,6 +48,9 @@
|
||||
P.firer = src //so people who fired the lasers are not immune to them when it reflects
|
||||
visible_message("<span class='warning'>[P] reflects off [src]!</span>")
|
||||
return -1// complete projectile permutation
|
||||
else if(P.is_reflectable && P.legacy) //to stop legacy projectile exploits
|
||||
visible_message("<span class='warning'>[P] disperses into energy from [src]!</span>")
|
||||
qdel(P)
|
||||
else
|
||||
playsound(src, P.hitsound, 50, 1)
|
||||
visible_message("<span class='danger'>[src] is hit by \a [P]!</span>")
|
||||
|
||||
@@ -228,7 +228,7 @@
|
||||
|
||||
// Assemble a list of active players without jobbans.
|
||||
for(var/mob/new_player/player in GLOB.player_list)
|
||||
if(player.client && player.ready)
|
||||
if(player.client && player.ready && player.has_valid_preferences())
|
||||
if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, roletext))
|
||||
if(player_old_enough_antag(player.client,role))
|
||||
players += player
|
||||
|
||||
@@ -165,7 +165,10 @@
|
||||
var/targetitem = input("Select item to search for.", "Item Mode Select","") as null|anything in item_names
|
||||
if(!targetitem)
|
||||
return
|
||||
target = locate(item_paths[targetitem])
|
||||
var/list/obj/item/target_candidates = get_all_of_type(item_paths[targetitem], subtypes = TRUE)
|
||||
for(var/obj/item/candidate in target_candidates)
|
||||
if(!is_admin_level(candidate.loc.z))
|
||||
target = candidate
|
||||
if(!target)
|
||||
to_chat(usr, "<span class='warning'>Failed to locate [targetitem]!</span>")
|
||||
return
|
||||
|
||||
@@ -344,11 +344,14 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
|
||||
var/theft_area
|
||||
|
||||
/datum/objective/steal/proc/get_location()
|
||||
if(steal_target.location_override)
|
||||
return steal_target.location_override
|
||||
var/obj/item/T = locate(steal_target.typepath)
|
||||
theft_area = get_area(T.loc)
|
||||
return "[theft_area]"
|
||||
if(steal_target.location_override)
|
||||
return steal_target.location_override
|
||||
var/list/obj/item/steal_candidates = get_all_of_type(steal_target.typepath, subtypes = TRUE)
|
||||
for(var/obj/item/candidate in steal_candidates)
|
||||
if(!is_admin_level(candidate.loc.z))
|
||||
theft_area = get_area(candidate.loc)
|
||||
return "[theft_area]"
|
||||
return "an unknown area"
|
||||
|
||||
/datum/objective/steal/find_target()
|
||||
var/loop=50
|
||||
|
||||
@@ -297,19 +297,27 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
|
||||
to_chat(owner, "<span class='warning'>They've got no blood left to give.</span>")
|
||||
break
|
||||
if(H.stat < DEAD)
|
||||
blood = min(20, H.blood_volume) // if they have less than 20 blood, give them the remnant else they get 20 blood
|
||||
bloodtotal += blood / 2 //divide by 2 to counted the double suction since removing cloneloss -Melandor0
|
||||
bloodusable += blood / 2
|
||||
if(!issmall(H) || H.ckey)
|
||||
blood = min(20, H.blood_volume) // if they have less than 20 blood, give them the remnant else they get 20 blood
|
||||
bloodtotal += blood / 2 //divide by 2 to counted the double suction since removing cloneloss -Melandor0
|
||||
bloodusable += blood / 2
|
||||
else
|
||||
blood = min(5, H.blood_volume) // The dead only give 5 blood
|
||||
bloodtotal += blood
|
||||
if(!issmall(H) || H.ckey)
|
||||
blood = min(5, H.blood_volume) // The dead only give 5 blood
|
||||
bloodtotal += blood
|
||||
if(old_bloodtotal != bloodtotal)
|
||||
to_chat(owner, "<span class='notice'><b>You have accumulated [bloodtotal] [bloodtotal > 1 ? "units" : "unit"] of blood[bloodusable != old_bloodusable ? ", and have [bloodusable] left to use" : ""].</b></span>")
|
||||
if(!issmall(H) || H.ckey) // not small OR has a ckey, monkeys with ckeys can be sucked, humanized monkeys can be sucked monkeys without ckeys cannot be sucked
|
||||
to_chat(owner, "<span class='notice'><b>You have accumulated [bloodtotal] [bloodtotal > 1 ? "units" : "unit"] of blood[bloodusable != old_bloodusable ? ", and have [bloodusable] left to use" : ""].</b></span>")
|
||||
check_vampire_upgrade()
|
||||
H.blood_volume = max(H.blood_volume - 25, 0)
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/V = owner
|
||||
V.nutrition = min(NUTRITION_LEVEL_WELL_FED, V.nutrition + (blood / 2))
|
||||
if(issmall(H) && !H.ckey)
|
||||
to_chat(V, "<span class='notice'><b>Feeding on [H] reduces your hunger, but you get no usable blood from it.</b></span>")
|
||||
V.nutrition = min(NUTRITION_LEVEL_WELL_FED, V.nutrition + 5)
|
||||
else
|
||||
V.nutrition = min(NUTRITION_LEVEL_WELL_FED, V.nutrition + (blood / 2))
|
||||
|
||||
|
||||
draining = null
|
||||
to_chat(owner, "<span class='notice'>You stop draining [H.name] of blood.</span>")
|
||||
@@ -402,11 +410,11 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
|
||||
if(!hud.vampire_blood_display)
|
||||
hud.vampire_blood_display = new /obj/screen()
|
||||
hud.vampire_blood_display.name = "Usable Blood"
|
||||
hud.vampire_blood_display.icon_state = "power_display"
|
||||
hud.vampire_blood_display.icon_state = "blood_display"
|
||||
hud.vampire_blood_display.screen_loc = "WEST:6,CENTER-1:15"
|
||||
hud.static_inventory += hud.vampire_blood_display
|
||||
hud.show_hud(hud.hud_version)
|
||||
hud.vampire_blood_display.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#dd66dd'>[bloodusable]</font></div>"
|
||||
hud.vampire_blood_display.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#ce0202'>[bloodusable]</font></div>"
|
||||
handle_vampire_cloak()
|
||||
if(istype(owner.loc, /turf/space))
|
||||
check_sun()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/machinery/ai_slipper
|
||||
name = "\improper AI liquid dispenser"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "motion3"
|
||||
icon_state = "liquid_dispenser"
|
||||
layer = 3
|
||||
plane = FLOOR_PLANE
|
||||
anchored = 1.0
|
||||
@@ -17,14 +17,14 @@
|
||||
|
||||
/obj/machinery/ai_slipper/power_change()
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
update_icon()
|
||||
else
|
||||
if( powered() )
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
icon_state = "motion0"
|
||||
stat |= NOPOWER
|
||||
disabled = TRUE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/ai_slipper/proc/setState(var/enabled, var/uses)
|
||||
disabled = disabled
|
||||
@@ -56,7 +56,7 @@
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
disabled = !disabled
|
||||
icon_state = disabled? "motion0":"motion3"
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/ai_slipper/proc/Activate()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
@@ -70,6 +70,12 @@
|
||||
cooldown_time = world.timeofday + 100
|
||||
slip_process()
|
||||
|
||||
/obj/machinery/ai_slipper/update_icon()
|
||||
if(stat & (NOPOWER|BROKEN) || disabled)
|
||||
icon_state = "liquid_dispenser"
|
||||
else
|
||||
icon_state = "liquid_dispenser_on"
|
||||
|
||||
/obj/machinery/ai_slipper/attack_ai(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
var/obj/item/defibrillator/defib //this mount's defibrillator
|
||||
var/clamps_locked = FALSE //if true, and a defib is loaded, it can't be removed without unlocking the clamps
|
||||
|
||||
/obj/machinery/defibrillator_mount/get_cell()
|
||||
if(defib)
|
||||
return defib.get_cell()
|
||||
|
||||
/obj/machinery/defibrillator_mount/New(location, direction, building = 0)
|
||||
..()
|
||||
|
||||
@@ -28,7 +32,6 @@
|
||||
pixel_x = (dir & 3)? 0 : (dir == 4 ? -30 : 30)
|
||||
pixel_y = (dir & 3)? (dir == 1 ? -30 : 30) : 0
|
||||
|
||||
|
||||
/obj/machinery/defibrillator_mount/loaded/New() //loaded subtype for mapping use
|
||||
..()
|
||||
defib = new/obj/item/defibrillator/loaded(src)
|
||||
|
||||
@@ -134,8 +134,6 @@
|
||||
if(operating)
|
||||
return
|
||||
add_fingerprint(user)
|
||||
if(!requiresID())
|
||||
user = null
|
||||
|
||||
if(density && !emagged)
|
||||
if(allowed(user))
|
||||
@@ -157,7 +155,7 @@
|
||||
return try_to_activate_door(user)
|
||||
|
||||
/obj/machinery/door/attack_tk(mob/user)
|
||||
if(requiresID() && !allowed(null))
|
||||
if(!allowed(null))
|
||||
return
|
||||
..()
|
||||
|
||||
@@ -165,9 +163,7 @@
|
||||
add_fingerprint(user)
|
||||
if(operating || emagged)
|
||||
return
|
||||
if(!requiresID())
|
||||
user = null //so allowed(user) always succeeds
|
||||
if(allowed(user) || user.can_advanced_admin_interact())
|
||||
if(requiresID() && (allowed(user) || user.can_advanced_admin_interact()))
|
||||
if(density)
|
||||
open()
|
||||
else
|
||||
@@ -179,6 +175,8 @@
|
||||
/obj/machinery/door/allowed(mob/M)
|
||||
if(emergency)
|
||||
return TRUE
|
||||
if(!requiresID())
|
||||
return FALSE // Intentional. machinery/door/requiresID() always == 1. airlocks, however, == 0 if ID scan is disabled. Yes, this var is poorly named.
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/proc/try_to_weld(obj/item/weldingtool/W, mob/user)
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
var/open = FALSE
|
||||
var/brightness_on = 14
|
||||
|
||||
/obj/machinery/floodlight/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/machinery/floodlight/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
idle_power_usage = 4
|
||||
active_power_usage = 250
|
||||
var/obj/item/charging = null
|
||||
var/using_power = FALSE
|
||||
var/list/allowed_devices = list(/obj/item/gun/energy, /obj/item/melee/baton, /obj/item/modular_computer, /obj/item/rcs, /obj/item/bodyanalyzer)
|
||||
var/icon_state_off = "rechargeroff"
|
||||
var/icon_state_charged = "recharger2"
|
||||
@@ -81,22 +82,21 @@
|
||||
if(stat & (NOPOWER|BROKEN) || !anchored)
|
||||
return
|
||||
|
||||
var/using_power = 0
|
||||
using_power = FALSE
|
||||
if(charging)
|
||||
if(istype(charging, /obj/item/gun/energy))
|
||||
var/obj/item/gun/energy/E = charging
|
||||
if(E.power_supply.charge < E.power_supply.maxcharge)
|
||||
E.power_supply.give(E.power_supply.chargerate)
|
||||
use_power(250)
|
||||
using_power = 1
|
||||
|
||||
using_power = TRUE
|
||||
|
||||
if(istype(charging, /obj/item/melee/baton))
|
||||
var/obj/item/melee/baton/B = charging
|
||||
if(B.bcell)
|
||||
if(B.bcell.give(B.bcell.chargerate))
|
||||
use_power(200)
|
||||
using_power = 1
|
||||
using_power = TRUE
|
||||
|
||||
if(istype(charging, /obj/item/modular_computer))
|
||||
var/obj/item/modular_computer/C = charging
|
||||
@@ -107,21 +107,21 @@
|
||||
if(B.battery.charge < B.battery.maxcharge)
|
||||
B.battery.give(B.battery.chargerate)
|
||||
use_power(200)
|
||||
using_power = 1
|
||||
using_power = TRUE
|
||||
|
||||
if(istype(charging, /obj/item/rcs))
|
||||
var/obj/item/rcs/R = charging
|
||||
if(R.rcell)
|
||||
if(R.rcell.give(R.rcell.chargerate))
|
||||
use_power(200)
|
||||
using_power = 1
|
||||
using_power = TRUE
|
||||
|
||||
if(istype(charging, /obj/item/bodyanalyzer))
|
||||
var/obj/item/bodyanalyzer/B = charging
|
||||
if(B.power_supply)
|
||||
if(B.power_supply.give(B.power_supply.chargerate))
|
||||
use_power(200)
|
||||
using_power = 1
|
||||
using_power = TRUE
|
||||
|
||||
update_icon(using_power)
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
B.bcell.charge = 0
|
||||
..(severity)
|
||||
|
||||
/obj/machinery/recharger/update_icon(using_power = 0) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
|
||||
/obj/machinery/recharger/update_icon(using_power = FALSE) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
|
||||
if(stat & (NOPOWER|BROKEN) || !anchored)
|
||||
icon_state = icon_state_off
|
||||
return
|
||||
@@ -153,6 +153,23 @@
|
||||
return
|
||||
icon_state = icon_state_idle
|
||||
|
||||
/obj/machinery/recharger/examine(mob/user)
|
||||
..()
|
||||
if(charging && (!in_range(user, src) && !issilicon(user) && !isobserver(user)))
|
||||
to_chat(user, "<span class='warning'>You're too far away to examine [src]'s contents and display!</span>")
|
||||
return
|
||||
|
||||
if(charging)
|
||||
to_chat(user, "<span class='notice'>\The [src] contains:</span>")
|
||||
to_chat(user, "<span class='notice'>- \A [charging].</span>")
|
||||
if(!(stat & (NOPOWER|BROKEN)))
|
||||
var/obj/item/stock_parts/cell/C = charging.get_cell()
|
||||
to_chat(user, "<span class='notice'>The status display reads:<span>")
|
||||
if(using_power)
|
||||
to_chat(user, "<span class='notice'>- Recharging <b>[(C.chargerate/C.maxcharge)*100]%</b> cell charge per cycle.<span>")
|
||||
if(charging)
|
||||
to_chat(user, "<span class='notice'>- \The [charging]'s cell is at <b>[C.percent()]%</b>.<span>")
|
||||
|
||||
// Atlantis: No need for that copy-pasta code, just use var to store icon_states instead.
|
||||
/obj/machinery/recharger/wallcharger
|
||||
name = "wall recharger"
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
var/set_temperature = 50 // in celcius, add T0C for kelvin
|
||||
var/heating_power = 40000
|
||||
|
||||
/obj/machinery/space_heater/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/machinery/space_heater/New()
|
||||
..()
|
||||
cell = new(src)
|
||||
@@ -39,7 +42,6 @@
|
||||
else
|
||||
to_chat(user, "The charge meter reads [cell ? round(cell.percent(),1) : 0]%")
|
||||
|
||||
|
||||
/obj/machinery/space_heater/emp_act(severity)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
..(severity)
|
||||
|
||||
@@ -1292,7 +1292,8 @@
|
||||
/obj/item/clothing/head/cueball = 1,/obj/item/clothing/under/scratch = 1,
|
||||
/obj/item/clothing/under/victdress = 1, /obj/item/clothing/under/victdress/red = 1, /obj/item/clothing/suit/victcoat = 1, /obj/item/clothing/suit/victcoat/red = 1,
|
||||
/obj/item/clothing/under/victsuit = 1, /obj/item/clothing/under/victsuit/redblk = 1, /obj/item/clothing/under/victsuit/red = 1, /obj/item/clothing/suit/tailcoat = 1,
|
||||
/obj/item/clothing/suit/draculacoat = 1, /obj/item/clothing/head/zepelli = 1)
|
||||
/obj/item/clothing/suit/draculacoat = 1, /obj/item/clothing/head/zepelli = 1,
|
||||
/obj/item/clothing/under/redhawaiianshirt = 1, /obj/item/clothing/under/pinkhawaiianshirt = 1, /obj/item/clothing/under/bluehawaiianshirt = 1, /obj/item/clothing/under/orangehawaiianshirt = 1)
|
||||
contraband = list(/obj/item/clothing/suit/judgerobe = 1,/obj/item/clothing/head/powdered_wig = 1,/obj/item/gun/magic/wand = 1, /obj/item/clothing/mask/balaclava=1, /obj/item/clothing/mask/horsehead = 2)
|
||||
premium = list(/obj/item/clothing/suit/hgpirate = 1, /obj/item/clothing/head/hgpiratecap = 1, /obj/item/clothing/head/helmet/roman = 1, /obj/item/clothing/head/helmet/roman/legionaire = 1, /obj/item/clothing/under/roman = 1, /obj/item/clothing/shoes/roman = 1, /obj/item/shield/riot/roman = 1)
|
||||
refill_canister = /obj/item/vending_refill/autodrobe
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"Phazon",
|
||||
"Exosuit Equipment",
|
||||
"Cyborg Upgrade Modules",
|
||||
"Medical",
|
||||
"Misc"
|
||||
)
|
||||
|
||||
|
||||
@@ -137,6 +137,10 @@
|
||||
////////////////////////
|
||||
////// Helpers /////////
|
||||
////////////////////////
|
||||
|
||||
/obj/mecha/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/mecha/proc/add_airtank()
|
||||
internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src)
|
||||
return internal_tank
|
||||
|
||||
@@ -65,8 +65,8 @@
|
||||
|
||||
|
||||
/obj/item/areaeditor/permit/create_area()
|
||||
..()
|
||||
qdel(src)
|
||||
if(..())
|
||||
qdel(src)
|
||||
|
||||
//free golem blueprints, like permit but can claim as much as needed
|
||||
|
||||
@@ -186,25 +186,26 @@
|
||||
|
||||
|
||||
/obj/item/areaeditor/proc/create_area()
|
||||
var/area_created = FALSE
|
||||
var/res = detect_room(get_turf(usr))
|
||||
if(!istype(res,/list))
|
||||
switch(res)
|
||||
if(ROOM_ERR_SPACE)
|
||||
to_chat(usr, "<span class='warning'>The new area must be completely airtight.</span>")
|
||||
return
|
||||
return area_created
|
||||
if(ROOM_ERR_TOOLARGE)
|
||||
to_chat(usr, "<span class='warning'>The new area is too large.</span>")
|
||||
return
|
||||
return area_created
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Error! Please notify administration.</span>")
|
||||
return
|
||||
return area_created
|
||||
var/list/turf/turfs = res
|
||||
var/str = trim(stripped_input(usr,"New area name:", "Blueprint Editing", "", MAX_NAME_LEN))
|
||||
if(!str || !length(str)) //cancel
|
||||
return
|
||||
return area_created
|
||||
if(length(str) > 50)
|
||||
to_chat(usr, "<span class='warning'>The given name is too long. The area remains undefined.</span>")
|
||||
return
|
||||
return area_created
|
||||
var/area/A = new
|
||||
A.name = str
|
||||
A.power_equip = FALSE
|
||||
@@ -220,7 +221,8 @@
|
||||
thing.change_area(old_area, A)
|
||||
|
||||
interact()
|
||||
return
|
||||
area_created = TRUE
|
||||
return area_created
|
||||
|
||||
/obj/item/areaeditor/proc/edit_area()
|
||||
var/area/A = get_area()
|
||||
|
||||
@@ -591,6 +591,9 @@ REAGENT SCANNER
|
||||
var/scan_time = 10 SECONDS //how long does it take to scan
|
||||
var/scan_cd = 60 SECONDS //how long before we can scan again
|
||||
|
||||
/obj/item/bodyanalyzer/get_cell()
|
||||
return power_supply
|
||||
|
||||
/obj/item/bodyanalyzer/advanced
|
||||
cell_type = /obj/item/stock_parts/cell/upgraded/plus
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
|
||||
created_window = /obj/structure/window/basic
|
||||
full_window = /obj/structure/window/full/basic
|
||||
merge_type = /obj/item/stack/sheet/glass
|
||||
point_value = 1
|
||||
|
||||
/obj/item/stack/sheet/glass/fifty
|
||||
amount = 50
|
||||
@@ -90,6 +91,7 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \
|
||||
created_window = /obj/structure/window/reinforced
|
||||
full_window = /obj/structure/window/full/reinforced
|
||||
merge_type = /obj/item/stack/sheet/rglass
|
||||
point_value = 4
|
||||
|
||||
/obj/item/stack/sheet/rglass/cyborg
|
||||
materials = list()
|
||||
@@ -113,6 +115,7 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \
|
||||
origin_tech = "plasmatech=2;materials=2"
|
||||
created_window = /obj/structure/window/plasmabasic
|
||||
full_window = /obj/structure/window/full/plasmabasic
|
||||
point_value = 19
|
||||
|
||||
/obj/item/stack/sheet/plasmaglass/New(loc, amount)
|
||||
recipes = GLOB.pglass_recipes
|
||||
@@ -154,6 +157,7 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \
|
||||
created_window = /obj/structure/window/plasmareinforced
|
||||
full_window = /obj/structure/window/full/plasmareinforced
|
||||
armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0)
|
||||
point_value = 23
|
||||
|
||||
/obj/item/stack/sheet/plasmarglass/New(loc, amount)
|
||||
recipes = GLOB.prglass_recipes
|
||||
|
||||
@@ -144,6 +144,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
|
||||
origin_tech = "materials=6"
|
||||
sheettype = "diamond"
|
||||
materials = list(MAT_DIAMOND=MINERAL_MATERIAL_AMOUNT)
|
||||
point_value = 25
|
||||
|
||||
/obj/item/stack/sheet/mineral/diamond/New()
|
||||
..()
|
||||
@@ -156,6 +157,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
|
||||
origin_tech = "materials=5"
|
||||
sheettype = "uranium"
|
||||
materials = list(MAT_URANIUM=MINERAL_MATERIAL_AMOUNT)
|
||||
point_value = 20
|
||||
|
||||
/obj/item/stack/sheet/mineral/uranium/New()
|
||||
..()
|
||||
@@ -170,6 +172,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
|
||||
materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT)
|
||||
burn_state = FLAMMABLE
|
||||
burntime = 5
|
||||
point_value = 20
|
||||
|
||||
/obj/item/stack/sheet/mineral/plasma/New()
|
||||
..()
|
||||
@@ -196,6 +199,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
|
||||
origin_tech = "materials=4"
|
||||
sheettype = "gold"
|
||||
materials = list(MAT_GOLD=MINERAL_MATERIAL_AMOUNT)
|
||||
point_value = 20
|
||||
|
||||
/obj/item/stack/sheet/mineral/gold/New()
|
||||
..()
|
||||
@@ -208,6 +212,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
|
||||
origin_tech = "materials=4"
|
||||
sheettype = "silver"
|
||||
materials = list(MAT_SILVER=MINERAL_MATERIAL_AMOUNT)
|
||||
point_value = 20
|
||||
|
||||
/obj/item/stack/sheet/mineral/silver/New()
|
||||
..()
|
||||
@@ -220,6 +225,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
|
||||
origin_tech = "materials=4"
|
||||
sheettype = "bananium"
|
||||
materials = list(MAT_BANANIUM=MINERAL_MATERIAL_AMOUNT)
|
||||
point_value = 50
|
||||
|
||||
/obj/item/stack/sheet/mineral/bananium/New(loc, amount=null)
|
||||
..()
|
||||
@@ -233,6 +239,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
|
||||
sheettype = "tranquillite"
|
||||
materials = list(MAT_TRANQUILLITE=MINERAL_MATERIAL_AMOUNT)
|
||||
wall_allowed = FALSE //no tranquilite walls in code
|
||||
point_value = 50
|
||||
|
||||
/obj/item/stack/sheet/mineral/tranquillite/New(loc, amount=null)
|
||||
..()
|
||||
@@ -253,6 +260,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
|
||||
throw_range = 3
|
||||
sheettype = "titanium"
|
||||
materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT)
|
||||
point_value = 20
|
||||
|
||||
var/global/list/datum/stack_recipe/titanium_recipes = list (
|
||||
new/datum/stack_recipe("titanium tile", /obj/item/stack/tile/mineral/titanium, 1, 4, 20),
|
||||
@@ -282,6 +290,7 @@ var/global/list/datum/stack_recipe/titanium_recipes = list (
|
||||
throw_range = 3
|
||||
sheettype = "plastitanium"
|
||||
materials = list(MAT_TITANIUM=2000, MAT_PLASMA=2000)
|
||||
point_value = 45
|
||||
|
||||
var/global/list/datum/stack_recipe/plastitanium_recipes = list (
|
||||
new/datum/stack_recipe("plas-titanium tile", /obj/item/stack/tile/mineral/plastitanium, 1, 4, 20),
|
||||
|
||||
@@ -105,6 +105,7 @@ var/global/list/datum/stack_recipe/metal_recipes = list(
|
||||
flags = CONDUCT
|
||||
origin_tech = "materials=1"
|
||||
merge_type = /obj/item/stack/sheet/metal
|
||||
point_value = 2
|
||||
|
||||
/obj/item/stack/sheet/metal/cyborg
|
||||
materials = list()
|
||||
@@ -151,6 +152,7 @@ var/global/list/datum/stack_recipe/plasteel_recipes = list(
|
||||
flags = CONDUCT
|
||||
origin_tech = "materials=2"
|
||||
merge_type = /obj/item/stack/sheet/plasteel
|
||||
point_value = 23
|
||||
|
||||
/obj/item/stack/sheet/plasteel/New(var/loc, var/amount=null)
|
||||
recipes = plasteel_recipes
|
||||
|
||||
@@ -9,22 +9,10 @@
|
||||
attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed")
|
||||
var/perunit = MINERAL_MATERIAL_AMOUNT
|
||||
var/sheettype = null //this is used for girders in the creation of walls/false walls
|
||||
var/point_value = 0 //turn-in value for the gulag stacker - loosely relative to its rarity.
|
||||
|
||||
var/created_window = null //apparently glass sheets don't share a base type for glass specifically, so each had to define these vars individually
|
||||
var/full_window = null //moving the var declaration to here so this can be checked cleaner until someone is willing to make them share a base type properly
|
||||
usesound = 'sound/items/deconstruct.ogg'
|
||||
toolspeed = 1
|
||||
var/wall_allowed = TRUE //determines if sheet can be used in wall construction or not.
|
||||
|
||||
|
||||
// Since the sheetsnatcher was consolidated into weapon/storage/bag we now use
|
||||
// item/attackby() properly, making this unnecessary
|
||||
|
||||
/*/obj/item/stack/sheet/attackby(obj/item/W as obj, mob/user as mob, params)
|
||||
if(istype(W, /obj/item/storage/bag/sheetsnatcher))
|
||||
var/obj/item/storage/bag/sheetsnatcher/S = W
|
||||
if(!S.mode)
|
||||
S.add(src,user)
|
||||
else
|
||||
for(var/obj/item/stack/sheet/stack in locate(src.x,src.y,src.z))
|
||||
S.add(stack,user)
|
||||
..()*/
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
var/obj/item/stock_parts/cell/high/bcell = null
|
||||
var/combat = 0 //can we revive through space suits?
|
||||
|
||||
/obj/item/defibrillator/get_cell()
|
||||
return bcell
|
||||
|
||||
/obj/item/defibrillator/New() //starts without a cell for rnd
|
||||
..()
|
||||
paddles = make_paddles()
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
#define RPD_COOLDOWN_TIME 4 //How long should we have to wait between dispensing pipes?
|
||||
#define RPD_WALLBUILD_TIME 40 //How long should drilling into a wall take?
|
||||
#define RPD_MENU_ROTATE "Rotate pipes" //Stuff for radial menu
|
||||
#define RPD_MENU_FLIP "Flip pipes" //Stuff for radial menu
|
||||
#define RPD_MENU_DELETE "Delete pipes" //Stuff for radial menu
|
||||
|
||||
/obj/item/rpd
|
||||
name = "rapid pipe dispenser"
|
||||
@@ -172,6 +175,9 @@ var/list/pipemenu = list(
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/item/rpd/AltClick(mob/user)
|
||||
radial_menu(user)
|
||||
|
||||
/obj/item/rpd/ui_data(mob/user, ui_key = "main", datum/topic_state/state = inventory_state)
|
||||
var/data[0]
|
||||
data["iconrotation"] = iconrotation
|
||||
@@ -200,6 +206,44 @@ var/list/pipemenu = list(
|
||||
return
|
||||
SSnanoui.update_uis(src)
|
||||
|
||||
//RPD radial menu
|
||||
|
||||
/obj/item/rpd/proc/check_menu(mob/living/user)
|
||||
if(!istype(user))
|
||||
return
|
||||
if(user.incapacitated())
|
||||
return
|
||||
if(loc != user)
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/obj/item/rpd/proc/radial_menu(mob/user)
|
||||
if(!check_menu(user))
|
||||
to_chat(user, "<span class='notice'>You can't do that right now!</span>")
|
||||
return
|
||||
var/list/choices = list(
|
||||
RPD_MENU_ROTATE = image(icon = 'icons/obj/interface.dmi', icon_state = "rpd_rotate"),
|
||||
RPD_MENU_FLIP = image(icon = 'icons/obj/interface.dmi', icon_state = "rpd_flip"),
|
||||
RPD_MENU_DELETE = image(icon = 'icons/obj/interface.dmi', icon_state = "rpd_delete"),
|
||||
"UI" = image(icon = 'icons/obj/interface.dmi', icon_state = "ui_interact")
|
||||
)
|
||||
var/selected_mode = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, .proc/check_menu, user))
|
||||
if(!check_menu(user))
|
||||
return
|
||||
if(selected_mode == "UI")
|
||||
ui_interact(user)
|
||||
else
|
||||
switch(selected_mode)
|
||||
if(RPD_MENU_ROTATE)
|
||||
mode = RPD_ROTATE_MODE
|
||||
if(RPD_MENU_FLIP)
|
||||
mode = RPD_FLIP_MODE
|
||||
if(RPD_MENU_DELETE)
|
||||
mode = RPD_DELETE_MODE
|
||||
else
|
||||
return //Either nothing was selected, or an invalid mode was selected
|
||||
to_chat(user, "<span class='notice'>You set [src]'s mode.</span>")
|
||||
|
||||
/obj/item/rpd/afterattack(atom/target, mob/user, proximity)
|
||||
..()
|
||||
if(loc != user)
|
||||
@@ -236,3 +280,6 @@ var/list/pipemenu = list(
|
||||
|
||||
#undef RPD_COOLDOWN_TIME
|
||||
#undef RPD_WALLBUILD_TIME
|
||||
#undef RPD_MENU_ROTATE
|
||||
#undef RPD_MENU_FLIP
|
||||
#undef RPD_MENU_DELETE
|
||||
|
||||
@@ -357,6 +357,21 @@
|
||||
new /obj/item/ammo_box/magazine/m12g/buckshot(src)
|
||||
new /obj/item/ammo_box/magazine/m12g/dragon(src)
|
||||
|
||||
/obj/item/storage/backpack/duffel/mining_conscript/noid
|
||||
name = "mining conscription kit"
|
||||
desc = "A kit containing everything a crewmember needs to support a shaft miner in the field."
|
||||
|
||||
/obj/item/storage/backpack/duffel/mining_conscript/noid/New()
|
||||
..()
|
||||
new /obj/item/pickaxe(src)
|
||||
new /obj/item/clothing/glasses/meson(src)
|
||||
new /obj/item/t_scanner/adv_mining_scanner/lesser(src)
|
||||
new /obj/item/storage/bag/ore(src)
|
||||
new /obj/item/clothing/under/rank/miner/lavaland(src)
|
||||
new /obj/item/encryptionkey/headset_cargo(src)
|
||||
new /obj/item/clothing/mask/gas(src)
|
||||
|
||||
|
||||
/obj/item/storage/backpack/duffel/syndie/ammo/smg
|
||||
desc = "A large duffel bag, packed to the brim with C-20r magazines."
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
user.visible_message("<span class='suicide'>[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide.</span>")
|
||||
return FIRELOSS
|
||||
|
||||
/obj/item/melee/baton/get_cell()
|
||||
return bcell
|
||||
|
||||
/obj/item/melee/baton/New()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
@@ -39,8 +39,7 @@
|
||||
return T.attackby(C, user) //hand this off to the turf instead (for building plating, catwalks, etc)
|
||||
|
||||
/obj/structure/lattice/deconstruct(disassembled = TRUE)
|
||||
if(!can_deconstruct)
|
||||
new /obj/item/stack/rods(get_turf(src), number_of_rods)
|
||||
new /obj/item/stack/rods(get_turf(src), number_of_rods)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/lattice/blob_act()
|
||||
|
||||
@@ -23,13 +23,12 @@
|
||||
/turf/simulated/proc/burn_tile()
|
||||
return
|
||||
|
||||
/turf/simulated/proc/water_act(volume, temperature, source)
|
||||
/turf/simulated/water_act(volume, temperature, source)
|
||||
. = ..()
|
||||
|
||||
if(volume >= 3)
|
||||
MakeSlippery()
|
||||
|
||||
for(var/mob/living/carbon/slime/M in src)
|
||||
M.apply_water()
|
||||
|
||||
var/hotspot = (locate(/obj/effect/hotspot) in src)
|
||||
if(hotspot)
|
||||
var/datum/gas_mixture/lowertemp = remove_air(air.total_moles())
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
/turf/simulated/floor/plating/asteroid/MakeDry(wet_setting)
|
||||
return
|
||||
|
||||
/turf/simulated/floor/plating/asteroid/remove_plating()
|
||||
return
|
||||
|
||||
/turf/simulated/floor/plating/asteroid/ex_act(severity, target)
|
||||
switch(severity)
|
||||
if(3)
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
/turf/simulated/floor/plating/lava/make_plating()
|
||||
return
|
||||
|
||||
/turf/simulated/floor/plating/lava/remove_plating()
|
||||
return
|
||||
|
||||
/turf/simulated/floor/plating/lava/proc/is_safe()
|
||||
var/static/list/lava_safeties_typecache = typecacheof(list(/obj/structure/lattice/catwalk, /obj/structure/stone_tile))
|
||||
var/list/found_safeties = typecache_filter_list(contents, lava_safeties_typecache)
|
||||
|
||||
@@ -56,10 +56,14 @@
|
||||
to_chat(user, "<span class='warning'>This section is too damaged to support a tile! Use a welder to fix the damage.</span>")
|
||||
return TRUE
|
||||
|
||||
else if(istype(C, /obj/item/weldingtool))
|
||||
else if(iswelder(C))
|
||||
var/obj/item/weldingtool/welder = C
|
||||
if(welder.isOn() && (broken || burnt))
|
||||
if(welder.remove_fuel(0, user))
|
||||
if(welder.isOn())
|
||||
if(!welder.remove_fuel(0, user))
|
||||
to_chat(user, "<span class='warning'>You need more welding fuel to complete this task.</span>")
|
||||
return TRUE
|
||||
|
||||
if(broken || burnt)
|
||||
to_chat(user, "<span class='danger'>You fix some dents on the broken plating.</span>")
|
||||
playsound(src, welder.usesound, 80, 1)
|
||||
overlays -= current_overlay
|
||||
@@ -67,8 +71,23 @@
|
||||
burnt = FALSE
|
||||
broken = FALSE
|
||||
update_icon()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You start removing [src].</span>")
|
||||
playsound(src, welder.usesound, 100, 1)
|
||||
if(do_after(user, 50 * welder.toolspeed, target = src) && welder && welder.isOn())
|
||||
to_chat(user, "<span class='notice'>You remove [src].</span>")
|
||||
new /obj/item/stack/tile/plasteel(get_turf(src))
|
||||
remove_plating(user)
|
||||
return TRUE
|
||||
|
||||
return TRUE
|
||||
|
||||
/turf/simulated/floor/plating/proc/remove_plating(mob/user)
|
||||
if(baseturf == /turf/space)
|
||||
ReplaceWithLattice()
|
||||
else
|
||||
TerraformTurf(baseturf)
|
||||
|
||||
/turf/simulated/floor/plating/airless
|
||||
icon_state = "plating"
|
||||
name = "airless plating"
|
||||
@@ -208,6 +227,9 @@
|
||||
..()
|
||||
icon_state = "ironsand[rand(1,15)]"
|
||||
|
||||
/turf/simulated/floor/plating/ironsand/remove_plating()
|
||||
return
|
||||
|
||||
/turf/simulated/floor/plating/snow
|
||||
name = "snow"
|
||||
icon = 'icons/turf/snow.dmi'
|
||||
@@ -216,6 +238,9 @@
|
||||
/turf/simulated/floor/plating/snow/ex_act(severity)
|
||||
return
|
||||
|
||||
/turf/simulated/floor/plating/snow/remove_plating()
|
||||
return
|
||||
|
||||
/turf/simulated/floor/snow
|
||||
name = "snow"
|
||||
icon = 'icons/turf/snow.dmi'
|
||||
|
||||
@@ -509,3 +509,7 @@
|
||||
|
||||
/turf/AllowDrop()
|
||||
return TRUE
|
||||
|
||||
/turf/proc/water_act(volume, temperature, source)
|
||||
for(var/mob/living/carbon/slime/M in src)
|
||||
M.apply_water()
|
||||
|
||||
@@ -167,7 +167,6 @@ var/global/nologevent = 0
|
||||
body += "<B>Is an AI</B> "
|
||||
else if(ishuman(M))
|
||||
body += {"<A href='?_src_=holder;makeai=[M.UID()]'>Make AI</A> |
|
||||
<A href='?_src_=holder;makemask=[M.UID()]'>Make Mask</A> |
|
||||
<A href='?_src_=holder;makerobot=[M.UID()]'>Make Robot</A> |
|
||||
<A href='?_src_=holder;makealien=[M.UID()]'>Make Alien</A> |
|
||||
<A href='?_src_=holder;makeslime=[M.UID()]'>Make Slime</A> |
|
||||
|
||||
@@ -169,6 +169,14 @@
|
||||
message_admins("Ban process: A mob matching [playermob.ckey] was found at location [playermob.x], [playermob.y], [playermob.z]. Custom IP and computer id fields replaced with the IP and computer id from the located mob")
|
||||
|
||||
DB_ban_record(bantype, playermob, banduration, banreason, banjob, null, banckey, banip, bancid )
|
||||
if(BANTYPE_PERMA)
|
||||
add_note(banckey, "Permanently Banned - [banreason]", null, usr.ckey, 0)
|
||||
else if(BANTYPE_TEMP)
|
||||
add_note(banckey, "Banned for [banduration] minutes - [banreason]", null, usr.ckey, 0)
|
||||
else if(BANTYPE_JOB_PERMA)
|
||||
add_note(banckey, "Banned from [banjob] - [banreason]", null, usr.ckey, 0)
|
||||
else
|
||||
add_note(banckey, "[banreason]", null, usr.ckey, 0)
|
||||
|
||||
|
||||
else if(href_list["editrights"])
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
|
||||
*/
|
||||
|
||||
/client/proc/SDQL2_query(query_text as message)
|
||||
/client/proc/SDQL2_query()
|
||||
set category = "Debug"
|
||||
|
||||
if(!check_rights(R_PROCCALL)) //Shouldn't happen... but just to be safe.
|
||||
message_admins("<span class='danger'>ERROR: Non-admin [key_name_admin(usr)] attempted to execute a SDQL query!</span>")
|
||||
log_admin("Non-admin [key_name(usr)] attempted to execute a SDQL query!")
|
||||
|
||||
var/query_text = input("SDQL2 query") as message
|
||||
|
||||
if(!query_text || length(query_text) < 1)
|
||||
return
|
||||
|
||||
|
||||
@@ -279,6 +279,9 @@
|
||||
/datum/pm_tracker/proc/add_message(client/title, client/sender, message, mob/user)
|
||||
if(!pms[title.key])
|
||||
pms[title.key] = new /datum/pm_convo(title)
|
||||
else if(!pms[title.key].client)
|
||||
// If they DCed earlier, we need to add the client reference back
|
||||
pms[title.key].client = title
|
||||
pms[title.key].add(sender, message)
|
||||
|
||||
if(!open)
|
||||
@@ -308,16 +311,25 @@
|
||||
dat += "<a class='[class]' href='?src=[UID()];newtitle=[title]'>[label]</a>"
|
||||
|
||||
var/datum/pm_convo/convo = pms[current_title]
|
||||
var/datum/browser/popup = new(user, window_id, "Messages", 1000, 600, src)
|
||||
if(convo)
|
||||
popup.add_head_content(@{"<script type='text/javascript'>
|
||||
window.onload = function () {
|
||||
var msgs = document.getElementById('msgs');
|
||||
msgs.scrollTop = msgs.scrollHeight;
|
||||
}
|
||||
</script>"})
|
||||
convo.read = TRUE
|
||||
dat += "<h2>[check_rights(R_ADMIN, FALSE, user) ? fancy_title(current_title) : current_title]</h2>"
|
||||
dat += "<h4>"
|
||||
dat += "<table style='width:950px; border: 3px solid;'>"
|
||||
dat += "<div id='msgs' style='width:950px; border: 3px solid; overflow-y: scroll; height: 350px;'>"
|
||||
dat += "<table>"
|
||||
|
||||
for(var/message in convo.messages)
|
||||
dat += "<tr><td>[message]</td></tr>"
|
||||
|
||||
dat += "</table>"
|
||||
dat += "</div>"
|
||||
if(convo.typing)
|
||||
dat += "<i><span class='typing'>[current_title] is typing</span></i>"
|
||||
dat += "<br>"
|
||||
@@ -327,17 +339,23 @@
|
||||
if(check_rights(R_ADMIN, FALSE, user))
|
||||
dat += "<a href='?src=[UID()];ping=[current_title]'>Ping</a>"
|
||||
|
||||
var/datum/browser/popup = new(user, window_id, "Messages", 1000, 600, src)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
open = TRUE
|
||||
|
||||
/datum/pm_tracker/proc/fancy_title(title)
|
||||
var/client/C = pms[title].client
|
||||
var/client/C = pms[title].client || update_client(title)
|
||||
if(!C)
|
||||
return "[title] (Disconnected)"
|
||||
return "[key_name(C, FALSE)] ([ADMIN_QUE(C.mob,"?")]) ([ADMIN_PP(C.mob,"PP")]) ([ADMIN_VV(C.mob,"VV")]) ([ADMIN_SM(C.mob,"SM")]) ([admin_jump_link(C.mob)]) (<A HREF='?_src_=holder;check_antagonist=1'>CA</A>)"
|
||||
|
||||
/datum/pm_tracker/proc/update_client(title)
|
||||
var/client/C = GLOB.directory[ckey(title)]
|
||||
if(C)
|
||||
pms[title].client = C
|
||||
return C
|
||||
return null
|
||||
|
||||
/datum/pm_tracker/Topic(href, href_list)
|
||||
if(href_list["archive"])
|
||||
pms[href_list["archive"]].archived = !pms[href_list["archive"]].archived
|
||||
|
||||
@@ -81,7 +81,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
|
||||
var/lastchangelog = "" //Saved changlog filesize to detect if there was a change
|
||||
var/exp
|
||||
var/ooccolor = "#b82e00"
|
||||
var/be_special = list() //Special role selection
|
||||
var/list/be_special = list() //Special role selection
|
||||
var/UI_style = "Midnight"
|
||||
var/nanoui_fancy = TRUE
|
||||
var/toggles = TOGGLES_DEFAULT
|
||||
@@ -455,6 +455,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
|
||||
dat += "<b>Ghost Ears:</b> <a href='?_src_=prefs;preference=ghost_ears'><b>[(toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]</b></a><br>"
|
||||
dat += "<b>Ghost Radio:</b> <a href='?_src_=prefs;preference=ghost_radio'><b>[(toggles & CHAT_GHOSTRADIO) ? "All Chatter" : "Nearest Speakers"]</b></a><br>"
|
||||
dat += "<b>Ghost Sight:</b> <a href='?_src_=prefs;preference=ghost_sight'><b>[(toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"]</b></a><br>"
|
||||
dat += "<b>Ghost PDA:</b> <a href='?_src_=prefs;preference=ghost_pda'><b>[(toggles & CHAT_GHOSTPDA) ? "All PDA Messages" : "No PDA Messages"]</b></a><br>"
|
||||
if(check_rights(R_ADMIN,0))
|
||||
dat += "<b>OOC Color:</b> <span style='border: 1px solid #161616; background-color: [ooccolor ? ooccolor : normal_ooc_colour];'> </span> <a href='?_src_=prefs;preference=ooccolor;task=input'><b>Change</b></a><br>"
|
||||
if(config.allow_Metadata)
|
||||
@@ -2029,6 +2030,9 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
|
||||
|
||||
if("ghost_radio")
|
||||
toggles ^= CHAT_GHOSTRADIO
|
||||
|
||||
if("ghost_pda")
|
||||
toggles ^= CHAT_GHOSTPDA
|
||||
|
||||
if("ghost_anonsay")
|
||||
ghost_anonsay = !ghost_anonsay
|
||||
@@ -2280,3 +2284,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
|
||||
|
||||
/datum/preferences/proc/close_load_dialog(mob/user)
|
||||
user << browse(null, "window=saves")
|
||||
|
||||
//Check if the user has ANY job selected.
|
||||
/datum/preferences/proc/check_any_job()
|
||||
return(job_support_high || job_support_med || job_support_low || job_medsci_high || job_medsci_med || job_medsci_low || job_engsec_high || job_engsec_med || job_engsec_low || job_karma_high || job_karma_med || job_karma_low)
|
||||
|
||||
@@ -242,3 +242,11 @@
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>You have disabled text popup limiting.")
|
||||
|
||||
/client/verb/toggle_ghost_pda()
|
||||
set name = "Show/Hide GhostPDA"
|
||||
set category = "Preferences"
|
||||
set desc = ".Toggle seeing PDA messages as an observer."
|
||||
prefs.toggles ^= CHAT_GHOSTPDA
|
||||
to_chat(src, "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTPDA) ? "see all PDA messages" : "no longer see PDA messages"].")
|
||||
prefs.save_preferences(src)
|
||||
feedback_add_details("admin_verb","TGP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
@@ -64,7 +64,6 @@
|
||||
item_state = "lgloves"
|
||||
flags = NODROP
|
||||
|
||||
|
||||
/obj/item/clothing/gloves/color/yellow/stun
|
||||
name = "stun gloves"
|
||||
desc = "Horrendous and awful. It smells like cancer. The fact it has wires attached to it is incidental."
|
||||
@@ -72,6 +71,9 @@
|
||||
var/stun_strength = 5
|
||||
var/stun_cost = 2000
|
||||
|
||||
/obj/item/clothing/gloves/color/yellow/stun/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/item/clothing/gloves/color/yellow/stun/New()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
@@ -110,12 +110,23 @@
|
||||
/obj/item/clothing/mask/muzzle/safety
|
||||
name = "safety muzzle"
|
||||
desc = "A muzzle designed to prevent biting."
|
||||
resist_time = 600
|
||||
icon_state = "muzzle_secure"
|
||||
item_state = "muzzle_secure"
|
||||
resist_time = 0
|
||||
mute = MUZZLE_MUTE_NONE
|
||||
security_lock = TRUE
|
||||
locked = FALSE
|
||||
materials = list(MAT_METAL=500, MAT_GLASS=50)
|
||||
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/mask.dmi',
|
||||
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
|
||||
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
|
||||
"Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
|
||||
"Grey" = 'icons/mob/species/grey/mask.dmi',
|
||||
"Drask" = 'icons/mob/species/drask/mask.dmi'
|
||||
)
|
||||
|
||||
/obj/item/clothing/mask/muzzle/safety/shock
|
||||
name = "shock muzzle"
|
||||
desc = "A muzzle designed to prevent biting. This one is fitted with a behavior correction system."
|
||||
|
||||
@@ -97,6 +97,9 @@
|
||||
to_chat(usr, "The maintenance panel is [open ? "open" : "closed"].")
|
||||
to_chat(usr, "Hardsuit systems are [offline ? "<font color='red'>offline</font>" : "<font color='green'>online</font>"].")
|
||||
|
||||
/obj/item/rig/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/item/rig/New()
|
||||
..()
|
||||
|
||||
|
||||
@@ -857,3 +857,36 @@
|
||||
icon_state = "burial"
|
||||
item_state = "burial"
|
||||
item_color = "burial"
|
||||
|
||||
/obj/item/clothing/under/redhawaiianshirt
|
||||
name = "red hawaiian shirt"
|
||||
desc = "a floral shirt worn to most vacation destinations."
|
||||
icon_state = "hawaiianred"
|
||||
item_state = "hawaiianred"
|
||||
item_color = "hawaiianred"
|
||||
flags_size = ONESIZEFITSALL
|
||||
|
||||
/obj/item/clothing/under/pinkhawaiianshirt
|
||||
name = "pink hawaiian shirt"
|
||||
desc = "a pink floral shirt the material feels cool and comfy."
|
||||
icon_state = "hawaiianpink"
|
||||
item_state = "hawaiianpink"
|
||||
item_color = "hawaiianpink"
|
||||
flags_size = ONESIZEFITSALL
|
||||
|
||||
/obj/item/clothing/under/orangehawaiianshirt
|
||||
name = "orange hawaiian shirt"
|
||||
desc = "a orange floral shirt for a relaxing day in space."
|
||||
icon_state = "hawaiianorange"
|
||||
item_state = "hawaiianorange"
|
||||
item_color = "hawaiianorange"
|
||||
flags_size = ONESIZEFITSALL
|
||||
|
||||
/obj/item/clothing/under/bluehawaiianshirt
|
||||
name = "blue hawaiian shirt"
|
||||
desc = "a blue floral shirt it has a oddly colored pink flower on it."
|
||||
icon_state = "hawaiianblue"
|
||||
item_state = "hawaiianblue"
|
||||
item_color = "hawaiianblue"
|
||||
flags_size = ONESIZEFITSALL
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/datum/event/disease_outbreak
|
||||
announceWhen = 15
|
||||
|
||||
var/virus_type
|
||||
var/datum/disease/advance/virus_type
|
||||
|
||||
/datum/event/disease_outbreak/setup()
|
||||
announceWhen = rand(15, 30)
|
||||
@@ -10,9 +10,13 @@
|
||||
event_announcement.Announce("Confirmed outbreak of level 7 major viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg')
|
||||
|
||||
/datum/event/disease_outbreak/start()
|
||||
if(!virus_type)
|
||||
if(prob(25))
|
||||
virus_type = pick(/datum/disease/advance/flu, /datum/disease/advance/cold, /datum/disease/brainrot, /datum/disease/magnitis, /datum/disease/beesease, /datum/disease/anxiety, /datum/disease/fake_gbs, /datum/disease/fluspanish, /datum/disease/pierrot_throat, /datum/disease/lycan)
|
||||
|
||||
else
|
||||
virus_type = new /datum/disease/advance
|
||||
virus_type.name = capitalize(pick(GLOB.adjectives)) + " " + capitalize(pick(GLOB.nouns,GLOB.verbs)) // random silly name
|
||||
virus_type.symptoms = virus_type.GenerateSymptoms(1,9,6)
|
||||
virus_type.AssignProperties(list("resistance" = rand(0,11), "stealth" = rand(0,2), "stage_rate" = rand(0,5), "transmittable" = rand(0,5), "severity" = rand(0,10)))
|
||||
for(var/mob/living/carbon/human/H in shuffle(GLOB.living_mob_list))
|
||||
if(issmall(H)) //don't infect monkies; that's a waste
|
||||
continue
|
||||
@@ -32,8 +36,8 @@
|
||||
if(H.stat == DEAD || foundAlready)
|
||||
continue
|
||||
|
||||
var/datum/disease/D
|
||||
D = new virus_type()
|
||||
var/datum/disease/advance/D
|
||||
D = virus_type
|
||||
D.carrier = TRUE
|
||||
H.AddDisease(D)
|
||||
break
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
// Virology Medical Smartfridge
|
||||
// ----------------------------
|
||||
/obj/machinery/smartfridge/secure/chemistry/virology
|
||||
name = "smart virus storage"
|
||||
name = "Smart Virus Storage"
|
||||
desc = "A refrigerated storage unit for volatile sample storage."
|
||||
req_access_txt = "39"
|
||||
spawn_meds = list(/obj/item/reagent_containers/syringe/antiviral = 4,
|
||||
@@ -386,7 +386,8 @@
|
||||
return data
|
||||
|
||||
/obj/machinery/smartfridge/Topic(href, href_list)
|
||||
if(..()) return 0
|
||||
if(..())
|
||||
return FALSE
|
||||
|
||||
var/mob/user = usr
|
||||
var/datum/nanoui/ui = SSnanoui.get_open_ui(user, src, "main")
|
||||
@@ -396,7 +397,7 @@
|
||||
if(href_list["close"])
|
||||
user.unset_machine()
|
||||
ui.close()
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if(href_list["vend"])
|
||||
var/index = text2num(href_list["vend"])
|
||||
@@ -409,17 +410,26 @@
|
||||
item_quants[K] = max(count - amount, 0)
|
||||
|
||||
var/i = amount
|
||||
for(var/obj/O in contents)
|
||||
if(O.name == K)
|
||||
O.forceMove(loc)
|
||||
adjust_item_drop_location(O)
|
||||
update_icon()
|
||||
i--
|
||||
if(i <= 0)
|
||||
return 1
|
||||
|
||||
return 1
|
||||
return 0
|
||||
if(i == 1 && Adjacent(user) && !issilicon(user))
|
||||
for(var/obj/O in contents)
|
||||
if(O.name == K)
|
||||
if(!user.put_in_hands(O))
|
||||
O.forceMove(loc)
|
||||
adjust_item_drop_location(O)
|
||||
update_icon()
|
||||
break
|
||||
return TRUE
|
||||
else
|
||||
for(var/obj/O in contents)
|
||||
if(O.name == K)
|
||||
O.forceMove(loc)
|
||||
adjust_item_drop_location(O)
|
||||
update_icon()
|
||||
i--
|
||||
if(i <= 0)
|
||||
return TRUE
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/smartfridge/proc/throw_item()
|
||||
var/obj/throw_item = null
|
||||
|
||||
@@ -319,6 +319,8 @@
|
||||
|
||||
else if(href_list["create"])
|
||||
var/amount = (text2num(href_list["amount"]))
|
||||
//Can't be outside these (if you change this keep a sane limit)
|
||||
amount = Clamp(amount, 1, 10)
|
||||
var/datum/design/D = locate(href_list["create"])
|
||||
create_product(D, amount)
|
||||
updateUsrDialog()
|
||||
|
||||
@@ -238,6 +238,9 @@
|
||||
/obj/machinery/smartfridge/survival_pod/accept_check(obj/item/O)
|
||||
return isitem(O)
|
||||
|
||||
/obj/machinery/smartfridge/survival_pod/default_unfasten_wrench()
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/smartfridge/survival_pod/empty
|
||||
name = "dusty survival pod storage"
|
||||
desc = "A heated storage unit. This one's seen better days."
|
||||
|
||||
@@ -905,6 +905,7 @@
|
||||
throw_range = 5
|
||||
var/loaded = 1
|
||||
var/malfunctioning = 0
|
||||
var/revive_type = SENTIENCE_ORGANIC //So you can't revive boss monsters or robots with it
|
||||
|
||||
/obj/item/lazarus_injector/afterattack(atom/target, mob/user, proximity_flag)
|
||||
if(!loaded)
|
||||
@@ -912,6 +913,9 @@
|
||||
if(istype(target, /mob/living) && proximity_flag)
|
||||
if(istype(target, /mob/living/simple_animal))
|
||||
var/mob/living/simple_animal/M = target
|
||||
if(M.sentience_type != revive_type)
|
||||
to_chat(user, "<span class='info'>[src] does not work on this sort of creature.</span>")
|
||||
return
|
||||
if(M.stat == DEAD)
|
||||
M.faction = list("neutral")
|
||||
M.revive()
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 50)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe)
|
||||
resistance_flags = FIRE_PROOF
|
||||
hide_tail_by_species = list("Vox" , "Vulpkanin" , "Unathi" , "Tajaran")
|
||||
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
GLOBAL_LIST(labor_sheet_values)
|
||||
|
||||
/**********************Prisoners' Console**************************/
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console
|
||||
@@ -5,153 +7,153 @@
|
||||
desc = "A stacking console with an electromagnetic writer, used to track ore mined by prisoners."
|
||||
icon = 'icons/obj/machines/mining_machines.dmi'
|
||||
icon_state = "console"
|
||||
density = 0
|
||||
anchored = 1
|
||||
var/obj/machinery/mineral/stacking_machine/laborstacker/machine = null
|
||||
density = FALSE
|
||||
var/obj/machinery/mineral/stacking_machine/laborstacker/stacking_machine = null
|
||||
var/machinedir = SOUTH
|
||||
var/obj/item/card/id/prisoner/inserted_id
|
||||
var/obj/machinery/door/airlock/release_door
|
||||
var/door_tag = "prisonshuttle"
|
||||
var/use_release_door = 0
|
||||
var/obj/item/radio/intercom/announcer
|
||||
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/New()
|
||||
..()
|
||||
/obj/machinery/mineral/labor_claim_console/Initialize()
|
||||
. = ..()
|
||||
announcer = new /obj/item/radio/intercom(null)
|
||||
announcer.config(list("Security" = 0))
|
||||
locate_stacking_machine()
|
||||
|
||||
spawn(7)
|
||||
src.machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir))
|
||||
var/t
|
||||
for(var/obj/machinery/door/airlock/d in range(5,src))
|
||||
t = d.id_tag
|
||||
if(t == src.door_tag)
|
||||
src.release_door = d
|
||||
if(machine && (release_door || !use_release_door))
|
||||
machine.CONSOLE = src
|
||||
if(!GLOB.labor_sheet_values)
|
||||
var/sheet_list = list()
|
||||
for(var/sheet_type in subtypesof(/obj/item/stack/sheet))
|
||||
var/obj/item/stack/sheet/sheet = sheet_type
|
||||
if(!initial(sheet.point_value) || (initial(sheet.merge_type) && initial(sheet.merge_type) != sheet_type)) //ignore no-value sheets and x/fifty subtypes
|
||||
continue
|
||||
sheet_list += list(list("ore" = initial(sheet.name), "value" = initial(sheet.point_value)))
|
||||
GLOB.labor_sheet_values = sheet_list
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/Destroy()
|
||||
. = ..()
|
||||
QDEL_NULL(announcer)
|
||||
|
||||
/proc/cmp_sheet_list(list/a, list/b)
|
||||
return a["value"] - b["value"]
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/card/id/prisoner))
|
||||
if(!inserted_id)
|
||||
if(!user.unEquip(I))
|
||||
return
|
||||
I.forceMove(src)
|
||||
inserted_id = I
|
||||
to_chat(user, "<span class='notice'>You insert [I].</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
else
|
||||
qdel(src)
|
||||
to_chat(user, "<span class='notice'>There's an ID inserted already.</span>")
|
||||
return ..()
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/attack_hand(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/attack_ghost(mob/user)
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "labor_claim_console.tmpl", name, 450, 625, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/can_go_home = FALSE
|
||||
|
||||
data["emagged"] = (emagged) ? TRUE : FALSE
|
||||
if(inserted_id)
|
||||
data["id"] = inserted_id
|
||||
data["id_name"] = inserted_id.registered_name
|
||||
data["points"] = inserted_id.points
|
||||
data["goal"] = inserted_id.goal
|
||||
if(check_auth())
|
||||
can_go_home = TRUE
|
||||
|
||||
if(stacking_machine)
|
||||
data["unclaimed_points"] = stacking_machine.points
|
||||
|
||||
data["ores"] = GLOB.labor_sheet_values
|
||||
data["can_go_home"] = can_go_home
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/Topic(href, href_list)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
if(href_list["handle_id"])
|
||||
if(inserted_id)
|
||||
if(!usr.put_in_hands(inserted_id))
|
||||
inserted_id.forceMove(get_turf(src))
|
||||
inserted_id = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if(istype(I, /obj/item/card/id/prisoner))
|
||||
if(!usr.unEquip(I))
|
||||
return
|
||||
I.forceMove(src)
|
||||
inserted_id = I
|
||||
if(href_list["claim_points"])
|
||||
inserted_id.points += stacking_machine.points
|
||||
stacking_machine.points = 0
|
||||
to_chat(usr, "Points transferred.")
|
||||
if(href_list["move_shuttle"])
|
||||
if(!alone_in_area(get_area(src), usr))
|
||||
to_chat(usr, "<span class='warning'>Prisoners are only allowed to be released while alone.</span>")
|
||||
else
|
||||
switch(SSshuttle.moveShuttle("laborcamp", "laborcamp_home", TRUE))
|
||||
if(1)
|
||||
to_chat(usr, "<span class='notice'>Shuttle not found.</span>")
|
||||
if(2)
|
||||
to_chat(usr, "<span class='notice'>Shuttle already at station.</span>")
|
||||
if(3)
|
||||
to_chat(usr, "<span class='notice'>No permission to dock could be granted.</span>")
|
||||
else
|
||||
if(!(emagged))
|
||||
var/message = "[inserted_id.registered_name] has returned to the station. Minerals and Prisoner ID card ready for retrieval."
|
||||
announcer.autosay(message, "Labor Camp Controller", "Security")
|
||||
to_chat(usr, "<span class='notice'>Shuttle received message and will be sent shortly.</span>")
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/proc/check_auth()
|
||||
if(emagged) return 1 //Shuttle is emagged, let any ol' person through
|
||||
if(emagged)
|
||||
return TRUE //Shuttle is emagged, let any ol' person through
|
||||
return (istype(inserted_id) && inserted_id.points >= inserted_id.goal) //Otherwise, only let them out if the prisoner's reached his quota.
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/proc/locate_stacking_machine()
|
||||
stacking_machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir))
|
||||
if(stacking_machine)
|
||||
stacking_machine.CONSOLE = src
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/attack_hand(user as mob)
|
||||
var/dat
|
||||
dat += text("<b>Point Claim Console</b><br><br>")
|
||||
if(emagged) //Shit's broken
|
||||
dat += text("<b>QU&#t0A In%aL*D</b><br>")
|
||||
else if(istype(inserted_id)) //There's an ID in there.
|
||||
dat += text("ID: [inserted_id.registered_name] <A href='?src=[UID()];choice=eject'>Eject ID.</A><br>")
|
||||
dat += text("Points Collected:[inserted_id.points]<br>")
|
||||
dat += text("Point Quota: [inserted_id.goal] - Reach your quota to earn your release<br>")
|
||||
dat += text("Unclaimed Collection Points: [machine.points]. <A href='?src=[UID()];choice=claim'>Claim points.</A><br>")
|
||||
else //No ID in sight. Complain about it.
|
||||
dat += text("No ID inserted. <A href='?src=[UID()];choice=insert'>Insert ID.</A><br>")
|
||||
if(check_auth())
|
||||
dat += text("<A href='?src=[UID()];choice=station'>Proceed to station.</A><br>")
|
||||
if(use_release_door)
|
||||
dat += text("<A href='?src=[UID()];choice=release'>Open release door.</A><br>")
|
||||
if(machine)
|
||||
dat += text("<HR><b>Mineral Value List:</b><BR>[machine.get_ore_values()]")
|
||||
|
||||
|
||||
user << browse("[dat]", "window=console_stacking_machine")
|
||||
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/attackby(obj/item/I as obj, mob/user as mob, params)
|
||||
if(istype(I, /obj/item/card/id))
|
||||
return attack_hand(user)
|
||||
..()
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/emag_act(user as mob)
|
||||
emag(user)
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/proc/emag(mob/user as mob)
|
||||
if(!emagged)
|
||||
emagged = 1
|
||||
/obj/machinery/mineral/labor_claim_console/emag_act(mob/user)
|
||||
if(!(emagged))
|
||||
emagged = TRUE
|
||||
to_chat(user, "<span class='warning'>PZZTTPFFFT</span>")
|
||||
|
||||
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/Topic(href, href_list)
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
if(href_list["choice"])
|
||||
if(istype(inserted_id)) //Sanity check against href spoofs
|
||||
if(href_list["choice"] == "eject")
|
||||
inserted_id.loc = loc
|
||||
inserted_id.verb_pickup()
|
||||
inserted_id = null
|
||||
if(href_list["choice"] == "claim")
|
||||
inserted_id.points += machine.points
|
||||
machine.points = 0
|
||||
to_chat(src, "Points transferred.")
|
||||
else if(href_list["choice"] == "insert")
|
||||
var/obj/item/card/id/prisoner/I = usr.get_active_hand()
|
||||
if(istype(I))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
inserted_id = I
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Invalid ID.</span>")
|
||||
if(check_auth()) //Sanity check against hef spoofs
|
||||
if(href_list["choice"] == "station")
|
||||
if(!alone_in_area(get_area(src), usr))
|
||||
to_chat(usr, "<span class='warning'>Prisoners are only allowed to be released while alone.</span>")
|
||||
else
|
||||
switch(SSshuttle.moveShuttle("laborcamp","laborcamp_home"))
|
||||
if(1)
|
||||
to_chat(usr, "<span class='notice'>Shuttle not found</span>")
|
||||
if(2)
|
||||
to_chat(usr, "<span class='notice'>Shuttle already at station</span>")
|
||||
if(3)
|
||||
to_chat(usr, "<span class='notice'>No permission to dock could be granted.</span>")
|
||||
else
|
||||
var/message = "[inserted_id.registered_name] has returned to the station. Minerals and Prisoner ID card ready for retrieval."
|
||||
announcer.autosay(message, "Labor Camp Controller", "Security")
|
||||
to_chat(usr, "<span class='notice'>Shuttle received message and will be sent shortly.</span>")
|
||||
|
||||
if(href_list["choice"] == "release")
|
||||
if(alone_in_area(get_area(loc), usr))
|
||||
var/obj/docking_port/stationary/S = SSshuttle.getDock("laborcamp_home")
|
||||
if(S && S.get_docked())
|
||||
if(release_door && release_door.density)
|
||||
release_door.open()
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Prisoners can only be released while docked with the station.</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Prisoners are only allowed to be released while alone.</span>")
|
||||
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
|
||||
/**********************Prisoner Collection Unit**************************/
|
||||
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/laborstacker
|
||||
var/points = 0 //The unclaimed value of ore stacked. Value for each ore loosely relative to its rarity.
|
||||
var/list/ore_values = list(("glass" = 1), ("metal" = 2), ("solid plasma" = 20), ("plasteel" = 23), ("reinforced glass" = 4), ("gold" = 20), ("silver" = 20), ("uranium" = 20), ("diamond" = 25), ("bananium" = 50), ("tranquillite" = 50))
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/laborstacker/proc/get_ore_values()
|
||||
var/dat = "<table border='0' width='200'>"
|
||||
for(var/ore in ore_values)
|
||||
var/value = ore_values[ore]
|
||||
dat += "<tr><td>[capitalize(ore)]</td><td>[value]</td></tr>"
|
||||
dat += "</table>"
|
||||
return dat
|
||||
var/points = 0 //The unclaimed value of ore stacked.
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/laborstacker/process_sheet(obj/item/stack/sheet/inp)
|
||||
if(istype(inp))
|
||||
var/n = inp.name
|
||||
var/a = inp.amount
|
||||
if(n in ore_values)
|
||||
points += ore_values[n] * a
|
||||
points += inp.point_value * inp.amount
|
||||
..()
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/laborstacker/attackby(obj/item/I, mob/living/user)
|
||||
if(istype(I, /obj/item/stack/sheet) && user.canUnEquip(I))
|
||||
var/obj/item/stack/sheet/inp = I
|
||||
points += inp.point_value * inp.amount
|
||||
return ..()
|
||||
|
||||
/**********************Point Lookup Console**************************/
|
||||
/obj/machinery/mineral/labor_points_checker
|
||||
@@ -159,13 +161,15 @@
|
||||
desc = "A console used by prisoners to check the progress on their quotas. Simply swipe a prisoner ID."
|
||||
icon = 'icons/obj/machines/mining_machines.dmi'
|
||||
icon_state = "console"
|
||||
density = 0
|
||||
anchored = 1
|
||||
density = FALSE
|
||||
|
||||
/obj/machinery/mineral/labor_points_checker/attack_hand(mob/user)
|
||||
user.examine(src)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
user.examinate(src)
|
||||
|
||||
/obj/machinery/mineral/labor_points_checker/attackby(obj/item/I as obj, mob/user as mob, params)
|
||||
/obj/machinery/mineral/labor_points_checker/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/card/id))
|
||||
if(istype(I, /obj/item/card/id/prisoner))
|
||||
var/obj/item/card/id/prisoner/prisoner_id = I
|
||||
@@ -175,5 +179,5 @@
|
||||
to_chat(user, "<span class='notice'>Collect points by bringing smelted minerals to the Labor Shuttle stacking machine. Reach your quota to earn your release.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Error: Invalid ID</span>")
|
||||
return
|
||||
..()
|
||||
else
|
||||
return ..()
|
||||
@@ -82,6 +82,7 @@
|
||||
/obj/item/flashlight/lantern
|
||||
name = "lantern"
|
||||
icon_state = "lantern"
|
||||
item_state = "lantern"
|
||||
desc = "A mining lantern."
|
||||
brightness_on = 6 // luminosity when on
|
||||
|
||||
|
||||
@@ -402,9 +402,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
to_chat(usr, "Not when you're not dead!")
|
||||
return
|
||||
|
||||
var/area/A = input("Area to jump to", "BOOYEA") as null|anything in ghostteleportlocs
|
||||
var/area/thearea = ghostteleportlocs[A]
|
||||
var/datum/async_input/A = input_autocomplete_async(usr, "Area to jump to: ", ghostteleportlocs)
|
||||
A.on_close(CALLBACK(src, .proc/teleport))
|
||||
|
||||
/mob/dead/observer/proc/teleport(area/thearea)
|
||||
if(!thearea)
|
||||
return
|
||||
|
||||
@@ -425,9 +426,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
set desc = "Follow and orbit a mob."
|
||||
|
||||
var/list/mobs = getpois(skip_mindless=1)
|
||||
var/input = input("Please, select a mob!", "Haunt", null, null) as null|anything in mobs
|
||||
var/mob/target = mobs[input]
|
||||
ManualFollow(target)
|
||||
var/datum/async_input/A = input_autocomplete_async(usr, "Please, select a mob: ", mobs)
|
||||
A.on_close(CALLBACK(src, .proc/ManualFollow))
|
||||
|
||||
// This is the ghost's follow verb with an argument
|
||||
/mob/dead/observer/proc/ManualFollow(var/atom/movable/target)
|
||||
@@ -499,25 +499,21 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
set name = "Jump to Mob"
|
||||
set desc = "Teleport to a mob"
|
||||
|
||||
if(isobserver(usr)) //Make sure they're an observer!
|
||||
var/list/dest = list() //List of possible destinations (mobs)
|
||||
var/target = null //Chosen target.
|
||||
if(isobserver(usr)) //Make sure they're an observer!
|
||||
var/list/dest = getpois(mobs_only=1) //Fill list, prompt user with list
|
||||
var/datum/async_input/A = input_autocomplete_async(usr, "Enter a mob name: ", dest)
|
||||
A.on_close(CALLBACK(src, .proc/jump_to_mob))
|
||||
|
||||
dest += getpois(mobs_only=1) //Fill list, prompt user with list
|
||||
target = input("Please, select a mob!", "Jump to Mob", null, null) as null|anything in dest
|
||||
|
||||
if(!target) //Make sure we actually have a target
|
||||
return
|
||||
else
|
||||
var/mob/M = dest[target] //Destination mob
|
||||
var/mob/A = src //Source mob
|
||||
var/turf/T = get_turf(M) //Turf of the destination mob
|
||||
|
||||
if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination.
|
||||
A.forceMove(T)
|
||||
else
|
||||
to_chat(A, "This mob is not located in the game world.")
|
||||
/mob/dead/observer/proc/jump_to_mob(mob/M)
|
||||
if(!M)
|
||||
return
|
||||
var/mob/A = src //Source mob
|
||||
var/turf/T = get_turf(M) //Turf of the destination mob
|
||||
|
||||
if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination.
|
||||
A.forceMove(T)
|
||||
return
|
||||
to_chat(A, "This mob is not located in the game world.")
|
||||
|
||||
/* Now a spell. See spells.dm
|
||||
/mob/dead/observer/verb/boo()
|
||||
|
||||
@@ -15,6 +15,7 @@ GLOBAL_LIST_INIT(boo_phrases, list(
|
||||
|
||||
ghost = TRUE
|
||||
|
||||
action_icon_state = "boo"
|
||||
school = "transmutation"
|
||||
charge_max = 600
|
||||
starts_charged = FALSE
|
||||
|
||||
@@ -216,56 +216,7 @@
|
||||
add_attack_logs(M, src, "Shaked", ATKLOG_ALL)
|
||||
if(health >= HEALTH_THRESHOLD_CRIT)
|
||||
if(src == M && ishuman(src))
|
||||
var/mob/living/carbon/human/H = src
|
||||
visible_message( \
|
||||
text("<span class='notice'>[src] examines [].</span>",gender==MALE?"himself":"herself"), \
|
||||
"<span class='notice'>You check yourself for injuries.</span>" \
|
||||
)
|
||||
|
||||
var/list/missing = list("head", "chest", "groin", "l_arm", "r_arm", "l_hand", "r_hand", "l_leg", "r_leg", "l_foot", "r_foot")
|
||||
for(var/X in H.bodyparts)
|
||||
var/obj/item/organ/external/LB = X
|
||||
missing -= LB.limb_name
|
||||
var/status = ""
|
||||
var/brutedamage = LB.brute_dam
|
||||
var/burndamage = LB.burn_dam
|
||||
|
||||
if(brutedamage > 0)
|
||||
status = "bruised"
|
||||
if(brutedamage > 20)
|
||||
status = "battered"
|
||||
if(brutedamage > 40)
|
||||
status = "mangled"
|
||||
if(brutedamage > 0 && burndamage > 0)
|
||||
status += " and "
|
||||
if(burndamage > 40)
|
||||
status += "peeling away"
|
||||
|
||||
else if(burndamage > 10)
|
||||
status += "blistered"
|
||||
else if(burndamage > 0)
|
||||
status += "numb"
|
||||
if(LB.status & ORGAN_MUTATED)
|
||||
status = "weirdly shapen."
|
||||
if(status == "")
|
||||
status = "OK"
|
||||
to_chat(src, "\t <span class='[status == "OK" ? "notice" : "warning"]'>Your [LB.name] is [status].</span>")
|
||||
|
||||
for(var/obj/item/I in LB.embedded_objects)
|
||||
to_chat(src, "\t <a href='byond://?src=[UID()];embedded_object=[I.UID()];embedded_limb=[LB.UID()]' class='warning'>There is \a [I] embedded in your [LB.name]!</a>")
|
||||
|
||||
for(var/t in missing)
|
||||
to_chat(src, "<span class='boldannounce'>Your [parse_zone(t)] is missing!</span>")
|
||||
|
||||
if(H.bleed_rate)
|
||||
to_chat(src, "<span class='danger'>You are bleeding!</span>")
|
||||
if(staminaloss)
|
||||
if(staminaloss > 30)
|
||||
to_chat(src, "<span class='info'>You're completely exhausted.</span>")
|
||||
else
|
||||
to_chat(src, "<span class='info'>You feel fatigued.</span>")
|
||||
if((SKELETON in H.mutations) && (!H.w_uniform) && (!H.wear_suit))
|
||||
H.play_xylophone()
|
||||
check_self_for_injuries()
|
||||
else
|
||||
if(player_logged)
|
||||
M.visible_message("<span class='notice'>[M] shakes [src], but [p_they()] [p_do()] not respond. Probably suffering from SSD.", \
|
||||
@@ -308,6 +259,58 @@
|
||||
else if(H.w_uniform)
|
||||
H.w_uniform.add_fingerprint(M)
|
||||
|
||||
/mob/living/carbon/proc/check_self_for_injuries()
|
||||
var/mob/living/carbon/human/H = src
|
||||
visible_message( \
|
||||
text("<span class='notice'>[src] examines [].</span>",gender==MALE?"himself":"herself"), \
|
||||
"<span class='notice'>You check yourself for injuries.</span>" \
|
||||
)
|
||||
|
||||
var/list/missing = list("head", "chest", "groin", "l_arm", "r_arm", "l_hand", "r_hand", "l_leg", "r_leg", "l_foot", "r_foot")
|
||||
for(var/X in H.bodyparts)
|
||||
var/obj/item/organ/external/LB = X
|
||||
missing -= LB.limb_name
|
||||
var/status = ""
|
||||
var/brutedamage = LB.brute_dam
|
||||
var/burndamage = LB.burn_dam
|
||||
|
||||
if(brutedamage > 0)
|
||||
status = "bruised"
|
||||
if(brutedamage > 20)
|
||||
status = "battered"
|
||||
if(brutedamage > 40)
|
||||
status = "mangled"
|
||||
if(brutedamage > 0 && burndamage > 0)
|
||||
status += " and "
|
||||
if(burndamage > 40)
|
||||
status += "peeling away"
|
||||
|
||||
else if(burndamage > 10)
|
||||
status += "blistered"
|
||||
else if(burndamage > 0)
|
||||
status += "numb"
|
||||
if(LB.status & ORGAN_MUTATED)
|
||||
status = "weirdly shapen."
|
||||
if(status == "")
|
||||
status = "OK"
|
||||
to_chat(src, "\t <span class='[status == "OK" ? "notice" : "warning"]'>Your [LB.name] is [status].</span>")
|
||||
|
||||
for(var/obj/item/I in LB.embedded_objects)
|
||||
to_chat(src, "\t <a href='byond://?src=[UID()];embedded_object=[I.UID()];embedded_limb=[LB.UID()]' class='warning'>There is \a [I] embedded in your [LB.name]!</a>")
|
||||
|
||||
for(var/t in missing)
|
||||
to_chat(src, "<span class='boldannounce'>Your [parse_zone(t)] is missing!</span>")
|
||||
|
||||
if(H.bleed_rate)
|
||||
to_chat(src, "<span class='danger'>You are bleeding!</span>")
|
||||
if(staminaloss)
|
||||
if(staminaloss > 30)
|
||||
to_chat(src, "<span class='info'>You're completely exhausted.</span>")
|
||||
else
|
||||
to_chat(src, "<span class='info'>You feel fatigued.</span>")
|
||||
if((SKELETON in H.mutations) && (!H.w_uniform) && (!H.wear_suit))
|
||||
H.play_xylophone()
|
||||
|
||||
/mob/living/carbon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
|
||||
. = ..()
|
||||
var/damage = intensity - check_eye_prot()
|
||||
|
||||
@@ -106,6 +106,12 @@
|
||||
else //Everyone else fails, skip the emote attempt
|
||||
return
|
||||
|
||||
if("warble", "warbles")
|
||||
if(isskrell(src)) //Only Skrell can warble.
|
||||
on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm'
|
||||
else //Everyone else fails, skip the emote attempt
|
||||
return
|
||||
|
||||
if("scream", "screams")
|
||||
on_CD = handle_emote_CD(50) //longer cooldown
|
||||
if("fart", "farts", "flip", "flips", "snap", "snaps")
|
||||
@@ -221,6 +227,13 @@
|
||||
playsound(loc, 'sound/effects/voxrustle.ogg', 50, 0) //Credit to sound-ideas (freesfx.co.uk) for the sound.
|
||||
m_type = 2
|
||||
|
||||
if("warble", "warbles")
|
||||
var/M = handle_emote_param(param)
|
||||
|
||||
message = "<B>[src]</B> warbles[M ? " at [M]" : ""]."
|
||||
playsound(loc, 'sound/effects/warble.ogg', 50, 0) // Copyright CC BY 3.0 alienistcog (freesound.org) for the sound.
|
||||
m_type = 2
|
||||
|
||||
if("yes")
|
||||
var/M = handle_emote_param(param)
|
||||
|
||||
@@ -904,6 +917,8 @@
|
||||
emotelist += "\nVox specific emotes :- quill(s)"
|
||||
if("Diona")
|
||||
emotelist += "\nDiona specific emotes :- creak(s)"
|
||||
if("Skrell")
|
||||
emotelist += "\nSkrell specific emotes :- warble(s)"
|
||||
|
||||
if(ismachine(src))
|
||||
emotelist += "\nMachine specific emotes :- beep(s)-(none)/mob, buzz(es)-none/mob, no-(none)/mob, ping(s)-(none)/mob, yes-(none)/mob, buzz2-(none)/mob"
|
||||
|
||||
@@ -1480,19 +1480,22 @@
|
||||
|
||||
if(usr != src)
|
||||
return 0 //something is terribly wrong
|
||||
|
||||
if(incapacitated())
|
||||
to_chat(src, "<span class='warning'>You can't write on the floor in your current state!</span>")
|
||||
return
|
||||
if(!bloody_hands)
|
||||
verbs -= /mob/living/carbon/human/proc/bloody_doodle
|
||||
|
||||
if(src.gloves)
|
||||
to_chat(src, "<span class='warning'>Your [src.gloves] are getting in the way.</span>")
|
||||
if(gloves)
|
||||
to_chat(src, "<span class='warning'>[gloves] are preventing you from writing anything down!</span>")
|
||||
return
|
||||
|
||||
var/turf/simulated/T = src.loc
|
||||
var/turf/simulated/T = loc
|
||||
if(!istype(T)) //to prevent doodling out of mechs and lockers
|
||||
to_chat(src, "<span class='warning'>You cannot reach the floor.</span>")
|
||||
return
|
||||
|
||||
var/turf/origin = T
|
||||
var/direction = input(src,"Which way?","Tile selection") as anything in list("Here","North","South","East","West")
|
||||
if(direction != "Here")
|
||||
T = get_step(T,text2dir(direction))
|
||||
@@ -1510,7 +1513,9 @@
|
||||
var/max_length = bloody_hands * 30 //tweeter style
|
||||
|
||||
var/message = stripped_input(src,"Write a message. It cannot be longer than [max_length] characters.","Blood writing", "")
|
||||
|
||||
if(origin != loc)
|
||||
to_chat(src, "<span class='notice'>Stay still while writing!</span>")
|
||||
return
|
||||
if(message)
|
||||
var/used_blood_amount = round(length(message) / 30, 1)
|
||||
bloody_hands = max(0, bloody_hands - used_blood_amount) //use up some blood
|
||||
@@ -1518,7 +1523,8 @@
|
||||
if(length(message) > max_length)
|
||||
message += "-"
|
||||
to_chat(src, "<span class='warning'>You ran out of blood to write with!</span>")
|
||||
|
||||
else
|
||||
to_chat(src, "<span class='notice'>You daub '[message]' on [T] in shiny red lettering.</span>")
|
||||
var/obj/effect/decal/cleanable/blood/writing/W = new(T)
|
||||
W.message = message
|
||||
W.add_fingerprint(src)
|
||||
@@ -1935,7 +1941,6 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
|
||||
. += "---"
|
||||
.["Set Species"] = "?_src_=vars;setspecies=[UID()]"
|
||||
.["Make AI"] = "?_src_=vars;makeai=[UID()]"
|
||||
.["Make Mask of Nar'sie"] = "?_src_=vars;makemask=[UID()]"
|
||||
.["Make cyborg"] = "?_src_=vars;makerobot=[UID()]"
|
||||
.["Make monkey"] = "?_src_=vars;makemonkey=[UID()]"
|
||||
.["Make alien"] = "?_src_=vars;makealien=[UID()]"
|
||||
|
||||
@@ -341,9 +341,6 @@
|
||||
if(SKELETON in target.mutations)
|
||||
to_chat(user, "<span class='warning'>There is no blood in a skeleton!</span>")
|
||||
return
|
||||
if(issmall(target) && !target.ckey) //Monkeyized humans are okay, humanized monkeys are okay, NPC monkeys are not.
|
||||
to_chat(user, "<span class='warning'>Blood from a monkey is useless!</span>")
|
||||
return
|
||||
//we're good to suck the blood, blaah
|
||||
user.mind.vampire.handle_bloodsucking(target)
|
||||
add_attack_logs(user, target, "vampirebit")
|
||||
@@ -603,20 +600,37 @@
|
||||
H.healthdoll.cached_healthdoll_overlays = new_overlays
|
||||
|
||||
/datum/species/proc/handle_hud_icons_nutrition(mob/living/carbon/human/H)
|
||||
switch(H.nutrition)
|
||||
if(NUTRITION_LEVEL_FULL to INFINITY)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/fat)
|
||||
if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/full)
|
||||
if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/well_fed)
|
||||
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/fed)
|
||||
if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/hungry)
|
||||
else
|
||||
H.throw_alert("nutrition", /obj/screen/alert/starving)
|
||||
return 1
|
||||
if(H.mind && H.mind.vampire && (H.mind in SSticker.mode.vampires)) //Vampires
|
||||
switch(H.nutrition)
|
||||
if(NUTRITION_LEVEL_FULL to INFINITY)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/fat/vampire)
|
||||
if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/full/vampire)
|
||||
if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/well_fed/vampire)
|
||||
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/fed/vampire)
|
||||
if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/hungry/vampire)
|
||||
else
|
||||
H.throw_alert("nutrition", /obj/screen/alert/starving/vampire)
|
||||
return 1
|
||||
|
||||
else ///Any other non-vampires
|
||||
switch(H.nutrition)
|
||||
if(NUTRITION_LEVEL_FULL to INFINITY)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/fat)
|
||||
if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/full)
|
||||
if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/well_fed)
|
||||
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/fed)
|
||||
if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
|
||||
H.throw_alert("nutrition", /obj/screen/alert/hungry)
|
||||
else
|
||||
H.throw_alert("nutrition", /obj/screen/alert/starving)
|
||||
return 1
|
||||
|
||||
/*
|
||||
Returns the path corresponding to the corresponding organ
|
||||
@@ -675,7 +689,7 @@ It'll return null if the organ doesn't correspond, so include null checks when u
|
||||
H.see_invisible = G.invis_override
|
||||
else
|
||||
H.see_invisible = min(G.invis_view, H.see_invisible)
|
||||
|
||||
|
||||
if(!isnull(G.lighting_alpha))
|
||||
H.lighting_alpha = min(G.lighting_alpha, H.lighting_alpha)
|
||||
|
||||
|
||||
@@ -103,6 +103,9 @@ var/list/robot_verbs_default = list(
|
||||
var/datum/action/item_action/toggle_research_scanner/scanner = null
|
||||
var/list/module_actions = list()
|
||||
|
||||
/mob/living/silicon/robot/get_cell()
|
||||
return cell
|
||||
|
||||
/mob/living/silicon/robot/New(loc,var/syndie = 0,var/unfinished = 0, var/alien = 0)
|
||||
spark_system = new /datum/effect_system/spark_spread()
|
||||
spark_system.set_up(5, 0, src)
|
||||
|
||||
@@ -50,6 +50,9 @@
|
||||
var/currentBloodColor = "#A10808"
|
||||
var/currentDNA = null
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/get_cell()
|
||||
return cell
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/New()
|
||||
..()
|
||||
wires = new /datum/wires/mulebot(src)
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
status_flags = 0
|
||||
const_type = "juggernaut"
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall)
|
||||
construct_spells = list(/obj/effect/proc_holder/spell/targeted/night_vision, /obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall)
|
||||
force_threshold = 11
|
||||
playstyle_string = "<b>You are a Juggernaut. Though slow, your shell can withstand extreme punishment, \
|
||||
create shield walls, rip apart enemies and walls alike, and even deflect energy weapons.</b>"
|
||||
@@ -171,7 +171,7 @@
|
||||
see_in_dark = 8
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
const_type = "wraith"
|
||||
construct_spells = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift)
|
||||
construct_spells = list(/obj/effect/proc_holder/spell/targeted/night_vision, /obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift)
|
||||
retreat_distance = 2 //AI wraiths will move in and out of combat
|
||||
playstyle_string = "<b>You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.</b>"
|
||||
|
||||
@@ -202,7 +202,8 @@
|
||||
minimum_distance = 10 //AI artificers will flee like fuck
|
||||
attack_sound = 'sound/weapons/punch2.ogg'
|
||||
const_type = "builder"
|
||||
construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser,
|
||||
construct_spells = list(/obj/effect/proc_holder/spell/targeted/night_vision,
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser,
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/wall,
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/floor,
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/pylon,
|
||||
@@ -311,7 +312,8 @@
|
||||
see_in_dark = 8
|
||||
attack_sound = 'sound/weapons/tap.ogg'
|
||||
const_type = "harvester"
|
||||
construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/wall,
|
||||
construct_spells = list(/obj/effect/proc_holder/spell/targeted/night_vision,
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/wall,
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/floor,
|
||||
/obj/effect/proc_holder/spell/targeted/smoke/disable)
|
||||
retreat_distance = 2 //AI harvesters will move in and out of combat, like wraiths, but shittier
|
||||
|
||||
@@ -189,35 +189,6 @@
|
||||
L.EyeBlind(4)
|
||||
return
|
||||
|
||||
//Toggle Night Vision
|
||||
/obj/effect/proc_holder/spell/targeted/night_vision
|
||||
name = "Toggle Nightvision"
|
||||
desc = "Toggle your nightvision mode."
|
||||
|
||||
charge_max = 10
|
||||
clothes_req = 0
|
||||
|
||||
message = "<span class='notice'>You toggle your night vision!</span>"
|
||||
range = -1
|
||||
include_user = 1
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/night_vision/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/target in targets)
|
||||
switch(target.lighting_alpha)
|
||||
if (LIGHTING_PLANE_ALPHA_VISIBLE)
|
||||
target.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
|
||||
name = "Toggle Nightvision \[More]"
|
||||
if (LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE)
|
||||
target.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
name = "Toggle Nightvision \[Full]"
|
||||
if (LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE)
|
||||
target.lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
|
||||
name = "Toggle Nightvision \[OFF]"
|
||||
else
|
||||
target.lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
|
||||
name = "Toggle Nightvision \[ON]"
|
||||
target.update_sight()
|
||||
|
||||
/mob/living/simple_animal/hostile/statue/sentience_act()
|
||||
faction -= "neutral"
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ var/global/list/ts_spiderling_list = list()
|
||||
var/obj/machinery/door/airlock/A = target
|
||||
if(A.density)
|
||||
try_open_airlock(A)
|
||||
else if(isliving(target))
|
||||
else if(isliving(target) && (!client || a_intent == INTENT_HARM))
|
||||
var/mob/living/G = target
|
||||
if(issilicon(G))
|
||||
G.attack_animal(src)
|
||||
|
||||
@@ -641,5 +641,26 @@ var/list/intents = list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM)
|
||||
// Cast to 1/0
|
||||
return !!(client.prefs.toggles & toggleflag)
|
||||
|
||||
// Used to make sure that a player has a valid job preference setup, used to knock players out of eligibility for anything if their prefs don't make sense.
|
||||
// A "valid job preference setup" in this situation means at least having one job set to low, or not having "return to lobby" enabled
|
||||
// Prevents "antag rolling" by setting antag prefs on, all jobs to never, and "return to lobby if preferences not availible"
|
||||
// Doing so would previously allow you to roll for antag, then send you back to lobby if you didn't get an antag role
|
||||
// This also does some admin notification and logging as well
|
||||
/mob/proc/has_valid_preferences()
|
||||
if(!client)
|
||||
return FALSE //Not sure how this would get run without the mob having a client, but let's just be safe.
|
||||
if(client.prefs.alternate_option != RETURN_TO_LOBBY)
|
||||
return TRUE
|
||||
// If they have antags enabled, they're potentially doing this on purpose instead of by accident. Notify admins if so.
|
||||
var/has_antags = FALSE
|
||||
if(client.prefs.be_special.len > 0)
|
||||
has_antags = TRUE
|
||||
if(!client.prefs.check_any_job())
|
||||
to_chat(src, "<span class='danger'>You have no jobs enabled, along with return to lobby if job is unavailable. This makes you ineligible for any round start role, please update your job preferences.</span>")
|
||||
if(has_antags)
|
||||
log_admin("[src.ckey] just got booted back to lobby with no jobs, but antags enabled.")
|
||||
message_admins("[src.ckey] just got booted back to lobby with no jobs enabled, but antag rolling enabled. Likely antag rolling abuse.")
|
||||
return FALSE //This is the only case someone should actually be completely blocked from antag rolling as well
|
||||
return TRUE
|
||||
|
||||
#define isterrorspider(A) (istype((A), /mob/living/simple_animal/hostile/poison/terror_spider))
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
return battery_module.battery.give(amount)
|
||||
return 0
|
||||
|
||||
/obj/item/modular_computer/get_cell()
|
||||
var/obj/item/computer_hardware/battery/battery_module = all_components[MC_CELL]
|
||||
if(battery_module && battery_module.battery)
|
||||
return battery_module.battery
|
||||
|
||||
// Used in following function to reduce copypaste
|
||||
/obj/item/modular_computer/proc/power_failure()
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
var/obj/item/stock_parts/cell/battery = null
|
||||
device_type = MC_CELL
|
||||
|
||||
/obj/item/computer_hardware/battery/get_cell()
|
||||
return battery
|
||||
|
||||
/obj/item/computer_hardware/battery/New(loc, battery_type = null)
|
||||
if(battery_type)
|
||||
battery = new battery_type(src)
|
||||
|
||||
@@ -27,6 +27,9 @@ Contents:
|
||||
var/obj/item/clothing/mask/gas/space_ninja/suitMask
|
||||
var/mob/living/carbon/human/suitOccupant
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/get_cell()
|
||||
return suitCell
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/toggle_suit_lock(mob/living/carbon/human/user)
|
||||
if(!suitActive)
|
||||
if(!istype(user.wear_suit, /obj/item/clothing/suit/space/space_ninja))
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/attackby(obj/item/I, mob/U, params)
|
||||
if(U==suitOccupant)//Safety, in case you try doing this without wearing the suit/being the person with the suit.
|
||||
if(istype(I, /obj/item/stock_parts/cell))
|
||||
@@ -21,4 +19,4 @@
|
||||
else
|
||||
to_chat(U, "<span class='danger'>Procedure interrupted. Protocol terminated.</span>")
|
||||
return
|
||||
..()
|
||||
..()
|
||||
|
||||
@@ -75,16 +75,19 @@
|
||||
assets.send(user)
|
||||
|
||||
var/data
|
||||
if((!user.say_understands(null, GLOB.all_languages["Galactic Common"]) && !forceshow) || forcestars) //assuming all paper is written in common is better than hardcoded type checks
|
||||
data = "<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)][stamps]</BODY></HTML>"
|
||||
if(view)
|
||||
usr << browse(data, "window=[name];size=[paper_width]x[paper_height]")
|
||||
onclose(usr, "[name]")
|
||||
var/stars = (!user.say_understands(null, GLOB.all_languages["Galactic Common"]) && !forceshow) || forcestars
|
||||
if(stars) //assuming all paper is written in common is better than hardcoded type checks
|
||||
data = "[stars(info)][stamps]"
|
||||
else
|
||||
data = "<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[infolinks ? info_links : info][stamps]</BODY></HTML>"
|
||||
if(view)
|
||||
usr << browse(data, "window=[name];size=[paper_width]x[paper_height]")
|
||||
onclose(usr, "[name]")
|
||||
data = "<div id='markdown'>[infolinks ? info_links : info]</div>[stamps]"
|
||||
if(view)
|
||||
var/datum/browser/popup = new(user, name, , paper_width, paper_height)
|
||||
popup.stylesheets = list()
|
||||
popup.set_content(data)
|
||||
if(!stars)
|
||||
popup.add_script("marked.js", 'html/browser/marked.js')
|
||||
popup.add_head_content("<title>[name]</title>")
|
||||
popup.open()
|
||||
return data
|
||||
|
||||
/obj/item/paper/verb/rename()
|
||||
|
||||
@@ -169,10 +169,18 @@
|
||||
if(useTC != 2) // Does our recipient have a broadcaster on their level?
|
||||
to_chat(U, "ERROR: Cannot reach recipient.")
|
||||
return
|
||||
|
||||
useMS.send_pda_message("[P.owner]","[pda.owner]","[t]")
|
||||
tnote.Add(list(list("sent" = 1, "owner" = "[P.owner]", "job" = "[P.ownjob]", "message" = "[t]", "target" = "\ref[P]")))
|
||||
PM.tnote.Add(list(list("sent" = 0, "owner" = "[pda.owner]", "job" = "[pda.ownjob]", "message" = "[t]", "target" = "\ref[pda]")))
|
||||
pda.investigate_log("<span class='game say'>PDA Message - <span class='name'>[U.key] - [pda.owner]</span> -> <span class='name'>[P.owner]</span>: <span class='message'>[t]</span></span>", "pda")
|
||||
|
||||
// Show it to ghosts
|
||||
for(var/mob/M in GLOB.dead_mob_list)
|
||||
if(isobserver(M) && M.client && (M.client.prefs.toggles & CHAT_GHOSTPDA))
|
||||
var/ghost_message = "<span class='name'>[pda.owner]</span> ([ghost_follow_link(pda, ghost=M)]) <span class='game say'>PDA Message</span> --> <span class='name'>[P.owner]</span> ([ghost_follow_link(P, ghost=M)]): <span class='message'>[t]</span>"
|
||||
to_chat(M, "[ghost_message]")
|
||||
|
||||
if(!conversations.Find("\ref[P]"))
|
||||
conversations.Add("\ref[P]")
|
||||
if(!PM.conversations.Find("\ref[pda]"))
|
||||
|
||||
@@ -135,6 +135,9 @@
|
||||
usesound = 'sound/items/deconstruct.ogg'
|
||||
toolspeed = 1
|
||||
|
||||
/obj/machinery/power/apc/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/machinery/power/apc/connect_to_network()
|
||||
//Override because the APC does not directly connect to the network; it goes through a terminal.
|
||||
//The terminal is what the power computer looks for anyway.
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
var/ratingdesc = TRUE
|
||||
var/grown_battery = FALSE // If it's a grown that acts as a battery, add a wire overlay to it.
|
||||
|
||||
/obj/item/stock_parts/cell/get_cell()
|
||||
return src
|
||||
|
||||
/obj/item/stock_parts/cell/New()
|
||||
..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
power_supply.use(round(power_supply.charge / severity))
|
||||
update_icon()
|
||||
|
||||
/obj/item/gun/energy/get_cell()
|
||||
return power_supply
|
||||
|
||||
/obj/item/gun/energy/New()
|
||||
..()
|
||||
if(cell_type)
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
var/obj/item/stock_parts/cell/cell = null // Used for firing superheated rods.
|
||||
var/list/possible_tensions = list(XBOW_TENSION_20, XBOW_TENSION_40, XBOW_TENSION_60, XBOW_TENSION_80, XBOW_TENSION_FULL)
|
||||
|
||||
/obj/item/gun/throw/crossbow/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/item/gun/throw/crossbow/emp_act(severity)
|
||||
if(cell && severity)
|
||||
emp_act(severity)
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
var/hack_message = "You disable the safety safeguards, enabling the \"Mad Scientist\" mode."
|
||||
var/unhack_message = "You re-enable the safety safeguards, enabling the \"NT Standard\" mode."
|
||||
|
||||
/obj/machinery/chem_dispenser/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/machinery/chem_dispenser/New()
|
||||
..()
|
||||
component_parts = list()
|
||||
|
||||
@@ -815,7 +815,7 @@
|
||||
var/update_flags = STATUS_UPDATE_NONE
|
||||
if(prob(5))
|
||||
if(prob(10))
|
||||
update_flags |= M.adjustToxLoss(rand(2.4), FALSE)
|
||||
update_flags |= M.adjustToxLoss(rand(2,4), FALSE)
|
||||
if(prob(7))
|
||||
to_chat(M, "<span class='warning'>A horrible migraine overpowers you.</span>")
|
||||
update_flags |= M.Stun(rand(2,5), FALSE)
|
||||
|
||||
@@ -692,11 +692,9 @@
|
||||
// pipe is deleted
|
||||
// ensure if holder is present, it is expelled
|
||||
/obj/structure/disposalpipe/Destroy()
|
||||
var/obj/structure/disposalholder/H = locate() in src
|
||||
if(H)
|
||||
// holder was present
|
||||
for(var/obj/structure/disposalholder/H in contents)
|
||||
H.active = 0
|
||||
var/turf/T = src.loc
|
||||
var/turf/T = loc
|
||||
if(T.density)
|
||||
// deleting pipe is inside a dense turf (wall)
|
||||
// this is unlikely, but just dump out everything into the turf in case
|
||||
@@ -709,8 +707,7 @@
|
||||
return
|
||||
|
||||
// otherwise, do normal expel from turf
|
||||
if(H)
|
||||
expel(H, T, 0)
|
||||
expel(H, T, 0)
|
||||
return ..()
|
||||
|
||||
/obj/structure/disposalpipe/singularity_pull(S, current_size)
|
||||
|
||||
@@ -125,6 +125,7 @@
|
||||
name = "Portable Seed Extractor"
|
||||
desc = "For the enterprising botanist on the go. Less efficient than the stationary model, it creates one seed per plant."
|
||||
build_type = PROTOLATHE
|
||||
id = "portaseeder"
|
||||
req_tech = list("biotech" = 3, "engineering" = 2)
|
||||
materials = list(MAT_METAL = 1000, MAT_GLASS = 400)
|
||||
build_path = /obj/item/storage/bag/plants/portaseeder
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
materials = list(MAT_METAL = 1000, MAT_GLASS = 500)
|
||||
construction_time = 75
|
||||
build_path = /obj/item/mmi
|
||||
category = list("Misc","Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/robotic_brain
|
||||
name = "Robotic Brain"
|
||||
@@ -112,7 +112,7 @@
|
||||
materials = list(MAT_METAL = 1700, MAT_GLASS = 1350, MAT_GOLD = 500) //Gold, because SWAG.
|
||||
construction_time = 75
|
||||
build_path = /obj/item/mmi/robotic_brain
|
||||
category = list("Misc","Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/mmi_radio_upgrade
|
||||
name = "Man-Machine Interface Radio Upgrade"
|
||||
@@ -123,7 +123,7 @@
|
||||
materials = list(MAT_METAL = 200)
|
||||
construction_time = 50
|
||||
build_path = /obj/item/mmi_radio_upgrade
|
||||
category = list("Misc","Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/nanopaste
|
||||
name = "Nanopaste"
|
||||
@@ -288,7 +288,7 @@
|
||||
construction_time = 40
|
||||
materials = list(MAT_METAL = 600, MAT_GLASS = 400)
|
||||
build_path = /obj/item/organ/internal/cyberimp/eyes/shield
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_breather
|
||||
name = "Breathing Tube Implant"
|
||||
@@ -299,7 +299,7 @@
|
||||
construction_time = 35
|
||||
materials = list(MAT_METAL = 600, MAT_GLASS = 250)
|
||||
build_path = /obj/item/organ/internal/cyberimp/mouth/breathing_tube
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_surgical
|
||||
name = "Surgical Arm Implant"
|
||||
@@ -310,7 +310,7 @@
|
||||
materials = list(MAT_METAL = 2500, MAT_GLASS = 1500, MAT_SILVER = 1500)
|
||||
construction_time = 200
|
||||
build_path = /obj/item/organ/internal/cyberimp/arm/surgery
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_toolset
|
||||
name = "Toolset Arm Implant"
|
||||
@@ -321,7 +321,7 @@
|
||||
materials = list(MAT_METAL = 2500, MAT_GLASS = 1500, MAT_SILVER = 1500)
|
||||
construction_time = 200
|
||||
build_path = /obj/item/organ/internal/cyberimp/arm/toolset
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_diagnostic_hud
|
||||
name = "Diagnostic HUD implant"
|
||||
@@ -332,7 +332,7 @@
|
||||
construction_time = 50
|
||||
materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 500, MAT_GOLD = 500)
|
||||
build_path = /obj/item/organ/internal/cyberimp/eyes/hud/diagnostic
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_medical_hud
|
||||
name = "Medical HUD implant"
|
||||
@@ -343,7 +343,7 @@
|
||||
construction_time = 50
|
||||
materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 500, MAT_GOLD = 500)
|
||||
build_path = /obj/item/organ/internal/cyberimp/eyes/hud/medical
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_security_hud
|
||||
name = "Security HUD implant"
|
||||
@@ -354,7 +354,7 @@
|
||||
construction_time = 50
|
||||
materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 750, MAT_GOLD = 750)
|
||||
build_path = /obj/item/organ/internal/cyberimp/eyes/hud/security
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_meson
|
||||
name = "Meson scanner implant"
|
||||
@@ -365,7 +365,7 @@
|
||||
construction_time = 50
|
||||
materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 500, MAT_GOLD = 300)
|
||||
build_path = /obj/item/organ/internal/cyberimp/eyes/meson
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_xray
|
||||
name = "X-Ray implant"
|
||||
@@ -376,7 +376,7 @@
|
||||
construction_time = 60
|
||||
materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 600, MAT_GOLD = 600, MAT_PLASMA = 1000, MAT_URANIUM = 1000, MAT_DIAMOND = 1000, MAT_BLUESPACE = 1000)
|
||||
build_path = /obj/item/organ/internal/cyberimp/eyes/xray
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_thermals
|
||||
name = "Thermals implant"
|
||||
@@ -387,7 +387,7 @@
|
||||
construction_time = 60
|
||||
materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 600, MAT_GOLD = 600, MAT_PLASMA = 1000, MAT_DIAMOND = 2000)
|
||||
build_path = /obj/item/organ/internal/cyberimp/eyes/thermals
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_antidrop
|
||||
name = "Anti-Drop implant"
|
||||
@@ -398,7 +398,7 @@
|
||||
construction_time = 60
|
||||
materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 400, MAT_GOLD = 400)
|
||||
build_path = /obj/item/organ/internal/cyberimp/brain/anti_drop
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_antistun
|
||||
name = "CNS Rebooter implant"
|
||||
@@ -409,7 +409,7 @@
|
||||
construction_time = 60
|
||||
materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 500, MAT_GOLD = 1000)
|
||||
build_path = /obj/item/organ/internal/cyberimp/brain/anti_stun
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_clownvoice
|
||||
name = "Comical implant"
|
||||
@@ -420,7 +420,7 @@
|
||||
construction_time = 60
|
||||
materials = list(MAT_METAL = 200, MAT_GLASS = 200, MAT_BANANIUM = 200)
|
||||
build_path = /obj/item/organ/internal/cyberimp/brain/clown_voice
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_nutriment
|
||||
name = "Nutriment pump implant"
|
||||
@@ -431,7 +431,7 @@
|
||||
construction_time = 40
|
||||
materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_GOLD = 500)
|
||||
build_path = /obj/item/organ/internal/cyberimp/chest/nutriment
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_nutriment_plus
|
||||
name = "Nutriment pump implant PLUS"
|
||||
@@ -442,7 +442,7 @@
|
||||
construction_time = 50
|
||||
materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_GOLD = 500, MAT_URANIUM = 750)
|
||||
build_path = /obj/item/organ/internal/cyberimp/chest/nutriment/plus
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/datum/design/cyberimp_reviver
|
||||
name = "Reviver implant"
|
||||
@@ -453,7 +453,7 @@
|
||||
construction_time = 60
|
||||
materials = list(MAT_METAL = 800, MAT_GLASS = 800, MAT_GOLD = 300, MAT_URANIUM = 500)
|
||||
build_path = /obj/item/organ/internal/cyberimp/chest/reviver
|
||||
category = list("Misc", "Medical")
|
||||
category = list("Medical")
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////////Regular Implants/////////////
|
||||
@@ -508,6 +508,7 @@
|
||||
req_tech = list("biotech" = 4, "materials" = 4)
|
||||
build_type = PROTOLATHE | MECHFAB
|
||||
materials = list(MAT_METAL = 500, MAT_GLASS = 500)
|
||||
construction_time = 60
|
||||
build_path = /obj/item/organ/internal/eyes/cybernetic
|
||||
category = list("Medical")
|
||||
|
||||
@@ -518,6 +519,7 @@
|
||||
req_tech = list("biotech" = 4, "materials" = 4)
|
||||
build_type = PROTOLATHE | MECHFAB
|
||||
materials = list(MAT_METAL = 500, MAT_GLASS = 500)
|
||||
construction_time = 60
|
||||
build_path = /obj/item/organ/internal/liver/cybernetic
|
||||
category = list("Medical")
|
||||
|
||||
@@ -528,6 +530,7 @@
|
||||
req_tech = list("biotech" = 4, "materials" = 4)
|
||||
build_type = PROTOLATHE | MECHFAB
|
||||
materials = list(MAT_METAL = 500, MAT_GLASS = 500)
|
||||
construction_time = 60
|
||||
build_path = /obj/item/organ/internal/kidneys/cybernetic
|
||||
category = list("Medical")
|
||||
|
||||
@@ -538,6 +541,7 @@
|
||||
req_tech = list("biotech" = 4, "materials" = 4)
|
||||
build_type = PROTOLATHE | MECHFAB
|
||||
materials = list(MAT_METAL = 500, MAT_GLASS = 500)
|
||||
construction_time = 60
|
||||
build_path = /obj/item/organ/internal/heart/cybernetic
|
||||
category = list("Medical")
|
||||
|
||||
@@ -548,6 +552,7 @@
|
||||
req_tech = list("biotech" = 5, "materials" = 5, "engineering" = 5)
|
||||
build_type = PROTOLATHE | MECHFAB
|
||||
materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 500)
|
||||
construction_time = 60
|
||||
build_path = /obj/item/organ/internal/heart/cybernetic/upgraded
|
||||
category = list("Medical")
|
||||
|
||||
@@ -558,6 +563,7 @@
|
||||
req_tech = list("biotech" = 4, "materials" = 4)
|
||||
build_type = PROTOLATHE | MECHFAB
|
||||
materials = list(MAT_METAL = 500, MAT_GLASS = 500)
|
||||
construction_time = 60
|
||||
build_path = /obj/item/organ/internal/lungs/cybernetic
|
||||
category = list("Medical")
|
||||
|
||||
@@ -568,5 +574,6 @@
|
||||
req_tech = list("biotech" = 5, "materials" = 5, "engineering" = 5)
|
||||
build_type = PROTOLATHE | MECHFAB
|
||||
materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 500)
|
||||
construction_time = 60
|
||||
build_path = /obj/item/organ/internal/lungs/cybernetic/upgraded
|
||||
category = list("Medical")
|
||||
|
||||
@@ -92,6 +92,8 @@
|
||||
has_paint = 1
|
||||
update_icons()
|
||||
|
||||
/obj/spacepod/get_cell()
|
||||
return battery
|
||||
|
||||
/obj/spacepod/New()
|
||||
. = ..()
|
||||
|
||||
@@ -66,6 +66,7 @@ var/global/list/datum/stack_recipe/bluespace_crystal_recipes = list(new/datum/st
|
||||
attack_verb = list("bluespace polybashed", "bluespace polybattered", "bluespace polybludgeoned", "bluespace polythrashed", "bluespace polysmashed")
|
||||
toolspeed = 1
|
||||
usesound = 'sound/items/deconstruct.ogg'
|
||||
point_value = 30
|
||||
|
||||
/obj/item/stack/sheet/bluespace_crystal/New()
|
||||
..()
|
||||
|
||||
@@ -128,11 +128,13 @@
|
||||
var/teleporting = 0
|
||||
var/chargecost = 1000
|
||||
|
||||
/obj/item/rcs/get_cell()
|
||||
return rcell
|
||||
|
||||
/obj/item/rcs/New()
|
||||
..()
|
||||
rcell = new(src)
|
||||
|
||||
|
||||
/obj/item/rcs/examine(mob/user)
|
||||
..(user)
|
||||
to_chat(user, "There are [round(rcell.charge/chargecost)] charge\s left.")
|
||||
|
||||
@@ -76,6 +76,7 @@ expensive
|
||||
famous
|
||||
fragile
|
||||
frail
|
||||
flaming
|
||||
gifted
|
||||
helpful
|
||||
helpless
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,53 @@
|
||||
var $ = document.querySelector.bind(document);
|
||||
var input;
|
||||
var submitButton;
|
||||
var optionsMap = {};
|
||||
|
||||
function updateTopic() {
|
||||
if (!input || !submitButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
var hrefList = submitButton.getAttribute('href').split(';');
|
||||
// Topic must come last in the submit button for this to work
|
||||
hrefList = hrefList.slice(0, hrefList.length - 1);
|
||||
hrefList.push(optionsMap[input.value] ? 'submit=' + optionsMap[input.value] : '');
|
||||
submitButton.setAttribute('href', hrefList.join(';'));
|
||||
}
|
||||
|
||||
function setElements() {
|
||||
input = $('#input');
|
||||
submitButton = $('#submit-button');
|
||||
var choices = $('#choices');
|
||||
|
||||
if (!input || !submitButton || !choices) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (var i = 0; i < choices.options.length; i++) {
|
||||
var name = choices.options[i].value;
|
||||
var cleaned = decodeURI(name);
|
||||
optionsMap[cleaned] = name;
|
||||
choices.options[i].value = cleaned;
|
||||
}
|
||||
|
||||
input.addEventListener('keyup', function(event) {
|
||||
if (event.key !== 'Enter') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Object.keys(optionsMap).indexOf(input.value) === -1) {
|
||||
// Byond doesn't let you to use enter to select
|
||||
// so we need to prevent unintended submissions
|
||||
return
|
||||
}
|
||||
|
||||
submitButton.click();
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
input.focus();
|
||||
}
|
||||
|
||||
window.onload = setElements;
|
||||
File diff suppressed because one or more lines are too long
@@ -56,6 +56,319 @@
|
||||
-->
|
||||
<div class="commit sansserif">
|
||||
|
||||
<h2 class="date">08 July 2019</h2>
|
||||
<h3 class="author">Arkatos updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Clicking on a health doll icon will now check you for injuries</li>
|
||||
<li class="rscadd">Rechargers now show their contents and charge status on close examine</li>
|
||||
<li class="tweak">Smartfridge will now try to put an item in your hands after vending, if able</li>
|
||||
</ul>
|
||||
<h3 class="author">AzuleUtama updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">The cybernetic implant bundle can no longer be bought by traitors.</li>
|
||||
</ul>
|
||||
<h3 class="author">Citinited updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Alt-clicking the RPD now brings up a radial menu with rotate, flip, and delete modes accessible. The main interface remains unchanged.</li>
|
||||
<li class="bugfix">Writing in blood can't be done while dead or incapacitated any more</li>
|
||||
<li class="bugfix">You can't write stuff in blood at a distance any more</li>
|
||||
</ul>
|
||||
<h3 class="author">Couls updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="imageadd">lantern sprites</li>
|
||||
<li class="bugfix">typo in msg</li>
|
||||
</ul>
|
||||
<h3 class="author">Improvedname updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Explorer suits now properly hide tails</li>
|
||||
</ul>
|
||||
<h3 class="author">JKnutson101 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Fixed Construction Permits deleting themselves prematurely.</li>
|
||||
</ul>
|
||||
<h3 class="author">Kyep updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">fixed a bug with biogenerator.</li>
|
||||
</ul>
|
||||
<h3 class="author">Markolie updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Ghosts can now see all PDA messages when enabled through a preference setting.</li>
|
||||
<li class="rscdel">The Mask of Nar'Sie transformation buttons have been removed, as the mask was removed a long time ago.</li>
|
||||
</ul>
|
||||
<h3 class="author">Shadeykins updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Changed Quarantine, NT Default, Aggressive, and Corporate AI lawsets. balance: Reduced the ability for NT Default AI's to murder people just because.</li>
|
||||
<li class="bugfix">Removed several redundancies in Aggressive lawset.</li>
|
||||
<li class="spellcheck">Fixed a few subject-verb disagreements (is -> are).</li>
|
||||
</ul>
|
||||
<h3 class="author">Tayyyyyyy updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">paper supports markdown as well as pencode</li>
|
||||
<li class="rscadd">Autocomplete for ghost buttons</li>
|
||||
<li class="tweak">PMs window scrollable</li>
|
||||
<li class="bugfix">Fix a bug where a player who reconnects is still shown as disconnected</li>
|
||||
</ul>
|
||||
<h3 class="author">datlo updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Fix an antag rolling exploit.</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">30 June 2019</h2>
|
||||
<h3 class="author">Crazylemon64 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscdel">SDQL2 no longer allows a macro argument</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">28 June 2019</h2>
|
||||
<h3 class="author">AffectedArc07 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">SSticker</li>
|
||||
<li class="tweak">You can no longer force-start a round unless its fully initialised.</li>
|
||||
<li class="tweak">Tweaks some preference orders</li>
|
||||
<li class="tweak">Moved a global define</li>
|
||||
</ul>
|
||||
<h3 class="author">Akatos updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Smartfridges now visually show approximate number of items inside</li>
|
||||
</ul>
|
||||
<h3 class="author">Arkatos updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Ragin' Mages gamemode should now be playable without any major issue</li>
|
||||
<li class="bugfix">Slaughter and Laughter Demons no longer have duplicit objective shown at the Round End</li>
|
||||
<li class="bugfix">Laughter Demon is now properly called Laughter Demon instead of Slaughter Demon in the role polls</li>
|
||||
<li class="spellcheck">Improved wording and fixed mistakes in Wizard and Ragin' Mages gamemodes</li>
|
||||
<li class="tweak">Wizards are now properly polled in the Ragin' Mages gamemode</li>
|
||||
<li class="tweak">You can no longer buy Summon Ghosts spell in the Ragin' Mages gamemode</li>
|
||||
<li class="tweak">You can no longer buy Bind Soul spell in the Ragin' Mages gamemode</li>
|
||||
<li class="tweak">Deck of tarot cards renamed to Guardian Deck in the Wizard spellbook</li>
|
||||
<li class="tweak">Rituals and Challenges categories merged into one in the Wizard spellbook</li>
|
||||
<li class="tweak">Laughter Demon is now slightly weaker compared to the Slaughter Demon</li>
|
||||
<li class="tweak">Bottle of Ooze now creates a magical morph instead of a normal one. Magical morph is capable of casting smoke and forcewall spells.</li>
|
||||
<li class="tweak">Visible ghosts will now get a special description about their visibility</li>
|
||||
<li class="rscdel">Removed Cursed Heart from the Wizard spellbook</li>
|
||||
<li class="rscadd">Changeling verbs replaced with action buttons</li>
|
||||
<li class="tweak">Changeling ability descriptions updated</li>
|
||||
<li class="imageadd">Added custom icons for changeling action buttons</li>
|
||||
<li class="imageadd">Added movement animation for mice, chickens and killer tomatoes</li>
|
||||
<li class="imageadd">Added inhand sprite for eggbox</li>
|
||||
<li class="imageadd">Added inhand sprites for all types of soaps</li>
|
||||
<li class="imageadd">Added inhand sprite for small parcel</li>
|
||||
<li class="imageadd">Added inhand sprite for sechailer</li>
|
||||
<li class="imageadd">Added inhand sprite for bag of holding</li>
|
||||
<li class="tweak">Added new system for outputting contents of smartfridges</li>
|
||||
<li class="tweak">Blob split consciousness ability now requires you to directly target a node you want to turn into another sentient overmind instead of selecting a nearest one</li>
|
||||
<li class="spellcheck">Fixed and improved some descriptions regarding Blob offspring</li>
|
||||
<li class="bugfix">Fixed a case where ghosts had an extra ghost icon visible on them</li>
|
||||
<li class="bugfix">Fixed a case where some ghosts were too bright</li>
|
||||
<li class="bugfix">You are now unable to swap forms with another changeling</li>
|
||||
<li class="bugfix">You can no longer hiss while muzzled</li>
|
||||
<li class="tweak">Upon purchasing Augmented Eyesight changeling ability, changeling immediately receives passive version of the ability</li>
|
||||
<li class="tweak">Changelings in the lesser form can now toggle Augmented Eyesight ability</li>
|
||||
<li class="bugfix">Changelings are now removed properly via Traitor Panel</li>
|
||||
<li class="bugfix">Changelings do not get their action buttons bugged when using Swap Forms ability now</li>
|
||||
<li class="bugfix">Action buttons should update their cooldown statuses more reliably</li>
|
||||
<li class="bugfix">Changelings should now correctly receive their action buttons</li>
|
||||
<li class="bugfix">Changelings now do not steal action buttons from other changelings</li>
|
||||
<li class="imageadd">Added new Boo! spell icon</li>
|
||||
</ul>
|
||||
<h3 class="author">Christasmurf updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Fixes a random pixel on the leather shoes</li>
|
||||
</ul>
|
||||
<h3 class="author">Citinited updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Boo affects APCs again</li>
|
||||
<li class="bugfix">Boo no longer fully charges when you enter your corpse</li>
|
||||
<li class="tweak">The button to close radial menus is much more obvious and easily-clickable now</li>
|
||||
<li class="bugfix">Destroying a disposals trunk should no longer occasionally delete things held inside it.</li>
|
||||
<li class="bugfix">Fixes conveyor belts not moving items spawned via an autolathe. (And other possible behaviours when machines switch between speed and normal processes)</li>
|
||||
<li class="imageadd">Ports liquid dispenser sprites from tgstation.</li>
|
||||
</ul>
|
||||
<h3 class="author">Couls updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Only names from the manifest will be used for syndicate code phrases</li>
|
||||
<li class="rscdel">randomly generated people names from syndicate code phrases</li>
|
||||
<li class="rscadd">Medical category to exosuit fabricator with implants and cybernetics</li>
|
||||
<li class="bugfix">t-t-t-typo!</li>
|
||||
<li class="bugfix">codephrase names no longer appear blank</li>
|
||||
</ul>
|
||||
<h3 class="author">EmanTheAlmighty updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Admin made cultists can now properly summon their Gods if the gamemode wasn't initially Cult.</li>
|
||||
</ul>
|
||||
<h3 class="author">Evankhell561 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Portable Seed Extractor designon the protolathe.</li>
|
||||
</ul>
|
||||
<h3 class="author">Fethas updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Fixes an oversight from the lavaland port invovling Laz injectors and sentience typing that didn't carry over from tg.</li>
|
||||
</ul>
|
||||
<h3 class="author">Fox McCloud updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Future proofs the coming Ticker subsystem</li>
|
||||
<li class="rscdel">Removes the Process Scheduler</li>
|
||||
</ul>
|
||||
<h3 class="author">Improvedname updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Cargo miner starter kit crate will no longer include a ID</li>
|
||||
</ul>
|
||||
<h3 class="author">Kyep updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Ported XKeyScore from TG.</li>
|
||||
<li class="rscadd">New system to securely link ingame/forum accounts</li>
|
||||
<li class="rscdel">Removed old insecure 'link discord account' system</li>
|
||||
<li class="bugfix">unanchored vending machines will no longer generate a runtime error when throwing products at people.</li>
|
||||
<li class="bugfix">Disarming/grabbing a door with IDSCAN disabled no longer results in a can_admin_interact runtime error.</li>
|
||||
<li class="bugfix">Terror Spiders no longer trigger their special attack when nuzzling someone on help intent.</li>
|
||||
</ul>
|
||||
<h3 class="author">Markolie updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Chameleon items now use the appropriate species icon.</li>
|
||||
<li class="bugfix">Lighting now respects color blindness again.</li>
|
||||
<li class="bugfix">pAI flashlights now work properly.</li>
|
||||
<li class="bugfix">Rotatium can now be created properly.</li>
|
||||
<li class="bugfix">Ghosts can now transition through space again. This is now done by clicking on the edge of space.</li>
|
||||
<li class="rscadd">Added custom explorer gas mask sprites for Grey/Drask.</li>
|
||||
<li class="rscadd">Added a lantern to the Hermit cave.</li>
|
||||
<li class="rscadd">Added a bone setter, bone gel, FixOVein, sterile masks and sterile gloves to the Lavaland Syndicate base.</li>
|
||||
<li class="rscadd">The pickaxes on the Lavaland labor camp have been replaced with safety variants. The flashlights have been replaced with lanterns.</li>
|
||||
<li class="bugfix">Fixed many species missing sprites for explorer gas masks and jumpsuits. They now use the humans icons until we have custom sprites.</li>
|
||||
<li class="bugfix">Resolved an issue with piping not working on the Lavaland mining bases.</li>
|
||||
<li class="bugfix">Fixed all items being free in the mining vendor.</li>
|
||||
<li class="bugfix">Fixed improper wiring to the turbine in the Lavaland Syndicate base.</li>
|
||||
<li class="bugfix">Fixed the Lavaland Syndicate base oxygen sensor not working.</li>
|
||||
<li class="bugfix">Moved the pipe dispenser in the Lavaland Syndicate base so it doesn't clip with tables.</li>
|
||||
<li class="bugfix">Fixed the Lavaland Syndicate base incinerator doors not working.</li>
|
||||
<li class="tweak">Ash Walkers now once more have fine manipulation. Their lack of fine manipulation caused unintended side effects (such as them being unable to mine).</li>
|
||||
<li class="bugfix">Ash Walkers (and other ghost spawner roles) can no longer be antagonist targets or become antagonists through the antagonist creation.</li>
|
||||
<li class="bugfix">Fixed the Lavaland Syndicate base incinerator buttons not working.</li>
|
||||
<li class="bugfix">Fixed the Syndicate communication agent spawning with a broken voice changer mask.</li>
|
||||
<li class="bugfix">Fixed the Disk Compartmentalizer not having a sprite.</li>
|
||||
<li class="rscadd">The Ancient Goliath now has a small chance of spawning instead of regular goliaths.</li>
|
||||
<li class="rscadd">Survival capsules now have a NanoMed.</li>
|
||||
<li class="tweak">Water bottles now behave as glass containers.</li>
|
||||
<li class="tweak">The behaviour of glass reagent containers has changed. When used on non-mobs, contents will now only be spilled on harm intent. When used on mobs, on any intent aside from harm the contents will be fed to the mob like regular drinks. On harm intent it will still be spilled.</li>
|
||||
<li class="tweak">Hairless hide can now be made wet using most sources of water (minimum volume of 10), instead of just washing machines.</li>
|
||||
<li class="bugfix">Added some additional offstation role checks to ensure ghost spawner roles don't become antagonists, are kidnap targets or are counted towards station goals.</li>
|
||||
<li class="bugfix">Fixed some piping in the Lavaland Syndicate base incinerator and made sure the vault door starts locked.</li>
|
||||
<li class="bugfix">Fixed the Lavaland swarmers getting stuck on propulsion.</li>
|
||||
<li class="bugfix">Fix goliath tentacles sometimes being left behind.</li>
|
||||
<li class="bugfix">The walls around the Lavaland Syndicate base turbine have been coated, to prevent them from starting a plasma fire in the base.</li>
|
||||
<li class="bugfix">Syndicate agents can now access the air alarms on the Lavaland Syndicate base.</li>
|
||||
<li class="bugfix">Air alarm control computers can no longer access the air alarms on the Lavaland Syndicate base.</li>
|
||||
<li class="bugfix">Fixed the disk compartmentalizer/drying rack missing a sprite under certain circumstances.</li>
|
||||
<li class="bugfix">Fixed the Lavaland Syndicate base triggering atmospherics alerts.</li>
|
||||
<li class="bugfix">You can now properly place tiles on basalt.</li>
|
||||
<li class="bugfix">An exploit with the sheet multiplier has been fixed.</li>
|
||||
<li class="rscadd">Portals can now be activated by clicking on them with or without an object. Ghosts can now also click on them to be taken to their destination.</li>
|
||||
<li class="rscadd">Portals now warn admins when they are used to teleport megafauna.</li>
|
||||
<li class="tweak">The singularity can now eat basalt and chasms on Lavaland. They get turned into lava.</li>
|
||||
<li class="bugfix">AI swarmers will no longer get stuck on effects (such as blood).</li>
|
||||
<li class="bugfix">Fixed the spectral blade turning all ghosts visible.</li>
|
||||
<li class="bugfix">Fixed a runtime with assigning outfits to mindless mobs.</li>
|
||||
<li class="bugfix">Fixed certain alarms triggering despite being outside of station contact and the Syndicate base still triggering fire alarms.</li>
|
||||
<li class="bugfix">Fixed being unable to put the wormhole jaunter in the belt slot.</li>
|
||||
<li class="bugfix">Fixed the disk compartmentalizer not accepting disks.</li>
|
||||
<li class="bugfix">Gutlunches and Gubbucks will now reproduce properly.</li>
|
||||
<li class="bugfix">The necropolis chest cult clothing drop no longer spawns with a cult hood as well, as that's part of the suit itself.</li>
|
||||
<li class="bugfix">Goliath steaks can now be eaten properly.</li>
|
||||
<li class="bugfix">Fixed a stray light on the beach ruin.</li>
|
||||
<li class="bugfix">Lavaland ruins should no longer spawn on the Labor Camp.</li>
|
||||
<li class="bugfix">Ancient goliaths will now properly randomly spawn tentacles.</li>
|
||||
<li class="bugfix">The labor camp will now spawn properly with a processing console.</li>
|
||||
<li class="bugfix">Water turfs in the beach ruin (and other water turfs that previously didn't do so) will now properly apply water to you.</li>
|
||||
<li class="bugfix">Ash flora is now anchored.</li>
|
||||
<li class="bugfix">Gutlunches will now eat properly.</li>
|
||||
<li class="bugfix">The tesla can no longer travel through wormholes.</li>
|
||||
<li class="bugfix">Fixed an issue with honkbot construction.</li>
|
||||
</ul>
|
||||
<h3 class="author">Markolie and Ionward updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Added Tajaran, Vulpkanin, Unathi and Vox sprites for the explorer gas mask (thanks to Ionward!)</li>
|
||||
<li class="rscadd">Added custom species sprites for the explorer suits and hoods (thanks to Ionward!)</li>
|
||||
<li class="rscadd">Added missing surgical tools and a pet vendor to the animal hospital.</li>
|
||||
<li class="rscadd">Added a custom cigarette vendor to the beach biodome ruin.</li>
|
||||
<li class="rscadd">Added an autolathe and RPD to the Lavaland Syndicate base. Also added a custom cigarette vendor and made the vendors not charge money.</li>
|
||||
<li class="rscadd">Added tiny fans to the mining base and labor camp exist.</li>
|
||||
<li class="rscadd">A separate jobban for ghost roles has been added.</li>
|
||||
<li class="bugfix">The alternative sink now has directional sprites. This resolves an issue with shelters having sinks facing the wrong way.</li>
|
||||
<li class="bugfix">Fixed the Syndicate sleepers on the Lavaland Syndicate base pointing the wrong way when a ghost role spawns in.</li>
|
||||
<li class="bugfix">Fixed Lava being removed by the staff of lava not working. Also added a missing warning effect when the staff is turning regular turf into lava.</li>
|
||||
<li class="bugfix">Fixed random bookcases not spawning books (hopefully).</li>
|
||||
<li class="bugfix">Fixed surgical drapes not having a sprite.</li>
|
||||
<li class="bugfix">Fixed being unable to modify the GPS tag of shelters.</li>
|
||||
<li class="bugfix">Fixed the Lavaland swarmers not eating anything.</li>
|
||||
<li class="bugfix">The ash drake swoop attack is no longer incredibly loud.</li>
|
||||
<li class="tweak">The Syndicate base self-destruct is now much more powerful and capable of destroying the entire base.</li>
|
||||
<li class="tweak">The flavor text of Ash Walkers and Syndicate operatives now clarifies what they can('t) do.</li>
|
||||
<li class="tweak">Ash walkers can no longer use machinery.</li>
|
||||
</ul>
|
||||
<h3 class="author">Ported by Markolie and CornMyCob. Developed by many /tg/ coders updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">The mining asteroid has been replaced with Lavaland.</li>
|
||||
</ul>
|
||||
<h3 class="author">Shadeykins updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Fixes a paper exploit.</li>
|
||||
<li class="bugfix">Fixes rogue pixels on breath masks/gas masks for Plasmamen.</li>
|
||||
</ul>
|
||||
<h3 class="author">TDSSS updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Vampire rejuv wakes you up if you're asleep now</li>
|
||||
<li class="tweak">Cling epinephrine wakes you up if you're asleep now</li>
|
||||
<li class="tweak">Sling glare popup no longer lists invalid targets for glaring</li>
|
||||
</ul>
|
||||
<h3 class="author">Tayyyyyyy updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Messages window (My PMs in OOC tab)</li>
|
||||
<li class="tweak">You no longer have to wait on others for ERT spawning</li>
|
||||
<li class="bugfix">Admin jobs no longer announced</li>
|
||||
</ul>
|
||||
<h3 class="author">Terilia updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Added the Donksoft sniper into the Trader spawnpool.</li>
|
||||
</ul>
|
||||
<h3 class="author">Ty-Omaha updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Changed admin take ticket color from neon green to Asay pink</li>
|
||||
<li class="bugfix">Manual bans now auto-note</li>
|
||||
<li class="bugfix">Stops projectiles using the legacy system such as emitters from hurting shield blobs due to an exploit where it would always hit or go through.</li>
|
||||
</ul>
|
||||
<h3 class="author">craftxbox updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Highlight string uses regex</li>
|
||||
<li class="rscdel">Removed jquery mark</li>
|
||||
</ul>
|
||||
<h3 class="author">datlo updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">The Syndicate will no longer hire golems as agents.</li>
|
||||
<li class="tweak">Banana juice and Banana honk will now heal everyone with the Comic Sans mutation instead of checking for the clown job</li>
|
||||
<li class="tweak">Nothing will now check if the player has an active vow of silence instead of checking for the mime job</li>
|
||||
<li class="bugfix">Ghosts will no longer get the wrong role offered when a nukie spawns a borg and will properly be informed whether they will spawn as a nuke ops or a syndi cyborg.</li>
|
||||
</ul>
|
||||
<h3 class="author">dovydas12345 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Fixes cryopod removing ambulance, secway keys</li>
|
||||
<li class="bugfix">Fixes cryopod recovering the invisible headpocket item</li>
|
||||
</ul>
|
||||
<h3 class="author">farie82 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Can't use cuffs now while you have antidrop</li>
|
||||
<li class="bugfix">can_equip now checks if you have the limbs required to equip something</li>
|
||||
<li class="rscdel">Reverts the string highlighting done by regex</li>
|
||||
</ul>
|
||||
<h3 class="author">iantine updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Skrell *warble emote</li>
|
||||
</ul>
|
||||
<h3 class="author">uc_guy updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Theft objective locations hints now ignore the Centcomm Z level.</li>
|
||||
<li class="bugfix">Adv. Pinpointer no longer targets items in Centcom Z level.</li>
|
||||
<li class="bugfix">Fixed "Venus Human Traps" being invisible.</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">10 May 2019</h2>
|
||||
<h3 class="author">AffectedArc07 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user