Merge branch 'headcrabs' of https://github.com/Terilia/Paradise into headcrabs

This commit is contained in:
Terilia
2019-08-13 14:38:53 +01:00
186 changed files with 10991 additions and 3205 deletions
+3 -2
View File
@@ -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
+2 -2
View File
@@ -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
+1
View File
@@ -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"))
+20 -9
View File
@@ -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
+35
View File
@@ -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."
+5 -4
View File
@@ -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
+6 -3
View File
@@ -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)
+3 -3
View File
@@ -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)
+4 -5
View File
@@ -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)
+2
View File
@@ -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
View File
@@ -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. ********************/
-10
View File
@@ -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
+81 -21
View File
@@ -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
..()
+27
View File
@@ -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()
+1 -1
View File
@@ -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"
+2 -1
View File
@@ -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, \
+4
View File
@@ -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
+4 -1
View File
@@ -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>")
+1 -1
View File
@@ -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
+4 -1
View File
@@ -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
+8 -5
View File
@@ -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
+17 -9
View File
@@ -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()
+10 -4
View File
@@ -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)
+4 -1
View File
@@ -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)
+4 -6
View File
@@ -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)
+2
View File
@@ -12,6 +12,8 @@
var/open = FALSE
var/brightness_on = 14
/obj/machinery/floodlight/get_cell()
return cell
/obj/machinery/floodlight/Initialize()
. = ..()
+25 -8
View File
@@ -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"
+3 -1
View File
@@ -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)
+2 -1
View File
@@ -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
+1
View File
@@ -33,6 +33,7 @@
"Phazon",
"Exosuit Equipment",
"Cyborg Upgrade Modules",
"Medical",
"Misc"
)
+4
View File
@@ -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
+10 -8
View File
@@ -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)
..()*/
+3
View File
@@ -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()
+47
View File
@@ -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()
+1 -2
View File
@@ -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()
+3 -4
View File
@@ -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)
+3
View File
@@ -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)
+28 -3
View File
@@ -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'
+4
View File
@@ -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()
-1
View File
@@ -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> |
+8
View File
@@ -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"])
+3 -1
View File
@@ -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
+21 -3
View File
@@ -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];'>&nbsp;&nbsp;&nbsp;</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()
+12 -1
View File
@@ -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
+9 -5
View File
@@ -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
+2
View File
@@ -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."
+4
View File
@@ -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()
+1
View File
@@ -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',
+133 -129
View File
@@ -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 ..()
+1
View File
@@ -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
+18 -22
View File
@@ -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()
+1
View File
@@ -15,6 +15,7 @@ GLOBAL_LIST_INIT(boo_phrases, list(
ghost = TRUE
action_icon_state = "boo"
school = "transmutation"
charge_max = 600
starts_charged = FALSE
+53 -50
View File
@@ -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"
+12 -7
View File
@@ -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)
+21
View File
@@ -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)
+3
View File
@@ -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 -3
View File
@@ -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
..()
..()
+12 -9
View File
@@ -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()
+8
View File
@@ -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]"))
+3
View File
@@ -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.
+3
View File
@@ -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)
+3
View File
@@ -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)
+3 -6
View File
@@ -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")
+2
View File
@@ -92,6 +92,8 @@
has_paint = 1
update_icons()
/obj/spacepod/get_cell()
return battery
/obj/spacepod/New()
. = ..()
+1
View File
@@ -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()
..()
+3 -1
View File
@@ -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.")
+1
View File
@@ -76,6 +76,7 @@ expensive
famous
fragile
frail
flaming
gifted
helpful
helpless
File diff suppressed because it is too large Load Diff
+53
View File
@@ -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
+313
View File
@@ -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