@@ -69,7 +69,7 @@
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "ntnet_relay", "NTNet Quantum Relay", ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, ui_key, "NtnetRelay", "NTNet Quantum Relay", ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
|
||||
|
||||
@@ -71,22 +71,17 @@
|
||||
/obj/machinery/vr_sleeper/update_icon_state()
|
||||
icon_state = "[initial(icon_state)][state_open ? "-open" : ""]"
|
||||
|
||||
/obj/machinery/vr_sleeper/open_machine()
|
||||
if(state_open)
|
||||
return
|
||||
if(occupant)
|
||||
SStgui.close_user_uis(occupant, src)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/vr_sleeper/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.lying || !iscarbon(target) || !Adjacent(target) || !user.canUseTopic(src, BE_CLOSE, TRUE, NO_TK))
|
||||
return
|
||||
close_machine(target)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/vr_sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
/obj/machinery/vr_sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_contained_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "vr_sleeper", "VR Sleeper", 475, 340, master_ui, state)
|
||||
ui = new(user, src, ui_key, "VrSleeper", "VR Sleeper", 475, 340, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/vr_sleeper/ui_act(action, params)
|
||||
@@ -130,11 +125,13 @@
|
||||
|
||||
/obj/machinery/vr_sleeper/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/is_living
|
||||
if(vr_mob && !QDELETED(vr_mob))
|
||||
is_living = isliving(vr_mob)
|
||||
data["can_delete_avatar"] = TRUE
|
||||
data["vr_avatar"] = list("name" = vr_mob.name)
|
||||
data["isliving"] = istype(vr_mob)
|
||||
if(data["isliving"])
|
||||
data["isliving"] = is_living
|
||||
if(is_living)
|
||||
var/status
|
||||
switch(vr_mob.stat)
|
||||
if(CONSCIOUS)
|
||||
@@ -146,6 +143,11 @@
|
||||
if(SOFT_CRIT)
|
||||
status = "Barely Conscious"
|
||||
data["vr_avatar"] += list("status" = status, "health" = vr_mob.health, "maxhealth" = vr_mob.maxHealth)
|
||||
else
|
||||
data["can_delete_avatar"] = FALSE
|
||||
data["vr_avatar"] = FALSE
|
||||
data["isliving"] = FALSE
|
||||
|
||||
data["toggle_open"] = state_open
|
||||
data["emagged"] = you_die_in_the_game_you_die_for_real
|
||||
data["isoccupant"] = (user == occupant)
|
||||
|
||||
@@ -62,7 +62,7 @@ GLOBAL_PROTECT(admin_verbs_admin)
|
||||
/client/proc/cmd_admin_check_player_exp, /* shows players by playtime */
|
||||
/client/proc/toggle_combo_hud, // toggle display of the combination pizza antag and taco sci/med/eng hud
|
||||
/client/proc/toggle_AI_interact, /*toggle admin ability to interact with machines as an AI*/
|
||||
/client/proc/open_shuttle_manipulator, /* Opens shuttle manipulator UI */
|
||||
/datum/admins/proc/open_shuttlepanel, /* Opens shuttle manipulator UI */
|
||||
/client/proc/respawn_character,
|
||||
/client/proc/secrets,
|
||||
/client/proc/toggle_hear_radio, /*allows admins to hide all radio output*/
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
/datum/borgpanel/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.admin_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "borgopanel", "Borg Panel", 700, 700, master_ui, state)
|
||||
ui = new(user, src, ui_key, "BorgPanel", "Borg Panel", 700, 700, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/borgpanel/ui_data(mob/user)
|
||||
|
||||
@@ -421,7 +421,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
new_character.real_name = record_found.fields["name"]
|
||||
new_character.gender = record_found.fields["gender"]
|
||||
new_character.age = record_found.fields["age"]
|
||||
new_character.hardset_dna(record_found.fields["identity"], record_found.fields["enzymes"], record_found.fields["name"], record_found.fields["blood_type"], new record_found.fields["species"], record_found.fields["features"])
|
||||
new_character.hardset_dna(record_found.fields["identity"], record_found.fields["enzymes"], null, record_found.fields["name"], record_found.fields["blood_type"], new record_found.fields["species"], record_found.fields["features"])
|
||||
else
|
||||
var/datum/preferences/A = new()
|
||||
A.copy_to(new_character)
|
||||
@@ -1058,13 +1058,6 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
|
||||
var/datum/atom_hud/A = GLOB.huds[ANTAG_HUD_TRAITOR]
|
||||
return A.hudusers[mob]
|
||||
|
||||
/client/proc/open_shuttle_manipulator()
|
||||
set category = "Admin"
|
||||
set name = "Shuttle Manipulator"
|
||||
set desc = "Opens the shuttle manipulator UI."
|
||||
|
||||
for(var/obj/machinery/shuttle_manipulator/M in GLOB.machines)
|
||||
M.ui_interact(usr)
|
||||
|
||||
/client/proc/run_weather()
|
||||
set category = "Fun"
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/datum/admins/proc/open_shuttlepanel()
|
||||
set category = "Admin"
|
||||
set name = "Shuttle Manipulator"
|
||||
set desc = "Opens the shuttle manipulator UI."
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
SSshuttle.ui_interact(usr)
|
||||
|
||||
|
||||
/obj/docking_port/mobile/proc/admin_fly_shuttle(mob/user)
|
||||
var/list/options = list()
|
||||
|
||||
for(var/port in SSshuttle.stationary)
|
||||
if (istype(port, /obj/docking_port/stationary/transit))
|
||||
continue // please don't do this
|
||||
var/obj/docking_port/stationary/S = port
|
||||
if (canDock(S) == SHUTTLE_CAN_DOCK)
|
||||
options[S.name || S.id] = S
|
||||
|
||||
options += "--------"
|
||||
options += "Infinite Transit"
|
||||
options += "Delete Shuttle"
|
||||
options += "Into The Sunset (delete & greentext 'escape')"
|
||||
|
||||
var/selection = input(user, "Select where to fly [name || id]:", "Fly Shuttle") as null|anything in options
|
||||
if(!selection)
|
||||
return
|
||||
|
||||
switch(selection)
|
||||
if("Infinite Transit")
|
||||
destination = null
|
||||
mode = SHUTTLE_IGNITING
|
||||
setTimer(ignitionTime)
|
||||
|
||||
if("Delete Shuttle")
|
||||
if(alert(user, "Really delete [name || id]?", "Delete Shuttle", "Cancel", "Really!") != "Really!")
|
||||
return
|
||||
jumpToNullSpace()
|
||||
|
||||
if("Into The Sunset (delete & greentext 'escape')")
|
||||
if(alert(user, "Really delete [name || id] and greentext escape objectives?", "Delete Shuttle", "Cancel", "Really!") != "Really!")
|
||||
return
|
||||
intoTheSunset()
|
||||
|
||||
else
|
||||
if(options[selection])
|
||||
request(options[selection])
|
||||
|
||||
/obj/docking_port/mobile/emergency/admin_fly_shuttle(mob/user)
|
||||
return // use the existing verbs for this
|
||||
|
||||
/obj/docking_port/mobile/arrivals/admin_fly_shuttle(mob/user)
|
||||
switch(alert(user, "Would you like to fly the arrivals shuttle once or change its destination?", "Fly Shuttle", "Fly", "Retarget", "Cancel"))
|
||||
if("Cancel")
|
||||
return
|
||||
if("Fly")
|
||||
return ..()
|
||||
|
||||
var/list/options = list()
|
||||
|
||||
for(var/port in SSshuttle.stationary)
|
||||
if (istype(port, /obj/docking_port/stationary/transit))
|
||||
continue // please don't do this
|
||||
var/obj/docking_port/stationary/S = port
|
||||
if (canDock(S) == SHUTTLE_CAN_DOCK)
|
||||
options[S.name || S.id] = S
|
||||
|
||||
var/selection = input(user, "Select the new arrivals destination:", "Fly Shuttle") as null|anything in options
|
||||
if(!selection)
|
||||
return
|
||||
target_dock = options[selection]
|
||||
if(!QDELETED(target_dock))
|
||||
destination = target_dock
|
||||
|
||||
@@ -23,6 +23,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
var/show_name_in_check_antagonists = FALSE //Will append antagonist name in admin listings - use for categories that share more than one antag type
|
||||
var/list/blacklisted_quirks = list(/datum/quirk/nonviolent,/datum/quirk/mute) // Quirks that will be removed upon gaining this antag. Pacifist and mute are default.
|
||||
var/threat = 0 // Amount of threat this antag poses, for dynamic mode
|
||||
var/show_to_ghosts = FALSE // Should this antagonist be shown as antag to ghosts? Shouldn't be used for stealthy antagonists like traitors
|
||||
|
||||
var/list/skill_modifiers
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
job_rank = ROLE_ABDUCTOR
|
||||
show_in_antagpanel = FALSE //should only show subtypes
|
||||
threat = 5
|
||||
show_to_ghosts = TRUE
|
||||
var/datum/team/abductor_team/team
|
||||
var/sub_role
|
||||
var/outfit
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "Blob"
|
||||
roundend_category = "blobs"
|
||||
antagpanel_category = "Blob"
|
||||
show_to_ghosts = TRUE
|
||||
job_rank = ROLE_BLOB
|
||||
threat = 20
|
||||
var/datum/action/innate/blobpop/pop_action
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
/datum/cellular_emporium/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "cellular_emporium", name, 900, 480, master_ui, state)
|
||||
ui = new(user, src, ui_key, "CellularEmporium", name, 900, 480, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/cellular_emporium/ui_data(mob/user)
|
||||
|
||||
@@ -38,10 +38,11 @@
|
||||
set_slab.update_quickbind()
|
||||
|
||||
/proc/generate_all_scripture()
|
||||
if(!GLOB.all_scripture.len)
|
||||
for(var/V in sortList(subtypesof(/datum/clockwork_scripture), /proc/cmp_clockscripture_priority))
|
||||
var/datum/clockwork_scripture/S = new V
|
||||
GLOB.all_scripture[S.type] = S
|
||||
if(GLOB.all_scripture.len)
|
||||
return
|
||||
for(var/V in sortList(subtypesof(/datum/clockwork_scripture) - list(/datum/clockwork_scripture/channeled, /datum/clockwork_scripture/create_object, /datum/clockwork_scripture/create_object/construct), /proc/cmp_clockscripture_priority))
|
||||
var/datum/clockwork_scripture/S = new V
|
||||
GLOB.all_scripture[S.type] = S
|
||||
|
||||
//changes construction value
|
||||
/proc/change_construction_value(amount)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/item/clockwork/slab //Clockwork slab: The most important tool in Ratvar's arsenal. Allows scripture recital, tutorials, and generates components.
|
||||
name = "clockwork slab"
|
||||
desc = "A strange metal tablet. A clock in the center turns around and around."
|
||||
clockwork_desc = "A link between you and the Celestial Derelict. It contains information, recites scripture, and is your most vital tool as a Servant.<br>\
|
||||
clockwork_desc = "A link between you and the Celestial Derelict. It contains information, recites scripture, and is your most vital tool as a Servant.\
|
||||
It can be used to link traps and triggers by attacking them with the slab. Keep in mind that traps linked with one another will activate in tandem!"
|
||||
|
||||
icon_state = "dread_ipad"
|
||||
@@ -15,16 +15,19 @@
|
||||
var/busy //If the slab is currently being used by something
|
||||
var/no_cost = FALSE //If the slab is admin-only and needs no components and has no scripture locks
|
||||
var/speed_multiplier = 1 //multiples how fast this slab recites scripture
|
||||
var/selected_scripture = SCRIPTURE_DRIVER
|
||||
// var/selected_scripture = SCRIPTURE_DRIVER //handled UI side
|
||||
var/obj/effect/proc_holder/slab/slab_ability //the slab's current bound ability, for certain scripture
|
||||
|
||||
var/recollecting = FALSE //if we're looking at fancy recollection
|
||||
var/recollecting = TRUE //if we're looking at fancy recollection. tutorial enabled by default
|
||||
var/recollection_category = "Default"
|
||||
|
||||
var/list/quickbound = list(/datum/clockwork_scripture/abscond, \
|
||||
/datum/clockwork_scripture/ranged_ability/kindle, /datum/clockwork_scripture/ranged_ability/hateful_manacles) //quickbound scripture, accessed by index
|
||||
var/maximum_quickbound = 5 //how many quickbound scriptures we can have
|
||||
|
||||
var/ui_x = 800
|
||||
var/ui_z = 420
|
||||
|
||||
var/obj/structure/destructible/clockwork/trap/linking //If we're linking traps together, which ones we're doing
|
||||
|
||||
/obj/item/clockwork/slab/internal //an internal motor for mobs running scripture
|
||||
@@ -146,8 +149,8 @@
|
||||
if(!quickbound[i])
|
||||
continue
|
||||
var/datum/clockwork_scripture/quickbind_slot = quickbound[i]
|
||||
. += "<b>Quickbind</b> button: <span class='[get_component_span(initial(quickbind_slot.primary_component))]'>[initial(quickbind_slot.name)]</span>."
|
||||
. += "<b>Available power:</b> <span class='bold brass'>[DisplayPower(get_clockwork_power())].</span>"
|
||||
. += "Quickbind button: <span class='[get_component_span(initial(quickbind_slot.primary_component))]'>[initial(quickbind_slot.name)]</span>."
|
||||
. += "Available power: <span class='bold brass'>[DisplayPower(get_clockwork_power())].</span>"
|
||||
|
||||
//Slab actions; Hierophant, Quickbind
|
||||
/obj/item/clockwork/slab/ui_action_click(mob/user, action)
|
||||
@@ -165,18 +168,19 @@
|
||||
user.emote("scream")
|
||||
user.apply_damage(5, BURN, BODY_ZONE_L_ARM)
|
||||
user.apply_damage(5, BURN, BODY_ZONE_R_ARM)
|
||||
return 0
|
||||
return FALSE
|
||||
if(!is_servant_of_ratvar(user))
|
||||
to_chat(user, "<span class='warning'>The information on [src]'s display shifts rapidly. After a moment, your head begins to pound, and you tear your eyes away.</span>")
|
||||
user.confused += 5
|
||||
user.dizziness += 5
|
||||
return 0
|
||||
if(user.confused || user.dizziness)
|
||||
user.confused += 5
|
||||
user.dizziness += 5
|
||||
return FALSE
|
||||
if(busy)
|
||||
to_chat(user, "<span class='warning'>[src] refuses to work, displaying the message: \"[busy]!\"</span>")
|
||||
return 0
|
||||
return FALSE
|
||||
if(!no_cost && !can_recite_scripture(user))
|
||||
to_chat(user, "<span class='nezbere'>[src] hums fitfully in your hands, but doesn't seem to do anything...</span>")
|
||||
return 0
|
||||
return FALSE
|
||||
access_display(user)
|
||||
|
||||
/obj/item/clockwork/slab/AltClick(mob/living/user)
|
||||
@@ -195,9 +199,7 @@
|
||||
/obj/item/clockwork/slab/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "clockwork_slab", name, 800, 420, master_ui, state)
|
||||
ui.set_autoupdate(FALSE) //we'll update this occasionally, but not as often as possible
|
||||
ui.set_style("clockwork")
|
||||
ui = new(user, src, ui_key, "ClockworkSlab", name, ui_x, ui_z, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/clockwork/slab/proc/recite_scripture(datum/clockwork_scripture/scripture, mob/living/user)
|
||||
@@ -207,10 +209,12 @@
|
||||
to_chat(user, "<span class='warning'>You need to hold the slab in your active hand to recite scripture!</span>")
|
||||
return FALSE
|
||||
var/initial_tier = initial(scripture.tier)
|
||||
if(initial_tier != SCRIPTURE_PERIPHERAL)
|
||||
if(!GLOB.ratvar_awakens && !no_cost && !SSticker.scripture_states[initial_tier])
|
||||
to_chat(user, "<span class='warning'>That scripture is not unlocked, and cannot be recited!</span>")
|
||||
return FALSE
|
||||
if(initial_tier == SCRIPTURE_PERIPHERAL)
|
||||
to_chat(user, "<span class='warning'>Nice try using href exploits</span>")
|
||||
return
|
||||
if(!GLOB.ratvar_awakens && !no_cost && !SSticker.scripture_states[initial_tier])
|
||||
to_chat(user, "<span class='warning'>That scripture is not unlocked, and cannot be recited!</span>")
|
||||
return FALSE
|
||||
var/datum/clockwork_scripture/scripture_to_recite = new scripture
|
||||
scripture_to_recite.slab = src
|
||||
scripture_to_recite.invoker = user
|
||||
@@ -218,26 +222,6 @@
|
||||
return TRUE
|
||||
|
||||
|
||||
//Guide to Serving Ratvar
|
||||
/obj/item/clockwork/slab/proc/recollection()
|
||||
var/list/textlist = list("If you're seeing this, file a bug report.")
|
||||
if(GLOB.ratvar_awakens)
|
||||
textlist = list("<font color=#BE8700 size=3><b>")
|
||||
for(var/i in 1 to 100)
|
||||
textlist += "HONOR RATVAR "
|
||||
textlist += "</b></font>"
|
||||
else
|
||||
textlist = list("<font color=#BE8700 size=3><b><center>[text2ratvar("Purge all untruths and honor Engine.")]</center></b></font><br>\
|
||||
\
|
||||
<b><i>NOTICE:</b> This information is out of date. Read the Ark & You primer in your backpack or read the wiki page for current info.</i><br>\
|
||||
<hr><br>\
|
||||
These pages serve as the archives of Ratvar, the Clockwork Justiciar. This section of your slab has information on being as a Servant, advice for what to do next, and \
|
||||
pointers for serving the master well. You should recommended that you check this area for help if you get stuck or need guidance on what to do next.<br><br>\
|
||||
\
|
||||
<i>Disclaimer: Many objects, terms, and phrases, such as Servant, Cache, and Slab, are capitalized like proper nouns. This is a quirk of the Ratvarian language; \
|
||||
do not let it confuse you! You are free to use the names in pronoun form when speaking in normal languages.<br>")
|
||||
return textlist.Join()
|
||||
|
||||
//Gets text for a certain section. "Default" is used for when you first open Recollection.
|
||||
//Current sections (make sure to update this if you add one:
|
||||
//- Basics
|
||||
@@ -246,255 +230,93 @@
|
||||
//- Scripture
|
||||
//- Power
|
||||
//- Conversion
|
||||
/obj/item/clockwork/slab/proc/get_recollection_text(section)
|
||||
var/list/dat = list()
|
||||
switch(section)
|
||||
if("Default")
|
||||
dat += "You can browse the above sections as you please. They're designed to be read in order, but feel free to pick and choose between them."
|
||||
if("Getting Started")
|
||||
dat += "<font color=#BE8700 size=3>Getting Started</font><br><br>"
|
||||
dat += "Welcome, Servant! This section houses the utmost basics of being a Servant of Ratvar, and is much more informal than the other sections. Being a Servant of \
|
||||
Ratvar is a very complex role, with many systems, objects, and resources to use effectively and creatively.<br><br>"
|
||||
dat += "This section of your clockwork slab covers everything that Servants have to be aware of, but is a long read because of how in-depth the systems are. Knowing \
|
||||
how to use the tools at your disposal makes all the difference between a clueless Servant and a great one.<br><br>"
|
||||
dat += "If this is your first time being a Servant, relax. It's very much possible that you'll fail, but it's impossible to learn without making mistakes. For the time \
|
||||
being, use the Hierophant Network button in the top left-hand corner of your screen to try and get in touch with your fellow Servants; ignore the others for now. This button \
|
||||
will let you send messages across space and time to all other Servants. This makes it great for coordinating, and you should use it often! <i>Note:</i> Using \
|
||||
this will cause you to whisper your message aloud, so doing so in a public place is very suspicious and you should try to restrict it to private use.<br><br>"
|
||||
dat += "If you aren't willing or don't have the time to read through every section, you can still help your teammates! Ask if they've set up a base. If they have, head there \
|
||||
and ask however you can help; chances are there's always something. If not, it's your job as a Servant to get one up and running! Try to find a secluded, low-traffic area, \
|
||||
like the auxiliary base or somewhere deep in maintenance. You'll want to go into the Drivers section of the slab and look for <i>Tinkerer's Cache.</i> Find a nice spot and \
|
||||
create one. This serves as a storage for <i>components,</i> the cult's primary resource. (Your slab's probably produced a few by now.) By attacking that cache with this \
|
||||
slab, you'll offload all your components into it, and all Servants will be able to use those components from any distance - all Tinkerer's Caches are linked!<br><br>"
|
||||
dat += "Once you have a base up and running, contact your fellows and let them know. You should come back here often to drop off the slab's components, and your fellows \
|
||||
should do the same, either in this cache or in ones of their own.<br><br>"
|
||||
dat += "If you think you're confident in taking further steps to help the cult, feel free to move onto the other sections. If not, let your allies know that you're new and \
|
||||
would appreciate the help they might offer you. Most experienced Servants would be happy to help; if everyone is inexperienced, then you'll have to step out of your comfort \
|
||||
zone and read onto the other sections. It's very likely that you might fail, but don't worry too much about it; you can't learn effectively without making mistakes.<br><br>"
|
||||
dat += "For now, welcome! If you're looking to learn, you should start with the <b>Basics</b> section, then move onto <b>Components</b> and <b>Scripture</b>. At the very \
|
||||
least, you should read the <b><i>Conversion</i></b> section, as it outlines the most important aspects of being a Servant. Good luck!<br><br>"
|
||||
dat += "<font color=#BE8700 size=3>-=-=-=-=-=-</font>"
|
||||
if("Basics")
|
||||
dat += "<font color=#BE8700 size=3>Servant Basics</font><br><br>"
|
||||
dat += "The first thing any Servant should know is their slab, inside and out. The clockwork slab is by far your most important tool. It allows you to speak with your \
|
||||
fellow Servants, create components that fuel many of your abilities, use those abilities, and should be kept safe and hidden on your person at all times. If you have not \
|
||||
done so already, it's a good idea to check for any fellow Servants using the Hierophant Network button in the top-left corner of your screen; due to the cult's nature, \
|
||||
teamwork is an instrumental component of your success.<br><br>" //get it? component? ha!
|
||||
dat += "As a Servant of Ratvar, the tools you are given focus around building and maintaining bases and outposts. A great deal of your power comes from stationary \
|
||||
structures, and without constructing a base somewhere, it's essentially impossible to succeed. Finding a good spot to build a base can be difficult, and it's recommended \
|
||||
that you choose an area in low-traffic part of the station (such as the auxiliary base). Make sure to disconnect any cameras in the area beforehand.<br><br>"
|
||||
dat += "Because of how complex being a Servant is, it isn't possible to fit much information into this section. It's highly recommended that you read the <b>Components</b> \
|
||||
and <b>Scripture</b> sections next. Not knowing how these two systems work will cripple both you and your fellows, and lead to a frustrating experience for everyone.<br><br>"
|
||||
dat += "<font color=#BE8700 size=3>-=-=-=-=-=-</font>"
|
||||
if("Terminology")
|
||||
dat += "<font color=#BE8700 size=3>Common Servant Terminology</font><br>"
|
||||
dat += "<i>This isn't intended to be read all at once; you are advised to treat it moreso as a glossary.</i><br><br>"
|
||||
dat += "<font color=#BE8700 size=3>General</font><br>"
|
||||
dat += "<font color=#BE8700><b>Servant:</b></font> A person or robot who serves Ratvar. You are one of these.<br>"
|
||||
dat += "<font color=#BE8700><b>Cache:</b></font> A <i>Tinkerer's Cache</i>, which is a structure that stores and creates components.<br>"
|
||||
dat += "<font color=#BE8700><b>CV:</b></font> Construction Value. All clockwork structures, floors, and walls increase this number.<br>"
|
||||
dat += "<font color=#BE8700><b>Vitality:</b></font> Used for healing effects, produced by Ratvarian spear attacks and Vitality Matrices.<br>"
|
||||
dat += "<font color=#BE8700><b>Geis:</b></font> An important scripture used to make normal crew and robots into Servants of Ratvar.<br>"
|
||||
dat += "<font color=#BE8700><b>Ark:</b></font> The cult's win condition, a huge structure that needs to be defended.<br><br>"
|
||||
dat += "<font color=#BE8700 size=3>Items</font><br>"
|
||||
dat += "<font color=#BE8700><b>Slab:</b></font> A clockwork slab, a Servant's most important tool. You're holding one! Keep it safe and hidden.<br>"
|
||||
dat += "<font color=#BE8700><b>Visor:</b></font> A judicial visor, which is a pair of glasses that can smite an area for a brief stun and delayed explosion.<br>"
|
||||
dat += "<font color=#BE8700><b>Wraith Specs:</b></font> Wraith spectacles, which provide true sight (X-ray, night vision) but damage the wearer's eyes.<br>"
|
||||
dat += "<font color=#BE8700><b>Spear:</b></font> A Ratvarian spear, which is a very powerful melee weapon that produces Vitality.<br>"
|
||||
dat += "<font color=#BE8700><b>Fabricator:</b></font> A replica fabricator, which converts objects into clockwork versions.<br><br>"
|
||||
dat += "<font color=#BE8700 size=3>Constructs</font><br>"
|
||||
dat += "<font color=#BE8700><b>Marauder:</b></font> A clockwork marauder, which is a powerful bodyguard that hides in its owner.<br><br>"
|
||||
dat += "<font color=#BE8700 size=3>Structures (* = requires power)</font><br>"
|
||||
dat += "<font color=#BE8700><b>Warden:</b></font> An ocular warden, which is a ranged turret that damages non-Servants that see it.<br>"
|
||||
dat += "<font color=#BE8700><b>Prism*:</b></font> A prolonging prism, which delays the shuttle for two minutes at a huge power cost.<br><br>"
|
||||
dat += "<font color=#BE8700><b>Motor*:</b></font> A mania motor, which serves as area-denial through negative effects and eventual conversion.<br>"
|
||||
dat += "<font color=#BE8700><b>Daemon*:</b></font> A tinkerer's daemon, which quickly creates components.<br>"
|
||||
dat += "<font color=#BE8700><b>Obelisk*:</b></font> A clockwork obelisk, which can broadcast large messages and allows limited teleportation.<br>"
|
||||
dat += "<font color=#BE8700 size=3>Sigils</font><br>"
|
||||
dat += "<i>Note: Sigils can be stacked on top of one another, making certain sigils very effective when paired!</i><br>"
|
||||
dat += "<font color=#BE8700><b>Transgression:</b></font> Stuns the first non-Servant to cross it for ten seconds and blinds others nearby. Disappears on use.<br>"
|
||||
dat += "<font color=#BE8700><b>Submission:</b></font> Converts the first non-Servant to stand on the sigil for seven seconds. Disappears on use.<br>"
|
||||
dat += "<font color=#BE8700><b>Matrix:</b></font> Drains health from non-Servants, producing Vitality. Can heal and revive Servants.<br>"
|
||||
dat += "<font color=#BE8700><b>Accession:</b></font> Identical to the Sigil of Submission, but doesn't disappear on use. It can also convert a single mindshielded target, but will disappear after doing this.<br>"
|
||||
dat += "<font color=#BE8700><b>Transmission:</b></font> Drains and stores power for clockwork structures. Feeding it brass sheets will create additional power.<br><br>"
|
||||
dat += "<font color=#BE8700 size=3>-=-=-=-=-=-</font>"
|
||||
if("Components")
|
||||
dat += "<font color=#BE8700 size=3>Components & Their Uses</font><br><br>"
|
||||
dat += "<b>Components</b> are your primary resource as a Servant. There are five types of component, with each one being used in different roles:<br><br>"
|
||||
dat += "Although this is a good rule of thumb, their effects become much more nuanced when used together. For instance, a turret might have both belligerent eyes and \
|
||||
vanguard cogwheels as construction requirements, because it defends its allies by harming its enemies.<br><br>"
|
||||
dat += "Components' primary use is fueling <b>scripture</b> (covered in its own section), and they can be created through various ways. This clockwork slab, for instance, \
|
||||
will make a random component of every type - or a specific one, if you choose a target component from the interface - every <b>remove me already</b>. This number will increase \
|
||||
as the amount of Servants in the covenant increase; additionally, slabs can only produce components when held by a Servant, and holding more than one slab will cause both \
|
||||
of them to halt progress until one of them is removed from their person.<br><br>"
|
||||
dat += "Your slab has an internal storage of components, but it isn't meant to be the main one. Instead, there's a <b>global storage</b> of components that can be \
|
||||
added to through various ways. Anything that needs components will first draw them from the global storage before attempting to draw them from the slab. Most methods of \
|
||||
component production add to the global storage. You can also offload components from your slab into the global storage by using it on a Tinkerer's Cache, a structure whose \
|
||||
primary purpose is to do just that (although it will also slowly produce components when placed near a brass wall.)<br><br>"
|
||||
dat += "<font color=#BE8700 size=3>-=-=-=-=-=-</font>"
|
||||
if("Scripture")
|
||||
dat += "<font color=#BE8700 size=3>The Ancient Scripture</font><br><br>"
|
||||
dat += "If you have experience with the Nar'Sian cult (or the \"blood cult\") then you will know of runes. They are the manifestations of the Geometer's power, and where most \
|
||||
of the cult's supernatural ability comes from. The Servant equivalent of runes is called <b>scripture</b>, and unlike runes, scripture is loaded into your clockwork slab.<br><br>"
|
||||
dat += "Each piece of scripture has widely-varying effects. Your most important scripture, <i>Geis</i>, is obvious and suspicious, but charges your slab with energy and allows \
|
||||
you to attack a non-Servant in melee range to restrain them and begin converting them into a Servant. This is just one example; each piece of scripture can be simple or \
|
||||
complex, be obvious or have hidden mechanics that can only be found through trial and error.<br><br>"
|
||||
dat += "Any given piece of scripture has a component cost listed in its \"Recite\" button. The acronyms for the components should be obvious if you've read about components \
|
||||
already; reciting this piece of scripture will consume the listed components, first from the global storage and then from your slab. Note that failing to recite a piece of \
|
||||
scripture will <i>not</i> consume the components required to recite it.<br><br>"
|
||||
dat += "It should also be noted that some scripture cannot be recited alone. Especially with more powerful scripture, you may need multiple Servants to recite a piece of \
|
||||
scripture; both of you will need to stand still until the recital completes. <i>Only human and silicon Servants are valid for scripture recital!</i> Constructs cannot help \
|
||||
in reciting scripture.<br><br>"
|
||||
dat += "Finally, scripture is separated into three \"tiers\" based on power: Drivers, Scripts, and Applications.[prob(1) ? " (The Revenant tier was removed a long time ago. \
|
||||
Get with the times.)" : ""] You can view the requirements to unlock each tier in its scripture list. Once a tier is unlocked, it's unlocked permanently; the cult only needs to fill the \
|
||||
requirement for unlocking a tier once!<br><br>"
|
||||
dat += "<font color=#BE8700 size=3>-=-=-=-=-=-</font>"
|
||||
if("Power")
|
||||
dat += "<font color=#BE8700 size=3>Power! Unlimited Power!</font><br><br>"
|
||||
dat += "In the early stages of the cult, the only resource that must be actively worried about is components. However, as new scripture is unlocked, a new resource \
|
||||
becomes necessary: <b>power</b>. Almost all clockwork structures require power to function in some way. There is nothing special about this power; it's mere electricity, \
|
||||
and can be harnessed in several ways.<br><br>"
|
||||
dat += "To begin with, if there is no other source of power nearby, structures will draw from the area's APC, assuming it has one. This is inefficient and ill-advised as \
|
||||
anything but a last resort. Instead, it is recommended that a <b>Sigil of Transmission</b> is created. This sigil serves as both battery and power generator for nearby clockwork \
|
||||
structures, and those structures will happily draw power from the sigil before they resort to APCs.<br><br>"
|
||||
dat += "Generating power is less easy. The most reliable and efficient way is using brass sheets; attacking a sigil of transmission with brass sheets will convert them \
|
||||
to power, at a rate of <b>[DisplayPower(POWER_FLOOR)]</b> per sheet. (Brass sheets are created from replica fabricators, which are explained more in detail in the <b>Conversion</b> section.) \
|
||||
Activating a sigil of transmission will also cause it to drain power from the nearby area, which, while effective, serves as an obvious tell that there is something wrong.<br><br>"
|
||||
dat += "Without power, many structures will not function, making a base vulnerable to attack. For this reason, it is critical that you keep an eye on your power reserves and \
|
||||
ensure that they remain comfortably high.<br><br>"
|
||||
dat += "<font color=#BE8700 size=3>-=-=-=-=-=-</font>"
|
||||
if("Conversion")
|
||||
dat += "<font color=#BE8700 size=3>Growing the Ranks</font><br><br>"
|
||||
dat += "Because the Servants of Ratvar are a cult, the main method to gain more power is to \"enlighten\" normal crew into new Servants. When a crewmember is converted, \
|
||||
they become a full-fledged Servant, ready and willing to serve the cause of Ratvar. It should also be noted that <i>silicon crew, such as cyborgs and the AI, can be \
|
||||
converted just like normal crew</i> and will gain special abilities; this is covered later. This section will also cover converting the station's structure itself; walls, \
|
||||
floors, windows, tables, and other objects can all be converted into clockwork versions, and serve an important purpose.<br><br>"
|
||||
dat += "<font color=#BE8700><b>A Note on Geis:</b></font> There are several ways to convert humans and silicons. However, the most important tool to making them work is \
|
||||
<b>Geis</b>, a Driver-tier scripture. Using it whispers an invocation very quickly and charges your slab with power. In addition to <i>making the slab visible in your hand,</i> \
|
||||
you can now use it on a target within melee range to bind and mute them. It is by far your most reliable tool for capturing potential converts and targets, though it is incredibly \
|
||||
obvious. In addition, you are unable to take any actions other than moving while your target is bound. The binding will last for 25 seconds and mute for about 13 seconds, though \
|
||||
allies can use Geis to refresh these effects.<br><br>"
|
||||
dat += "<font color=#BE8700><b>Converting:</b></font> The two methods of conversion are the <b>sigil of submission</b>, whose purpose is to do so, and the <b>mania motor.</b> \
|
||||
The sigil of submission is a sigil that, when stood on by a non-Servant for eight seconds, will convert that non-Servant. This is the only practical way to convert targets. \
|
||||
Sigils of submission are cheap, early, and permanent! Make sure sigils of submission are placed only in bases or otherwise hidden spots, or with a sigil of transgression on them. \
|
||||
The mania motor, however, is generally unreliable and unlocked later, only converting those who stand near it for an extended period.<br><br>"
|
||||
dat += "<font color=#BE8700><b>Converting Humans:</b></font> For obvious reasons, humans are the most common conversion target. Because every crew member is different, and \
|
||||
may be armed with different equipment, you should take precautions to ensure that they aren't able to resist. If able, removing a headset is essential, as is restraining \
|
||||
them through handcuffs, cable ties, or other restraints. Some crew, like security, are also implanted with mindshield implants; these will prevent conversion and must be \
|
||||
surgically removed before they are an eligible convert. <i>Note:</i> The captain is <i>never</i> an eligible convert and should instead be killed or imprisoned. If security \
|
||||
begins administering mindshield implants, this will greatly inhibit conversion. Also note that mindshield implants can be broken by a sigil of accession automatically, but \
|
||||
the sigil will disappear.<br><br>"
|
||||
dat += "<font color=#BE8700><b>Converting Silicons:</b></font> Due to their robotic nature, silicons are generally more predictable than humans in terms of conversion. \
|
||||
However, they are also much, much harder to subdue, especially cyborgs. The easiest way to convert a cyborg is by using Geis to restrain them, then dragging them to a sigil \
|
||||
of submission. If you stack a sigil of transgression and a sigil of submission, a crossing cyborg will be stunned and helpless to escape before they are converted.<br><br>"
|
||||
dat += "Converting AIs is very often the hardest task of the cult, and has been the downfall of countless successful Servants. Their omnipresence across the station, \
|
||||
coupled with their secure location and ability to lock themselves securely, makes them a powerful target. However, once the AI itself is reached, it is usually completely \
|
||||
helpless to resist its own conversion. A very common tactic is to take advantage of a converted cyborg to rush the AI before it is able to react.<br><br>"
|
||||
dat += "Even once an AI is converted, care must be taken to ensure that it remains hidden. Not only does the AI's core become brassy and thus obvious to an outside \
|
||||
observer, but <i>the AI loses the ability to speak in anything but Ratvarian.</i> For this reason, it has to remain completely silent over common radio channels if stealth \
|
||||
is at all a priority. This is suspicious and will rapidly lead to the crew checking on it, which usually results in the cult's outing. It is, however, necessary to convert \
|
||||
all AIs present on the station before the Ark becomes invokable, so this must be done at some point.<br><br>"
|
||||
dat += "<font color=#BE8700><b>Converting the Station:</b></font> Converted objects all serve a purpose and are important to the cult's success. To convert objects, \
|
||||
a Servant needs to use a <b>replica fabricator,</b> a handheld tool that uses power to replace objects with clockwork versions. Different clockwork objects have different \
|
||||
effects and are often crucial. The most noteworthy are <b>clockwork walls,</b> which automatically \"link\" to any nearby Tinkerer's Caches, causing them to <b>slowly \
|
||||
generate components.</b> This is incredibly useful for obvious reasons, and creating a clockwork wall near every Tinkerer's Cache should be prioritized. Clockwork floors \
|
||||
will slowly heal any toxin damage suffered by Servants standing on them, and clockwork airlocks can only be opened by Servants.<br><br>"
|
||||
dat += "The replica fabricator itself is also worth noting. In addition to replacing objects, it can also create brass sheets at the cost of power by using the \
|
||||
fabricator in-hand. It can also be used to repair any damaged clockwork structures.<br><br>"
|
||||
dat += "Replacing objects is almost as, if not as important as, converting new Servants. A base is impossible to manage without clockwork walls at the very least, and \
|
||||
once the cult has been outed and the crew are actively searching, there is little reason not to use as many as possible.<br><br>"
|
||||
dat += "<font color=#BE8700 size=3>-=-=-=-=-=-</font>"
|
||||
else
|
||||
dat += "<font color=#BE8700 size=3>404: [section ? section : "Section"] Not Found!</font><br><br>\
|
||||
One of the cogscarabs must've misplaced this section, because the game wasn't able to find any info regarding it. Report this to the coders!"
|
||||
return "<br><br>[dat.Join()]<br><br>"
|
||||
|
||||
//Gets the quickbound scripture as a text block.
|
||||
/obj/item/clockwork/slab/proc/get_recollection_quickbinds()
|
||||
var/list/dat = list()
|
||||
dat += "<font color=#BE8700 size=3>Quickbound Scripture</font><br>\
|
||||
<i>You can have up to five scriptures bound to action buttons for easy use.</i><br><br>"
|
||||
if(LAZYLEN(quickbound))
|
||||
for(var/i in 1 to maximum_quickbound)
|
||||
if(LAZYLEN(quickbound) < i || !quickbound[i])
|
||||
dat += "A <b>Quickbind</b> slot, currently set to <b><font color=#BE8700>Nothing</font></b>.<br>"
|
||||
else
|
||||
var/datum/clockwork_scripture/quickbind_slot = quickbound[i]
|
||||
dat += "A <b>Quickbind</b> slot, currently set to <b><font color=[get_component_color_bright(initial(quickbind_slot.primary_component))]>[initial(quickbind_slot.name)]</font></b>.<br>"
|
||||
return dat.Join()
|
||||
|
||||
|
||||
/obj/item/clockwork/slab/ui_data(mob/user) //we display a lot of data via TGUI
|
||||
var/list/data = list()
|
||||
data["power"] = "<b><font color=#B18B25>[DisplayPower(get_clockwork_power())]</b> power is available for scripture and other consumers.</font>"
|
||||
|
||||
switch(selected_scripture) //display info based on selected scripture tier
|
||||
if(SCRIPTURE_DRIVER)
|
||||
data["tier_info"] = "<font color=#B18B25><b>These scriptures are permanently unlocked.</b></font>"
|
||||
if(SCRIPTURE_SCRIPT)
|
||||
if(SSticker.scripture_states[SCRIPTURE_SCRIPT])
|
||||
data["tier_info"] = "<font color=#B18B25><b>These scriptures are permanently unlocked.</b></font>"
|
||||
else
|
||||
data["tier_info"] = "<font color=#B18B25><i>These scriptures will automatically unlock when the Ark is halfway ready or if [DisplayPower(SCRIPT_UNLOCK_THRESHOLD)] of power is reached.</i></font>"
|
||||
if(SCRIPTURE_APPLICATION)
|
||||
if(SSticker.scripture_states[SCRIPTURE_APPLICATION])
|
||||
data["tier_info"] = "<font color=#B18B25><b>These scriptures are permanently unlocked.</b></font>"
|
||||
else
|
||||
data["tier_info"] = "<font color=#B18B25><i>Unlock these optional scriptures by converting another servant or if [DisplayPower(APPLICATION_UNLOCK_THRESHOLD)] of power is reached..</i></font>"
|
||||
|
||||
data["selected"] = selected_scripture
|
||||
data["scripturecolors"] = "<font color=#DAAA18>Scriptures in <b>yellow</b> are related to construction and building.</font><br>\
|
||||
<font color=#6E001A>Scriptures in <b>red</b> are related to attacking and offense.</font><br>\
|
||||
<font color=#1E8CE1>Scriptures in <b>blue</b> are related to healing and defense.</font><br>\
|
||||
<font color=#AF0AAF>Scriptures in <b>purple</b> are niche but still important!</font><br>\
|
||||
<font color=#DAAA18><i>Scriptures with italicized names are important to success.</i></font>"
|
||||
generate_all_scripture()
|
||||
|
||||
data["scripture"] = list()
|
||||
. = list()
|
||||
.["recollection"] = recollecting
|
||||
.["power"] = DisplayPower(get_clockwork_power())
|
||||
.["power_unformatted"] = get_clockwork_power()
|
||||
// .["rec_text"] = recollection() handled TGUI side
|
||||
.["HONOR_RATVAR"] = GLOB.ratvar_awakens
|
||||
.["scripture"] = list()
|
||||
for(var/s in GLOB.all_scripture)
|
||||
var/datum/clockwork_scripture/S = GLOB.all_scripture[s]
|
||||
if(S.tier == selected_scripture) //display only scriptures of the selected tier
|
||||
var/scripture_color = get_component_color_bright(S.primary_component)
|
||||
var/list/temp_info = list("name" = "<font color=[scripture_color]><b>[S.name]</b></font>",
|
||||
"descname" = "<font color=[scripture_color]>([S.descname])</font>",
|
||||
"tip" = "[S.desc]\n[S.usage_tip]",
|
||||
"required" = "([DisplayPower(S.power_cost)][S.special_power_text ? "+ [replacetext(S.special_power_text, "POWERCOST", "[DisplayPower(S.special_power_cost)]")]" : ""])",
|
||||
"type" = "[S.type]",
|
||||
"quickbind" = S.quickbind)
|
||||
if(S.important)
|
||||
temp_info["name"] = "<i>[temp_info["name"]]</i>"
|
||||
var/found = quickbound.Find(S.type)
|
||||
if(found)
|
||||
temp_info["bound"] = "<b>[found]</b>"
|
||||
if(S.invokers_required > 1)
|
||||
temp_info["invokers"] = "<font color=#B18B25>Invokers: <b>[S.invokers_required]</b></font>"
|
||||
data["scripture"] += list(temp_info)
|
||||
data["recollection"] = recollecting
|
||||
if(recollecting)
|
||||
data["recollection_categories"] = GLOB.ratvar_awakens ? list() : list(\
|
||||
list("name" = "Getting Started", "desc" = "First-time servant? Read this first."), \
|
||||
list("name" = "Basics", "desc" = "A primer on how to play as a servant."), \
|
||||
list("name" = "Terminology", "desc" = "Common acronyms, words, and terms."), \
|
||||
list("name" = "Components", "desc" = "Information on components, your primary resource."), \
|
||||
list("name" = "Scripture", "desc" = "Information on scripture, ancient tools used by the cult."), \
|
||||
list("name" = "Power", "desc" = "The power system that certain objects use to function."), \
|
||||
list("name" = "Conversion", "desc" = "Converting the crew, cyborgs, and very walls to your cause."), \
|
||||
)
|
||||
data["rec_text"] = recollection()
|
||||
data["rec_section"] = GLOB.ratvar_awakens ? "" : get_recollection_text(recollection_category)
|
||||
data["rec_binds"] = GLOB.ratvar_awakens ? "" : get_recollection_quickbinds()
|
||||
return data
|
||||
if(S.tier == SCRIPTURE_PERIPHERAL) //yes, tiers are the tabs.
|
||||
continue
|
||||
|
||||
var/list/data = list()
|
||||
data["name"] = S.name
|
||||
data["descname"] = S.descname
|
||||
data["tip"] = "[S.desc]\n[S.usage_tip]"
|
||||
data["required"] = "([DisplayPower(S.power_cost)][S.special_power_text ? "+ [replacetext(S.special_power_text, "POWERCOST", "[DisplayPower(S.special_power_cost)]")]" : ""])"
|
||||
data["required_unformatted"] = S.power_cost
|
||||
data["type"] = "[S.type]"
|
||||
data["quickbind"] = S.quickbind //this is if it cant quickbind
|
||||
data["fontcolor"] = get_component_color_bright(S.primary_component)
|
||||
data["important"] = S.important //italic!
|
||||
|
||||
var/found = quickbound.Find(S.type)
|
||||
if(found)
|
||||
data["bound"] = found //number (pos) on where is it on the list
|
||||
if(S.invokers_required > 1)
|
||||
data["invokers"] = "Invokers: [S.invokers_required]"
|
||||
|
||||
.["rec_binds"] = list()
|
||||
for(var/i in 1 to maximum_quickbound)
|
||||
if(GLOB.ratvar_awakens)
|
||||
return
|
||||
if(LAZYLEN(quickbound) < i || !quickbound[i])
|
||||
.["rec_binds"] += list(list())
|
||||
else
|
||||
var/datum/clockwork_scripture/quickbind_slot = quickbound[i]
|
||||
.["rec_binds"] += list(list(
|
||||
"name" = initial(quickbind_slot.name),
|
||||
"color" = get_component_color_bright(initial(quickbind_slot.primary_component))
|
||||
))
|
||||
|
||||
.["scripture"][S.tier] += list(data)
|
||||
|
||||
/obj/item/clockwork/slab/ui_static_data(mob/user)
|
||||
. = list()
|
||||
.["tier_infos"] = list()
|
||||
.["tier_infos"][SCRIPTURE_DRIVER] = list(
|
||||
"requirement" = "None, this is already unlocked",
|
||||
"ready" = TRUE //to bold it on JS side, and to say "These scriptures are permanently unlocked."
|
||||
)
|
||||
.["tier_infos"][SCRIPTURE_SCRIPT] = list(
|
||||
"requirement" = "These scriptures will automatically unlock when the Ark is halfway ready or if [DisplayPower(SCRIPT_UNLOCK_THRESHOLD)] of power is reached.",
|
||||
"ready" = SSticker.scripture_states[SCRIPTURE_SCRIPT] //huh, on the gamemode ticker? okay...
|
||||
)
|
||||
.["tier_infos"][SCRIPTURE_APPLICATION] = list(
|
||||
"requirement" = "Unlock these optional scriptures by converting another servant or if [DisplayPower(APPLICATION_UNLOCK_THRESHOLD)] of power is reached..",
|
||||
"ready" = SSticker.scripture_states[SCRIPTURE_APPLICATION]
|
||||
)
|
||||
|
||||
// .["selected"] = selected_scripture
|
||||
generate_all_scripture()
|
||||
.["recollection_categories"] = GLOB.ratvar_awakens ? list() : list(
|
||||
list("name" = "Getting Started", "desc" = "First-time servant? Read this first."),
|
||||
list("name" = "Basics", "desc" = "A primer on how to play as a servant."),
|
||||
list("name" = "Terminology", "desc" = "Common acronyms, words, and terms."),
|
||||
list("name" = "Components", "desc" = "Information on components, your primary resource."),
|
||||
list("name" = "Scripture", "desc" = "Information on scripture, ancient tools used by the cult."),
|
||||
list("name" = "Power", "desc" = "The power system that certain objects use to function."),
|
||||
list("name" = "Conversion", "desc" = "Converting the crew, cyborgs, and very walls to your cause.")
|
||||
)
|
||||
// .["rec_section"]["title"] //this is here if ever we decided to return these back.
|
||||
// .["rec_section"]["info"]// wall of info for the thing
|
||||
|
||||
/obj/item/clockwork/slab/ui_act(action, params)
|
||||
switch(action)
|
||||
if("toggle")
|
||||
recollecting = !recollecting
|
||||
if("recite")
|
||||
INVOKE_ASYNC(src, .proc/recite_scripture, text2path(params["category"]), usr, FALSE)
|
||||
if("select")
|
||||
selected_scripture = params["category"]
|
||||
INVOKE_ASYNC(src, .proc/recite_scripture, text2path(params["script"]), usr, FALSE)
|
||||
if("bind")
|
||||
var/datum/clockwork_scripture/path = text2path(params["category"]) //we need a path and not a string
|
||||
var/datum/clockwork_scripture/path = text2path(params["script"]) //we need a path and not a string
|
||||
if(!ispath(path, /datum/clockwork_scripture) || !initial(path.quickbind) || initial(path.tier) == SCRIPTURE_PERIPHERAL) //fuck you href bus
|
||||
to_chat(usr, "<span class='warning'>Nice try using href exploits</span>")
|
||||
return
|
||||
var/found_index = quickbound.Find(path)
|
||||
if(found_index) //hey, we already HAVE this bound
|
||||
if(LAZYLEN(quickbound) == found_index) //if it's the last scripture, remove it instead of leaving a null
|
||||
@@ -512,8 +334,8 @@
|
||||
quickbind_to_slot(path, target_index)
|
||||
if("rec_category")
|
||||
recollection_category = params["category"]
|
||||
ui_interact(usr)
|
||||
return 1
|
||||
update_static_data()
|
||||
return TRUE
|
||||
|
||||
/obj/item/clockwork/slab/proc/quickbind_to_slot(datum/clockwork_scripture/scripture, index) //takes a typepath(typecast for initial()) and binds it to a slot
|
||||
if(!ispath(scripture) || !scripture || (scripture in quickbound))
|
||||
|
||||
@@ -92,6 +92,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
|
||||
//Don't delete upon mind destruction, otherwise soul re-selling will break.
|
||||
delete_on_mind_deletion = FALSE
|
||||
threat = 5
|
||||
show_to_ghosts = TRUE
|
||||
var/obligation
|
||||
var/ban
|
||||
var/bane
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "Sentient Disease"
|
||||
roundend_category = "diseases"
|
||||
antagpanel_category = "Disease"
|
||||
show_to_ghosts = TRUE
|
||||
var/disease_name = ""
|
||||
|
||||
/datum/antagonist/disease/on_gain()
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
var/list/name_source
|
||||
threat = -5
|
||||
show_in_antagpanel = FALSE
|
||||
show_to_ghosts = TRUE
|
||||
antag_moodlet = /datum/mood_event/focused
|
||||
|
||||
/datum/antagonist/ert/on_gain()
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
roundend_category = "monkeys"
|
||||
antagpanel_category = "Monkey"
|
||||
threat = 3
|
||||
show_to_ghosts = TRUE
|
||||
var/datum/team/monkey/monkey_team
|
||||
var/monkey_only = TRUE
|
||||
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
show_in_antagpanel = FALSE
|
||||
show_name_in_check_antagonists = TRUE
|
||||
threat = 5
|
||||
show_to_ghosts = TRUE
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
antagpanel_category = "Ninja"
|
||||
job_rank = ROLE_NINJA
|
||||
show_name_in_check_antagonists = TRUE
|
||||
show_to_ghosts = TRUE
|
||||
antag_moodlet = /datum/mood_event/focused
|
||||
threat = 8
|
||||
var/helping_station = FALSE
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
density = TRUE
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
|
||||
ui_x = 350
|
||||
ui_y = 442
|
||||
|
||||
var/timer_set = 90
|
||||
var/default_timer_set = 90
|
||||
var/minimum_timer_set = 90
|
||||
@@ -262,8 +265,7 @@
|
||||
/obj/machinery/nuclearbomb/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state=GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "nuclear_bomb", name, 350, 442, master_ui, state)
|
||||
ui.set_style(ui_style)
|
||||
ui = new(user, src, ui_key, "NuclearBomb", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/nuclearbomb/ui_data(mob/user)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
antag_moodlet = /datum/mood_event/focused
|
||||
threat = 10
|
||||
skill_modifiers = list(/datum/skill_modifier/job/level/wiring)
|
||||
show_to_ghosts = TRUE
|
||||
var/datum/team/nuclear/nuke_team
|
||||
var/always_new_team = FALSE //If not assigned a team by default ops will try to join existing ones, set this to TRUE to always create new team.
|
||||
var/send_to_spawnpoint = TRUE //Should the user be moved to default spawnpoint.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
show_in_antagpanel = FALSE
|
||||
var/datum/objective/mission
|
||||
var/datum/team/ert/ert_team
|
||||
show_to_ghosts = TRUE
|
||||
|
||||
/datum/antagonist/official/greet()
|
||||
to_chat(owner, "<B><font size=3 color=red>You are a CentCom Official.</font></B>")
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
roundend_category = "space pirates"
|
||||
antagpanel_category = "Pirate"
|
||||
threat = 5
|
||||
show_to_ghosts = TRUE
|
||||
var/datum/team/pirate/crew
|
||||
|
||||
/datum/antagonist/pirate/greet()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
show_in_antagpanel = FALSE
|
||||
show_name_in_check_antagonists = TRUE
|
||||
threat = 5
|
||||
show_to_ghosts = TRUE
|
||||
|
||||
/datum/antagonist/revenant/greet()
|
||||
owner.announce_objectives()
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/datum/antagonist/santa
|
||||
name = "Santa"
|
||||
show_in_antagpanel = FALSE
|
||||
show_name_in_check_antagonists = TRUE
|
||||
show_to_ghosts = TRUE
|
||||
|
||||
/datum/antagonist/santa/on_gain()
|
||||
. = ..()
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
threat = 10
|
||||
job_rank = ROLE_ALIEN
|
||||
show_in_antagpanel = FALSE
|
||||
show_to_ghosts = TRUE
|
||||
|
||||
/datum/antagonist/slaughter/on_gain()
|
||||
forge_objectives()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Support unit gets it's own very basic antag datum for admin logging.
|
||||
/// Support unit gets it's own very basic antag datum for admin logging.
|
||||
/datum/antagonist/traitor/contractor_support
|
||||
name = "Contractor Support Unit"
|
||||
antag_moodlet = /datum/mood_event/focused
|
||||
@@ -8,11 +8,13 @@
|
||||
should_equip = FALSE /// Don't give them an uplink.
|
||||
var/datum/team/contractor_team/contractor_team
|
||||
|
||||
/datum/team/contractor_team // Team for storing both the contractor and their support unit - only really for the HUD and admin logging.
|
||||
/// Team for storing both the contractor and their support unit - only really for the HUD and admin logging.
|
||||
/datum/team/contractor_team
|
||||
show_roundend_report = FALSE
|
||||
|
||||
/datum/antagonist/traitor/contractor_support/forge_traitor_objectives()
|
||||
var/datum/objective/generic_objective = new
|
||||
|
||||
generic_objective.name = "Follow Contractor's Orders"
|
||||
generic_objective.explanation_text = "Follow your orders. Assist agents in this mission area."
|
||||
generic_objective.completed = TRUE
|
||||
@@ -25,7 +27,9 @@
|
||||
var/static/list/contractor_items = typecacheof(/datum/contractor_item/, TRUE)
|
||||
var/datum/syndicate_contract/current_contract
|
||||
var/list/datum/syndicate_contract/assigned_contracts = list()
|
||||
|
||||
var/list/assigned_targets = list() // used as a blacklist to make sure we're not assigning targets already assigned
|
||||
var/contracts_completed = 0
|
||||
var/contract_TC_payed_out = 0 // Keeping track for roundend reporting
|
||||
var/contract_TC_to_redeem = 0 // Used internally and roundend reporting - what TC we have available to cashout.
|
||||
|
||||
@@ -34,7 +38,8 @@
|
||||
var/datum/contractor_item/contractor_item = new path
|
||||
hub_items.Add(contractor_item)
|
||||
|
||||
/datum/contractor_hub/proc/create_contracts(datum/mind/owner) // 6 initial contracts
|
||||
/datum/contractor_hub/proc/create_contracts(datum/mind/owner)
|
||||
// 6 initial contracts
|
||||
var/list/to_generate = list(
|
||||
CONTRACT_PAYOUT_LARGE,
|
||||
CONTRACT_PAYOUT_MEDIUM,
|
||||
@@ -44,61 +49,74 @@
|
||||
CONTRACT_PAYOUT_SMALL
|
||||
)
|
||||
|
||||
var/lowest_TC_threshold = 30 // We don't want the sum of all the payouts to be under this amount
|
||||
//What the fuck
|
||||
if(length(to_generate) > length(GLOB.data_core.locked))
|
||||
to_generate.Cut(1, length(GLOB.data_core.locked))
|
||||
// We don't want the sum of all the payouts to be under this amount
|
||||
var/lowest_TC_threshold = 30
|
||||
|
||||
var/total = 0
|
||||
var/lowest_paying_sum = 0
|
||||
var/datum/syndicate_contract/lowest_paying_contract
|
||||
|
||||
to_generate = shuffle(to_generate) // Randomise order, so we don't have contracts always in payout order.
|
||||
var/start_index = 1 // Support contract generation happening multiple times
|
||||
if(assigned_contracts.len != 0)
|
||||
// Randomise order, so we don't have contracts always in payout order.
|
||||
to_generate = shuffle(to_generate)
|
||||
// Support contract generation happening multiple times
|
||||
var/start_index = 1
|
||||
if (assigned_contracts.len != 0)
|
||||
start_index = assigned_contracts.len + 1
|
||||
|
||||
for(var/i = 1; i <= to_generate.len; i++) // Generate contracts, and find the lowest paying.
|
||||
// Generate contracts, and find the lowest paying.
|
||||
for (var/i = 1; i <= to_generate.len; i++)
|
||||
var/datum/syndicate_contract/contract_to_add = new(owner, assigned_targets, to_generate[i])
|
||||
var/contract_payout_total = contract_to_add.contract.payout + contract_to_add.contract.payout_bonus
|
||||
assigned_targets.Add(contract_to_add.contract.target)
|
||||
if(!lowest_paying_contract || (contract_payout_total < lowest_paying_sum))
|
||||
if (!lowest_paying_contract || (contract_payout_total < lowest_paying_sum))
|
||||
lowest_paying_sum = contract_payout_total
|
||||
lowest_paying_contract = contract_to_add
|
||||
total += contract_payout_total
|
||||
contract_to_add.id = start_index
|
||||
assigned_contracts.Add(contract_to_add)
|
||||
start_index++
|
||||
if(total < lowest_TC_threshold) // If the threshold for TC payouts isn't reached, boost the lowest paying contract
|
||||
|
||||
// If the threshold for TC payouts isn't reached, boost the lowest paying contract
|
||||
if (total < lowest_TC_threshold)
|
||||
lowest_paying_contract.contract.payout_bonus += (lowest_TC_threshold - total)
|
||||
|
||||
/datum/contractor_item
|
||||
var/name // Name of item
|
||||
var/desc // description of item
|
||||
var/item // item path, no item path means the purchase needs it's own handle_purchase()
|
||||
var/item_icon = "fa-broadcast-tower" // fontawesome icon to use inside the hub - https://fontawesome.com/icons/
|
||||
var/item_icon = "broadcast-tower" // fontawesome icon to use inside the hub - https://fontawesome.com/icons/
|
||||
var/limited = -1 // Any number above 0 for how many times it can be bought in a round for a single traitor. -1 is unlimited.
|
||||
var/cost // Cost of the item in contract rep.
|
||||
|
||||
/datum/contractor_item/contract_reroll
|
||||
name = "Contract Reroll"
|
||||
desc = "Request a reroll of your current contract list. Will generate a new target, payment, and dropoff for the contracts you currently have available."
|
||||
item_icon = "fa-dice"
|
||||
item_icon = "dice"
|
||||
limited = 2
|
||||
cost = 0
|
||||
|
||||
/datum/contractor_item/contract_reroll/handle_purchase(var/datum/contractor_hub/hub)
|
||||
. = ..()
|
||||
if (.)
|
||||
var/list/new_target_list = list() // We're not regenerating already completed/aborted/extracting contracts, but we don't want to repeat their targets.
|
||||
/// We're not regenerating already completed/aborted/extracting contracts, but we don't want to repeat their targets.
|
||||
var/list/new_target_list = list()
|
||||
for(var/datum/syndicate_contract/contract_check in hub.assigned_contracts)
|
||||
if (contract_check.status != CONTRACT_STATUS_ACTIVE && contract_check.status != CONTRACT_STATUS_INACTIVE)
|
||||
if (contract_check.contract.target)
|
||||
new_target_list.Add(contract_check.contract.target)
|
||||
continue
|
||||
for(var/datum/syndicate_contract/rerolling_contract in hub.assigned_contracts) // Reroll contracts without duplicates
|
||||
/// Reroll contracts without duplicates
|
||||
for(var/datum/syndicate_contract/rerolling_contract in hub.assigned_contracts)
|
||||
if (rerolling_contract.status != CONTRACT_STATUS_ACTIVE && rerolling_contract.status != CONTRACT_STATUS_INACTIVE)
|
||||
continue
|
||||
rerolling_contract.generate(new_target_list)
|
||||
new_target_list.Add(rerolling_contract.contract.target)
|
||||
hub.assigned_targets = new_target_list // Set our target list with the new set we've generated.
|
||||
|
||||
/// Set our target list with the new set we've generated.
|
||||
hub.assigned_targets = new_target_list
|
||||
/datum/contractor_item/contractor_pinpointer
|
||||
name = "Contractor Pinpointer"
|
||||
desc = "A pinpointer that finds targets even without active suit sensors. Due to taking advantage of an exploit within the system, it can't pinpoint to the same accuracy as the traditional models. Becomes permanently locked to the user that first activates it."
|
||||
@@ -125,20 +143,25 @@
|
||||
|
||||
/datum/contractor_item/contractor_partner/handle_purchase(var/datum/contractor_hub/hub, mob/living/user)
|
||||
. = ..()
|
||||
|
||||
if (.)
|
||||
to_chat(user, "<span class='notice'>The uplink vibrates quietly, connecting to nearby agents...</span>")
|
||||
var/list/mob/candidates = pollGhostCandidates("Do you want to play as the Contractor Support Unit for [user.real_name]?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_CONTRACTOR_SUPPORT)
|
||||
|
||||
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the Contractor Support Unit for [user.real_name]?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_CONTRACTOR_SUPPORT)
|
||||
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
spawn_contractor_partner(user, C.key)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>No available agents at this time, please try again later.</span>")
|
||||
limited += 1 // refund and add the limit back.
|
||||
// refund and add the limit back.
|
||||
limited += 1
|
||||
hub.contract_rep += cost
|
||||
hub.purchased_items -= src
|
||||
|
||||
/datum/outfit/contractor_partner
|
||||
name = "Contractor Support Unit"
|
||||
|
||||
uniform = /obj/item/clothing/under/chameleon
|
||||
suit = /obj/item/clothing/suit/chameleon
|
||||
back = /obj/item/storage/backpack
|
||||
@@ -148,28 +171,35 @@
|
||||
ears = /obj/item/radio/headset/chameleon
|
||||
id = /obj/item/card/id/syndicate
|
||||
r_hand = /obj/item/storage/toolbox/syndicate
|
||||
|
||||
backpack_contents = list(/obj/item/storage/box/survival, /obj/item/implanter/uplink, /obj/item/clothing/mask/chameleon,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/lighter)
|
||||
|
||||
/datum/outfit/contractor_partner/post_equip(mob/living/carbon/human/H, visualsOnly)
|
||||
. = ..()
|
||||
var/obj/item/clothing/mask/cigarette/syndicate/cig = H.get_item_by_slot(SLOT_WEAR_MASK)
|
||||
cig.light() // pre-light their cig for extra badass
|
||||
var/obj/item/clothing/mask/cigarette/syndicate/cig = H.get_item_by_slot(ITEM_SLOT_MASK)
|
||||
// pre-light their cig
|
||||
cig.light()
|
||||
|
||||
/datum/contractor_item/contractor_partner/proc/spawn_contractor_partner(mob/living/user, key)
|
||||
var/mob/living/carbon/human/partner = new()
|
||||
var/datum/outfit/contractor_partner/partner_outfit = new()
|
||||
|
||||
partner_outfit.equip(partner)
|
||||
|
||||
var/obj/structure/closet/supplypod/arrival_pod = new()
|
||||
|
||||
arrival_pod.style = STYLE_SYNDICATE
|
||||
arrival_pod.explosionSize = list(0,0,0,1)
|
||||
arrival_pod.bluespace = TRUE
|
||||
var/turf/free_location = find_obstruction_free_location(2, user)
|
||||
if (!free_location) // We really want to send them - if we can't find a nice location just land it on top of them.
|
||||
// We really want to send them - if we can't find a nice location just land it on top of them.
|
||||
if (!free_location)
|
||||
free_location = get_turf(user)
|
||||
partner.forceMove(arrival_pod)
|
||||
partner.ckey = key
|
||||
partner_mind = partner.mind // We give a reference to the mind that'll be the support unit
|
||||
/// We give a reference to the mind that'll be the support unit
|
||||
partner_mind = partner.mind
|
||||
partner_mind.make_Contractor_Support()
|
||||
to_chat(partner_mind.current, "\n<span class='alertwarning'>[user.real_name] is your superior. Follow any, and all orders given by them. You're here to support their mission only.</span>")
|
||||
to_chat(partner_mind.current, "<span class='alertwarning'>Should they perish, or be otherwise unavailable, you're to assist other active agents in this mission area to the best of your ability.</span>\n\n")
|
||||
@@ -186,7 +216,7 @@
|
||||
. = ..()
|
||||
if (.)
|
||||
power_fail(35, 50)
|
||||
priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", "poweroff")
|
||||
priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", "poweroff.ogg")
|
||||
|
||||
// Subtract cost, and spawn if it's an item.
|
||||
/datum/contractor_item/proc/handle_purchase(var/datum/contractor_hub/hub, mob/living/user)
|
||||
@@ -199,6 +229,7 @@
|
||||
else if (limited == 0)
|
||||
return FALSE
|
||||
hub.purchased_items.Add(src)
|
||||
user.playsound_local(user, 'sound/machines/uplinkpurchase.ogg', 100)
|
||||
if (item && ispath(item))
|
||||
var/atom/item_to_create = new item(get_turf(user))
|
||||
|
||||
|
||||
@@ -4,47 +4,70 @@
|
||||
var/datum/objective/contract/contract = new()
|
||||
var/target_rank
|
||||
var/ransom = 0
|
||||
var/payout_type = null
|
||||
var/payout_type
|
||||
var/wanted_message
|
||||
|
||||
var/list/victim_belongings = list()
|
||||
|
||||
/datum/syndicate_contract/New(contract_owner, blacklist, type=CONTRACT_PAYOUT_SMALL)
|
||||
contract.owner = contract_owner
|
||||
payout_type = type
|
||||
|
||||
generate(blacklist)
|
||||
|
||||
/datum/syndicate_contract/proc/generate(blacklist)
|
||||
contract.find_target(null, blacklist)
|
||||
var/datum/data/record/record = find_record("name", contract.target.name, GLOB.data_core.general)
|
||||
if(record)
|
||||
|
||||
var/datum/data/record/record
|
||||
if (contract.target)
|
||||
record = find_record("name", contract.target.name, GLOB.data_core.general)
|
||||
|
||||
if (record)
|
||||
target_rank = record.fields["rank"]
|
||||
else
|
||||
target_rank = "Unknown"
|
||||
|
||||
if (payout_type == CONTRACT_PAYOUT_LARGE)
|
||||
contract.payout_bonus = rand(9,13)
|
||||
else if(payout_type == CONTRACT_PAYOUT_MEDIUM)
|
||||
else if (payout_type == CONTRACT_PAYOUT_MEDIUM)
|
||||
contract.payout_bonus = rand(6,8)
|
||||
else
|
||||
contract.payout_bonus = rand(2,4)
|
||||
|
||||
contract.payout = rand(0, 2)
|
||||
contract.generate_dropoff()
|
||||
|
||||
ransom = 100 * rand(18, 45)
|
||||
|
||||
var/base = pick_list(WANTED_FILE, "basemessage")
|
||||
var/verb_string = pick_list(WANTED_FILE, "verb")
|
||||
var/noun = pick_list_weighted(WANTED_FILE, "noun")
|
||||
var/location = pick_list_weighted(WANTED_FILE, "location")
|
||||
wanted_message = "[base] [verb_string] [noun] [location]."
|
||||
|
||||
/datum/syndicate_contract/proc/handle_extraction(var/mob/living/user)
|
||||
if (contract.target && contract.dropoff_check(user, contract.target.current))
|
||||
|
||||
var/turf/free_location = find_obstruction_free_location(3, user, contract.dropoff)
|
||||
if(free_location) // We've got a valid location, launch.
|
||||
|
||||
if (free_location)
|
||||
// We've got a valid location, launch.
|
||||
launch_extraction_pod(free_location)
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
// Launch the pod to collect our victim.
|
||||
/datum/syndicate_contract/proc/launch_extraction_pod(turf/empty_pod_turf)
|
||||
var/obj/structure/closet/supplypod/extractionpod/empty_pod = new()
|
||||
|
||||
RegisterSignal(empty_pod, COMSIG_ATOM_ENTERED, .proc/enter_check)
|
||||
|
||||
empty_pod.stay_after_drop = TRUE
|
||||
empty_pod.reversing = TRUE
|
||||
empty_pod.explosionSize = list(0,0,0,1)
|
||||
empty_pod.leavingSound = 'sound/effects/podwoosh.ogg'
|
||||
|
||||
new /obj/effect/abstract/DPtarget(empty_pod_turf, empty_pod)
|
||||
|
||||
/datum/syndicate_contract/proc/enter_check(datum/source, sent_mob)
|
||||
@@ -52,37 +75,55 @@
|
||||
if(isliving(sent_mob))
|
||||
var/mob/living/M = sent_mob
|
||||
var/datum/antagonist/traitor/traitor_data = contract.owner.has_antag_datum(/datum/antagonist/traitor)
|
||||
|
||||
if(M == contract.target.current)
|
||||
traitor_data.contractor_hub.contract_TC_to_redeem += contract.payout
|
||||
traitor_data.contractor_hub.contracts_completed += 1
|
||||
|
||||
if(M.stat != DEAD)
|
||||
traitor_data.contractor_hub.contract_TC_to_redeem += contract.payout_bonus
|
||||
|
||||
status = CONTRACT_STATUS_COMPLETE
|
||||
|
||||
if(traitor_data.contractor_hub.current_contract == src)
|
||||
traitor_data.contractor_hub.current_contract = null
|
||||
|
||||
traitor_data.contractor_hub.contract_rep += 2
|
||||
else
|
||||
status = CONTRACT_STATUS_ABORTED // Sending a target that wasn't even yours is as good as just aborting it
|
||||
|
||||
if(traitor_data.contractor_hub.current_contract == src)
|
||||
traitor_data.contractor_hub.current_contract = null
|
||||
|
||||
if(iscarbon(M))
|
||||
for(var/obj/item/W in M)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(W == H.w_uniform || W == H.shoes)
|
||||
continue //So all they're left with are shoes and uniform.
|
||||
if(W == H.w_uniform)
|
||||
continue //So all they're left with are shoes and uniform.
|
||||
if(W == H.shoes)
|
||||
continue
|
||||
|
||||
|
||||
M.transferItemToLoc(W)
|
||||
victim_belongings.Add(W)
|
||||
|
||||
var/obj/structure/closet/supplypod/extractionpod/pod = source
|
||||
pod.send_up(pod) // Handle the pod returning
|
||||
|
||||
// Handle the pod returning
|
||||
pod.send_up(pod)
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/target = M // After we remove items, at least give them what they need to live.
|
||||
var/mob/living/carbon/human/target = M
|
||||
|
||||
// After we remove items, at least give them what they need to live.
|
||||
target.dna.species.give_important_for_life(target)
|
||||
handleVictimExperience(M) // After pod is sent we start the victim narrative/heal.
|
||||
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
||||
var/points_to_check = min(D.account_balance, ransom)
|
||||
D.adjust_money(min(points_to_check, ransom))
|
||||
priority_announce("One of your crew was captured by a rival organisation - we've needed to pay their ransom to bring them back. \
|
||||
As is policy we've taken a portion of the station's funds to offset the overall cost.", null, "attention", null, "Nanotrasen Asset Protection")
|
||||
As is policy we've taken a portion of the station's funds to offset the overall cost.", null, "attention", null, "Nanotrasen Asset Protection")
|
||||
|
||||
sleep(30)
|
||||
|
||||
@@ -128,13 +169,18 @@
|
||||
M.Dizzy(15)
|
||||
M.confused += 20
|
||||
|
||||
/datum/syndicate_contract/proc/returnVictim(var/mob/living/M) // We're returning the victim
|
||||
// We're returning the victim
|
||||
/datum/syndicate_contract/proc/returnVictim(var/mob/living/M)
|
||||
var/list/possible_drop_loc = list()
|
||||
|
||||
for(var/turf/possible_drop in contract.dropoff.contents)
|
||||
if(!is_blocked_turf(possible_drop))
|
||||
possible_drop_loc.Add(possible_drop)
|
||||
if(!isspaceturf(possible_drop) && !isclosedturf(possible_drop))
|
||||
if(!is_blocked_turf(possible_drop))
|
||||
possible_drop_loc.Add(possible_drop)
|
||||
|
||||
if(possible_drop_loc.len > 0)
|
||||
var/pod_rand_loc = rand(1, possible_drop_loc.len)
|
||||
|
||||
var/obj/structure/closet/supplypod/return_pod = new()
|
||||
return_pod.bluespace = TRUE
|
||||
return_pod.explosionSize = list(0,0,0,0)
|
||||
@@ -144,8 +190,10 @@
|
||||
for(var/obj/item/W in M)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(W == H.w_uniform || W == H.shoes)
|
||||
if(W == H.w_uniform)
|
||||
continue //So all they're left with are shoes and uniform.
|
||||
if(W == H.shoes)
|
||||
continue
|
||||
M.dropItemToGround(W)
|
||||
for(var/obj/item/W in victim_belongings)
|
||||
W.forceMove(return_pod)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
var/move_to_lair = TRUE
|
||||
var/outfit_type = /datum/outfit/wizard
|
||||
var/wiz_age = WIZARD_AGE_MIN /* Wizards by nature cannot be too young. */
|
||||
show_to_ghosts = TRUE
|
||||
|
||||
/datum/antagonist/wizard/on_gain()
|
||||
register()
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
name = "Xenomorph"
|
||||
job_rank = ROLE_ALIEN
|
||||
show_in_antagpanel = FALSE
|
||||
show_to_ghosts = TRUE
|
||||
var/datum/team/xeno/xeno_team
|
||||
threat = 3
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
icon_state = "health"
|
||||
custom_materials = list(/datum/material/iron=800, /datum/material/glass=200)
|
||||
attachable = TRUE
|
||||
secured = FALSE
|
||||
|
||||
var/scanning = FALSE
|
||||
var/health_scan
|
||||
@@ -12,7 +11,8 @@
|
||||
|
||||
/obj/item/assembly/health/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Use a multitool to swap between \"detect death\" mode and \"detect critical state\" mode.</span>"
|
||||
. += "Use it in hand to turn it off/on and Alt-click to swap between \"detect death\" mode and \"detect critical state\" mode."
|
||||
. += "[src.scanning ? "The sensor is on and you can see [health_scan] displayed on the screen" : "The sensor is off"]."
|
||||
|
||||
/obj/item/assembly/health/activate()
|
||||
if(!..())
|
||||
@@ -30,14 +30,13 @@
|
||||
update_icon()
|
||||
return secured
|
||||
|
||||
/obj/item/assembly/health/multitool_act(mob/living/user, obj/item/I)
|
||||
/obj/item/assembly/health/AltClick(mob/living/user)
|
||||
if(alarm_health == HEALTH_THRESHOLD_CRIT)
|
||||
alarm_health = HEALTH_THRESHOLD_DEAD
|
||||
to_chat(user, "<span class='notice'>You toggle [src] to \"detect death\" mode.</span>")
|
||||
else
|
||||
alarm_health = HEALTH_THRESHOLD_CRIT
|
||||
to_chat(user, "<span class='notice'>You toggle [src] to \"detect critical state\" mode.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/health/process()
|
||||
if(!scanning || !secured)
|
||||
@@ -46,7 +45,6 @@
|
||||
var/atom/A = src
|
||||
if(connected && connected.holder)
|
||||
A = connected.holder
|
||||
|
||||
for(A, A && !ismob(A), A=A.loc);
|
||||
// like get_turf(), but for mobs.
|
||||
var/mob/living/M = A
|
||||
@@ -71,36 +69,7 @@
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return
|
||||
|
||||
/obj/item/assembly/health/ui_interact(mob/user as mob)//TODO: Change this to the wires thingy
|
||||
/obj/item/assembly/health/attack_self(mob/user)
|
||||
. = ..()
|
||||
if(!secured)
|
||||
user.show_message("<span class='warning'>The [name] is unsecured!</span>")
|
||||
return FALSE
|
||||
var/dat = "<TT><B>Health Sensor</B></TT>"
|
||||
dat += "<BR><A href='?src=[REF(src)];scanning=1'>[scanning?"On":"Off"]</A>"
|
||||
if(scanning && health_scan)
|
||||
dat += "<BR>Health: [health_scan]"
|
||||
user << browse(dat, "window=hscan")
|
||||
onclose(user, "hscan")
|
||||
|
||||
/obj/item/assembly/health/Topic(href, href_list)
|
||||
..()
|
||||
if(!ismob(usr))
|
||||
return
|
||||
|
||||
var/mob/user = usr
|
||||
|
||||
if(!user.canUseTopic(src))
|
||||
usr << browse(null, "window=hscan")
|
||||
onclose(usr, "hscan")
|
||||
return
|
||||
|
||||
if(href_list["scanning"])
|
||||
toggle_scan()
|
||||
|
||||
if(href_list["close"])
|
||||
usr << browse(null, "window=hscan")
|
||||
return
|
||||
|
||||
attack_self(user)
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You toggle [src] [src.scanning ? "off" : "on"].</span>")
|
||||
toggle_scan()
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
icon_state = "infrared"
|
||||
custom_materials = list(/datum/material/iron=1000, /datum/material/glass=500)
|
||||
is_position_sensitive = TRUE
|
||||
|
||||
var/ui_x = 225
|
||||
var/ui_y = 110
|
||||
var/on = FALSE
|
||||
var/visible = FALSE
|
||||
var/maxlength = 8
|
||||
@@ -38,7 +39,7 @@
|
||||
|
||||
/obj/item/assembly/infra/activate()
|
||||
if(!..())
|
||||
return FALSE//Cooldown check
|
||||
return FALSE //Cooldown check
|
||||
on = !on
|
||||
refreshBeam()
|
||||
update_icon()
|
||||
@@ -69,7 +70,7 @@
|
||||
holder.update_icon()
|
||||
return
|
||||
|
||||
/obj/item/assembly/infra/dropped(mob/user)
|
||||
/obj/item/assembly/infra/dropped()
|
||||
. = ..()
|
||||
if(holder)
|
||||
holder_movement() //sync the dir of the device as well if it's contained in a TTV or an assembly holder
|
||||
@@ -133,7 +134,7 @@
|
||||
. = ..()
|
||||
setDir(t)
|
||||
|
||||
/obj/item/assembly/infra/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
|
||||
/obj/item/assembly/infra/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, gentle = FALSE)
|
||||
. = ..()
|
||||
olddir = dir
|
||||
|
||||
@@ -176,55 +177,56 @@
|
||||
return
|
||||
return refreshBeam()
|
||||
|
||||
/obj/item/assembly/infra/ui_interact(mob/user)//TODO: change this this to the wire control panel
|
||||
. = ..()
|
||||
if(is_secured(user))
|
||||
user.set_machine(src)
|
||||
var/dat = "<TT><B>Infrared Laser</B></TT>"
|
||||
dat += "<BR><B>Status</B>: [on ? "<A href='?src=[REF(src)];state=0'>On</A>" : "<A href='?src=[REF(src)];state=1'>Off</A>"]"
|
||||
dat += "<BR><B>Visibility</B>: [visible ? "<A href='?src=[REF(src)];visible=0'>Visible</A>" : "<A href='?src=[REF(src)];visible=1'>Invisible</A>"]"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];refresh=1'>Refresh</A>"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];close=1'>Close</A>"
|
||||
user << browse(dat, "window=infra")
|
||||
onclose(user, "infra")
|
||||
return
|
||||
|
||||
/obj/item/assembly/infra/Topic(href, href_list)
|
||||
..()
|
||||
if(usr.incapacitated() || !in_range(loc, usr))
|
||||
usr << browse(null, "window=infra")
|
||||
onclose(usr, "infra")
|
||||
return
|
||||
if(href_list["state"])
|
||||
on = !(on)
|
||||
update_icon()
|
||||
refreshBeam()
|
||||
if(href_list["visible"])
|
||||
visible = !(visible)
|
||||
update_icon()
|
||||
refreshBeam()
|
||||
if(href_list["close"])
|
||||
usr << browse(null, "window=infra")
|
||||
return
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
|
||||
/obj/item/assembly/infra/setDir()
|
||||
. = ..()
|
||||
refreshBeam()
|
||||
|
||||
/obj/item/assembly/infra/ui_status(mob/user)
|
||||
if(is_secured(user))
|
||||
return ..()
|
||||
return UI_CLOSE
|
||||
|
||||
/obj/item/assembly/infra/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "InfraredEmitter", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/assembly/infra/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["on"] = on
|
||||
data["visible"] = visible
|
||||
return data
|
||||
|
||||
/obj/item/assembly/infra/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("power")
|
||||
on = !on
|
||||
. = TRUE
|
||||
if("visibility")
|
||||
visible = !visible
|
||||
. = TRUE
|
||||
|
||||
update_icon()
|
||||
refreshBeam()
|
||||
|
||||
/***************************IBeam*********************************/
|
||||
|
||||
/obj/effect/beam/i_beam
|
||||
name = "infrared beam"
|
||||
icon = 'icons/obj/projectiles.dmi'
|
||||
icon_state = "ibeam"
|
||||
var/obj/item/assembly/infra/master
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
pass_flags = PASSTABLE|PASSGLASS|PASSGRILLE|LETPASSTHROW
|
||||
var/obj/item/assembly/infra/master
|
||||
|
||||
/obj/effect/beam/i_beam/Crossed(atom/movable/AM as mob|obj)
|
||||
. = ..()
|
||||
if(istype(AM, /obj/effect/beam))
|
||||
return
|
||||
if (isitem(AM))
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
icon_state = "prox"
|
||||
custom_materials = list(/datum/material/iron=800, /datum/material/glass=200)
|
||||
attachable = TRUE
|
||||
|
||||
var/ui_x = 250
|
||||
var/ui_y = 185
|
||||
var/scanning = FALSE
|
||||
var/timing = FALSE
|
||||
var/time = 10
|
||||
@@ -26,7 +27,7 @@
|
||||
|
||||
/obj/item/assembly/prox_sensor/activate()
|
||||
if(!..())
|
||||
return FALSE//Cooldown check
|
||||
return FALSE //Cooldown check
|
||||
if(!scanning)
|
||||
timing = !timing
|
||||
else
|
||||
@@ -41,7 +42,6 @@
|
||||
else
|
||||
proximity_monitor.SetHost(src,src)
|
||||
|
||||
|
||||
/obj/item/assembly/prox_sensor/toggle_secure()
|
||||
secured = !secured
|
||||
if(!secured)
|
||||
@@ -56,8 +56,6 @@
|
||||
update_icon()
|
||||
return secured
|
||||
|
||||
|
||||
|
||||
/obj/item/assembly/prox_sensor/HasProximity(atom/movable/AM as mob|obj)
|
||||
if (istype(AM, /obj/effect/beam))
|
||||
return
|
||||
@@ -75,7 +73,6 @@
|
||||
next_activate = world.time + 30
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/assembly/prox_sensor/process()
|
||||
if(!timing)
|
||||
return
|
||||
@@ -111,50 +108,47 @@
|
||||
holder.update_icon()
|
||||
return
|
||||
|
||||
/obj/item/assembly/prox_sensor/ui_interact(mob/user)//TODO: Change this to the wires thingy
|
||||
. = ..()
|
||||
/obj/item/assembly/prox_sensor/ui_status(mob/user)
|
||||
if(is_secured(user))
|
||||
var/second = time % 60
|
||||
var/minute = (time - second) / 60
|
||||
var/dat = "<TT><B>Proximity Sensor</B></TT>"
|
||||
if(!scanning)
|
||||
dat += "<BR>[(timing ? "<A href='?src=[REF(src)];time=0'>Arming</A>" : "<A href='?src=[REF(src)];time=1'>Not Arming</A>")] [minute]:[second]"
|
||||
dat += "<BR><A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>"
|
||||
dat += "<BR><A href='?src=[REF(src)];scanning=[scanning?"0'>Armed":"1'>Unarmed (Movement sensor active when armed!)"]</A>"
|
||||
dat += "<BR>Detection range: <A href='?src=[REF(src)];sense=down'>-</A> [sensitivity] <A href='?src=[REF(src)];sense=up'>+</A>"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];refresh=1'>Refresh</A>"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];close=1'>Close</A>"
|
||||
user << browse(dat, "window=prox")
|
||||
onclose(user, "prox")
|
||||
return ..()
|
||||
return UI_CLOSE
|
||||
|
||||
/obj/item/assembly/prox_sensor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "ProximitySensor", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/assembly/prox_sensor/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["seconds"] = round(time % 60)
|
||||
data["minutes"] = round((time - data["seconds"]) / 60)
|
||||
data["timing"] = timing
|
||||
data["scanning"] = scanning
|
||||
data["sensitivity"] = sensitivity
|
||||
return data
|
||||
|
||||
/obj/item/assembly/prox_sensor/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
|
||||
/obj/item/assembly/prox_sensor/Topic(href, href_list)
|
||||
..()
|
||||
if(usr.incapacitated() || !in_range(loc, usr))
|
||||
usr << browse(null, "window=prox")
|
||||
onclose(usr, "prox")
|
||||
return
|
||||
|
||||
if(href_list["sense"])
|
||||
sensitivity_change(((href_list["sense"] == "up") ? 1 : -1))
|
||||
|
||||
if(href_list["scanning"])
|
||||
toggle_scan(text2num(href_list["scanning"]))
|
||||
|
||||
if(href_list["time"])
|
||||
timing = text2num(href_list["time"])
|
||||
update_icon()
|
||||
|
||||
if(href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
time += tp
|
||||
time = min(max(round(time), 0), 600)
|
||||
|
||||
if(href_list["close"])
|
||||
usr << browse(null, "window=prox")
|
||||
return
|
||||
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
|
||||
switch(action)
|
||||
if("scanning")
|
||||
toggle_scan(!scanning)
|
||||
. = TRUE
|
||||
if("sense")
|
||||
var/value = text2num(params["range"])
|
||||
if(value)
|
||||
sensitivity_change(value)
|
||||
. = TRUE
|
||||
if("time")
|
||||
timing = !timing
|
||||
update_icon()
|
||||
. = TRUE
|
||||
if("input")
|
||||
var/value = text2num(params["adjust"])
|
||||
if(value)
|
||||
value = round(time + value)
|
||||
time = clamp(value, 0, 600)
|
||||
. = TRUE
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
custom_materials = list(/datum/material/iron=400, /datum/material/glass=120)
|
||||
wires = WIRE_RECEIVE | WIRE_PULSE | WIRE_RADIO_PULSE | WIRE_RADIO_RECEIVE
|
||||
attachable = TRUE
|
||||
|
||||
var/ui_x = 280
|
||||
var/ui_y = 132
|
||||
var/code = DEFAULT_SIGNALER_CODE
|
||||
var/frequency = FREQ_SIGNALER
|
||||
var/datum/radio_frequency/radio_connection
|
||||
@@ -47,14 +48,16 @@
|
||||
holder.update_icon()
|
||||
return
|
||||
|
||||
/obj/item/assembly/signaler/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
if(!is_secured(user))
|
||||
return
|
||||
/obj/item/assembly/signaler/ui_status(mob/user)
|
||||
if(is_secured(user))
|
||||
return ..()
|
||||
return UI_CLOSE
|
||||
|
||||
/obj/item/assembly/signaler/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
var/ui_width = 280
|
||||
var/ui_height = 132
|
||||
ui = new(user, src, ui_key, "signaler", name, ui_width, ui_height, master_ui, state)
|
||||
ui = new(user, src, ui_key, "Signaler", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/assembly/signaler/ui_data(mob/user)
|
||||
@@ -231,4 +234,4 @@
|
||||
/obj/item/assembly/signaler/cyborg/attackby(obj/item/W, mob/user, params)
|
||||
return
|
||||
/obj/item/assembly/signaler/cyborg/screwdriver_act(mob/living/user, obj/item/I)
|
||||
return
|
||||
return
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
icon_state = "timer"
|
||||
custom_materials = list(/datum/material/iron=500, /datum/material/glass=50)
|
||||
attachable = TRUE
|
||||
|
||||
var/ui_x = 275
|
||||
var/ui_y = 115
|
||||
var/timing = FALSE
|
||||
var/time = 5
|
||||
var/saved_time = 5
|
||||
@@ -41,7 +42,6 @@
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/assembly/timer/toggle_secure()
|
||||
secured = !secured
|
||||
if(secured)
|
||||
@@ -52,7 +52,6 @@
|
||||
update_icon()
|
||||
return secured
|
||||
|
||||
|
||||
/obj/item/assembly/timer/proc/timer_end()
|
||||
if(!secured || next_activate > world.time)
|
||||
return FALSE
|
||||
@@ -66,7 +65,6 @@
|
||||
timing = TRUE
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/item/assembly/timer/process()
|
||||
if(!timing)
|
||||
return
|
||||
@@ -76,7 +74,6 @@
|
||||
timer_end()
|
||||
time = saved_time
|
||||
|
||||
|
||||
/obj/item/assembly/timer/update_icon()
|
||||
cut_overlays()
|
||||
attached_overlays = list()
|
||||
@@ -86,50 +83,44 @@
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
|
||||
|
||||
/obj/item/assembly/timer/ui_interact(mob/user)//TODO: Have this use the wires
|
||||
. = ..()
|
||||
/obj/item/assembly/timer/ui_status(mob/user)
|
||||
if(is_secured(user))
|
||||
var/second = time % 60
|
||||
var/minute = (time - second) / 60
|
||||
var/dat = "<TT><B>Timing Unit</B></TT>"
|
||||
dat += "<BR>[(timing ? "<A href='?src=[REF(src)];time=0'>Timing</A>" : "<A href='?src=[REF(src)];time=1'>Not Timing</A>")] [minute]:[second]"
|
||||
dat += "<BR><A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];repeat=[(loop ? "0'>Stop repeating" : "1'>Set to repeat")]</A>"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];refresh=1'>Refresh</A>"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];close=1'>Close</A>"
|
||||
var/datum/browser/popup = new(user, "timer", name)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
return ..()
|
||||
return UI_CLOSE
|
||||
|
||||
/obj/item/assembly/timer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "Timer", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/assembly/timer/Topic(href, href_list)
|
||||
..()
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
usr << browse(null, "window=timer")
|
||||
onclose(usr, "timer")
|
||||
/obj/item/assembly/timer/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["seconds"] = round(time % 60)
|
||||
data["minutes"] = round((time - data["seconds"]) / 60)
|
||||
data["timing"] = timing
|
||||
data["loop"] = loop
|
||||
return data
|
||||
|
||||
/obj/item/assembly/timer/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["time"])
|
||||
timing = text2num(href_list["time"])
|
||||
if(timing && istype(holder, /obj/item/transfer_valve))
|
||||
var/timer_message = "[ADMIN_LOOKUPFLW(usr)] activated [src] attachment on [holder]."
|
||||
message_admins(timer_message)
|
||||
GLOB.bombers += timer_message
|
||||
log_game("[key_name(usr)] activated [src] attachment on [holder]")
|
||||
update_icon()
|
||||
if(href_list["repeat"])
|
||||
loop = text2num(href_list["repeat"])
|
||||
|
||||
if(href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
time += tp
|
||||
time = min(max(round(time), 1), 600)
|
||||
saved_time = time
|
||||
|
||||
if(href_list["close"])
|
||||
usr << browse(null, "window=timer")
|
||||
return
|
||||
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
switch(action)
|
||||
if("time")
|
||||
timing = !timing
|
||||
if(timing && istype(holder, /obj/item/transfer_valve))
|
||||
log_game(usr, "activated a", src, "attachment on [holder]")
|
||||
update_icon()
|
||||
. = TRUE
|
||||
if("repeat")
|
||||
loop = !loop
|
||||
. = TRUE
|
||||
if("input")
|
||||
var/value = text2num(params["adjust"])
|
||||
if(value)
|
||||
value = round(time + value)
|
||||
time = clamp(value, 1, 600)
|
||||
saved_time = time
|
||||
. = TRUE
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/*
|
||||
Asset cache quick users guide:
|
||||
|
||||
Make a datum in asset_list_items.dm with your assets for your thing.
|
||||
Checkout asset_list.dm for the helper subclasses
|
||||
The simple subclass will most like be of use for most cases.
|
||||
Then call get_asset_datum() with the type of the datum you created and store the return
|
||||
Then call .send(client) on that stored return value.
|
||||
|
||||
Note: If your code uses output() with assets you will need to call asset_flush on the client and wait for it to return before calling output(). You only need do this if .send(client) returned TRUE
|
||||
*/
|
||||
|
||||
@@ -98,3 +100,4 @@ Note: If your code uses output() with assets you will need to call asset_flush o
|
||||
//The same asset will always lead to the same asset name
|
||||
/proc/generate_asset_name(file)
|
||||
return "asset.[md5(fcopy_rsc(file))]"
|
||||
|
||||
|
||||
@@ -226,3 +226,5 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
/datum/asset/simple/icon_states/multiple_icons/register()
|
||||
for(var/i in icons)
|
||||
..(i)
|
||||
|
||||
|
||||
|
||||
@@ -1,27 +1,10 @@
|
||||
//DEFINITIONS FOR ASSET DATUMS START HERE.
|
||||
/* uncomment this and delete the tgui def bellow this for the new tgui
|
||||
|
||||
/datum/asset/simple/tgui
|
||||
assets = list(
|
||||
"tgui.bundle.js" = 'tgui/packages/tgui/public/tgui.bundle.js',
|
||||
"tgui.bundle.css" = 'tgui/packages/tgui/public/tgui.bundle.css',
|
||||
)
|
||||
*/
|
||||
/datum/asset/simple/tgui
|
||||
assets = list(
|
||||
// Old TGUI
|
||||
"tgui.css" = 'tgui/assets/tgui.css',
|
||||
"tgui.js" = 'tgui/assets/tgui.js',
|
||||
// tgui-next
|
||||
"tgui-main.html" = 'tgui-next/packages/tgui/public/tgui-main.html',
|
||||
"tgui.bundle.js" = 'tgui-next/packages/tgui/public/tgui.bundle.js',
|
||||
"tgui.bundle.css" = 'tgui-next/packages/tgui/public/tgui.bundle.css',
|
||||
// Old TGUI compatability
|
||||
"tgui-fallback.html" = 'tgui-next/packages/tgui/public/tgui-fallback.html',
|
||||
"shim-html5shiv.js" = 'tgui-next/packages/tgui/public/shim-html5shiv.js',
|
||||
"shim-ie8.js" = 'tgui-next/packages/tgui/public/shim-ie8.js',
|
||||
"shim-dom4.js" = 'tgui-next/packages/tgui/public/shim-dom4.js',
|
||||
"shim-css-om.js" = 'tgui-next/packages/tgui/public/shim-css-om.js',
|
||||
)
|
||||
|
||||
/datum/asset/group/tgui
|
||||
children = list(
|
||||
@@ -56,17 +39,17 @@
|
||||
"smmon_3.gif" = 'icons/program_icons/smmon_3.gif',
|
||||
"smmon_4.gif" = 'icons/program_icons/smmon_4.gif',
|
||||
"smmon_5.gif" = 'icons/program_icons/smmon_5.gif',
|
||||
"smmon_6.gif" = 'icons/program_icons/smmon_6.gif'
|
||||
//"borg_mon.gif" = 'icons/program_icons/borg_mon.gif'
|
||||
"smmon_6.gif" = 'icons/program_icons/smmon_6.gif',
|
||||
"borg_mon.gif" = 'icons/program_icons/borg_mon.gif'
|
||||
)
|
||||
/* uncomment if you're porting the new ntnet app
|
||||
|
||||
/datum/asset/simple/radar_assets
|
||||
assets = list(
|
||||
"ntosradarbackground.png" = 'icons/UI_Icons/tgui/ntosradar_background.png',
|
||||
"ntosradarpointer.png" = 'icons/UI_Icons/tgui/ntosradar_pointer.png',
|
||||
"ntosradarpointerS.png" = 'icons/UI_Icons/tgui/ntosradar_pointer_S.png'
|
||||
)
|
||||
*/
|
||||
|
||||
/datum/asset/spritesheet/simple/pda
|
||||
name = "pda"
|
||||
assets = list(
|
||||
@@ -95,7 +78,6 @@
|
||||
"refresh" = 'icons/pda_icons/pda_refresh.png',
|
||||
"scanner" = 'icons/pda_icons/pda_scanner.png',
|
||||
"signaler" = 'icons/pda_icons/pda_signaler.png',
|
||||
//"skills" = 'icons/pda_icons/pda_skills.png',
|
||||
"status" = 'icons/pda_icons/pda_status.png',
|
||||
"dronephone" = 'icons/pda_icons/pda_dronephone.png',
|
||||
"emoji" = 'icons/pda_icons/pda_emoji.png'
|
||||
@@ -115,12 +97,9 @@
|
||||
"stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png',
|
||||
"stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png',
|
||||
"stamp-law" = 'icons/stamp_icons/large_stamp-law.png'
|
||||
//"stamp-chap" = 'icons/stamp_icons/large_stamp-chap.png',
|
||||
//"stamp-mime" = 'icons/stamp_icons/large_stamp-mime.png',
|
||||
//"stamp-centcom" = 'icons/stamp_icons/large_stamp-centcom.png',
|
||||
//"stamp-syndicate" = 'icons/stamp_icons/large_stamp-syndicate.png'
|
||||
)
|
||||
|
||||
|
||||
/datum/asset/simple/IRV
|
||||
assets = list(
|
||||
"jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js',
|
||||
@@ -168,12 +147,13 @@
|
||||
"jquery.min.js" = 'code/modules/goonchat/browserassets/js/jquery.min.js',
|
||||
)
|
||||
|
||||
|
||||
/datum/asset/simple/goonchat
|
||||
assets = list(
|
||||
"json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js',
|
||||
"browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js',
|
||||
"browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css',
|
||||
"browserOutput_dark.css" = 'code/modules/goonchat/browserassets/css/browserOutput_dark.css', //dark theme, cit specific
|
||||
"browserOutput_dark.css" = 'code/modules/goonchat/browserassets/css/browserOutput_dark.css',
|
||||
"browserOutput_light.css" = 'code/modules/goonchat/browserassets/css/browserOutput_light.css'
|
||||
)
|
||||
|
||||
@@ -219,6 +199,16 @@
|
||||
"none_button.png" = 'html/none_button.png',
|
||||
)
|
||||
|
||||
/datum/asset/simple/arcade
|
||||
assets = list(
|
||||
"boss1.gif" = 'icons/UI_Icons/Arcade/boss1.gif',
|
||||
"boss2.gif" = 'icons/UI_Icons/Arcade/boss2.gif',
|
||||
"boss3.gif" = 'icons/UI_Icons/Arcade/boss3.gif',
|
||||
"boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif',
|
||||
"boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif',
|
||||
"boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif',
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/minesweeper
|
||||
name = "minesweeper"
|
||||
assets = list(
|
||||
@@ -237,45 +227,7 @@
|
||||
"minehit" = 'icons/UI_Icons/minesweeper_tiles/minehit.png'
|
||||
)
|
||||
|
||||
/* Port the app game thing
|
||||
/datum/asset/simple/arcade
|
||||
assets = list(
|
||||
"boss1.gif" = 'icons/UI_Icons/Arcade/boss1.gif',
|
||||
"boss2.gif" = 'icons/UI_Icons/Arcade/boss2.gif',
|
||||
"boss3.gif" = 'icons/UI_Icons/Arcade/boss3.gif',
|
||||
"boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif',
|
||||
"boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif',
|
||||
"boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif',
|
||||
)
|
||||
*/
|
||||
/*
|
||||
/datum/asset/spritesheet/simple/achievements
|
||||
name ="achievements"
|
||||
assets = list(
|
||||
"default" = 'icons/UI_Icons/Achievements/default.png',
|
||||
"basemisc" = 'icons/UI_Icons/Achievements/basemisc.png',
|
||||
"baseboss" = 'icons/UI_Icons/Achievements/baseboss.png',
|
||||
"baseskill" = 'icons/UI_Icons/Achievements/baseskill.png',
|
||||
"bbgum" = 'icons/UI_Icons/Achievements/Boss/bbgum.png',
|
||||
"colossus" = 'icons/UI_Icons/Achievements/Boss/colossus.png',
|
||||
"hierophant" = 'icons/UI_Icons/Achievements/Boss/hierophant.png',
|
||||
"legion" = 'icons/UI_Icons/Achievements/Boss/legion.png',
|
||||
"miner" = 'icons/UI_Icons/Achievements/Boss/miner.png',
|
||||
"swarmer" = 'icons/UI_Icons/Achievements/Boss/swarmer.png',
|
||||
"tendril" = 'icons/UI_Icons/Achievements/Boss/tendril.png',
|
||||
"featofstrength" = 'icons/UI_Icons/Achievements/Misc/featofstrength.png',
|
||||
"helbital" = 'icons/UI_Icons/Achievements/Misc/helbital.png',
|
||||
"jackpot" = 'icons/UI_Icons/Achievements/Misc/jackpot.png',
|
||||
"meteors" = 'icons/UI_Icons/Achievements/Misc/meteors.png',
|
||||
"timewaste" = 'icons/UI_Icons/Achievements/Misc/timewaste.png',
|
||||
"upgrade" = 'icons/UI_Icons/Achievements/Misc/upgrade.png',
|
||||
"clownking" = 'icons/UI_Icons/Achievements/Misc/clownking.png',
|
||||
"clownthanks" = 'icons/UI_Icons/Achievements/Misc/clownthanks.png',
|
||||
"rule8" = 'icons/UI_Icons/Achievements/Misc/rule8.png',
|
||||
"snail" = 'icons/UI_Icons/Achievements/Misc/snail.png',
|
||||
"mining" = 'icons/UI_Icons/Achievements/Skills/mining.png',
|
||||
)
|
||||
*/
|
||||
|
||||
/datum/asset/spritesheet/simple/pills
|
||||
name ="pills"
|
||||
assets = list(
|
||||
@@ -313,8 +265,8 @@
|
||||
/datum/asset/spritesheet/pipes
|
||||
name = "pipes"
|
||||
|
||||
/datum/asset/spritesheet/pipes/register() //we do not have chempipes
|
||||
for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi', 'icons/obj/atmospherics/pipes/transit_tube.dmi'))
|
||||
/datum/asset/spritesheet/pipes/register()
|
||||
for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi'))
|
||||
InsertAll("", each, GLOB.alldirs)
|
||||
..()
|
||||
|
||||
@@ -323,7 +275,7 @@
|
||||
name = "design"
|
||||
|
||||
/datum/asset/spritesheet/research_designs/register()
|
||||
for(var/path in subtypesof(/datum/design))
|
||||
for (var/path in subtypesof(/datum/design))
|
||||
var/datum/design/D = path
|
||||
|
||||
var/icon_file
|
||||
@@ -381,9 +333,9 @@
|
||||
name = "vending"
|
||||
|
||||
/datum/asset/spritesheet/vending/register()
|
||||
for(var/k in GLOB.vending_products)
|
||||
for (var/k in GLOB.vending_products)
|
||||
var/atom/item = k
|
||||
if(!ispath(item, /atom))
|
||||
if (!ispath(item, /atom))
|
||||
continue
|
||||
|
||||
var/icon_file = initial(item.icon)
|
||||
@@ -394,12 +346,12 @@
|
||||
if(icon_state in icon_states_list)
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
var/c = initial(item.color)
|
||||
if(!isnull(c) && c != "#FFFFFF")
|
||||
if (!isnull(c) && c != "#FFFFFF")
|
||||
I.Blend(c, ICON_MULTIPLY)
|
||||
else
|
||||
var/icon_states_string
|
||||
for(var/an_icon_state in icon_states_list)
|
||||
if(!icon_states_string)
|
||||
for (var/an_icon_state in icon_states_list)
|
||||
if (!icon_states_string)
|
||||
icon_states_string = "[json_encode(an_icon_state)](\ref[an_icon_state])"
|
||||
else
|
||||
icon_states_string += ", [json_encode(an_icon_state)](\ref[an_icon_state])"
|
||||
@@ -418,7 +370,12 @@
|
||||
"dna_extra.gif" = 'html/dna_extra.gif'
|
||||
)
|
||||
|
||||
/datum/asset/simple/vv
|
||||
/datum/asset/simple/orbit
|
||||
assets = list(
|
||||
"view_variables.css" = 'html/admin/view_variables.css'
|
||||
"ghost.png" = 'html/ghost.png'
|
||||
)
|
||||
|
||||
assets = list(
|
||||
"ghost.png" = 'html/ghost.png'
|
||||
)
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -241,7 +241,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "airalarm", name, 440, 650, master_ui, state)
|
||||
ui = new(user, src, ui_key, "AirAlarm", name, 440, 650, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/airalarm/ui_data(mob/user)
|
||||
|
||||
@@ -26,6 +26,21 @@ Passive gate is similar to the regular pump except:
|
||||
construction_type = /obj/item/pipe/directional
|
||||
pipe_state = "passivegate"
|
||||
|
||||
ui_x = 335
|
||||
ui_y = 115
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/passive_gate/CtrlClick(mob/user)
|
||||
if(can_interact(user))
|
||||
on = !on
|
||||
update_icon()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/passive_gate/AltClick(mob/user)
|
||||
if(can_interact(user))
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
update_icon()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/passive_gate/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
@@ -91,7 +106,7 @@ Passive gate is similar to the regular pump except:
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_pump", name, 335, 115, master_ui, state)
|
||||
ui = new(user, src, ui_key, "AtmosPump", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/passive_gate/ui_data()
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_pump", name, 335, 115, master_ui, state)
|
||||
ui = new(user, src, ui_key, "AtmosPump", name, 335, 115, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/pump/ui_data()
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_pump", name, 310, 115, master_ui, state)
|
||||
ui = new(user, src, ui_key, "AtmosPump", name, 310, 115, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/volume_pump/ui_data()
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_filter", name, 475, 185, master_ui, state)
|
||||
ui = new(user, src, ui_key, "AtmosFilter", name, 475, 185, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/ui_data()
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_mixer", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, ui_key, "AtmosMixer", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/mixer/ui_data()
|
||||
|
||||
@@ -324,7 +324,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "cryo", name, 400, 550, master_ui, state)
|
||||
ui = new(user, src, ui_key, "Cryo", name, 400, 550, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/ui_data()
|
||||
|
||||
@@ -20,6 +20,21 @@
|
||||
|
||||
pipe_state = "injector"
|
||||
|
||||
ui_x = 310
|
||||
ui_y = 115
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/outlet_injector/CtrlClick(mob/user)
|
||||
if(can_interact(user))
|
||||
on = !on
|
||||
update_icon()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/outlet_injector/AltClick(mob/user)
|
||||
if(can_interact(user))
|
||||
volume_rate = MAX_TRANSFER_RATE
|
||||
update_icon()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/outlet_injector/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
@@ -140,7 +155,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_pump", name, 310, 115, master_ui, state)
|
||||
ui = new(user, src, ui_key, "AtmosPump", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/outlet_injector/ui_data()
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "thermomachine", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, ui_key, "ThermoMachine", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/thermomachine/ui_data(mob/user)
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
desc = "A canister for the storage of gas."
|
||||
icon_state = "yellow"
|
||||
density = TRUE
|
||||
ui_x = 300
|
||||
ui_y = 232
|
||||
|
||||
var/valve_open = FALSE
|
||||
var/obj/machinery/atmospherics/components/binary/passive_gate/pump
|
||||
@@ -34,6 +36,7 @@
|
||||
var/restricted = FALSE
|
||||
req_access = list()
|
||||
|
||||
var/update = 0
|
||||
var/static/list/label2types = list(
|
||||
"n2" = /obj/machinery/portable_atmospherics/canister/nitrogen,
|
||||
"o2" = /obj/machinery/portable_atmospherics/canister/oxygen,
|
||||
@@ -159,11 +162,11 @@
|
||||
/obj/machinery/portable_atmospherics/canister/proto
|
||||
name = "prototype canister"
|
||||
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/proto/default
|
||||
name = "prototype canister"
|
||||
desc = "The best way to fix an atmospheric emergency... or the best way to introduce one."
|
||||
icon_state = "proto"
|
||||
icon_state = "proto"
|
||||
volume = 5000
|
||||
max_integrity = 300
|
||||
temperature_resistance = 2000 + T0C
|
||||
@@ -171,6 +174,7 @@
|
||||
can_min_release_pressure = (ONE_ATMOSPHERE / 30)
|
||||
prototype = TRUE
|
||||
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/proto/default/oxygen
|
||||
name = "prototype canister"
|
||||
desc = "A prototype canister for a prototype bike, what could go wrong?"
|
||||
@@ -192,6 +196,7 @@
|
||||
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/Destroy()
|
||||
qdel(pump)
|
||||
pump = null
|
||||
@@ -215,7 +220,6 @@
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/update_overlays()
|
||||
. = ..()
|
||||
|
||||
if(holding)
|
||||
. += "can-open"
|
||||
if(connected_port)
|
||||
@@ -245,7 +249,8 @@
|
||||
new /obj/item/stack/sheet/metal (loc, 5)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/welder_act(mob/living/user, obj/item/I)
|
||||
obj/machinery/portable_atmospherics/canister/welder_act(mob/living/user, obj/item/I)
|
||||
..()
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return FALSE
|
||||
|
||||
@@ -273,10 +278,9 @@
|
||||
T.assume_air(expelled_gas)
|
||||
air_update_turf()
|
||||
|
||||
stat |= BROKEN
|
||||
obj_break()
|
||||
density = FALSE
|
||||
playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
|
||||
update_icon()
|
||||
playsound(src.loc, 'sound/effects/spray.ogg', 10, TRUE, -3)
|
||||
investigate_log("was destroyed.", INVESTIGATE_ATMOS)
|
||||
|
||||
if(holding)
|
||||
@@ -319,7 +323,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "canister", name, 420, 405, master_ui, state)
|
||||
ui = new(user, src, ui_key, "Canister", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/ui_data()
|
||||
@@ -354,7 +358,7 @@
|
||||
return
|
||||
switch(action)
|
||||
if("relabel")
|
||||
var/label = input("New canister label:", name) as null|anything in label2types
|
||||
var/label = input("New canister label:", name) as null|anything in sortList(label2types)
|
||||
if(label && !..())
|
||||
var/newtype = label2types[label]
|
||||
if(newtype)
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
name = "portable air pump"
|
||||
icon_state = "psiphon:0"
|
||||
density = TRUE
|
||||
ui_x = 300
|
||||
ui_y = 315
|
||||
|
||||
var/on = FALSE
|
||||
var/direction = PUMP_OUT
|
||||
@@ -32,7 +34,6 @@
|
||||
/obj/machinery/portable_atmospherics/pump/update_icon_state()
|
||||
icon_state = "psiphon:[on]"
|
||||
|
||||
|
||||
/obj/machinery/portable_atmospherics/pump/update_overlays()
|
||||
. = ..()
|
||||
if(holding)
|
||||
@@ -79,14 +80,14 @@
|
||||
on = FALSE
|
||||
update_icon()
|
||||
else if(on && holding && direction == PUMP_OUT)
|
||||
investigate_log("[key_name(user)] started a transfer into [holding].<br>", INVESTIGATE_ATMOS)
|
||||
investigate_log("[key_name(user)] started a transfer into [holding].", INVESTIGATE_ATMOS)
|
||||
|
||||
|
||||
/obj/machinery/portable_atmospherics/pump/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "portable_pump", name, 300, 315, master_ui, state)
|
||||
ui = new(user, src, ui_key, "PortablePump", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/portable_atmospherics/pump/ui_data()
|
||||
@@ -121,14 +122,14 @@
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [ADMIN_VERBOSEJMP(src)]")
|
||||
log_admin("[key_name(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [AREACOORD(src)]")
|
||||
else if(on && direction == PUMP_OUT)
|
||||
investigate_log("[key_name(usr)] started a transfer into [holding].<br>", INVESTIGATE_ATMOS)
|
||||
investigate_log("[key_name(usr)] started a transfer into [holding].", INVESTIGATE_ATMOS)
|
||||
. = TRUE
|
||||
if("direction")
|
||||
if(direction == PUMP_OUT)
|
||||
direction = PUMP_IN
|
||||
else
|
||||
if(on && holding)
|
||||
investigate_log("[key_name(usr)] started a transfer into [holding].<br>", INVESTIGATE_ATMOS)
|
||||
investigate_log("[key_name(usr)] started a transfer into [holding].", INVESTIGATE_ATMOS)
|
||||
direction = PUMP_OUT
|
||||
. = TRUE
|
||||
if("pressure")
|
||||
@@ -142,10 +143,6 @@
|
||||
else if(pressure == "max")
|
||||
pressure = PUMP_MAX_PRESSURE
|
||||
. = TRUE
|
||||
else if(pressure == "input")
|
||||
pressure = input("New release pressure ([PUMP_MIN_PRESSURE]-[PUMP_MAX_PRESSURE] kPa):", name, pump.target_pressure) as num|null
|
||||
if(!isnull(pressure) && !..())
|
||||
. = TRUE
|
||||
else if(text2num(pressure) != null)
|
||||
pressure = text2num(pressure)
|
||||
. = TRUE
|
||||
@@ -154,7 +151,6 @@
|
||||
investigate_log("was set to [pump.target_pressure] kPa by [key_name(usr)].", INVESTIGATE_ATMOS)
|
||||
if("eject")
|
||||
if(holding)
|
||||
holding.forceMove(drop_location())
|
||||
holding = null
|
||||
replace_tank(usr, FALSE)
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
name = "portable air scrubber"
|
||||
icon_state = "pscrubber:0"
|
||||
density = TRUE
|
||||
ui_x = 320
|
||||
ui_y = 350
|
||||
|
||||
var/on = FALSE
|
||||
var/volume_rate = 1000
|
||||
@@ -64,7 +66,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "portable_scrubber", name, 320, 335, master_ui, state)
|
||||
ui = new(user, src, ui_key, "PortableScrubber", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/ui_data()
|
||||
|
||||
@@ -1,246 +1,327 @@
|
||||
/// Station home gateway
|
||||
GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation)
|
||||
/// List of possible gateway destinations.
|
||||
GLOBAL_LIST_EMPTY(gateway_destinations)
|
||||
|
||||
/**
|
||||
* Corresponds to single entry in gateway control.
|
||||
*
|
||||
* Will NOT be added automatically to GLOB.gateway_destinations list.
|
||||
*/
|
||||
/datum/gateway_destination
|
||||
var/name = "Unknown Destination"
|
||||
var/wait = 0 /// How long after roundstart this destination becomes active
|
||||
var/enabled = TRUE /// If disabled, the destination won't be availible
|
||||
var/hidden = FALSE /// Will not show on gateway controls at all.
|
||||
|
||||
/* Can a gateway link to this destination right now. */
|
||||
/datum/gateway_destination/proc/is_availible()
|
||||
return enabled && (world.time - SSticker.round_start_time >= wait)
|
||||
|
||||
/* Returns user-friendly description why you can't connect to this destination, displayed in UI */
|
||||
/datum/gateway_destination/proc/get_availible_reason()
|
||||
. = "Unreachable"
|
||||
if(world.time - SSticker.round_start_time < wait)
|
||||
. = "Connection desynchronized. Recalibration in progress."
|
||||
|
||||
/* Check if the movable is allowed to arrive at this destination (exile implants mostly) */
|
||||
/datum/gateway_destination/proc/incoming_pass_check(atom/movable/AM)
|
||||
return TRUE
|
||||
|
||||
/* Get the actual turf we'll arrive at */
|
||||
/datum/gateway_destination/proc/get_target_turf()
|
||||
CRASH("get target turf not implemented for this destination type")
|
||||
|
||||
/* Called after moving the movable to target turf */
|
||||
/datum/gateway_destination/proc/post_transfer(atom/movable/AM)
|
||||
if (ismob(AM))
|
||||
var/mob/M = AM
|
||||
if (M.client)
|
||||
M.client.move_delay = max(world.time + 5, M.client.move_delay)
|
||||
|
||||
/* Called when gateway activates with this destination. */
|
||||
/datum/gateway_destination/proc/activate(obj/machinery/gateway/activated)
|
||||
return
|
||||
|
||||
/* Called when gateway targeting this destination deactivates. */
|
||||
/datum/gateway_destination/proc/deactivate(obj/machinery/gateway/deactivated)
|
||||
return
|
||||
|
||||
/* Returns data used by gateway controller ui */
|
||||
/datum/gateway_destination/proc/get_ui_data()
|
||||
. = list()
|
||||
.["ref"] = REF(src)
|
||||
.["name"] = name
|
||||
.["availible"] = is_availible()
|
||||
.["reason"] = get_availible_reason()
|
||||
if(wait)
|
||||
.["timeout"] = max(1 - (wait - (world.time - SSticker.round_start_time)) / wait, 0)
|
||||
|
||||
/* Destination is another gateway */
|
||||
/datum/gateway_destination/gateway
|
||||
/// The gateway this destination points at
|
||||
var/obj/machinery/gateway/target_gateway
|
||||
|
||||
/* We set the target gateway target to activator gateway */
|
||||
/datum/gateway_destination/gateway/activate(obj/machinery/gateway/activated)
|
||||
if(!target_gateway.target)
|
||||
target_gateway.activate(activated)
|
||||
|
||||
/* We turn off the target gateway if it's linked with us */
|
||||
/datum/gateway_destination/gateway/deactivate(obj/machinery/gateway/deactivated)
|
||||
if(target_gateway.target == deactivated.destination)
|
||||
target_gateway.deactivate()
|
||||
|
||||
/datum/gateway_destination/gateway/is_availible()
|
||||
return ..() && target_gateway.calibrated && !target_gateway.target && target_gateway.powered()
|
||||
|
||||
/datum/gateway_destination/gateway/get_availible_reason()
|
||||
. = ..()
|
||||
if(!target_gateway.calibrated)
|
||||
. = "Exit gateway malfunction. Manual recalibration required."
|
||||
if(target_gateway.target)
|
||||
. = "Exit gateway in use."
|
||||
if(!target_gateway.powered())
|
||||
. = "Exit gateway unpowered."
|
||||
|
||||
/datum/gateway_destination/gateway/get_target_turf()
|
||||
return get_step(target_gateway.portal,SOUTH)
|
||||
|
||||
/datum/gateway_destination/gateway/post_transfer(atom/movable/AM)
|
||||
. = ..()
|
||||
addtimer(CALLBACK(AM,/atom/movable.proc/setDir,SOUTH),0)
|
||||
|
||||
/* Special home destination, so we can check exile implants */
|
||||
/datum/gateway_destination/gateway/home
|
||||
|
||||
/datum/gateway_destination/gateway/home/incoming_pass_check(atom/movable/AM)
|
||||
if(isliving(AM))
|
||||
if(check_exile_implant(AM))
|
||||
return FALSE
|
||||
else
|
||||
for(var/mob/living/L in AM.contents)
|
||||
if(check_exile_implant(L))
|
||||
target_gateway.say("Rejecting [AM]: Exile implant detected in contained lifeform.")
|
||||
return FALSE
|
||||
if(AM.has_buckled_mobs())
|
||||
for(var/mob/living/L in AM.buckled_mobs)
|
||||
if(check_exile_implant(L))
|
||||
target_gateway.say("Rejecting [AM]: Exile implant detected in close proximity lifeform.")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/gateway_destination/gateway/home/proc/check_exile_implant(mob/living/L)
|
||||
for(var/obj/item/implant/exile/E in L.implants)//Checking that there is an exile implant
|
||||
to_chat(L, "<span class='userdanger'>The station gate has detected your exile implant and is blocking your entry.</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/* Destination is one ore more turfs - created by landmarks */
|
||||
/datum/gateway_destination/point
|
||||
var/list/target_turfs = list()
|
||||
/// Used by away landmarks
|
||||
var/id
|
||||
|
||||
/datum/gateway_destination/point/get_target_turf()
|
||||
return pick(target_turfs)
|
||||
|
||||
/* Dense invisible object starting the teleportation. Created by gateways on activation. */
|
||||
/obj/effect/gateway_portal_bumper
|
||||
var/obj/machinery/gateway/gateway
|
||||
density = TRUE
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
|
||||
/obj/effect/gateway_portal_bumper/Bumped(atom/movable/AM)
|
||||
if(get_dir(src,AM) == SOUTH)
|
||||
gateway.Transfer(AM)
|
||||
|
||||
/obj/effect/gateway_portal_bumper/Destroy(force)
|
||||
. = ..()
|
||||
gateway = null
|
||||
|
||||
/obj/machinery/gateway
|
||||
name = "gateway"
|
||||
desc = "A mysterious gateway built by unknown hands, it allows for faster than light travel to far-flung locations."
|
||||
icon = 'icons/obj/machines/gateway.dmi'
|
||||
icon_state = "off"
|
||||
density = TRUE
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
var/active = 0
|
||||
var/checkparts = TRUE
|
||||
var/list/obj/effect/landmark/randomspawns = list()
|
||||
|
||||
// 3x2 offset by one row
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
bound_height = 64
|
||||
bound_width = 96
|
||||
bound_x = -32
|
||||
bound_y = 0
|
||||
density = TRUE
|
||||
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 100
|
||||
active_power_usage = 5000
|
||||
|
||||
var/calibrated = TRUE
|
||||
var/list/linked = list()
|
||||
var/can_link = FALSE //Is this the centerpiece?
|
||||
/// Type of instanced gateway destination, needs to be subtype of /datum/gateway_destination/gateway
|
||||
var/destination_type = /datum/gateway_destination/gateway
|
||||
/// Name of the generated destination
|
||||
var/destination_name = "Unknown Gateway"
|
||||
/// This is our own destination, pointing at this gateway
|
||||
var/datum/gateway_destination/gateway/destination
|
||||
/// This is current active destination
|
||||
var/datum/gateway_destination/target
|
||||
/// bumper object, the thing that starts actual teleport
|
||||
var/obj/effect/gateway_portal_bumper/portal
|
||||
|
||||
/obj/machinery/gateway/Initialize()
|
||||
randomspawns = GLOB.awaydestinations
|
||||
generate_destination()
|
||||
update_icon()
|
||||
if(!istype(src, /obj/machinery/gateway/centerstation) && !istype(src, /obj/machinery/gateway/centeraway))
|
||||
switch(dir)
|
||||
if(SOUTH,SOUTHEAST,SOUTHWEST)
|
||||
density = FALSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/gateway/proc/toggleoff()
|
||||
for(var/obj/machinery/gateway/G in linked)
|
||||
G.active = 0
|
||||
G.update_icon()
|
||||
active = 0
|
||||
/obj/machinery/gateway/proc/generate_destination()
|
||||
destination = new destination_type
|
||||
destination.name = destination_name
|
||||
destination.target_gateway = src
|
||||
GLOB.gateway_destinations += destination
|
||||
|
||||
/obj/machinery/gateway/proc/deactivate()
|
||||
var/datum/gateway_destination/dest = target
|
||||
target = null
|
||||
dest.deactivate(src)
|
||||
QDEL_NULL(portal)
|
||||
use_power = IDLE_POWER_USE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/gateway/proc/detect()
|
||||
if(!can_link)
|
||||
return FALSE
|
||||
linked = list() //clear the list
|
||||
var/turf/T = loc
|
||||
var/ready = FALSE
|
||||
|
||||
for(var/i in GLOB.alldirs)
|
||||
T = get_step(loc, i)
|
||||
var/obj/machinery/gateway/G = locate(/obj/machinery/gateway) in T
|
||||
if(G)
|
||||
linked.Add(G)
|
||||
continue
|
||||
|
||||
//this is only done if we fail to find a part
|
||||
ready = FALSE
|
||||
toggleoff()
|
||||
break
|
||||
|
||||
if((linked.len == 8) || !checkparts)
|
||||
ready = TRUE
|
||||
return ready
|
||||
/obj/machinery/gateway/process()
|
||||
if((stat & (NOPOWER)) && use_power)
|
||||
if(target)
|
||||
deactivate()
|
||||
return
|
||||
|
||||
/obj/machinery/gateway/update_icon_state()
|
||||
icon_state = active ? "on" : "off"
|
||||
if(target)
|
||||
icon_state = "on"
|
||||
else
|
||||
icon_state = "off"
|
||||
|
||||
/obj/machinery/gateway/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!detect())
|
||||
return
|
||||
if(!active)
|
||||
toggleon(user)
|
||||
return
|
||||
toggleoff()
|
||||
|
||||
/obj/machinery/gateway/proc/toggleon(mob/user)
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/gateway/safe_throw_at()
|
||||
/obj/machinery/gateway/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE)
|
||||
return
|
||||
|
||||
/obj/machinery/gateway/proc/generate_bumper()
|
||||
portal = new(get_turf(src))
|
||||
portal.gateway = src
|
||||
|
||||
/obj/machinery/gateway/proc/activate(datum/gateway_destination/D)
|
||||
if(!powered() || target)
|
||||
return
|
||||
target = D
|
||||
target.activate(destination)
|
||||
generate_bumper()
|
||||
use_power = ACTIVE_POWER_USE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/gateway/proc/Transfer(atom/movable/AM)
|
||||
if(!target || !target.incoming_pass_check(AM))
|
||||
return
|
||||
AM.forceMove(target.get_target_turf())
|
||||
target.post_transfer(AM)
|
||||
|
||||
/* Station's primary gateway */
|
||||
/obj/machinery/gateway/centerstation
|
||||
destination_type = /datum/gateway_destination/gateway/home
|
||||
destination_name = "Home Gateway"
|
||||
|
||||
/obj/machinery/gateway/centerstation/Initialize()
|
||||
. = ..()
|
||||
if(!GLOB.the_gateway)
|
||||
GLOB.the_gateway = src
|
||||
update_icon()
|
||||
wait = world.time + CONFIG_GET(number/gateway_delay) //+ thirty minutes default
|
||||
awaygate = locate(/obj/machinery/gateway/centeraway)
|
||||
|
||||
/obj/machinery/gateway/centerstation/Destroy()
|
||||
if(GLOB.the_gateway == src)
|
||||
GLOB.the_gateway = null
|
||||
return ..()
|
||||
|
||||
//this is da important part wot makes things go
|
||||
/obj/machinery/gateway/centerstation
|
||||
density = TRUE
|
||||
icon_state = "offcenter"
|
||||
use_power = IDLE_POWER_USE
|
||||
|
||||
//warping vars
|
||||
var/wait = 0 //this just grabs world.time at world start
|
||||
var/obj/machinery/gateway/centeraway/awaygate = null
|
||||
can_link = TRUE
|
||||
|
||||
/obj/machinery/gateway/centerstation/update_icon_state()
|
||||
icon_state = active ? "oncenter" : "offcenter"
|
||||
|
||||
/obj/machinery/gateway/centerstation/process()
|
||||
if((stat & (NOPOWER)) && use_power)
|
||||
if(active)
|
||||
toggleoff()
|
||||
return
|
||||
|
||||
if(active)
|
||||
use_power(5000)
|
||||
|
||||
/obj/machinery/gateway/centerstation/toggleon(mob/user)
|
||||
if(!detect())
|
||||
return
|
||||
if(!powered())
|
||||
return
|
||||
if(!awaygate)
|
||||
to_chat(user, "<span class='notice'>Error: No destination found.</span>")
|
||||
return
|
||||
if(world.time < wait)
|
||||
to_chat(user, "<span class='notice'>Error: Warpspace triangulation in progress. Estimated time to completion: [DisplayTimeText(wait - world.time)].</span>")
|
||||
return
|
||||
|
||||
for(var/obj/machinery/gateway/G in linked)
|
||||
G.active = 1
|
||||
G.update_icon()
|
||||
active = 1
|
||||
update_icon()
|
||||
|
||||
//okay, here's the good teleporting stuff
|
||||
/obj/machinery/gateway/centerstation/Bumped(atom/movable/AM)
|
||||
if(!active)
|
||||
return
|
||||
if(!detect())
|
||||
return
|
||||
if(!awaygate || QDELETED(awaygate))
|
||||
return
|
||||
|
||||
if(awaygate.calibrated)
|
||||
AM.forceMove(get_step(awaygate.loc, SOUTH))
|
||||
AM.setDir(SOUTH)
|
||||
if (ismob(AM))
|
||||
var/mob/M = AM
|
||||
if (M.client)
|
||||
M.client.move_delay = max(world.time + 5, M.client.move_delay)
|
||||
return
|
||||
/obj/machinery/gateway/multitool_act(mob/living/user, obj/item/I)
|
||||
if(calibrated)
|
||||
to_chat(user, "<span class='alert'>The gate is already calibrated, there is no work for you to do here.</span>")
|
||||
else
|
||||
var/obj/effect/landmark/dest = pick(randomspawns)
|
||||
if(dest)
|
||||
AM.forceMove(get_turf(dest))
|
||||
AM.setDir(SOUTH)
|
||||
use_power(5000)
|
||||
return
|
||||
|
||||
/obj/machinery/gateway/centeraway/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/multitool))
|
||||
if(calibrated)
|
||||
to_chat(user, "\black The gate is already calibrated, there is no work for you to do here.")
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='boldnotice'>Recalibration successful!</span>: \black This gate's systems have been fine tuned. Travel to this gate will now be on target.")
|
||||
calibrated = TRUE
|
||||
return
|
||||
|
||||
/////////////////////////////////////Away////////////////////////
|
||||
|
||||
|
||||
/obj/machinery/gateway/centeraway
|
||||
density = TRUE
|
||||
icon_state = "offcenter"
|
||||
use_power = NO_POWER_USE
|
||||
var/obj/machinery/gateway/centerstation/stationgate = null
|
||||
can_link = TRUE
|
||||
|
||||
|
||||
/obj/machinery/gateway/centeraway/Initialize()
|
||||
. = ..()
|
||||
update_icon()
|
||||
stationgate = locate(/obj/machinery/gateway/centerstation)
|
||||
|
||||
|
||||
/obj/machinery/gateway/centeraway/update_icon_state()
|
||||
icon_state = active ? "oncenter" : "offcenter"
|
||||
|
||||
/obj/machinery/gateway/centeraway/toggleon(mob/user)
|
||||
if(!detect())
|
||||
return
|
||||
if(!stationgate)
|
||||
to_chat(user, "<span class='notice'>Error: No destination found.</span>")
|
||||
return
|
||||
|
||||
for(var/obj/machinery/gateway/G in linked)
|
||||
G.active = 1
|
||||
G.update_icon()
|
||||
active = 1
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/gateway/centeraway/proc/check_exile_implant(mob/living/L)
|
||||
for(var/obj/item/implant/exile/E in L.implants)//Checking that there is an exile implant
|
||||
to_chat(L, "\black The station gate has detected your exile implant and is blocking your entry.")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/gateway/centeraway/Bumped(atom/movable/AM)
|
||||
if(!detect())
|
||||
return
|
||||
if(!active)
|
||||
return
|
||||
if(!stationgate || QDELETED(stationgate))
|
||||
return
|
||||
if(isliving(AM))
|
||||
if(check_exile_implant(AM))
|
||||
return
|
||||
else
|
||||
for(var/mob/living/L in AM.contents)
|
||||
if(check_exile_implant(L))
|
||||
say("Rejecting [AM]: Exile implant detected in contained lifeform.")
|
||||
return
|
||||
if(AM.has_buckled_mobs())
|
||||
for(var/mob/living/L in AM.buckled_mobs)
|
||||
if(check_exile_implant(L))
|
||||
say("Rejecting [AM]: Exile implant detected in close proximity lifeform.")
|
||||
return
|
||||
AM.forceMove(get_step(stationgate.loc, SOUTH))
|
||||
AM.setDir(SOUTH)
|
||||
if (ismob(AM))
|
||||
var/mob/M = AM
|
||||
if (M.client)
|
||||
M.client.move_delay = max(world.time + 5, M.client.move_delay)
|
||||
|
||||
|
||||
/obj/machinery/gateway/centeraway/admin
|
||||
desc = "A mysterious gateway built by unknown hands, this one seems more compact."
|
||||
|
||||
/obj/machinery/gateway/centeraway/admin/Initialize()
|
||||
. = ..()
|
||||
if(stationgate && !stationgate.awaygate)
|
||||
stationgate.awaygate = src
|
||||
|
||||
/obj/machinery/gateway/centeraway/admin/detect()
|
||||
to_chat(user, "<span class='boldnotice'>Recalibration successful!</span>: \black This gate's systems have been fine tuned. Travel to this gate will now be on target.")
|
||||
calibrated = TRUE
|
||||
return TRUE
|
||||
|
||||
/* Doesn't need control console or power, always links to home when interacting. */
|
||||
/obj/machinery/gateway/away
|
||||
density = TRUE
|
||||
use_power = NO_POWER_USE
|
||||
|
||||
/obj/machinery/gateway/away/interact(mob/user, special_state)
|
||||
. = ..()
|
||||
if(!target)
|
||||
if(!GLOB.the_gateway)
|
||||
to_chat(user,"<span class='warning'>Home gateway is not responding!</span>")
|
||||
if(GLOB.the_gateway.target)
|
||||
to_chat(user,"<span class='warning'>Home gateway already in use!</span>")
|
||||
return
|
||||
activate(GLOB.the_gateway.destination)
|
||||
else
|
||||
deactivate()
|
||||
|
||||
/* Gateway control computer */
|
||||
/obj/machinery/computer/gateway_control
|
||||
name = "Gateway Control"
|
||||
desc = "Human friendly interface to the mysterious gate next to it."
|
||||
var/obj/machinery/gateway/G
|
||||
|
||||
/obj/machinery/computer/gateway_control/Initialize(mapload, obj/item/circuitboard/C)
|
||||
. = ..()
|
||||
try_to_linkup()
|
||||
|
||||
/obj/machinery/computer/gateway_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui, force_open, datum/tgui/master_ui, datum/ui_state/state = GLOB.default_state)
|
||||
. = ..()
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "Gateway", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/gateway_control/ui_data(mob/user)
|
||||
. = ..()
|
||||
.["gateway_present"] = G
|
||||
.["gateway_status"] = G ? G.powered() : FALSE
|
||||
.["current_target"] = G?.target?.get_ui_data()
|
||||
var/list/destinations = list()
|
||||
if(G)
|
||||
for(var/datum/gateway_destination/D in GLOB.gateway_destinations)
|
||||
if(D == G.destination)
|
||||
continue
|
||||
destinations += list(D.get_ui_data())
|
||||
.["destinations"] = destinations
|
||||
|
||||
/obj/machinery/computer/gateway_control/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
switch(action)
|
||||
if("linkup")
|
||||
try_to_linkup()
|
||||
return TRUE
|
||||
if("activate")
|
||||
var/datum/gateway_destination/D = locate(params["destination"]) in GLOB.gateway_destinations
|
||||
try_to_connect(D)
|
||||
return TRUE
|
||||
if("deactivate")
|
||||
if(G && G.target)
|
||||
G.deactivate()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/gateway_control/proc/try_to_linkup()
|
||||
G = locate(/obj/machinery/gateway) in view(7,get_turf(src))
|
||||
|
||||
/obj/machinery/computer/gateway_control/proc/try_to_connect(datum/gateway_destination/D)
|
||||
if(!D || !G)
|
||||
return
|
||||
if(!D.is_availible() || G.target)
|
||||
return
|
||||
G.activate(D)
|
||||
|
||||
/obj/item/paper/fluff/gateway
|
||||
info = "Congratulations,<br><br>Your station has been selected to carry out the Gateway Project.<br><br>The equipment will be shipped to you at the start of the next quarter.<br> You are to prepare a secure location to house the equipment as outlined in the attached documents.<br><br>--Nanotrasen Blue Space Research"
|
||||
info = "Congratulations,<br><br>Your station has been selected to carry out the Gateway Project.<br><br>The equipment will be shipped to you at the start of the next quarter.<br> You are to prepare a secure location to house the equipment as outlined in the attached documents.<br><br>--Nanotrasen Bluespace Research"
|
||||
name = "Confidential Correspondence, Pg 1"
|
||||
|
||||
@@ -15,24 +15,28 @@
|
||||
INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!")
|
||||
GLOB.random_zlevels_generated[name] = TRUE
|
||||
|
||||
/proc/reset_gateway_spawns(reset = FALSE)
|
||||
for(var/obj/machinery/gateway/G in world)
|
||||
if(reset)
|
||||
G.randomspawns = GLOB.awaydestinations
|
||||
else
|
||||
G.randomspawns.Add(GLOB.awaydestinations)
|
||||
|
||||
/obj/effect/landmark/awaystart
|
||||
name = "away mission spawn"
|
||||
desc = "Randomly picked away mission spawn points."
|
||||
var/id
|
||||
var/delay = TRUE // If the generated destination should be delayed by configured gateway delay
|
||||
|
||||
/obj/effect/landmark/awaystart/New()
|
||||
GLOB.awaydestinations += src
|
||||
..()
|
||||
/obj/effect/landmark/awaystart/Initialize()
|
||||
. = ..()
|
||||
var/datum/gateway_destination/point/current
|
||||
for(var/datum/gateway_destination/point/D in GLOB.gateway_destinations)
|
||||
if(D.id == id)
|
||||
current = D
|
||||
if(!current)
|
||||
current = new
|
||||
current.id = id
|
||||
if(delay)
|
||||
current.wait = CONFIG_GET(number/gateway_delay)
|
||||
GLOB.gateway_destinations += current
|
||||
current.target_turfs += get_turf(src)
|
||||
|
||||
/obj/effect/landmark/awaystart/Destroy()
|
||||
GLOB.awaydestinations -= src
|
||||
return ..()
|
||||
/obj/effect/landmark/awaystart/nodelay
|
||||
delay = FALSE
|
||||
|
||||
/proc/generateMapList(filename)
|
||||
. = list()
|
||||
|
||||
@@ -55,7 +55,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "centcom_podlauncher", "Config/Launch Supplypod", 700, 700, master_ui, state)
|
||||
ui = new(user, src, ui_key, "CentcomPodLauncher", "Config/Launch Supplypod", 700, 700, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/centcom_podlauncher/ui_data(mob/user) //Sends info about the pod to the UI.
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "cargo", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, ui_key, "Cargo", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/cargo/ui_data()
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
All sales are near instantaneous - please choose carefully"
|
||||
icon_screen = "supply_express"
|
||||
circuit = /obj/item/circuitboard/computer/cargo/express
|
||||
ui_x = 600
|
||||
ui_y = 700
|
||||
blockade_warning = "Bluespace instability detected. Delivery impossible."
|
||||
req_access = list(ACCESS_QM)
|
||||
var/message
|
||||
@@ -90,7 +92,7 @@
|
||||
/obj/machinery/computer/cargo/express/ui_interact(mob/living/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "cargo_express", name, 600, 700, master_ui, state)
|
||||
ui = new(user, src, ui_key, "CargoExpress", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/cargo/express/ui_data(mob/user)
|
||||
|
||||
@@ -20,9 +20,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
When somebody clicks a link in game, this Topic is called first.
|
||||
It does the stuff in this proc and then is redirected to the Topic() proc for the src=[0xWhatever]
|
||||
(if specified in the link). ie locate(hsrc).Topic()
|
||||
|
||||
Such links can be spoofed.
|
||||
|
||||
Because of this certain things MUST be considered whenever adding a Topic() for something:
|
||||
- Can it be fed harmful values which could cause runtimes?
|
||||
- Is the Topic call an admin-only thing?
|
||||
@@ -36,10 +34,11 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
if(!usr || usr != mob) //stops us calling Topic for somebody else's client. Also helps prevent usr=null
|
||||
return
|
||||
|
||||
// asset_cache
|
||||
var/asset_cache_job
|
||||
if(href_list["asset_cache_confirm_arrival"])
|
||||
asset_cache_job = asset_cache_confirm_arrival(href_list["asset_cache_confirm_arrival"])
|
||||
if (!asset_cache_job)
|
||||
if(!asset_cache_job)
|
||||
return
|
||||
|
||||
var/mtl = CONFIG_GET(number/minute_topic_limit)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
var/list/log = list()
|
||||
var/range = 8
|
||||
var/view_check = TRUE
|
||||
var/forensicPrintCount = 0
|
||||
actions_types = list(/datum/action/item_action/displayDetectiveScanResults)
|
||||
|
||||
/datum/action/item_action/displayDetectiveScanResults
|
||||
@@ -42,12 +43,15 @@
|
||||
/obj/item/detective_scanner/proc/PrintReport()
|
||||
// Create our paper
|
||||
var/obj/item/paper/P = new(get_turf(src))
|
||||
P.name = "paper- 'Scanner Report'"
|
||||
P.info = "<center><font size='6'><B>Scanner Report</B></font></center><HR><BR>"
|
||||
|
||||
//This could be a global count like sec and med record printouts. See GLOB.data_core.medicalPrintCount AKA datacore.dm
|
||||
var frNum = ++forensicPrintCount
|
||||
|
||||
P.name = text("FR-[] 'Forensic Record'", frNum)
|
||||
P.info = text("<center><B>Forensic Record - (FR-[])</B></center><HR><BR>", frNum)
|
||||
P.info += jointext(log, "<BR>")
|
||||
P.info += "<HR><B>Notes:</B><BR>"
|
||||
P.info_links = P.info
|
||||
P.updateinfolinks()
|
||||
P.update_icon()
|
||||
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
@@ -216,4 +220,4 @@
|
||||
return
|
||||
to_chat(user, "<span class='notice'><B>Scanner Report</B></span>")
|
||||
for(var/iterLog in log)
|
||||
to_chat(user, iterLog)
|
||||
to_chat(user, iterLog)
|
||||
|
||||
@@ -225,7 +225,8 @@
|
||||
suit_type = /obj/item/clothing/suit/space
|
||||
helmet_type = /obj/item/clothing/head/helmet/space
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/jetpack/void
|
||||
storage_type = /obj/item/tank/internals/oxygen
|
||||
|
||||
|
||||
/obj/machinery/loot_locator
|
||||
name = "Booty Locator"
|
||||
@@ -280,8 +281,9 @@
|
||||
|
||||
/obj/machinery/computer/piratepad_control
|
||||
name = "cargo hold control terminal"
|
||||
resistance_flags = INDESTRUCTIBLE
|
||||
var/status_report = "Idle"
|
||||
ui_x = 600
|
||||
ui_y = 230
|
||||
var/status_report = "Ready for delivery."
|
||||
var/obj/machinery/piratepad/pad
|
||||
var/warmup_time = 100
|
||||
var/sending = FALSE
|
||||
@@ -298,7 +300,6 @@
|
||||
if (istype(I) && istype(I.buffer,/obj/machinery/piratepad))
|
||||
to_chat(user, "<span class='notice'>You link [src] with [I.buffer] in [I] buffer.</span>")
|
||||
pad = I.buffer
|
||||
updateDialog()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/piratepad_control/LateInitialize()
|
||||
@@ -311,29 +312,43 @@
|
||||
else
|
||||
pad = locate() in range(4,src)
|
||||
|
||||
/obj/machinery/computer/piratepad_control/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/list/t = list()
|
||||
t += "<div class='statusDisplay'>Cargo Hold Control<br>"
|
||||
t += "Current cargo value : [points]"
|
||||
t += "</div>"
|
||||
if(!pad)
|
||||
t += "<div class='statusDisplay'>No pad located.</div><BR>"
|
||||
else
|
||||
t += "<br>[status_report]<br>"
|
||||
if(!sending)
|
||||
t += "<a href='?src=[REF(src)];recalc=1;'>Recalculate Value</a><a href='?src=[REF(src)];send=1'>Send</a>"
|
||||
else
|
||||
t += "<a href='?src=[REF(src)];stop=1'>Stop sending</a>"
|
||||
/obj/machinery/computer/piratepad_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "CargoHoldTerminal", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
var/datum/browser/popup = new(user, "piratepad", name, 300, 500)
|
||||
popup.set_content(t.Join())
|
||||
popup.open()
|
||||
/obj/machinery/computer/piratepad_control/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["points"] = points
|
||||
data["pad"] = pad ? TRUE : FALSE
|
||||
data["sending"] = sending
|
||||
data["status_report"] = status_report
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/piratepad_control/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(!pad)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("recalc")
|
||||
recalc()
|
||||
. = TRUE
|
||||
if("send")
|
||||
start_sending()
|
||||
. = TRUE
|
||||
if("stop")
|
||||
stop_sending()
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/computer/piratepad_control/proc/recalc()
|
||||
if(sending)
|
||||
return
|
||||
status_report = "Predicted value:<br>"
|
||||
status_report = "Predicted value: "
|
||||
var/value = 0
|
||||
var/datum/export_report/ex = new
|
||||
for(var/atom/movable/AM in get_turf(pad))
|
||||
if(AM == pad)
|
||||
@@ -341,7 +356,12 @@
|
||||
export_item_and_contents(AM, EXPORT_PIRATE | EXPORT_CARGO | EXPORT_CONTRABAND | EXPORT_EMAG, apply_elastic = FALSE, dry_run = TRUE, external_report = ex)
|
||||
|
||||
for(var/datum/export/E in ex.total_amount)
|
||||
status_report += E.total_printout(ex,notes = FALSE) + "<br>"
|
||||
status_report += E.total_printout(ex,notes = FALSE)
|
||||
status_report += " "
|
||||
value += ex.total_value[E]
|
||||
|
||||
if(!value)
|
||||
status_report += "0"
|
||||
|
||||
/obj/machinery/computer/piratepad_control/proc/send()
|
||||
if(!sending)
|
||||
@@ -354,14 +374,15 @@
|
||||
continue
|
||||
export_item_and_contents(AM, EXPORT_PIRATE | EXPORT_CARGO | EXPORT_CONTRABAND | EXPORT_EMAG, apply_elastic = FALSE, delete_unsold = FALSE, external_report = ex)
|
||||
|
||||
status_report = "Sold:<br>"
|
||||
status_report = "Sold: "
|
||||
var/value = 0
|
||||
for(var/datum/export/E in ex.total_amount)
|
||||
var/export_text = E.total_printout(ex,notes = FALSE) //Don't want nanotrasen messages, makes no sense here.
|
||||
if(!export_text)
|
||||
continue
|
||||
|
||||
status_report += export_text + "<br>"
|
||||
status_report += export_text
|
||||
status_report += " "
|
||||
value += ex.total_value[E]
|
||||
|
||||
if(!total_report)
|
||||
@@ -374,11 +395,12 @@
|
||||
|
||||
points += value
|
||||
|
||||
if(!value)
|
||||
status_report += "Nothing"
|
||||
pad.visible_message("<span class='notice'>[pad] activates!</span>")
|
||||
flick(pad.sending_state,pad)
|
||||
pad.icon_state = pad.idle_state
|
||||
sending = FALSE
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/computer/piratepad_control/proc/start_sending()
|
||||
if(sending)
|
||||
@@ -397,20 +419,6 @@
|
||||
pad.icon_state = pad.idle_state
|
||||
deltimer(sending_timer)
|
||||
|
||||
/obj/machinery/computer/piratepad_control/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(pad)
|
||||
if(href_list["recalc"])
|
||||
recalc()
|
||||
if(href_list["send"])
|
||||
start_sending()
|
||||
if(href_list["stop"])
|
||||
stop_sending()
|
||||
updateDialog()
|
||||
else
|
||||
updateDialog()
|
||||
|
||||
/datum/export/pirate
|
||||
export_category = EXPORT_PIRATE
|
||||
|
||||
@@ -435,6 +443,8 @@
|
||||
var/mob/living/carbon/human/H = AM
|
||||
if(H.stat != CONSCIOUS || !H.mind || !H.mind.assigned_role) //mint condition only
|
||||
return 0
|
||||
else if("pirate" in H.faction) //can't ransom your fellow pirates to CentCom!
|
||||
return 0
|
||||
else
|
||||
if(H.mind.assigned_role in GLOB.command_positions)
|
||||
return 3000
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
/obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "smartvend", name, 440, 550, master_ui, state)
|
||||
ui = new(user, src, ui_key, "SmartVend", name, 440, 550, master_ui, state)
|
||||
ui.set_autoupdate(FALSE)
|
||||
ui.open()
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
/obj/machinery/computer/holodeck/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "holodeck", name, 400, 500, master_ui, state)
|
||||
ui = new(user, src, ui_key, "Holodeck", name, 400, 500, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/holodeck/ui_data(mob/user)
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
|
||||
/obj/item/paper/fluff/holodeck/trek_diploma
|
||||
name = "paper - Starfleet Academy Diploma"
|
||||
info = {"<h2>Starfleet Academy</h2></br><p>Official Diploma</p></br>"}
|
||||
info = {"__Starfleet Academy__\nOfficial Diploma"}
|
||||
|
||||
/obj/item/paper/fluff/holodeck/disclaimer
|
||||
name = "Holodeck Disclaimer"
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
features["mcolor"] = "#59CE00"
|
||||
for(var/V in quirks)
|
||||
new V(podman)
|
||||
podman.hardset_dna(null,null,podman.real_name,blood_type, new /datum/species/pod,features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman
|
||||
podman.hardset_dna(null,null,null,podman.real_name,blood_type, new /datum/species/pod,features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman
|
||||
podman.set_cloned_appearance()
|
||||
|
||||
else //else, one packet of seeds. maybe two
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/datum/language_menu/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.language_menu_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "language_menu", "Language Menu", 700, 600, master_ui, state)
|
||||
ui = new(user, src, ui_key, "LanguageMenu", "Language Menu", 700, 600, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/language_menu/ui_data(mob/user)
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "codex_gigas", name, 450, 450, master_ui, state)
|
||||
ui = new(user, src, ui_key, "CodexGigas", name, 450, 450, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/book/codex_gigas/ui_data(mob/user)
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
/obj/structure/chisel_message/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "engraved_message", name, 600, 300, master_ui, state)
|
||||
ui = new(user, src, ui_key, "EngravedMessage", name, 600, 300, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/structure/chisel_message/ui_data(mob/user)
|
||||
|
||||
@@ -92,6 +92,7 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
|
||||
say("<span class='danger'>Launch sequence activated! Prepare for drop!!</span>")
|
||||
playsound(loc, 'sound/machines/warning-buzzer.ogg', 70, 0)
|
||||
launch_warning = FALSE
|
||||
log_shuttle("[key_name(usr)] has launched the auxillary base.")
|
||||
else if(!shuttle_error)
|
||||
say("Shuttle request uploaded. Please stand away from the doors.")
|
||||
else
|
||||
|
||||
@@ -19,7 +19,7 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list(
|
||||
singular_name = "marker beacon"
|
||||
desc = "Prism-brand path illumination devices. Used by miners to mark paths and warn of danger."
|
||||
icon = 'icons/obj/lighting.dmi'
|
||||
icon_state = "marker"
|
||||
icon_state = "markerbronze"
|
||||
merge_type = /obj/item/stack/marker_beacon
|
||||
max_amount = 100
|
||||
novariants = TRUE
|
||||
|
||||
@@ -8,6 +8,9 @@ GLOBAL_LIST(labor_sheet_values)
|
||||
icon = 'icons/obj/machines/mining_machines.dmi'
|
||||
icon_state = "console"
|
||||
density = FALSE
|
||||
ui_x = 315
|
||||
ui_y = 430
|
||||
|
||||
var/obj/machinery/mineral/stacking_machine/laborstacker/stacking_machine = null
|
||||
var/machinedir = SOUTH
|
||||
var/obj/machinery/door/airlock/release_door
|
||||
@@ -36,7 +39,7 @@ GLOBAL_LIST(labor_sheet_values)
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "labor_claim_console", name, 315, 430, master_ui, state)
|
||||
ui = new(user, src, ui_key, "LaborClaimConsole", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/ui_data(mob/user)
|
||||
@@ -100,7 +103,6 @@ GLOBAL_LIST(labor_sheet_values)
|
||||
Radio.talk_into(src, "A prisoner has returned to the station. Minerals and Prisoner ID card ready for retrieval.", FREQ_SECURITY)
|
||||
to_chat(usr, "<span class='notice'>Shuttle received message and will be sent shortly.</span>")
|
||||
. = TRUE
|
||||
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/proc/locate_stacking_machine()
|
||||
stacking_machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir))
|
||||
@@ -110,12 +112,9 @@ GLOBAL_LIST(labor_sheet_values)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
to_chat(user, "<span class='warning'>PZZTTPFFFT</span>")
|
||||
return TRUE
|
||||
if(!(obj_flags & EMAGGED))
|
||||
obj_flags |= EMAGGED
|
||||
to_chat(user, "<span class='warning'>PZZTTPFFFT</span>")
|
||||
|
||||
/**********************Prisoner Collection Unit**************************/
|
||||
|
||||
|
||||
@@ -3,9 +3,54 @@
|
||||
/**********************Mineral processing unit console**************************/
|
||||
|
||||
/obj/machinery/mineral
|
||||
speed_process = TRUE
|
||||
init_process = FALSE
|
||||
/// The current direction of `input_turf`, in relation to the machine.
|
||||
var/input_dir = NORTH
|
||||
/// The current direction, in relation to the machine, that items will be output to.
|
||||
var/output_dir = SOUTH
|
||||
/// The turf the machines listens to for items to pick up. Calls the `pickup_item()` proc.
|
||||
var/turf/input_turf = null
|
||||
/// Determines if this machine needs to pick up items. Used to avoid registering signals to `/mineral` machines that don't pickup items.
|
||||
var/needs_item_input = FALSE
|
||||
|
||||
/obj/machinery/mineral/Initialize(mapload)
|
||||
. = ..()
|
||||
if(needs_item_input && anchored)
|
||||
register_input_turf()
|
||||
|
||||
/// Gets the turf in the `input_dir` direction adjacent to the machine, and registers signals for ATOM_ENTERED and ATOM_CREATED. Calls the `pickup_item()` proc when it receives these signals.
|
||||
/obj/machinery/mineral/proc/register_input_turf()
|
||||
input_turf = get_step(src, input_dir)
|
||||
if(input_turf) // make sure there is actually a turf
|
||||
RegisterSignal(input_turf, list(COMSIG_ATOM_CREATED, COMSIG_ATOM_ENTERED), .proc/pickup_item)
|
||||
|
||||
/// Unregisters signals that are registered the machine's input turf, if it has one.
|
||||
/obj/machinery/mineral/proc/unregister_input_turf()
|
||||
if(input_turf)
|
||||
UnregisterSignal(input_turf, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_CREATED))
|
||||
|
||||
/obj/machinery/mineral/Moved()
|
||||
. = ..()
|
||||
if(!needs_item_input || !anchored)
|
||||
return
|
||||
unregister_input_turf()
|
||||
register_input_turf()
|
||||
|
||||
/**
|
||||
Base proc for all `/mineral` subtype machines to use. Place your item pickup behavior in this proc when you override it for your specific machine.
|
||||
|
||||
Called when the COMSIG_ATOM_ENTERED and COMSIG_ATOM_CREATED signals are sent.
|
||||
|
||||
Arguments:
|
||||
* source - the turf that is listening for the signals.
|
||||
* target - the atom that just moved onto the `source` turf.
|
||||
* oldLoc - the old location that `target` was at before moving onto `source`.
|
||||
*/
|
||||
/obj/machinery/mineral/proc/pickup_item(datum/source, atom/movable/target, atom/oldLoc)
|
||||
return
|
||||
|
||||
/// Generic unloading proc. Takes an atom as an argument and forceMove's it to the turf adjacent to this machine in the `output_dir` direction.
|
||||
/obj/machinery/mineral/proc/unload_mineral(atom/movable/S)
|
||||
S.forceMove(drop_location())
|
||||
var/turf/T = get_step(src,output_dir)
|
||||
@@ -19,7 +64,6 @@
|
||||
density = TRUE
|
||||
var/obj/machinery/mineral/processing_unit/machine = null
|
||||
var/machinedir = EAST
|
||||
speed_process = TRUE
|
||||
|
||||
/obj/machinery/mineral/processing_unit_console/Initialize()
|
||||
. = ..()
|
||||
@@ -58,6 +102,7 @@
|
||||
|
||||
if(href_list["set_on"])
|
||||
machine.on = (href_list["set_on"] == "on")
|
||||
START_PROCESSING(SSmachines, machine)
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
@@ -75,6 +120,7 @@
|
||||
icon = 'icons/obj/machines/mining_machines.dmi'
|
||||
icon_state = "furnace"
|
||||
density = TRUE
|
||||
needs_item_input = TRUE
|
||||
var/obj/machinery/mineral/CONSOLE = null
|
||||
var/on = FALSE
|
||||
var/datum/material/selected_material = null
|
||||
@@ -93,9 +139,6 @@
|
||||
QDEL_NULL(stored_research)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/mineral/processing_unit/HasProximity(atom/movable/AM)
|
||||
if(istype(AM, /obj/item/stack/ore) && AM.loc == get_step(src, input_dir))
|
||||
process_ore(AM)
|
||||
|
||||
/obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/stack/ore/O)
|
||||
if(QDELETED(O))
|
||||
@@ -144,8 +187,14 @@
|
||||
|
||||
return dat
|
||||
|
||||
/obj/machinery/mineral/processing_unit/pickup_item(datum/source, atom/movable/target, atom/oldLoc)
|
||||
if(QDELETED(target))
|
||||
return
|
||||
if(istype(target, /obj/item/stack/ore))
|
||||
process_ore(target)
|
||||
|
||||
/obj/machinery/mineral/processing_unit/process()
|
||||
if (on)
|
||||
if(on)
|
||||
if(selected_material)
|
||||
smelt_ore()
|
||||
|
||||
@@ -155,6 +204,8 @@
|
||||
|
||||
if(CONSOLE)
|
||||
CONSOLE.updateUsrDialog()
|
||||
else
|
||||
STOP_PROCESSING(SSmachines, src)
|
||||
|
||||
/obj/machinery/mineral/processing_unit/proc/smelt_ore()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
/obj/machinery/mineral/ore_redemption/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "ore_redemption_machine", "Ore Redemption Machine", 440, 550, master_ui, state)
|
||||
ui = new(user, src, ui_key, "OreRedemptionMachine", "Ore Redemption Machine", 440, 550, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/ui_data(mob/user)
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
icon_state = "mining"
|
||||
density = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/mining_equipment_vendor
|
||||
ui_x = 425
|
||||
ui_y = 600
|
||||
var/icon_deny = "mining-deny"
|
||||
var/obj/item/card/id/inserted_id
|
||||
var/list/prize_list = list( //if you add something to this, please, for the love of god, sort it by price/type. use tabs and not spaces.
|
||||
@@ -84,9 +86,14 @@
|
||||
src.equipment_path = path
|
||||
src.cost = cost
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
/obj/machinery/mineral/equipment_vendor/Initialize()
|
||||
. = ..()
|
||||
build_inventory()
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/proc/build_inventory()
|
||||
for(var/p in prize_list)
|
||||
var/datum/data/mining_equipment/M = p
|
||||
GLOB.vending_products[M.equipment_path] = 1
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/update_icon_state()
|
||||
if(powered())
|
||||
@@ -94,44 +101,82 @@
|
||||
else
|
||||
icon_state = "[initial(icon_state)]-off"
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/list/dat = list()
|
||||
dat += "<br><b>Equipment point cost list:</b><BR><table border='0' width='300'>"
|
||||
/obj/machinery/mineral/equipment_vendor/ui_base_html(html)
|
||||
var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/vending)
|
||||
. = replacetext(html, "<!--customheadhtml-->", assets.css_tag())
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/vending)
|
||||
assets.send(user)
|
||||
ui = new(user, src, ui_key, "MiningVendor", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/ui_static_data(mob/user)
|
||||
. = list()
|
||||
.["product_records"] = list()
|
||||
for(var/datum/data/mining_equipment/prize in prize_list)
|
||||
dat += "<tr><td>[prize.equipment_name]</td><td>[prize.cost]</td><td><A href='?src=[REF(src)];purchase=[REF(prize)]'>Purchase</A></td></tr>"
|
||||
dat += "</table>"
|
||||
var/list/product_data = list(
|
||||
path = replacetext(replacetext("[prize.equipment_path]", "/obj/item/", ""), "/", "-"),
|
||||
name = prize.equipment_name,
|
||||
price = prize.cost,
|
||||
ref = REF(prize)
|
||||
)
|
||||
.["product_records"] += list(product_data)
|
||||
|
||||
var/datum/browser/popup = new(user, "miningvendor", "Mining Equipment Vendor", 400, 350)
|
||||
popup.set_content(dat.Join())
|
||||
popup.open()
|
||||
return
|
||||
/obj/machinery/mineral/equipment_vendor/ui_data(mob/user)
|
||||
. = list()
|
||||
var/mob/living/carbon/human/H
|
||||
var/obj/item/card/id/C
|
||||
if(ishuman(user))
|
||||
H = user
|
||||
C = H.get_idcard(TRUE)
|
||||
if(C)
|
||||
.["user"] = list()
|
||||
.["user"]["points"] = C.mining_points
|
||||
if(C.assignment)
|
||||
.["user"]["job"] = C.assignment
|
||||
else
|
||||
.["user"]["job"] = "No Job"
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/Topic(href, href_list)
|
||||
/obj/machinery/mineral/equipment_vendor/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(href_list["purchase"])
|
||||
var/mob/M = usr
|
||||
var/obj/item/card/id/I = M.get_idcard(TRUE)
|
||||
if(istype(I))
|
||||
var/datum/data/mining_equipment/prize = locate(href_list["purchase"]) in prize_list
|
||||
if (!prize || !(prize in prize_list))
|
||||
to_chat(usr, "<span class='warning'>Error: Invalid choice!</span>")
|
||||
|
||||
switch(action)
|
||||
if("purchase")
|
||||
var/mob/M = usr
|
||||
var/obj/item/card/id/I = M.get_idcard(TRUE)
|
||||
if(!istype(I))
|
||||
to_chat(usr, "<span class='alert'>Error: An ID is required!</span>")
|
||||
flick(icon_deny, src)
|
||||
return
|
||||
var/datum/data/mining_equipment/prize = locate(params["ref"]) in prize_list
|
||||
if(!prize || !(prize in prize_list))
|
||||
to_chat(usr, "<span class='alert'>Error: Invalid choice!</span>")
|
||||
flick(icon_deny, src)
|
||||
return
|
||||
if(prize.cost > I.mining_points)
|
||||
to_chat(usr, "<span class='warning'>Error: Insufficient credits for [prize.equipment_name] on [I]!</span>")
|
||||
to_chat(usr, "<span class='alert'>Error: Insufficient points for [prize.equipment_name] on [I]!</span>")
|
||||
flick(icon_deny, src)
|
||||
else
|
||||
I.mining_points -= prize.cost
|
||||
to_chat(usr, "<span class='notice'>[src] clanks to life briefly before vending [prize.equipment_name]!</span>")
|
||||
new prize.equipment_path(src.loc)
|
||||
SSblackbox.record_feedback("nested tally", "mining_equipment_bought", 1, list("[type]", "[prize.equipment_path]"))
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Error: An ID with a registered account is required!</span>")
|
||||
flick(icon_deny, src)
|
||||
updateUsrDialog()
|
||||
return
|
||||
return
|
||||
I.mining_points -= prize.cost
|
||||
to_chat(usr, "<span class='notice'>[src] clanks to life briefly before vending [prize.equipment_name]!</span>")
|
||||
new prize.equipment_path(loc)
|
||||
SSblackbox.record_feedback("nested tally", "mining_equipment_bought", 1, list("[type]", "[prize.equipment_path]"))
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/mining_voucher))
|
||||
RedeemVoucher(I, user)
|
||||
return
|
||||
if(default_deconstruction_screwdriver(user, "mining-open", "mining", I))
|
||||
return
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/mining_voucher))
|
||||
|
||||
+96
-77
@@ -6,12 +6,15 @@
|
||||
icon = 'icons/obj/economy.dmi'
|
||||
icon_state = "coinpress0"
|
||||
density = TRUE
|
||||
var/newCoins = 0 //how many coins the machine made in it's last load
|
||||
input_dir = EAST
|
||||
ui_x = 300
|
||||
ui_y = 250
|
||||
needs_item_input = TRUE
|
||||
var/obj/item/storage/bag/money/bag_to_use
|
||||
var/produced_coins = 0 // how many coins the machine has made in it's last cycle
|
||||
var/processing = FALSE
|
||||
var/chosen = /datum/material/iron //which material will be used to make coins
|
||||
var/coinsToProduce = 10
|
||||
speed_process = TRUE
|
||||
var/obj/item/storage/bag/money/bag_to_use
|
||||
|
||||
|
||||
/obj/machinery/mineral/mint/Initialize()
|
||||
. = ..()
|
||||
@@ -28,89 +31,105 @@
|
||||
/datum/material/mythril,
|
||||
/datum/material/plastic,
|
||||
/datum/material/runite
|
||||
), MINERAL_MATERIAL_AMOUNT * 50, FALSE, /obj/item/stack)
|
||||
chosen = SSmaterials.GetMaterialRef(chosen)
|
||||
), MINERAL_MATERIAL_AMOUNT * 75, FALSE, /obj/item/stack)
|
||||
chosen = SSmaterials.GetMaterialRef(chosen)
|
||||
|
||||
/obj/machinery/mineral/mint/process()
|
||||
var/turf/T = get_step(src, input_dir)
|
||||
if(!T)
|
||||
|
||||
/obj/machinery/mineral/mint/pickup_item(datum/source, atom/movable/target, atom/oldLoc)
|
||||
if(QDELETED(target))
|
||||
return
|
||||
if(!istype(target, /obj/item/stack))
|
||||
return
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
for(var/obj/item/stack/sheet/O in T)
|
||||
var/inserted = materials.insert_item(O)
|
||||
if(inserted)
|
||||
qdel(O)
|
||||
var/obj/item/stack/S = target
|
||||
|
||||
/obj/machinery/mineral/mint/attack_hand(mob/user)
|
||||
if(materials.insert_item(S))
|
||||
qdel(S)
|
||||
|
||||
/obj/machinery/mineral/mint/process()
|
||||
if(processing)
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/datum/material/M = chosen
|
||||
|
||||
if(!M)
|
||||
processing = FALSE
|
||||
icon_state = "coinpress0"
|
||||
return
|
||||
|
||||
icon_state = "coinpress1"
|
||||
var/coin_mat = MINERAL_MATERIAL_AMOUNT
|
||||
|
||||
for(var/sheets in 1 to 2)
|
||||
if(materials.use_amount_mat(coin_mat, chosen))
|
||||
for(var/coin_to_make in 1 to 5)
|
||||
create_coins()
|
||||
produced_coins++
|
||||
CHECK_TICK
|
||||
else
|
||||
var/found_new = FALSE
|
||||
for(var/datum/material/inserted_material in materials.materials)
|
||||
var/amount = materials.get_material_amount(inserted_material)
|
||||
|
||||
if(amount)
|
||||
chosen = inserted_material
|
||||
found_new = TRUE
|
||||
|
||||
if(!found_new)
|
||||
processing = FALSE
|
||||
else
|
||||
STOP_PROCESSING(SSmachines, src)
|
||||
icon_state = "coinpress0"
|
||||
|
||||
/obj/machinery/mineral/mint/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "Mint", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/mineral/mint/ui_data()
|
||||
var/list/data = list()
|
||||
data["inserted_materials"] = list()
|
||||
data["chosen_material"] = null
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
for(var/datum/material/inserted_material in materials.materials)
|
||||
var/amount = materials.get_material_amount(inserted_material)
|
||||
if(!amount)
|
||||
continue
|
||||
data["inserted_materials"] += list(list(
|
||||
"material" = inserted_material.name,
|
||||
"amount" = amount,
|
||||
))
|
||||
if(chosen == inserted_material)
|
||||
data["chosen_material"] = inserted_material.name
|
||||
|
||||
data["produced_coins"] = produced_coins
|
||||
data["processing"] = processing
|
||||
|
||||
return data;
|
||||
|
||||
/obj/machinery/mineral/mint/ui_act(action, params, datum/tgui/ui)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/dat = "<b>Coin Press</b><br>"
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
for(var/datum/material/M in materials.materials)
|
||||
var/amount = materials.get_material_amount(M)
|
||||
if(!amount && chosen != M)
|
||||
continue
|
||||
dat += "<br><b>[M.name] amount:</b> [amount] cm<sup>3</sup> "
|
||||
if (chosen == M)
|
||||
dat += "<b>Chosen</b>"
|
||||
else
|
||||
dat += "<A href='?src=[REF(src)];choose=[REF(M)]'>Choose</A>"
|
||||
|
||||
var/datum/material/M = chosen
|
||||
|
||||
dat += "<br><br>Will produce [coinsToProduce] [lowertext(M.name)] coins if enough materials are available.<br>"
|
||||
dat += "<A href='?src=[REF(src)];chooseAmt=-10'>-10</A> "
|
||||
dat += "<A href='?src=[REF(src)];chooseAmt=-5'>-5</A> "
|
||||
dat += "<A href='?src=[REF(src)];chooseAmt=-1'>-1</A> "
|
||||
dat += "<A href='?src=[REF(src)];chooseAmt=1'>+1</A> "
|
||||
dat += "<A href='?src=[REF(src)];chooseAmt=5'>+5</A> "
|
||||
dat += "<A href='?src=[REF(src)];chooseAmt=10'>+10</A> "
|
||||
|
||||
dat += "<br><br>In total this machine produced <font color='green'><b>[newCoins]</b></font> coins."
|
||||
dat += "<br><A href='?src=[REF(src)];makeCoins=[1]'>Make coins</A>"
|
||||
user << browse(dat, "window=mint")
|
||||
|
||||
/obj/machinery/mineral/mint/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
if(processing==1)
|
||||
to_chat(usr, "<span class='notice'>The machine is processing.</span>")
|
||||
return
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
if(href_list["choose"])
|
||||
var/datum/material/new_material = locate(href_list["choose"])
|
||||
if(istype(new_material))
|
||||
chosen = new_material
|
||||
if(href_list["chooseAmt"])
|
||||
coinsToProduce = clamp(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000)
|
||||
updateUsrDialog()
|
||||
if(href_list["makeCoins"])
|
||||
var/temp_coins = coinsToProduce
|
||||
if(action == "startpress")
|
||||
if (!processing)
|
||||
produced_coins = 0
|
||||
processing = TRUE
|
||||
icon_state = "coinpress1"
|
||||
var/coin_mat = MINERAL_MATERIAL_AMOUNT * 0.2
|
||||
var/datum/material/M = chosen
|
||||
if(!M)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
while(coinsToProduce > 0 && materials.use_amount_mat(coin_mat, chosen))
|
||||
create_coins()
|
||||
coinsToProduce--
|
||||
newCoins++
|
||||
src.updateUsrDialog()
|
||||
sleep(5)
|
||||
|
||||
icon_state = "coinpress0"
|
||||
START_PROCESSING(SSmachines, src)
|
||||
return TRUE
|
||||
if (action == "stoppress")
|
||||
processing = FALSE
|
||||
coinsToProduce = temp_coins
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
STOP_PROCESSING(SSmachines, src)
|
||||
return TRUE
|
||||
if (action == "changematerial")
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
for(var/datum/material/mat in materials.materials)
|
||||
if (params["material_name"] == mat.name)
|
||||
chosen = mat
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mineral/mint/proc/create_coins()
|
||||
var/turf/T = get_step(src,output_dir)
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
density = TRUE
|
||||
pressure_resistance = 5*ONE_ATMOSPHERE
|
||||
|
||||
var/ui_x = 335
|
||||
var/ui_y = 415
|
||||
|
||||
/obj/structure/ore_box/attackby(obj/item/W, mob/user, params)
|
||||
if (istype(W, /obj/item/stack/ore))
|
||||
user.transferItemToLoc(W, src)
|
||||
@@ -24,16 +27,16 @@
|
||||
|
||||
/obj/structure/ore_box/crowbar_act(mob/living/user, obj/item/I)
|
||||
if(I.use_tool(src, user, 50, volume=50))
|
||||
user.visible_message("[user] pries \the [src] apart.",
|
||||
user.visible_message("<span class='notice'>[user] pries \the [src] apart.</span>",
|
||||
"<span class='notice'>You pry apart \the [src].</span>",
|
||||
"<span class='italics'>You hear splitting wood.</span>")
|
||||
"<span class='hear'>You hear splitting wood.</span>")
|
||||
deconstruct(TRUE, user)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/ore_box/examine(mob/living/user)
|
||||
if(Adjacent(user) && istype(user))
|
||||
ui_interact(user)
|
||||
return ..()
|
||||
. = ..()
|
||||
|
||||
/obj/structure/ore_box/attack_hand(mob/user)
|
||||
. = ..()
|
||||
@@ -62,7 +65,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "ore_box", name, 335, 415, master_ui, state)
|
||||
ui = new(user, src, ui_key, "OreBox", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/structure/ore_box/ui_data()
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/datum/notificationpanel/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "notificationpanel", "Notification Preferences", 270, 360, master_ui, state)
|
||||
ui = new(user, src, ui_key, "NotificationPreferences", "Notification Preferences", 270, 360, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/notificationpanel/ui_data(mob/user)
|
||||
|
||||
@@ -54,6 +54,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
|
||||
// Used for displaying in ghost chat, without changing the actual name
|
||||
// of the mob
|
||||
var/deadchat_name
|
||||
var/datum/orbit_menu/orbit_menu
|
||||
var/datum/spawners_menu/spawners_menu
|
||||
|
||||
/mob/dead/observer/Initialize(mapload, mob/body)
|
||||
@@ -161,6 +162,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
|
||||
|
||||
updateallghostimages()
|
||||
|
||||
QDEL_NULL(orbit_menu)
|
||||
QDEL_NULL(spawners_menu)
|
||||
return ..()
|
||||
|
||||
@@ -490,10 +492,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
set name = "Orbit" // "Haunt"
|
||||
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)
|
||||
if(!orbit_menu)
|
||||
orbit_menu = new(src)
|
||||
|
||||
orbit_menu.ui_interact(src)
|
||||
|
||||
// This is the ghost's follow verb with an argument
|
||||
/mob/dead/observer/proc/ManualFollow(atom/movable/target)
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/datum/orbit_menu
|
||||
var/mob/dead/observer/owner
|
||||
|
||||
/datum/orbit_menu/New(mob/dead/observer/new_owner)
|
||||
if(!istype(new_owner))
|
||||
qdel(src)
|
||||
owner = new_owner
|
||||
|
||||
/datum/orbit_menu/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "Orbit", "Orbit", 350, 700, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/orbit_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
if (..())
|
||||
return
|
||||
|
||||
if (action == "orbit")
|
||||
var/list/pois = getpois(skip_mindless = 1)
|
||||
var/atom/movable/poi = pois[params["name"]]
|
||||
if (poi != null)
|
||||
owner.ManualFollow(poi)
|
||||
ui.close()
|
||||
|
||||
/datum/orbit_menu/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
var/list/alive = list()
|
||||
var/list/antagonists = list()
|
||||
var/list/dead = list()
|
||||
var/list/ghosts = list()
|
||||
var/list/misc = list()
|
||||
var/list/npcs = list()
|
||||
|
||||
var/list/pois = getpois(skip_mindless = 1)
|
||||
for (var/name in pois)
|
||||
var/list/serialized = list()
|
||||
serialized["name"] = name
|
||||
|
||||
var/poi = pois[name]
|
||||
|
||||
var/mob/M = poi
|
||||
if (istype(M))
|
||||
if (isobserver(M))
|
||||
ghosts += list(serialized)
|
||||
else if (M.stat == DEAD)
|
||||
dead += list(serialized)
|
||||
else if (M.mind == null)
|
||||
npcs += list(serialized)
|
||||
else
|
||||
var/number_of_orbiters = M.orbiters?.orbiters?.len
|
||||
if (number_of_orbiters)
|
||||
serialized["orbiters"] = number_of_orbiters
|
||||
|
||||
var/datum/mind/mind = M.mind
|
||||
var/was_antagonist = FALSE
|
||||
|
||||
for (var/_A in mind.antag_datums)
|
||||
var/datum/antagonist/A = _A
|
||||
if (A.show_to_ghosts)
|
||||
was_antagonist = TRUE
|
||||
serialized["antag"] = A.name
|
||||
antagonists += list(serialized)
|
||||
break
|
||||
|
||||
if (!was_antagonist)
|
||||
alive += list(serialized)
|
||||
else
|
||||
misc += list(serialized)
|
||||
|
||||
data["alive"] = alive
|
||||
data["antagonists"] = antagonists
|
||||
data["dead"] = dead
|
||||
data["ghosts"] = ghosts
|
||||
data["misc"] = misc
|
||||
data["npcs"] = npcs
|
||||
|
||||
return data
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
status_flags = CANUNCONSCIOUS|CANPUSH
|
||||
|
||||
var/heat_protection = 0.5
|
||||
heat_protection = 0.5
|
||||
var/leaping = 0
|
||||
gib_type = /obj/effect/decal/cleanable/blood/gibs/xeno
|
||||
unique_name = 1
|
||||
|
||||
@@ -64,3 +64,11 @@
|
||||
|
||||
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
|
||||
var/tackling = FALSE //Whether or not we are tackling, this will prevent the knock into effects for carbons
|
||||
|
||||
/// Protection (insulation) from the heat, Value 0-1 corresponding to the percentage of protection
|
||||
var/heat_protection = 0 // No heat protection
|
||||
/// Protection (insulation) from the cold, Value 0-1 corresponding to the percentage of protection
|
||||
var/cold_protection = 0 // No cold protection
|
||||
|
||||
/// Timer id of any transformation
|
||||
var/transformation_timer
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
enable_intentional_sprint_mode()
|
||||
|
||||
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /atom.proc/clean_blood)
|
||||
GLOB.human_list += src
|
||||
|
||||
|
||||
/mob/living/carbon/human/ComponentInitialize()
|
||||
@@ -47,6 +48,7 @@
|
||||
/mob/living/carbon/human/Destroy()
|
||||
QDEL_NULL(physiology)
|
||||
QDEL_NULL_LIST(vore_organs) // CITADEL EDIT belly stuff
|
||||
GLOB.human_list -= src
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/prepare_data_huds()
|
||||
|
||||
@@ -382,7 +382,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
//keep it at the right spot, so we can't have people taking shortcuts
|
||||
var/location = C.dna.mutation_index.Find(inert_mutation)
|
||||
C.dna.mutation_index[location] = new_species.inert_mutation
|
||||
C.dna.default_mutation_genes[location] = C.dna.mutation_index[location]
|
||||
C.dna.mutation_index[new_species.inert_mutation] = create_sequence(new_species.inert_mutation)
|
||||
C.dna.default_mutation_genes[new_species.inert_mutation] = C.dna.mutation_index[new_species.inert_mutation]
|
||||
|
||||
if(!new_species.has_field_of_vision && has_field_of_vision && ishuman(C) && CONFIG_GET(flag/use_field_of_vision))
|
||||
var/datum/component/field_of_vision/F = C.GetComponent(/datum/component/field_of_vision)
|
||||
|
||||
@@ -314,7 +314,7 @@
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "slime_swap_body", name, 400, 400, master_ui, state)
|
||||
ui = new(user, src, ui_key, "SlimeBodySwapper", name, 400, 400, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/action/innate/swap_body/ui_data(mob/user)
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/datum/robot_control
|
||||
var/mob/living/silicon/ai/owner
|
||||
|
||||
/datum/robot_control/New(mob/living/silicon/ai/new_owner)
|
||||
if(!istype(new_owner))
|
||||
qdel(src)
|
||||
owner = new_owner
|
||||
|
||||
/datum/robot_control/proc/is_interactable(mob/user)
|
||||
if(user != owner || owner.incapacitated())
|
||||
return FALSE
|
||||
if(owner.control_disabled)
|
||||
to_chat(user, "<span class='warning'>Wireless control is disabled.</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/robot_control/ui_status(mob/user)
|
||||
if(is_interactable(user))
|
||||
return ..()
|
||||
return UI_CLOSE
|
||||
|
||||
/datum/robot_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "RemoteRobotControl", "Remote Robot Control", 500, 500, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/robot_control/ui_data(mob/user)
|
||||
if(!owner || user != owner)
|
||||
return
|
||||
var/list/data = list()
|
||||
var/turf/ai_current_turf = get_turf(owner)
|
||||
var/ai_zlevel = ai_current_turf.z
|
||||
|
||||
data["robots"] = list()
|
||||
for(var/mob/living/simple_animal/bot/B in GLOB.bots_list)
|
||||
if(B.z != ai_zlevel || B.remote_disabled) //Only non-emagged bots on the same Z-level are detected!
|
||||
continue
|
||||
var/list/robot_data = list(
|
||||
name = B.name,
|
||||
model = B.model,
|
||||
mode = B.get_mode(),
|
||||
hacked = B.hacked,
|
||||
location = get_area_name(B, TRUE),
|
||||
ref = REF(B)
|
||||
)
|
||||
data["robots"] += list(robot_data)
|
||||
|
||||
return data
|
||||
|
||||
/datum/robot_control/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(!is_interactable(usr))
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("callbot") //Command a bot to move to a selected location.
|
||||
if(owner.call_bot_cooldown > world.time)
|
||||
to_chat(usr, "<span class='danger'>Error: Your last call bot command is still processing, please wait for the bot to finish calculating a route.</span>")
|
||||
return
|
||||
owner.Bot = locate(params["ref"]) in GLOB.bots_list
|
||||
if(!owner.Bot || owner.Bot.remote_disabled || owner.control_disabled)
|
||||
return
|
||||
owner.waypoint_mode = TRUE
|
||||
to_chat(usr, "<span class='notice'>Set your waypoint by clicking on a valid location free of obstructions.</span>")
|
||||
. = TRUE
|
||||
if("interface") //Remotely connect to a bot!
|
||||
owner.Bot = locate(params["ref"]) in GLOB.bots_list
|
||||
if(!owner.Bot || owner.Bot.remote_disabled || owner.control_disabled)
|
||||
return
|
||||
owner.Bot.attack_ai(usr)
|
||||
. = TRUE
|
||||
@@ -115,6 +115,19 @@
|
||||
else
|
||||
return "<span class='average'>[mode_name[mode]]</span>"
|
||||
|
||||
/**
|
||||
* Returns a status string about the bot's current status, if it's moving, manually controlled, or idle.
|
||||
*/
|
||||
/mob/living/simple_animal/bot/proc/get_mode_ui()
|
||||
if(client) //Player bots do not have modes, thus the override. Also an easy way for PDA users/AI to know when a bot is a player.
|
||||
return paicard ? "pAI Controlled" : "Autonomous"
|
||||
else if(!on)
|
||||
return "Inactive"
|
||||
else if(!mode)
|
||||
return "Idle"
|
||||
else
|
||||
return "[mode_name[mode]]"
|
||||
|
||||
/mob/living/simple_animal/bot/proc/turn_on()
|
||||
if(stat)
|
||||
return FALSE
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "mulebot", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, ui_key, "Mule", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/ui_data(mob/user)
|
||||
|
||||
@@ -558,3 +558,17 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
|
||||
//Can the mob see reagents inside of containers?
|
||||
/mob/proc/can_see_reagents()
|
||||
return stat == DEAD || silicon_privileges //Dead guys and silicons can always see reagents
|
||||
|
||||
/mob/proc/is_blind()
|
||||
SHOULD_BE_PURE(TRUE)
|
||||
return eye_blind ? TRUE : HAS_TRAIT(src, TRAIT_BLIND)
|
||||
|
||||
/mob/proc/can_read(obj/O)
|
||||
if(is_blind())
|
||||
to_chat(src, "<span class='warning'>As you are trying to read [O], you suddenly feel very stupid!</span>")
|
||||
return
|
||||
if(!is_literate())
|
||||
to_chat(src, "<span class='notice'>You try to read [O], but can't comprehend any of it.</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -1,26 +1,8 @@
|
||||
/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG))
|
||||
if (mob_transforming)
|
||||
#define TRANSFORMATION_DURATION 22
|
||||
|
||||
/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_DEFAULTMSG))
|
||||
if(mob_transforming || transformation_timer)
|
||||
return
|
||||
//Handle items on mob
|
||||
|
||||
//first implants & organs
|
||||
var/list/stored_implants = list()
|
||||
var/list/int_organs = list()
|
||||
|
||||
if (tr_flags & TR_KEEPIMPLANTS)
|
||||
for(var/X in implants)
|
||||
var/obj/item/implant/IMP = X
|
||||
stored_implants += IMP
|
||||
IMP.removed(src, 1, 1)
|
||||
|
||||
var/list/missing_bodyparts_zones = get_missing_limbs()
|
||||
|
||||
var/obj/item/cavity_object
|
||||
|
||||
var/obj/item/bodypart/chest/CH = get_bodypart(BODY_ZONE_CHEST)
|
||||
if(CH.cavity_item)
|
||||
cavity_object = CH.cavity_item
|
||||
CH.cavity_item = null
|
||||
|
||||
if(tr_flags & TR_KEEPITEMS)
|
||||
var/Itemlist = get_equipped_items(TRUE)
|
||||
@@ -30,13 +12,36 @@
|
||||
|
||||
//Make mob invisible and spawn animation
|
||||
mob_transforming = TRUE
|
||||
Stun(INFINITY, ignore_canstun = TRUE)
|
||||
Paralyze(TRANSFORMATION_DURATION, ignore_canstun = TRUE)
|
||||
icon = null
|
||||
cut_overlays()
|
||||
invisibility = INVISIBILITY_MAXIMUM
|
||||
|
||||
new /obj/effect/temp_visual/monkeyify(loc)
|
||||
sleep(22)
|
||||
|
||||
transformation_timer = addtimer(CALLBACK(src, .proc/finish_monkeyize, tr_flags), TRANSFORMATION_DURATION, TIMER_UNIQUE)
|
||||
|
||||
/mob/living/carbon/proc/finish_monkeyize(tr_flags)
|
||||
transformation_timer = null
|
||||
|
||||
var/list/missing_bodyparts_zones = get_missing_limbs()
|
||||
|
||||
var/list/stored_implants = list()
|
||||
|
||||
if (tr_flags & TR_KEEPIMPLANTS)
|
||||
for(var/X in implants)
|
||||
var/obj/item/implant/IMP = X
|
||||
stored_implants += IMP
|
||||
IMP.removed(src, 1, 1)
|
||||
|
||||
var/list/int_organs = list()
|
||||
var/obj/item/cavity_object
|
||||
|
||||
var/obj/item/bodypart/chest/CH = get_bodypart(BODY_ZONE_CHEST)
|
||||
if(CH.cavity_item)
|
||||
cavity_object = CH.cavity_item
|
||||
CH.cavity_item = null
|
||||
|
||||
var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey( loc )
|
||||
|
||||
// hash the original name?
|
||||
@@ -50,6 +55,7 @@
|
||||
|
||||
if(tr_flags & TR_KEEPSE)
|
||||
O.dna.mutation_index = dna.mutation_index
|
||||
O.dna.default_mutation_genes = dna.default_mutation_genes
|
||||
O.dna.set_se(1, GET_INITIALIZED_MUTATION(RACEMUT))
|
||||
|
||||
if(suiciding)
|
||||
@@ -149,12 +155,33 @@
|
||||
////////////////////////// Humanize //////////////////////////////
|
||||
//Could probably be merged with monkeyize but other transformations got their own procs, too
|
||||
|
||||
/mob/living/carbon/proc/humanize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG))
|
||||
if (mob_transforming)
|
||||
/mob/living/carbon/proc/humanize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_DEFAULTMSG))
|
||||
if (mob_transforming || transformation_timer)
|
||||
return
|
||||
//Handle items on mob
|
||||
|
||||
//first implants & organs
|
||||
//now the rest
|
||||
if (tr_flags & TR_KEEPITEMS)
|
||||
var/Itemlist = get_equipped_items(TRUE)
|
||||
Itemlist += held_items
|
||||
for(var/obj/item/W in Itemlist)
|
||||
dropItemToGround(W, TRUE)
|
||||
if (client)
|
||||
client.screen -= W
|
||||
|
||||
//Make mob invisible and spawn animation
|
||||
mob_transforming = TRUE
|
||||
Paralyze(TRANSFORMATION_DURATION, ignore_canstun = TRUE)
|
||||
|
||||
icon = null
|
||||
cut_overlays()
|
||||
invisibility = INVISIBILITY_MAXIMUM
|
||||
new /obj/effect/temp_visual/monkeyify/humanify(loc)
|
||||
|
||||
transformation_timer = addtimer(CALLBACK(src, .proc/finish_humanize, tr_flags), TRANSFORMATION_DURATION, TIMER_UNIQUE)
|
||||
|
||||
/mob/living/carbon/proc/finish_humanize(tr_flags)
|
||||
transformation_timer = null
|
||||
|
||||
var/list/stored_implants = list()
|
||||
var/list/int_organs = list()
|
||||
|
||||
@@ -173,25 +200,6 @@
|
||||
cavity_object = CH.cavity_item
|
||||
CH.cavity_item = null
|
||||
|
||||
//now the rest
|
||||
if (tr_flags & TR_KEEPITEMS)
|
||||
var/Itemlist = get_equipped_items(TRUE)
|
||||
Itemlist += held_items
|
||||
for(var/obj/item/W in Itemlist)
|
||||
dropItemToGround(W, TRUE)
|
||||
if (client)
|
||||
client.screen -= W
|
||||
|
||||
|
||||
|
||||
//Make mob invisible and spawn animation
|
||||
mob_transforming = TRUE
|
||||
Stun(22, ignore_canstun = TRUE)
|
||||
icon = null
|
||||
cut_overlays()
|
||||
invisibility = INVISIBILITY_MAXIMUM
|
||||
new /obj/effect/temp_visual/monkeyify/humanify(loc)
|
||||
sleep(22)
|
||||
var/mob/living/carbon/human/O = new( loc )
|
||||
for(var/obj/item/C in O.loc)
|
||||
O.equip_to_appropriate_slot(C)
|
||||
@@ -208,6 +216,7 @@
|
||||
|
||||
if(tr_flags & TR_KEEPSE)
|
||||
O.dna.mutation_index = dna.mutation_index
|
||||
O.dna.default_mutation_genes = dna.default_mutation_genes
|
||||
O.dna.set_se(0, GET_INITIALIZED_MUTATION(RACEMUT))
|
||||
O.domutcheck()
|
||||
|
||||
@@ -353,7 +362,7 @@
|
||||
qdel(src)
|
||||
|
||||
/mob/living/carbon/human/proc/Robotize(delete_items = 0, transfer_after = TRUE)
|
||||
if (mob_transforming)
|
||||
if(mob_transforming)
|
||||
return
|
||||
for(var/obj/item/W in src)
|
||||
if(delete_items)
|
||||
@@ -582,6 +591,48 @@
|
||||
. = new_mob
|
||||
qdel(src)
|
||||
|
||||
|
||||
/* Certain mob types have problems and should not be allowed to be controlled by players.
|
||||
*
|
||||
* This proc is here to force coders to manually place their mob in this list, hopefully tested.
|
||||
* This also gives a place to explain -why- players shouldnt be turn into certain mobs and hopefully someone can fix them.
|
||||
*/
|
||||
/mob/proc/safe_animal(MP)
|
||||
|
||||
//Bad mobs! - Remember to add a comment explaining what's wrong with the mob
|
||||
if(!MP)
|
||||
return 0 //Sanity, this should never happen.
|
||||
|
||||
if(ispath(MP, /mob/living/simple_animal/hostile/construct))
|
||||
return 0 //Verbs do not appear for players.
|
||||
|
||||
//Good mobs!
|
||||
if(ispath(MP, /mob/living/simple_animal/pet/cat))
|
||||
return 1
|
||||
if(ispath(MP, /mob/living/simple_animal/pet/dog/corgi))
|
||||
return 1
|
||||
if(ispath(MP, /mob/living/simple_animal/crab))
|
||||
return 1
|
||||
if(ispath(MP, /mob/living/simple_animal/hostile/carp))
|
||||
return 1
|
||||
if(ispath(MP, /mob/living/simple_animal/hostile/mushroom))
|
||||
return 1
|
||||
if(ispath(MP, /mob/living/simple_animal/shade))
|
||||
return 1
|
||||
if(ispath(MP, /mob/living/simple_animal/hostile/killertomato))
|
||||
return 1
|
||||
if(ispath(MP, /mob/living/simple_animal/mouse))
|
||||
return 1 //It is impossible to pull up the player panel for mice (Fixed! - Nodrak)
|
||||
if(ispath(MP, /mob/living/simple_animal/hostile/bear))
|
||||
return 1 //Bears will auto-attack mobs, even if they're player controlled (Fixed! - Nodrak)
|
||||
if(ispath(MP, /mob/living/simple_animal/parrot))
|
||||
return 1 //Parrots are no longer unfinished! -Nodrak
|
||||
|
||||
//Not in here? Must be untested!
|
||||
return 0
|
||||
|
||||
#undef TRANSFORMATION_DURATION
|
||||
|
||||
/mob/living/proc/turn_into_pickle()
|
||||
//if they're already a pickle, turn them back instead
|
||||
if(istype(src, /mob/living/simple_animal/pickle))
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
if (!ui)
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/headers)
|
||||
assets.send(user)
|
||||
|
||||
ui = new(user, src, ui_key, "ntos_main", "NtOS Main menu", 400, 500, master_ui, state)
|
||||
ui.set_style("ntos")
|
||||
assets = get_asset_datum(/datum/asset/simple/arcade)
|
||||
assets.send(user)
|
||||
ui = new(user, src, ui_key, "NtosMain", "NtOS Main menu", 400, 500, master_ui, state)
|
||||
ui.open()
|
||||
ui.set_autoupdate(state = 1)
|
||||
|
||||
|
||||
@@ -85,3 +85,4 @@
|
||||
var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
|
||||
hard_drive.store_file(new/datum/computer_file/program/chatclient())
|
||||
hard_drive.store_file(new/datum/computer_file/program/nttransfer())
|
||||
hard_drive.store_file(new/datum/computer_file/program/arcade())
|
||||
|
||||
@@ -1,26 +1,45 @@
|
||||
// /program/ files are executable programs that do things.
|
||||
/datum/computer_file/program
|
||||
filetype = "PRG"
|
||||
filename = "UnknownProgram" // File name. FILE NAME MUST BE UNIQUE IF YOU WANT THE PROGRAM TO BE DOWNLOADABLE FROM NTNET!
|
||||
var/required_access = null // List of required accesses to *run* the program.
|
||||
var/transfer_access = null // List of required access to download or file host the program
|
||||
var/program_state = PROGRAM_STATE_KILLED// PROGRAM_STATE_KILLED or PROGRAM_STATE_BACKGROUND or PROGRAM_STATE_ACTIVE - specifies whether this program is running.
|
||||
var/obj/item/modular_computer/computer // Device that runs this program.
|
||||
var/filedesc = "Unknown Program" // User-friendly name of this program.
|
||||
var/extended_desc = "N/A" // Short description of this program's function.
|
||||
var/program_icon_state = null // Program-specific screen icon state
|
||||
var/requires_ntnet = 0 // Set to 1 for program to require nonstop NTNet connection to run. If NTNet connection is lost program crashes.
|
||||
var/requires_ntnet_feature = 0 // Optional, if above is set to 1 checks for specific function of NTNet (currently NTNET_SOFTWAREDOWNLOAD, NTNET_PEERTOPEER, NTNET_SYSTEMCONTROL and NTNET_COMMUNICATION)
|
||||
var/ntnet_status = 1 // NTNet status, updated every tick by computer running this program. Don't use this for checks if NTNet works, computers do that. Use this for calculations, etc.
|
||||
var/usage_flags = PROGRAM_ALL // Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL
|
||||
var/network_destination = null // Optional string that describes what NTNet server/system this program connects to. Used in default logging.
|
||||
var/available_on_ntnet = 1 // Whether the program can be downloaded from NTNet. Set to 0 to disable.
|
||||
var/available_on_syndinet = 0 // Whether the program can be downloaded from SyndiNet (accessible via emagging the computer). Set to 1 to enable.
|
||||
var/tgui_id // ID of TGUI interface
|
||||
var/ui_style // ID of custom TGUI style (optional)
|
||||
var/ui_x = 575 // Default size of TGUI window, in pixels
|
||||
/// File name. FILE NAME MUST BE UNIQUE IF YOU WANT THE PROGRAM TO BE DOWNLOADABLE FROM NTNET!
|
||||
filename = "UnknownProgram"
|
||||
/// List of required accesses to *run* the program.
|
||||
var/required_access = null
|
||||
/// List of required access to download or file host the program
|
||||
var/transfer_access = null
|
||||
/// PROGRAM_STATE_KILLED or PROGRAM_STATE_BACKGROUND or PROGRAM_STATE_ACTIVE - specifies whether this program is running.
|
||||
var/program_state = PROGRAM_STATE_KILLED
|
||||
/// Device that runs this program.
|
||||
var/obj/item/modular_computer/computer
|
||||
/// User-friendly name of this program.
|
||||
var/filedesc = "Unknown Program"
|
||||
/// Short description of this program's function.
|
||||
var/extended_desc = "N/A"
|
||||
/// Program-specific screen icon state
|
||||
var/program_icon_state = null
|
||||
/// Set to 1 for program to require nonstop NTNet connection to run. If NTNet connection is lost program crashes.
|
||||
var/requires_ntnet = FALSE
|
||||
/// Optional, if above is set to 1 checks for specific function of NTNet (currently NTNET_SOFTWAREDOWNLOAD, NTNET_PEERTOPEER, NTNET_SYSTEMCONTROL and NTNET_COMMUNICATION)
|
||||
var/requires_ntnet_feature = 0
|
||||
/// NTNet status, updated every tick by computer running this program. Don't use this for checks if NTNet works, computers do that. Use this for calculations, etc.
|
||||
var/ntnet_status = 1
|
||||
/// Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL
|
||||
var/usage_flags = PROGRAM_ALL
|
||||
/// Optional string that describes what NTNet server/system this program connects to. Used in default logging.
|
||||
var/network_destination = null
|
||||
/// Whether the program can be downloaded from NTNet. Set to 0 to disable.
|
||||
var/available_on_ntnet = 1
|
||||
/// Whether the program can be downloaded from SyndiNet (accessible via emagging the computer). Set to 1 to enable.
|
||||
var/available_on_syndinet = 0
|
||||
/// ID of TGUI interface
|
||||
var/tgui_id
|
||||
/// Default size of TGUI window, in pixels
|
||||
var/ui_x = 575
|
||||
var/ui_y = 700
|
||||
var/ui_header = null // Example: "something.gif" - a header image that will be rendered in computer's UI when this program is running at background. Images are taken from /icons/program_icons. Be careful not to use too large images!
|
||||
/// Example: "something.gif" - a header image that will be rendered in computer's UI when this program is running at background. Images are taken from /icons/program_icons. Be careful not to use too large images!
|
||||
var/ui_header = null
|
||||
///Assets specific to programs
|
||||
var/list/special_assets = list()
|
||||
|
||||
/datum/computer_file/program/New(obj/item/modular_computer/comp = null)
|
||||
..()
|
||||
@@ -50,23 +69,23 @@
|
||||
/datum/computer_file/program/proc/generate_network_log(text)
|
||||
if(computer)
|
||||
return computer.add_log(text)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/datum/computer_file/program/proc/is_supported_by_hardware(hardware_flag = 0, loud = 0, mob/user = null)
|
||||
if(!(hardware_flag & usage_flags))
|
||||
if(loud && computer && user)
|
||||
to_chat(user, "<span class='danger'>\The [computer] flashes an \"Hardware Error - Incompatible software\" warning.</span>")
|
||||
return 0
|
||||
return 1
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/computer_file/program/proc/get_signal(specific_action = 0)
|
||||
if(computer)
|
||||
return computer.get_ntnet_status(specific_action)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
// Called by Process() on device that runs us, once every tick.
|
||||
/datum/computer_file/program/proc/process_tick()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
// Check if the user can run program. Only humans can operate computer. Automatically called in run_program()
|
||||
// User has to wear their ID for ID Scan to work.
|
||||
@@ -87,7 +106,7 @@
|
||||
if(IsAdminGhost(user))
|
||||
return TRUE
|
||||
|
||||
if(computer && computer.hasSiliconAccessInArea(user))
|
||||
if(issilicon(user))
|
||||
return TRUE
|
||||
|
||||
if(ishuman(user))
|
||||
@@ -98,6 +117,7 @@
|
||||
D = card_slot.GetID()
|
||||
var/mob/living/carbon/human/h = user
|
||||
var/obj/item/card/id/I = h.get_idcard(TRUE)
|
||||
|
||||
if(!I && !D)
|
||||
if(loud)
|
||||
to_chat(user, "<span class='danger'>\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning.</span>")
|
||||
@@ -123,7 +143,7 @@
|
||||
// This is performed on program startup. May be overridden to add extra logic. Remember to include ..() call. Return 1 on success, 0 on failure.
|
||||
// When implementing new program based device, use this to run the program.
|
||||
/datum/computer_file/program/proc/run_program(mob/living/user)
|
||||
if(can_run(user, 1))
|
||||
if(can_run(user, TRUE))
|
||||
if(requires_ntnet && network_destination)
|
||||
generate_network_log("Connection opened to [network_destination].")
|
||||
program_state = PROGRAM_STATE_ACTIVE
|
||||
@@ -143,12 +163,11 @@
|
||||
if(!ui && tgui_id)
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/headers)
|
||||
assets.send(user)
|
||||
for(var/i in special_assets)
|
||||
assets = get_asset_datum(i)
|
||||
assets.send(user)
|
||||
|
||||
ui = new(user, src, ui_key, tgui_id, filedesc, ui_x, ui_y, state = state)
|
||||
|
||||
if(ui_style)
|
||||
ui.set_style(ui_style)
|
||||
ui.set_autoupdate(state = 1)
|
||||
ui.open()
|
||||
|
||||
// CONVENTIONS, READ THIS WHEN CREATING NEW PROGRAM AND OVERRIDING THIS PROC:
|
||||
@@ -156,7 +175,7 @@
|
||||
// Calls beginning with "PRG_" are reserved for programs handling.
|
||||
// Calls beginning with "PC_" are reserved for computer handling (by whatever runs the program)
|
||||
// ALWAYS INCLUDE PARENT CALL ..() OR DIE IN FIRE.
|
||||
/datum/computer_file/program/ui_act(action,params,datum/tgui/ui)
|
||||
/datum/computer_file/program/ui_act(action,list/params,datum/tgui/ui)
|
||||
if(..())
|
||||
return TRUE
|
||||
if(computer)
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
program_icon_state = "generic"
|
||||
extended_desc = "This program is capable of reconstructing damaged AI systems. Requires direct AI connection via intellicard slot."
|
||||
size = 12
|
||||
requires_ntnet = 0
|
||||
usage_flags = PROGRAM_CONSOLE
|
||||
requires_ntnet = FALSE
|
||||
usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP
|
||||
transfer_access = ACCESS_HEADS
|
||||
available_on_ntnet = 1
|
||||
tgui_id = "ntos_ai_restorer"
|
||||
ui_x = 600
|
||||
available_on_ntnet = TRUE
|
||||
tgui_id = "NtosAiRestorer"
|
||||
ui_x = 370
|
||||
ui_y = 400
|
||||
|
||||
/// Variable dictating if we are in the process of restoring the AI in the inserted intellicard
|
||||
var/restoring = FALSE
|
||||
|
||||
/datum/computer_file/program/aidiag/proc/get_ai(cardcheck)
|
||||
@@ -30,11 +30,11 @@
|
||||
if(ai_slot.stored_card.AI)
|
||||
return ai_slot.stored_card.AI
|
||||
|
||||
return null
|
||||
return
|
||||
|
||||
/datum/computer_file/program/aidiag/ui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
return
|
||||
|
||||
var/mob/living/silicon/ai/A = get_ai()
|
||||
if(!A)
|
||||
@@ -44,6 +44,7 @@
|
||||
if("PRG_beginReconstruction")
|
||||
if(A && A.health < 100)
|
||||
restoring = TRUE
|
||||
A.notify_ghost_cloning("Your core files are being restored!", source = computer)
|
||||
return TRUE
|
||||
if("PRG_eject")
|
||||
if(computer.all_components[MC_AI])
|
||||
@@ -53,7 +54,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/computer_file/program/aidiag/process_tick()
|
||||
..()
|
||||
. = ..()
|
||||
if(!restoring) //Put the check here so we don't check for an ai all the time
|
||||
return
|
||||
var/obj/item/aicard/cardhold = get_ai(2)
|
||||
@@ -73,13 +74,13 @@
|
||||
restoring = FALSE
|
||||
return
|
||||
ai_slot.locked =TRUE
|
||||
A.adjustOxyLoss(-1, 0)
|
||||
A.adjustFireLoss(-1, 0)
|
||||
A.adjustToxLoss(-1, 0)
|
||||
A.adjustBruteLoss(-1, 0)
|
||||
A.adjustOxyLoss(-5, 0)
|
||||
A.adjustFireLoss(-5, 0)
|
||||
A.adjustToxLoss(-5, 0)
|
||||
A.adjustBruteLoss(-5, 0)
|
||||
A.updatehealth()
|
||||
if(A.health >= 0 && A.stat == DEAD)
|
||||
A.revive()
|
||||
A.revive(full_heal = FALSE, admin_revive = FALSE)
|
||||
// Finished restoring
|
||||
if(A.health >= 100)
|
||||
ai_slot.locked = FALSE
|
||||
@@ -90,14 +91,14 @@
|
||||
|
||||
/datum/computer_file/program/aidiag/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
var/mob/living/silicon/ai/AI
|
||||
// A shortcut for getting the AI stored inside the computer. The program already does necessary checks.
|
||||
AI = get_ai()
|
||||
var/mob/living/silicon/ai/AI = get_ai()
|
||||
|
||||
var/obj/item/aicard/aicard = get_ai(2)
|
||||
|
||||
data["ejectable"] = TRUE
|
||||
data["AI_present"] = FALSE
|
||||
data["error"] = null
|
||||
if(!aicard)
|
||||
data["nocard"] = TRUE
|
||||
data["error"] = "Please insert an intelliCard."
|
||||
else
|
||||
if(!AI)
|
||||
@@ -107,15 +108,15 @@
|
||||
if(cardhold.flush)
|
||||
data["error"] = "Flush in progress"
|
||||
else
|
||||
data["AI_present"] = TRUE
|
||||
data["name"] = AI.name
|
||||
data["restoring"] = restoring
|
||||
data["laws"] = AI.laws.get_law_list(include_zeroth = 1)
|
||||
data["health"] = (AI.health + 100) / 2
|
||||
data["isDead"] = AI.stat == DEAD
|
||||
data["ai_laws"] = AI.laws.get_law_list(include_zeroth = 1)
|
||||
data["laws"] = AI.laws.get_law_list(include_zeroth = 1)
|
||||
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/aidiag/kill_program(forced)
|
||||
restoring = FALSE
|
||||
return ..(forced)
|
||||
return ..()
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
requires_ntnet = 1
|
||||
network_destination = "alarm monitoring network"
|
||||
size = 5
|
||||
tgui_id = "ntos_station_alert"
|
||||
tgui_id = "NtosStationAlertConsole"
|
||||
ui_x = 315
|
||||
ui_y = 500
|
||||
|
||||
@@ -72,15 +72,23 @@
|
||||
/datum/computer_file/program/alarm_monitor/proc/cancelAlarm(class, area/A, obj/origin)
|
||||
var/list/L = alarms[class]
|
||||
var/cleared = 0
|
||||
var/arealevelalarm = FALSE // set to TRUE for alarms that set/clear whole areas
|
||||
if (class=="Fire")
|
||||
arealevelalarm = TRUE
|
||||
for (var/I in L)
|
||||
if (I == A.name)
|
||||
var/list/alarm = L[I]
|
||||
var/list/srcs = alarm[3]
|
||||
if (origin in srcs)
|
||||
srcs -= origin
|
||||
if (srcs.len == 0)
|
||||
if (!arealevelalarm) // the traditional behaviour
|
||||
var/list/alarm = L[I]
|
||||
var/list/srcs = alarm[3]
|
||||
if (origin in srcs)
|
||||
srcs -= origin
|
||||
if (srcs.len == 0)
|
||||
cleared = 1
|
||||
L -= I
|
||||
else
|
||||
L -= I // wipe the instances entirely
|
||||
cleared = 1
|
||||
L -= I
|
||||
|
||||
|
||||
update_alarm_display()
|
||||
return !cleared
|
||||
|
||||
@@ -8,20 +8,20 @@
|
||||
available_on_ntnet = 0
|
||||
unsendable = 1
|
||||
undeletable = 1
|
||||
tgui_id = "synd_contract"
|
||||
ui_style = "syndicate"
|
||||
ui_x = 600
|
||||
tgui_id = "SyndContractor"
|
||||
ui_x = 500
|
||||
ui_y = 600
|
||||
var/error = ""
|
||||
var/page = CONTRACT_UPLINK_PAGE_CONTRACTS
|
||||
var/info_screen = TRUE
|
||||
var/assigned = FALSE
|
||||
var/first_load = TRUE
|
||||
|
||||
/datum/computer_file/program/contract_uplink/run_program(var/mob/living/user)
|
||||
. = ..(user)
|
||||
|
||||
/datum/computer_file/program/contract_uplink/ui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
return TRUE
|
||||
var/mob/living/user = usr
|
||||
var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = computer.all_components[MC_HDD]
|
||||
switch(action)
|
||||
@@ -31,27 +31,32 @@
|
||||
hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id].status = CONTRACT_STATUS_ACTIVE
|
||||
hard_drive.traitor_data.contractor_hub.current_contract = hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id]
|
||||
program_icon_state = "single_contract"
|
||||
return 1
|
||||
return TRUE
|
||||
if("PRG_login")
|
||||
var/datum/antagonist/traitor/traitor_data = user.mind.has_antag_datum(/datum/antagonist/traitor)
|
||||
if(traitor_data) // Bake their data right into the hard drive, or we don't allow non-antags gaining access to unused contract system. We also create their contracts at this point.
|
||||
if(!traitor_data.contractor_hub) // Only play greet sound, and handle contractor hub when assigning for the first time.
|
||||
|
||||
// Bake their data right into the hard drive, or we don't allow non-antags gaining access to an unused
|
||||
// contract system.
|
||||
// We also create their contracts at this point.
|
||||
if(traitor_data)
|
||||
// Only play greet sound, and handle contractor hub when assigning for the first time.
|
||||
if(!traitor_data.contractor_hub)
|
||||
user.playsound_local(user, 'sound/effects/contractstartup.ogg', 100, FALSE)
|
||||
traitor_data.contractor_hub = new
|
||||
traitor_data.contractor_hub.create_hub_items()
|
||||
user.playsound_local(user, 'sound/effects/contractstartup.ogg', 100, 0)
|
||||
// Stops any topic exploits such as logging in multiple times on a single system.
|
||||
// Stops any topic exploits such as logging in multiple times on a single system.
|
||||
if(!assigned)
|
||||
traitor_data.contractor_hub.create_contracts(traitor_data.owner)
|
||||
hard_drive.traitor_data = traitor_data
|
||||
program_icon_state = "contracts"
|
||||
assigned = TRUE
|
||||
else
|
||||
error = "Incorrect login details."
|
||||
return 1
|
||||
error = "UNAUTHORIZED USER"
|
||||
return TRUE
|
||||
if("PRG_call_extraction")
|
||||
if(hard_drive.traitor_data.contractor_hub.current_contract.status != CONTRACT_STATUS_EXTRACTING)
|
||||
if(hard_drive.traitor_data.contractor_hub.current_contract.handle_extraction(user))
|
||||
user.playsound_local(user, 'sound/effects/confirmdropoff.ogg', 100, 1)
|
||||
user.playsound_local(user, 'sound/effects/confirmdropoff.ogg', 100, TRUE)
|
||||
hard_drive.traitor_data.contractor_hub.current_contract.status = CONTRACT_STATUS_EXTRACTING
|
||||
program_icon_state = "extracted"
|
||||
else
|
||||
@@ -59,17 +64,18 @@
|
||||
error = "Either both you or your target aren't at the dropoff location, or the pod hasn't got a valid place to land. Clear space, or make sure you're both inside."
|
||||
else
|
||||
user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50)
|
||||
error = "Already extracting... Place the target into the pod. If the pod was destroyed, you will need to cancel this contract."
|
||||
return 1
|
||||
error = "Already extracting... Place the target into the pod. If the pod was destroyed, this contract is no longer possible."
|
||||
return TRUE
|
||||
if("PRG_contract_abort")
|
||||
var/contract_id = hard_drive.traitor_data.contractor_hub.current_contract.id
|
||||
hard_drive.traitor_data.contractor_hub.current_contract = null
|
||||
hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id].status = CONTRACT_STATUS_ABORTED
|
||||
program_icon_state = "contracts"
|
||||
return 1
|
||||
return TRUE
|
||||
if("PRG_redeem_TC")
|
||||
if(hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem)
|
||||
var/obj/item/stack/telecrystal/crystals = new /obj/item/stack/telecrystal(get_turf(user), hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem)
|
||||
var/obj/item/stack/telecrystal/crystals = new /obj/item/stack/telecrystal(get_turf(user),
|
||||
hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.put_in_hands(crystals))
|
||||
@@ -78,22 +84,23 @@
|
||||
to_chat(user, "<span class='notice'>Your payment materializes onto the floor.</span>")
|
||||
hard_drive.traitor_data.contractor_hub.contract_TC_payed_out += hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem
|
||||
hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem = 0
|
||||
return 1
|
||||
return TRUE
|
||||
else
|
||||
user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50)
|
||||
return 1
|
||||
return TRUE
|
||||
if("PRG_clear_error")
|
||||
error = ""
|
||||
if("PRG_contractor_hub")
|
||||
page = CONTRACT_UPLINK_PAGE_HUB
|
||||
program_icon_state = "store"
|
||||
if("PRG_hub_back")
|
||||
page = CONTRACT_UPLINK_PAGE_CONTRACTS
|
||||
program_icon_state = "contracts"
|
||||
return TRUE
|
||||
if("PRG_set_first_load_finished")
|
||||
first_load = FALSE
|
||||
return TRUE
|
||||
if("PRG_toggle_info")
|
||||
info_screen = !info_screen
|
||||
return TRUE
|
||||
if("buy_hub")
|
||||
if(hard_drive.traitor_data.owner.current == user)
|
||||
var/item = params["item"]
|
||||
for (var/datum/contractor_item/hub_item in hard_drive.traitor_data.contractor_hub.hub_items)
|
||||
for(var/datum/contractor_item/hub_item in hard_drive.traitor_data.contractor_hub.hub_items)
|
||||
if (hub_item.name == item)
|
||||
hub_item.handle_purchase(hard_drive.traitor_data.contractor_hub, user)
|
||||
else
|
||||
@@ -104,21 +111,28 @@
|
||||
var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = computer.all_components[MC_HDD]
|
||||
var/screen_to_be = null
|
||||
|
||||
data["first_load"] = first_load
|
||||
if(hard_drive && hard_drive.traitor_data != null)
|
||||
var/datum/antagonist/traitor/traitor_data = hard_drive.traitor_data
|
||||
error = ""
|
||||
data = get_header_data()
|
||||
data += get_header_data()
|
||||
if(traitor_data.contractor_hub.current_contract)
|
||||
data["ongoing_contract"] = TRUE
|
||||
screen_to_be = "single_contract"
|
||||
if(traitor_data.contractor_hub.current_contract.status == CONTRACT_STATUS_EXTRACTING)
|
||||
data["extraction_enroute"] = TRUE
|
||||
screen_to_be = "extracted"
|
||||
else
|
||||
data["extraction_enroute"] = FALSE
|
||||
else
|
||||
data["ongoing_contract"] = FALSE
|
||||
data["extraction_enroute"] = FALSE
|
||||
data["logged_in"] = TRUE
|
||||
data["station_name"] = GLOB.station_name
|
||||
data["redeemable_tc"] = traitor_data.contractor_hub.contract_TC_to_redeem
|
||||
data["earned_tc"] = traitor_data.contractor_hub.contract_TC_payed_out
|
||||
data["contracts_completed"] = traitor_data.contractor_hub.contracts_completed
|
||||
data["contract_rep"] = traitor_data.contractor_hub.contract_rep
|
||||
data["page"] = page
|
||||
data["info_screen"] = info_screen
|
||||
data["error"] = error
|
||||
for(var/datum/contractor_item/hub_item in traitor_data.contractor_hub.hub_items)
|
||||
data["contractor_hub_items"] += list(list(
|
||||
@@ -136,7 +150,8 @@
|
||||
"payout_bonus" = contract.contract.payout_bonus,
|
||||
"dropoff" = contract.contract.dropoff,
|
||||
"id" = contract.id,
|
||||
"status" = contract.status
|
||||
"status" = contract.status,
|
||||
"message" = contract.wanted_message
|
||||
))
|
||||
|
||||
var/direction
|
||||
@@ -155,14 +170,8 @@
|
||||
else
|
||||
direction = "???"
|
||||
data["dropoff_direction"] = direction
|
||||
if (page == CONTRACT_UPLINK_PAGE_HUB)
|
||||
screen_to_be = "store"
|
||||
if (!screen_to_be)
|
||||
screen_to_be = "contracts"
|
||||
else
|
||||
data["logged_in"] = FALSE
|
||||
if (!screen_to_be)
|
||||
screen_to_be = "assign"
|
||||
program_icon_state = screen_to_be
|
||||
update_computer_icon()
|
||||
return data
|
||||
return data
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
program_icon_state = "hostile"
|
||||
extended_desc = "This advanced script can perform denial of service attacks against NTNet quantum relays. The system administrator will probably notice this. Multiple devices can run this program together against same relay for increased effect"
|
||||
size = 20
|
||||
requires_ntnet = 1
|
||||
available_on_ntnet = 0
|
||||
available_on_syndinet = 1
|
||||
tgui_id = "ntos_net_dos"
|
||||
ui_style = "syndicate"
|
||||
requires_ntnet = TRUE
|
||||
available_on_ntnet = FALSE
|
||||
available_on_syndinet = TRUE
|
||||
tgui_id = "NtosNetDos"
|
||||
ui_x = 400
|
||||
ui_y = 250
|
||||
|
||||
@@ -37,64 +36,55 @@
|
||||
if(target)
|
||||
target.dos_sources.Remove(src)
|
||||
target = null
|
||||
executed = 0
|
||||
executed = FALSE
|
||||
|
||||
..()
|
||||
|
||||
/datum/computer_file/program/ntnet_dos/ui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
switch(action)
|
||||
if("PRG_target_relay")
|
||||
for(var/obj/machinery/ntnet_relay/R in SSnetworks.station_network.relays)
|
||||
if("[R.uid]" == params["targid"])
|
||||
target = R
|
||||
return 1
|
||||
break
|
||||
return TRUE
|
||||
if("PRG_reset")
|
||||
if(target)
|
||||
target.dos_sources.Remove(src)
|
||||
target = null
|
||||
executed = 0
|
||||
executed = FALSE
|
||||
error = ""
|
||||
return 1
|
||||
return TRUE
|
||||
if("PRG_execute")
|
||||
if(target)
|
||||
executed = 1
|
||||
executed = TRUE
|
||||
target.dos_sources.Add(src)
|
||||
if(SSnetworks.station_network.intrusion_detection_enabled)
|
||||
var/obj/item/computer_hardware/network_card/network_card = computer.all_components[MC_NET]
|
||||
SSnetworks.station_network.add_log("IDS WARNING - Excess traffic flood targeting relay [target.uid] detected from device: [network_card.get_network_tag()]")
|
||||
SSnetworks.station_network.intrusion_detection_alarm = 1
|
||||
return 1
|
||||
SSnetworks.station_network.intrusion_detection_alarm = TRUE
|
||||
return TRUE
|
||||
|
||||
/datum/computer_file/program/ntnet_dos/ui_data(mob/user)
|
||||
if(!SSnetworks.station_network)
|
||||
return
|
||||
|
||||
var/list/data = list()
|
||||
var/list/data = get_header_data()
|
||||
|
||||
data = get_header_data()
|
||||
|
||||
if(error)
|
||||
data["error"] = error
|
||||
else if(target && executed)
|
||||
data["target"] = 1
|
||||
data["error"] = error
|
||||
if(target && executed)
|
||||
data["target"] = TRUE
|
||||
data["speed"] = dos_speed
|
||||
|
||||
// This is mostly visual, generate some strings of 1s and 0s
|
||||
// Probability of 1 is equal of completion percentage of DoS attack on this relay.
|
||||
// Combined with UI updates this adds quite nice effect to the UI
|
||||
var/percentage = target.dos_overload * 100 / target.dos_capacity
|
||||
data["dos_strings"] = list()
|
||||
for(var/j, j<10, j++)
|
||||
var/string = ""
|
||||
for(var/i, i<20, i++)
|
||||
string = "[string][prob(percentage)]"
|
||||
data["dos_strings"] += list(list("nums" = string))
|
||||
data["overload"] = target.dos_overload
|
||||
data["capacity"] = target.dos_capacity
|
||||
else
|
||||
data["target"] = FALSE
|
||||
data["relays"] = list()
|
||||
for(var/obj/machinery/ntnet_relay/R in SSnetworks.station_network.relays)
|
||||
data["relays"] += list(list("id" = R.uid))
|
||||
data["focus"] = target ? target.uid : null
|
||||
|
||||
return data
|
||||
return data
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
program_icon_state = "hostile"
|
||||
extended_desc = "This virus can destroy hard drive of system it is executed on. It may be obfuscated to look like another non-malicious program. Once armed, it will destroy the system upon next execution."
|
||||
size = 13
|
||||
requires_ntnet = 0
|
||||
available_on_ntnet = 0
|
||||
available_on_syndinet = 1
|
||||
tgui_id = "ntos_revelation"
|
||||
ui_style = "syndicate"
|
||||
requires_ntnet = FALSE
|
||||
available_on_ntnet = FALSE
|
||||
available_on_syndinet = TRUE
|
||||
tgui_id = "NtosRevelation"
|
||||
ui_x = 400
|
||||
ui_y = 250
|
||||
|
||||
@@ -22,7 +21,7 @@
|
||||
/datum/computer_file/program/revelation/proc/activate()
|
||||
if(computer)
|
||||
computer.visible_message("<span class='notice'>\The [computer]'s screen brightly flashes and loud electrical buzzing is heard.</span>")
|
||||
computer.enabled = 0
|
||||
computer.enabled = FALSE
|
||||
computer.update_icon()
|
||||
var/obj/item/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
|
||||
var/obj/item/computer_hardware/battery/battery_module = computer.all_components[MC_CELL]
|
||||
@@ -44,18 +43,20 @@
|
||||
|
||||
/datum/computer_file/program/revelation/ui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
switch(action)
|
||||
if("PRG_arm")
|
||||
armed = !armed
|
||||
return TRUE
|
||||
if("PRG_activate")
|
||||
activate()
|
||||
return TRUE
|
||||
if("PRG_obfuscate")
|
||||
var/mob/living/user = usr
|
||||
var/newname = sanitize(input(user, "Enter new program name: "))
|
||||
var/newname = params["new_name"]
|
||||
if(!newname)
|
||||
return
|
||||
filedesc = newname
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/computer_file/program/revelation/clone()
|
||||
@@ -68,4 +69,4 @@
|
||||
|
||||
data["armed"] = armed
|
||||
|
||||
return data
|
||||
return data
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/datum/computer_file/program/arcade
|
||||
filename = "arcade"
|
||||
filedesc = "Nanotrasen Micro Arcade"
|
||||
program_icon_state = "arcade"
|
||||
extended_desc = "This port of the classic game 'Outbomb Cuban Pete', redesigned to run on tablets, with thrilling graphics and chilling storytelling."
|
||||
requires_ntnet = FALSE
|
||||
network_destination = "arcade network"
|
||||
size = 6
|
||||
tgui_id = "NtosArcade"
|
||||
ui_x = 450
|
||||
ui_y = 350
|
||||
|
||||
///Returns TRUE if the game is being played.
|
||||
var/game_active = TRUE
|
||||
///This disables buttom actions from having any impact if TRUE. Resets to FALSE when the player is allowed to make an action again.
|
||||
var/pause_state = FALSE
|
||||
var/boss_hp = 45
|
||||
var/boss_mp = 15
|
||||
var/player_hp = 30
|
||||
var/player_mp = 10
|
||||
var/ticket_count = 0
|
||||
///Shows what text is shown on the app, usually showing the log of combat actions taken by the player.
|
||||
var/heads_up = "Nanotrasen says, winners make us money."
|
||||
var/boss_name = "Cuban Pete's Minion"
|
||||
///Determines which boss image to use on the UI.
|
||||
var/boss_id = 1
|
||||
|
||||
/datum/computer_file/program/arcade/proc/game_check(mob/user)
|
||||
sleep(5)
|
||||
if(boss_hp <= 0)
|
||||
heads_up = "You have crushed [boss_name]! Rejoice!"
|
||||
playsound(computer.loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3, falloff = 10)
|
||||
game_active = FALSE
|
||||
program_icon_state = "arcade_off"
|
||||
if(istype(computer))
|
||||
computer.update_icon()
|
||||
ticket_count += 1
|
||||
sleep(10)
|
||||
else if(player_hp <= 0 || player_mp <= 0)
|
||||
heads_up = "You have been defeated... how will the station survive?"
|
||||
playsound(computer.loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3, falloff = 10)
|
||||
game_active = FALSE
|
||||
program_icon_state = "arcade_off"
|
||||
if(istype(computer))
|
||||
computer.update_icon()
|
||||
sleep(10)
|
||||
|
||||
/datum/computer_file/program/arcade/proc/enemy_check(mob/user)
|
||||
var/boss_attackamt = 0 //Spam protection from boss attacks as well.
|
||||
var/boss_mpamt = 0
|
||||
var/bossheal = 0
|
||||
if(pause_state == TRUE)
|
||||
boss_attackamt = rand(3,6)
|
||||
boss_mpamt = rand (2,4)
|
||||
bossheal = rand (4,6)
|
||||
if(game_active == FALSE)
|
||||
return
|
||||
if (boss_mp <= 5)
|
||||
heads_up = "[boss_mpamt] magic power has been stolen from you!"
|
||||
playsound(computer.loc, 'sound/arcade/steal.ogg', 50, TRUE, extrarange = -3, falloff = 10)
|
||||
player_mp -= boss_mpamt
|
||||
boss_mp += boss_mpamt
|
||||
else if(boss_mp > 5 && boss_hp <12)
|
||||
heads_up = "[boss_name] heals for [bossheal] health!"
|
||||
playsound(computer.loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3, falloff = 10)
|
||||
boss_hp += bossheal
|
||||
boss_mp -= boss_mpamt
|
||||
else
|
||||
heads_up = "[boss_name] attacks you for [boss_attackamt] damage!"
|
||||
playsound(computer.loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3, falloff = 10)
|
||||
player_hp -= boss_attackamt
|
||||
|
||||
pause_state = FALSE
|
||||
game_check()
|
||||
|
||||
/datum/computer_file/program/arcade/ui_interact(mob/user, ui_key, datum/tgui/ui, force_open, datum/tgui/master_ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/arcade)
|
||||
assets.send(user)
|
||||
|
||||
/datum/computer_file/program/arcade/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
|
||||
data["Hitpoints"] = boss_hp
|
||||
data["PlayerHitpoints"] = player_hp
|
||||
data["PlayerMP"] = player_mp
|
||||
data["TicketCount"] = ticket_count
|
||||
data["GameActive"] = game_active
|
||||
data["PauseState"] = pause_state
|
||||
data["Status"] = heads_up
|
||||
data["BossID"] = "boss[boss_id].gif"
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/arcade/ui_act(action, list/params)
|
||||
if(..())
|
||||
return TRUE
|
||||
var/obj/item/computer_hardware/printer/printer
|
||||
if(computer)
|
||||
printer = computer.all_components[MC_PRINT]
|
||||
|
||||
switch(action)
|
||||
if("Attack")
|
||||
var/attackamt = 0 //Spam prevention.
|
||||
if(pause_state == FALSE)
|
||||
attackamt = rand(2,6)
|
||||
pause_state = TRUE
|
||||
heads_up = "You attack for [attackamt] damage."
|
||||
playsound(computer.loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3, falloff = 10)
|
||||
boss_hp -= attackamt
|
||||
sleep(10)
|
||||
game_check()
|
||||
enemy_check()
|
||||
return TRUE
|
||||
if("Heal")
|
||||
var/healamt = 0 //More Spam Prevention.
|
||||
var/healcost = 0
|
||||
if(pause_state == FALSE)
|
||||
healamt = rand(6,8)
|
||||
var/maxPointCost = 3
|
||||
healcost = rand(1, maxPointCost)
|
||||
pause_state = TRUE
|
||||
heads_up = "You heal for [healamt] damage."
|
||||
playsound(computer.loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3, falloff = 10)
|
||||
player_hp += healamt
|
||||
player_mp -= healcost
|
||||
sleep(10)
|
||||
game_check()
|
||||
enemy_check()
|
||||
return TRUE
|
||||
if("Recharge_Power")
|
||||
var/rechargeamt = 0 //As above.
|
||||
if(pause_state == FALSE)
|
||||
rechargeamt = rand(4, 7)
|
||||
pause_state = TRUE
|
||||
heads_up = "You regain [rechargeamt] magic power."
|
||||
playsound(computer.loc, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3, falloff = 10)
|
||||
player_mp += rechargeamt
|
||||
sleep(10)
|
||||
game_check()
|
||||
enemy_check()
|
||||
return TRUE
|
||||
if("Dispense_Tickets")
|
||||
if(!printer)
|
||||
to_chat(usr, "<span class='notice'>Hardware error: A printer is required to redeem tickets.</span>")
|
||||
return
|
||||
if(printer.stored_paper <= 0)
|
||||
to_chat(usr, "<span class='notice'>Hardware error: Printer is out of paper.</span>")
|
||||
return
|
||||
else
|
||||
computer.visible_message("<span class='notice'>\The [computer] prints out paper.</span>")
|
||||
if(ticket_count >= 1)
|
||||
new /obj/item/stack/arcadeticket((get_turf(computer)), 1)
|
||||
to_chat(usr, "<span class='notice'>[src] dispenses a ticket!</span>")
|
||||
ticket_count -= 1
|
||||
printer.stored_paper -= 1
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>You don't have any stored tickets!</span>")
|
||||
return TRUE
|
||||
if("Start_Game")
|
||||
game_active = TRUE
|
||||
boss_hp = 45
|
||||
player_hp = 30
|
||||
player_mp = 10
|
||||
heads_up = "You stand before [boss_name]! Prepare for battle!"
|
||||
program_icon_state = "arcade"
|
||||
boss_id = rand(1,6)
|
||||
pause_state = FALSE
|
||||
if(istype(computer))
|
||||
computer.update_icon()
|
||||
@@ -0,0 +1,33 @@
|
||||
/datum/computer_file/program/atmosscan
|
||||
filename = "atmosscan"
|
||||
filedesc = "Atmospheric Scanner"
|
||||
program_icon_state = "air"
|
||||
extended_desc = "A small built-in sensor reads out the atmospheric conditions around the device."
|
||||
network_destination = "atmos scan"
|
||||
size = 4
|
||||
tgui_id = "NtosAtmos"
|
||||
ui_x = 300
|
||||
ui_y = 350
|
||||
|
||||
/datum/computer_file/program/atmosscan/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
var/list/airlist = list()
|
||||
var/turf/T = get_turf(ui_host())
|
||||
if(T)
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
var/list/env_gases = environment.gases
|
||||
var/pressure = environment.return_pressure()
|
||||
var/total_moles = environment.total_moles()
|
||||
data["AirPressure"] = round(pressure,0.1)
|
||||
data["AirTemp"] = round(environment.temperature-T0C)
|
||||
if (total_moles)
|
||||
for(var/id in env_gases)
|
||||
var/gas_level = env_gases[id][MOLES]/total_moles
|
||||
if(gas_level > 0)
|
||||
airlist += list(list("name" = "[env_gases[id][GAS_META][META_GAS_NAME]]", "percentage" = round(gas_level*100, 0.01)))
|
||||
data["AirData"] = airlist
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/atmosscan/ui_act(action, list/params)
|
||||
if(..())
|
||||
return TRUE
|
||||
@@ -0,0 +1,69 @@
|
||||
/datum/computer_file/program/borg_monitor
|
||||
filename = "cyborgmonitor"
|
||||
filedesc = "Cyborg Remote Monitoring"
|
||||
ui_header = "borg_mon.gif"
|
||||
program_icon_state = "generic"
|
||||
extended_desc = "This program allows for remote monitoring of station cyborgs."
|
||||
requires_ntnet = TRUE
|
||||
transfer_access = ACCESS_ROBOTICS
|
||||
network_destination = "cyborg remote monitoring"
|
||||
size = 5
|
||||
tgui_id = "NtosCyborgRemoteMonitor"
|
||||
ui_x = 600
|
||||
ui_y = 800
|
||||
|
||||
/datum/computer_file/program/borg_monitor/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
|
||||
data["card"] = FALSE
|
||||
if(computer.GetID())
|
||||
data["card"] = TRUE
|
||||
|
||||
data["cyborgs"] = list()
|
||||
for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs)
|
||||
if((get_turf(computer)).z != (get_turf(R)).z)
|
||||
continue
|
||||
if(R.scrambledcodes)
|
||||
continue
|
||||
|
||||
var/list/upgrade
|
||||
for(var/obj/item/borg/upgrade/I in R.upgrades)
|
||||
upgrade += "\[[I.name]\] "
|
||||
|
||||
var/shell = FALSE
|
||||
if(R.shell && !R.ckey)
|
||||
shell = TRUE
|
||||
|
||||
var/list/cyborg_data = list(
|
||||
name = R.name,
|
||||
locked_down = R.locked_down,
|
||||
status = R.stat,
|
||||
shell_discon = shell,
|
||||
charge = R.cell ? round(R.cell.percent()) : null,
|
||||
module = R.module ? "[R.module.name] Module" : "No Module Detected",
|
||||
upgrades = upgrade,
|
||||
ref = REF(R)
|
||||
)
|
||||
data["cyborgs"] += list(cyborg_data)
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/borg_monitor/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("messagebot")
|
||||
var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs
|
||||
if(!istype(R))
|
||||
return
|
||||
var/obj/item/card/id/ID = computer.GetID()
|
||||
if(!ID)
|
||||
return
|
||||
var/message = stripped_input(usr, message = "Enter message to be sent to remote cyborg.", title = "Send Message")
|
||||
if(!message)
|
||||
return
|
||||
to_chat(R, "<br><br><span class='notice'>Message from [ID.registered_name] -- \"[message]\"</span><br>")
|
||||
SEND_SOUND(R, 'sound/machines/twobeep_high.ogg')
|
||||
if(R.connected_ai)
|
||||
to_chat(R.connected_ai, "<br><br><span class='notice'>Message from [ID.registered_name] to [R] -- \"[message]\"</span><br>")
|
||||
SEND_SOUND(R.connected_ai, 'sound/machines/twobeep_high.ogg')
|
||||
@@ -1,3 +1,11 @@
|
||||
#define CARDCON_DEPARTMENT_SERVICE "Service"
|
||||
#define CARDCON_DEPARTMENT_SECURITY "Security"
|
||||
#define CARDCON_DEPARTMENT_MEDICAL "Medical"
|
||||
#define CARDCON_DEPARTMENT_SUPPLY "Supply"
|
||||
#define CARDCON_DEPARTMENT_SCIENCE "Science"
|
||||
#define CARDCON_DEPARTMENT_ENGINEERING "Engineering"
|
||||
#define CARDCON_DEPARTMENT_COMMAND "Command"
|
||||
|
||||
/datum/computer_file/program/card_mod
|
||||
filename = "cardmod"
|
||||
filedesc = "ID Card Modification"
|
||||
@@ -6,97 +14,90 @@
|
||||
transfer_access = ACCESS_HEADS
|
||||
requires_ntnet = 0
|
||||
size = 8
|
||||
tgui_id = "ntos_card"
|
||||
ui_x = 600
|
||||
ui_y = 700
|
||||
tgui_id = "NtosCard"
|
||||
ui_x = 450
|
||||
ui_y = 520
|
||||
|
||||
var/mod_mode = 1
|
||||
var/is_centcom = 0
|
||||
var/show_assignments = 0
|
||||
var/minor = 0
|
||||
var/authenticated = 0
|
||||
var/list/reg_ids = list()
|
||||
var/list/region_access = null
|
||||
var/list/head_subordinates = null
|
||||
var/target_dept = 0 //Which department this computer has access to. 0=all departments
|
||||
var/change_position_cooldown = 30
|
||||
//Jobs you cannot open new positions for
|
||||
var/list/blacklisted = list(
|
||||
"AI",
|
||||
"Assistant",
|
||||
"Cyborg",
|
||||
"Captain",
|
||||
"Head of Personnel",
|
||||
"Head of Security",
|
||||
"Chief Engineer",
|
||||
"Research Director",
|
||||
"Chief Medical Officer")
|
||||
var/is_centcom = FALSE
|
||||
var/minor = FALSE
|
||||
var/authenticated = FALSE
|
||||
var/list/region_access
|
||||
var/list/head_subordinates
|
||||
///Which departments this computer has access to. Defined as access regions. null = all departments
|
||||
var/target_dept
|
||||
|
||||
//The scaling factor of max total positions in relation to the total amount of people on board the station in %
|
||||
var/max_relative_positions = 30 //30%: Seems reasonable, limit of 6 @ 20 players
|
||||
//For some reason everything was exploding if this was static.
|
||||
var/list/sub_managers
|
||||
|
||||
//This is used to keep track of opened positions for jobs to allow instant closing
|
||||
//Assoc array: "JobName" = (int)<Opened Positions>
|
||||
var/list/opened_positions = list();
|
||||
/datum/computer_file/program/card_mod/New(obj/item/modular_computer/comp)
|
||||
. = ..()
|
||||
sub_managers = list(
|
||||
"[ACCESS_HOP]" = list(
|
||||
"department" = list(CARDCON_DEPARTMENT_SERVICE, CARDCON_DEPARTMENT_COMMAND),
|
||||
"region" = 1,
|
||||
"head" = "Head of Personnel"
|
||||
),
|
||||
"[ACCESS_HOS]" = list(
|
||||
"department" = CARDCON_DEPARTMENT_SECURITY,
|
||||
"region" = 2,
|
||||
"head" = "Head of Security"
|
||||
),
|
||||
"[ACCESS_CMO]" = list(
|
||||
"department" = CARDCON_DEPARTMENT_MEDICAL,
|
||||
"region" = 3,
|
||||
"head" = "Chief Medical Officer"
|
||||
),
|
||||
"[ACCESS_RD]" = list(
|
||||
"department" = CARDCON_DEPARTMENT_SCIENCE,
|
||||
"region" = 4,
|
||||
"head" = "Research Director"
|
||||
),
|
||||
"[ACCESS_CE]" = list(
|
||||
"department" = CARDCON_DEPARTMENT_ENGINEERING,
|
||||
"region" = 5,
|
||||
"head" = "Chief Engineer"
|
||||
)
|
||||
)
|
||||
|
||||
/datum/computer_file/program/card_mod/New()
|
||||
..()
|
||||
addtimer(CALLBACK(src, .proc/SetConfigCooldown), 0)
|
||||
/datum/computer_file/program/card_mod/proc/authenticate(mob/user, obj/item/card/id/id_card)
|
||||
if(!id_card)
|
||||
return
|
||||
|
||||
/datum/computer_file/program/card_mod/proc/SetConfigCooldown()
|
||||
change_position_cooldown = CONFIG_GET(number/id_console_jobslot_delay)
|
||||
region_access = list()
|
||||
if(!target_dept && (ACCESS_CHANGE_IDS in id_card.access))
|
||||
minor = FALSE
|
||||
authenticated = TRUE
|
||||
update_static_data(user)
|
||||
return TRUE
|
||||
|
||||
/datum/computer_file/program/card_mod/event_idremoved(background, slot)
|
||||
if(!slot || slot == 2)// slot being false means both are removed
|
||||
minor = 0
|
||||
authenticated = 0
|
||||
head_subordinates = null
|
||||
region_access = null
|
||||
var/list/head_types = list()
|
||||
for(var/access_text in sub_managers)
|
||||
var/list/info = sub_managers[access_text]
|
||||
var/access = text2num(access_text)
|
||||
if((access in id_card.access) && ((info["region"] in target_dept) || !length(target_dept)))
|
||||
region_access += info["region"]
|
||||
//I don't even know what I'm doing anymore
|
||||
head_types += info["head"]
|
||||
|
||||
head_subordinates = list()
|
||||
if(length(head_types))
|
||||
for(var/j in SSjob.occupations)
|
||||
var/datum/job/job = j
|
||||
for(var/head in head_types)//god why
|
||||
if(head in job.department_head)
|
||||
head_subordinates += job.title
|
||||
|
||||
/datum/computer_file/program/card_mod/proc/job_blacklisted(jobtitle)
|
||||
return (jobtitle in blacklisted)
|
||||
if(length(region_access))
|
||||
minor = TRUE
|
||||
authenticated = TRUE
|
||||
update_static_data(user)
|
||||
return TRUE
|
||||
|
||||
|
||||
//Logic check for if you can open the job
|
||||
/datum/computer_file/program/card_mod/proc/can_open_job(datum/job/job)
|
||||
if(job)
|
||||
if(!job_blacklisted(job.title))
|
||||
if((job.total_positions <= GLOB.player_list.len * (max_relative_positions / 100)))
|
||||
var/delta = (world.time / 10) - GLOB.time_last_changed_position
|
||||
if((change_position_cooldown < delta) || (opened_positions[job.title] < 0))
|
||||
return 1
|
||||
return -2
|
||||
return 0
|
||||
return 0
|
||||
|
||||
//Logic check for if you can close the job
|
||||
/datum/computer_file/program/card_mod/proc/can_close_job(datum/job/job)
|
||||
if(job)
|
||||
if(!job_blacklisted(job.title))
|
||||
if(job.total_positions > job.current_positions)
|
||||
var/delta = (world.time / 10) - GLOB.time_last_changed_position
|
||||
if((change_position_cooldown < delta) || (opened_positions[job.title] > 0))
|
||||
return 1
|
||||
return -2
|
||||
return 0
|
||||
return 0
|
||||
|
||||
/datum/computer_file/program/card_mod/proc/format_jobs(list/jobs)
|
||||
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
|
||||
var/obj/item/card/id/id_card = card_slot.stored_card
|
||||
var/list/formatted = list()
|
||||
for(var/job in jobs)
|
||||
formatted.Add(list(list(
|
||||
"display_name" = replacetext(job, " ", " "),
|
||||
"target_rank" = id_card && id_card.assignment ? id_card.assignment : "Unassigned",
|
||||
"job" = job)))
|
||||
|
||||
return formatted
|
||||
return FALSE
|
||||
|
||||
/datum/computer_file/program/card_mod/ui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
var/obj/item/computer_hardware/card_slot/card_slot
|
||||
var/obj/item/computer_hardware/printer/printer
|
||||
@@ -106,192 +107,220 @@
|
||||
if(!card_slot)
|
||||
return
|
||||
|
||||
var/obj/item/card/id/user_id_card = null
|
||||
var/mob/user = usr
|
||||
var/obj/item/card/id/user_id_card = user.get_idcard(FALSE)
|
||||
|
||||
var/obj/item/card/id/id_card = card_slot.stored_card
|
||||
var/obj/item/card/id/auth_card = card_slot.stored_card2
|
||||
|
||||
if(auth_card)
|
||||
user_id_card = auth_card
|
||||
else
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/h = user
|
||||
user_id_card = h.get_idcard(TRUE)
|
||||
|
||||
switch(action)
|
||||
if("PRG_switchm")
|
||||
if(params["target"] == "mod")
|
||||
mod_mode = 1
|
||||
else if (params["target"] == "manifest")
|
||||
mod_mode = 0
|
||||
else if (params["target"] == "manage")
|
||||
mod_mode = 2
|
||||
if("PRG_togglea")
|
||||
if(show_assignments)
|
||||
show_assignments = 0
|
||||
else
|
||||
show_assignments = 1
|
||||
if("PRG_authenticate")
|
||||
if(!computer || !user_id_card)
|
||||
playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
|
||||
return
|
||||
if(authenticate(user, user_id_card))
|
||||
playsound(computer, 'sound/machines/terminal_on.ogg', 50, FALSE)
|
||||
return TRUE
|
||||
if("PRG_logout")
|
||||
authenticated = FALSE
|
||||
playsound(computer, 'sound/machines/terminal_off.ogg', 50, FALSE)
|
||||
return TRUE
|
||||
if("PRG_print")
|
||||
if(computer && printer) //This option should never be called if there is no printer
|
||||
if(mod_mode)
|
||||
if(authorized())
|
||||
var/contents = {"<h4>Access Report</h4>
|
||||
<u>Prepared By:</u> [user_id_card && user_id_card.registered_name ? user_id_card.registered_name : "Unknown"]<br>
|
||||
<u>For:</u> [id_card.registered_name ? id_card.registered_name : "Unregistered"]<br>
|
||||
<hr>
|
||||
<u>Assignment:</u> [id_card.assignment]<br>
|
||||
<u>Access:</u><br>
|
||||
"}
|
||||
if(!computer || !printer)
|
||||
return
|
||||
if(!authenticated)
|
||||
return
|
||||
var/contents = {"<h4>Access Report</h4>
|
||||
<u>Prepared By:</u> [user_id_card && user_id_card.registered_name ? user_id_card.registered_name : "Unknown"]<br>
|
||||
<u>For:</u> [id_card.registered_name ? id_card.registered_name : "Unregistered"]<br>
|
||||
<hr>
|
||||
<u>Assignment:</u> [id_card.assignment]<br>
|
||||
<u>Access:</u><br>
|
||||
"}
|
||||
|
||||
var/known_access_rights = get_all_accesses()
|
||||
for(var/A in id_card.access)
|
||||
if(A in known_access_rights)
|
||||
contents += " [get_access_desc(A)]"
|
||||
var/known_access_rights = get_all_accesses()
|
||||
for(var/A in id_card.access)
|
||||
if(A in known_access_rights)
|
||||
contents += " [get_access_desc(A)]"
|
||||
|
||||
if(!printer.print_text(contents,"access report"))
|
||||
to_chat(usr, "<span class='notice'>Hardware error: Printer was unable to print the file. It may be out of paper.</span>")
|
||||
return
|
||||
else
|
||||
computer.visible_message("<span class='notice'>\The [computer] prints out paper.</span>")
|
||||
else
|
||||
var/contents = {"<h4>Crew Manifest</h4>
|
||||
<br>
|
||||
[GLOB.data_core ? GLOB.data_core.get_manifest(0) : ""]
|
||||
"}
|
||||
if(!printer.print_text(contents,text("crew manifest ([])", STATION_TIME_TIMESTAMP("hh:mm:ss", world.time))))
|
||||
to_chat(usr, "<span class='notice'>Hardware error: Printer was unable to print the file. It may be out of paper.</span>")
|
||||
return
|
||||
else
|
||||
computer.visible_message("<span class='notice'>\The [computer] prints out paper.</span>")
|
||||
if("PRG_eject")
|
||||
if(computer && card_slot)
|
||||
var/select = params["target"]
|
||||
switch(select)
|
||||
if("id")
|
||||
if(id_card)
|
||||
GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment)
|
||||
card_slot.try_eject(1, user)
|
||||
else
|
||||
var/obj/item/I = usr.get_active_held_item()
|
||||
if (istype(I, /obj/item/card/id))
|
||||
if(!usr.transferItemToLoc(I, computer))
|
||||
return
|
||||
card_slot.stored_card = I
|
||||
if("auth")
|
||||
if(auth_card)
|
||||
if(id_card)
|
||||
GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment)
|
||||
head_subordinates = null
|
||||
region_access = null
|
||||
authenticated = 0
|
||||
minor = 0
|
||||
card_slot.try_eject(2, user)
|
||||
else
|
||||
var/obj/item/I = usr.get_active_held_item()
|
||||
if (istype(I, /obj/item/card/id))
|
||||
if(!usr.transferItemToLoc(I, computer))
|
||||
return
|
||||
card_slot.stored_card2 = I
|
||||
if("PRG_terminate")
|
||||
if(computer && ((id_card.assignment in head_subordinates) || id_card.assignment == "Assistant"))
|
||||
id_card.assignment = "Unassigned"
|
||||
remove_nt_access(id_card)
|
||||
|
||||
if("PRG_edit")
|
||||
if(computer && authorized())
|
||||
if(params["name"])
|
||||
var/temp_name = reject_bad_name(input("Enter name.", "Name", id_card.registered_name))
|
||||
if(temp_name)
|
||||
id_card.registered_name = temp_name
|
||||
else
|
||||
computer.visible_message("<span class='notice'>[computer] buzzes rudely.</span>")
|
||||
//else if(params["account"])
|
||||
// var/account_num = text2num(input("Enter account number.", "Account", id_card.associated_account_number))
|
||||
// id_card.associated_account_number = account_num
|
||||
if("PRG_assign")
|
||||
if(computer && authorized() && id_card)
|
||||
var/t1 = params["assign_target"]
|
||||
if(t1 == "Custom")
|
||||
var/temp_t = reject_bad_text(input("Enter a custom job assignment.","Assignment", id_card.assignment), 45)
|
||||
//let custom jobs function as an impromptu alt title, mainly for sechuds
|
||||
if(temp_t)
|
||||
id_card.assignment = temp_t
|
||||
else
|
||||
var/list/access = list()
|
||||
if(is_centcom)
|
||||
access = get_centcom_access(t1)
|
||||
else
|
||||
var/datum/job/jobdatum
|
||||
for(var/jobtype in typesof(/datum/job))
|
||||
var/datum/job/J = new jobtype
|
||||
if(ckey(J.title) == ckey(t1))
|
||||
jobdatum = J
|
||||
break
|
||||
if(!jobdatum)
|
||||
to_chat(usr, "<span class='warning'>No log exists for this job: [t1]</span>")
|
||||
return
|
||||
|
||||
access = jobdatum.get_access()
|
||||
|
||||
remove_nt_access(id_card)
|
||||
apply_access(id_card, access)
|
||||
id_card.assignment = t1
|
||||
|
||||
if("PRG_access")
|
||||
if(params["allowed"] && computer && authorized())
|
||||
var/access_type = text2num(params["access_target"])
|
||||
var/access_allowed = text2num(params["allowed"])
|
||||
if(access_type in (is_centcom ? get_all_centcom_access() : get_all_accesses()))
|
||||
id_card.access -= access_type
|
||||
if(!access_allowed)
|
||||
id_card.access += access_type
|
||||
if("PRG_open_job")
|
||||
var/edit_job_target = params["target"]
|
||||
var/datum/job/j = SSjob.GetJob(edit_job_target)
|
||||
if(!j)
|
||||
return 0
|
||||
if(can_open_job(j) != 1)
|
||||
return 0
|
||||
if(opened_positions[edit_job_target] >= 0)
|
||||
GLOB.time_last_changed_position = world.time / 10
|
||||
j.total_positions++
|
||||
opened_positions[edit_job_target]++
|
||||
if("PRG_close_job")
|
||||
var/edit_job_target = params["target"]
|
||||
var/datum/job/j = SSjob.GetJob(edit_job_target)
|
||||
if(!j)
|
||||
return 0
|
||||
if(can_close_job(j) != 1)
|
||||
return 0
|
||||
//Allow instant closing without cooldown if a position has been opened before
|
||||
if(opened_positions[edit_job_target] <= 0)
|
||||
GLOB.time_last_changed_position = world.time / 10
|
||||
j.total_positions--
|
||||
opened_positions[edit_job_target]--
|
||||
if("PRG_regsel")
|
||||
if(!reg_ids)
|
||||
reg_ids = list()
|
||||
var/regsel = text2num(params["region"])
|
||||
if(regsel in reg_ids)
|
||||
reg_ids -= regsel
|
||||
if(!printer.print_text(contents,"access report"))
|
||||
to_chat(usr, "<span class='notice'>Hardware error: Printer was unable to print the file. It may be out of paper.</span>")
|
||||
return
|
||||
else
|
||||
reg_ids += regsel
|
||||
playsound(computer, 'sound/machines/terminal_on.ogg', 50, FALSE)
|
||||
computer.visible_message("<span class='notice'>\The [computer] prints out a paper.</span>")
|
||||
return TRUE
|
||||
if("PRG_eject")
|
||||
if(!computer || !card_slot)
|
||||
return
|
||||
if(id_card)
|
||||
GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment)
|
||||
card_slot.try_eject(TRUE, user)
|
||||
else
|
||||
var/obj/item/I = user.get_active_held_item()
|
||||
if(istype(I, /obj/item/card/id))
|
||||
if(!user.transferItemToLoc(I, computer))
|
||||
return
|
||||
card_slot.stored_card = I
|
||||
playsound(computer, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
|
||||
return TRUE
|
||||
if("PRG_terminate")
|
||||
if(!computer || !authenticated)
|
||||
return
|
||||
if(minor)
|
||||
if(!(id_card.assignment in head_subordinates) && id_card.assignment != "Assistant")
|
||||
return
|
||||
|
||||
if(id_card)
|
||||
id_card.name = text("[id_card.registered_name]'s ID Card ([id_card.assignment])")
|
||||
id_card.access -= get_all_centcom_access() + get_all_accesses()
|
||||
id_card.assignment = "Unassigned"
|
||||
id_card.update_label()
|
||||
playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
|
||||
return TRUE
|
||||
if("PRG_edit")
|
||||
if(!computer || !authenticated || !id_card)
|
||||
return
|
||||
var/new_name = params["name"]
|
||||
if(!new_name)
|
||||
return
|
||||
id_card.registered_name = new_name
|
||||
id_card.update_label()
|
||||
playsound(computer, "terminal_type", 50, FALSE)
|
||||
return TRUE
|
||||
if("PRG_assign")
|
||||
if(!computer || !authenticated || !id_card)
|
||||
return
|
||||
var/target = params["assign_target"]
|
||||
if(!target)
|
||||
return
|
||||
|
||||
return 1
|
||||
if(target == "Custom")
|
||||
var/custom_name = params["custom_name"]
|
||||
if(custom_name)
|
||||
id_card.assignment = custom_name
|
||||
id_card.update_label()
|
||||
else
|
||||
if(minor && !(target in head_subordinates))
|
||||
return
|
||||
var/list/new_access = list()
|
||||
if(is_centcom)
|
||||
new_access = get_centcom_access(target)
|
||||
else
|
||||
var/datum/job/job
|
||||
for(var/jobtype in subtypesof(/datum/job))
|
||||
var/datum/job/J = new jobtype
|
||||
if(J.title == target)
|
||||
job = J
|
||||
break
|
||||
if(!job)
|
||||
to_chat(user, "<span class='warning'>No class exists for this job: [target]</span>")
|
||||
return
|
||||
new_access = job.get_access()
|
||||
id_card.access -= get_all_centcom_access() + get_all_accesses()
|
||||
id_card.access |= new_access
|
||||
id_card.assignment = target
|
||||
id_card.update_label()
|
||||
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
return TRUE
|
||||
if("PRG_access")
|
||||
if(!computer || !authenticated)
|
||||
return
|
||||
var/access_type = text2num(params["access_target"])
|
||||
if(access_type in (is_centcom ? get_all_centcom_access() : get_all_accesses()))
|
||||
if(access_type in id_card.access)
|
||||
id_card.access -= access_type
|
||||
else
|
||||
id_card.access |= access_type
|
||||
playsound(computer, "terminal_type", 50, FALSE)
|
||||
return TRUE
|
||||
if("PRG_grantall")
|
||||
if(!computer || !authenticated || minor)
|
||||
return
|
||||
id_card.access |= (is_centcom ? get_all_centcom_access() : get_all_accesses())
|
||||
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
return TRUE
|
||||
if("PRG_denyall")
|
||||
if(!computer || !authenticated || minor)
|
||||
return
|
||||
id_card.access.Cut()
|
||||
playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
|
||||
return TRUE
|
||||
if("PRG_grantregion")
|
||||
if(!computer || !authenticated)
|
||||
return
|
||||
var/region = text2num(params["region"])
|
||||
if(isnull(region))
|
||||
return
|
||||
id_card.access |= get_region_accesses(region)
|
||||
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
return TRUE
|
||||
if("PRG_denyregion")
|
||||
if(!computer || !authenticated)
|
||||
return
|
||||
var/region = text2num(params["region"])
|
||||
if(isnull(region))
|
||||
return
|
||||
id_card.access -= get_region_accesses(region)
|
||||
playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
|
||||
return TRUE
|
||||
|
||||
/datum/computer_file/program/card_mod/proc/remove_nt_access(obj/item/card/id/id_card)
|
||||
id_card.access -= get_all_accesses()
|
||||
id_card.access -= get_all_centcom_access()
|
||||
|
||||
/datum/computer_file/program/card_mod/proc/apply_access(obj/item/card/id/id_card, list/accesses)
|
||||
id_card.access |= accesses
|
||||
|
||||
/datum/computer_file/program/card_mod/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["station_name"] = station_name()
|
||||
data["centcom_access"] = is_centcom
|
||||
data["minor"] = target_dept || minor ? TRUE : FALSE
|
||||
|
||||
var/list/departments = target_dept
|
||||
if(is_centcom)
|
||||
departments = list("CentCom" = get_all_centcom_jobs())
|
||||
else if(isnull(departments))
|
||||
departments = list(
|
||||
CARDCON_DEPARTMENT_COMMAND = list("Captain"),
|
||||
CARDCON_DEPARTMENT_ENGINEERING = GLOB.engineering_positions,
|
||||
CARDCON_DEPARTMENT_MEDICAL = GLOB.medical_positions,
|
||||
CARDCON_DEPARTMENT_SCIENCE = GLOB.science_positions,
|
||||
CARDCON_DEPARTMENT_SECURITY = GLOB.security_positions,
|
||||
CARDCON_DEPARTMENT_SUPPLY = GLOB.supply_positions,
|
||||
CARDCON_DEPARTMENT_SERVICE = GLOB.civilian_positions
|
||||
)
|
||||
data["jobs"] = list()
|
||||
for(var/department in departments)
|
||||
var/list/job_list = departments[department]
|
||||
var/list/department_jobs = list()
|
||||
for(var/job in job_list)
|
||||
if(minor && !(job in head_subordinates))
|
||||
continue
|
||||
department_jobs += list(list(
|
||||
"display_name" = replacetext(job, " ", " "),
|
||||
"job" = job
|
||||
))
|
||||
if(length(department_jobs))
|
||||
data["jobs"][department] = department_jobs
|
||||
|
||||
var/list/regions = list()
|
||||
for(var/i in 1 to 7)
|
||||
if((minor || target_dept) && !(i in region_access))
|
||||
continue
|
||||
|
||||
var/list/accesses = list()
|
||||
for(var/access in get_region_accesses(i))
|
||||
if (get_access_desc(access))
|
||||
accesses += list(list(
|
||||
"desc" = replacetext(get_access_desc(access), " ", " "),
|
||||
"ref" = access,
|
||||
))
|
||||
|
||||
regions += list(list(
|
||||
"name" = get_region_accesses_name(i),
|
||||
"regid" = i,
|
||||
"accesses" = accesses
|
||||
))
|
||||
|
||||
data["regions"] = regions
|
||||
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/card_mod/ui_data(mob/user)
|
||||
|
||||
var/list/data = get_header_data()
|
||||
|
||||
var/obj/item/computer_hardware/card_slot/card_slot
|
||||
@@ -301,181 +330,34 @@
|
||||
card_slot = computer.all_components[MC_CARD]
|
||||
printer = computer.all_components[MC_PRINT]
|
||||
|
||||
data["mmode"] = mod_mode
|
||||
|
||||
var/authed = 0
|
||||
if(computer)
|
||||
if(card_slot)
|
||||
var/obj/item/card/id/auth_card = card_slot.stored_card2
|
||||
data["auth_name"] = auth_card ? strip_html_simple(auth_card.name) : "-----"
|
||||
authed = authorized()
|
||||
|
||||
|
||||
if(mod_mode == 2)
|
||||
data["slots"] = list()
|
||||
var/list/pos = list()
|
||||
for(var/datum/job/job in SSjob.occupations)
|
||||
if(job.title in blacklisted)
|
||||
continue
|
||||
|
||||
var/list/status_open = build_manage(job,1)
|
||||
var/list/status_close = build_manage(job,0)
|
||||
|
||||
pos.Add(list(list(
|
||||
"title" = job.title,
|
||||
"current" = job.current_positions,
|
||||
"total" = job.total_positions,
|
||||
"status_open" = (authed && !minor) ? status_open["enable"]: 0,
|
||||
"status_close" = (authed && !minor) ? status_close["enable"] : 0,
|
||||
"desc_open" = status_open["desc"],
|
||||
"desc_close" = status_close["desc"])))
|
||||
data["slots"] = pos
|
||||
|
||||
data["src"] = "[REF(src)]"
|
||||
data["station_name"] = station_name()
|
||||
|
||||
|
||||
if(!mod_mode)
|
||||
data["manifest"] = list()
|
||||
var/list/crew = list()
|
||||
for(var/datum/data/record/t in sortRecord(GLOB.data_core.general))
|
||||
crew.Add(list(list(
|
||||
"name" = t.fields["name"],
|
||||
"rank" = t.fields["rank"])))
|
||||
|
||||
data["manifest"] = crew
|
||||
data["assignments"] = show_assignments
|
||||
if(computer)
|
||||
data["have_id_slot"] = !!card_slot
|
||||
data["have_printer"] = !!printer
|
||||
if(!card_slot && mod_mode == 1)
|
||||
mod_mode = 0 //We can't modify IDs when there is no card reader
|
||||
else
|
||||
data["have_id_slot"] = 0
|
||||
data["have_printer"] = 0
|
||||
data["have_id_slot"] = FALSE
|
||||
data["have_printer"] = FALSE
|
||||
|
||||
data["centcom_access"] = is_centcom
|
||||
|
||||
|
||||
data["authenticated"] = authed
|
||||
|
||||
|
||||
if(mod_mode == 1 && computer)
|
||||
if(card_slot)
|
||||
var/obj/item/card/id/id_card = card_slot.stored_card
|
||||
|
||||
data["has_id"] = !!id_card
|
||||
data["id_rank"] = id_card && id_card.assignment ? html_encode(id_card.assignment) : "Unassigned"
|
||||
data["id_owner"] = id_card && id_card.registered_name ? html_encode(id_card.registered_name) : "-----"
|
||||
data["id_name"] = id_card ? strip_html_simple(id_card.name) : "-----"
|
||||
|
||||
if(show_assignments)
|
||||
data["engineering_jobs"] = format_jobs(GLOB.engineering_positions)
|
||||
data["medical_jobs"] = format_jobs(GLOB.medical_positions)
|
||||
data["science_jobs"] = format_jobs(GLOB.science_positions)
|
||||
data["security_jobs"] = format_jobs(GLOB.security_positions)
|
||||
data["cargo_jobs"] = format_jobs(GLOB.supply_positions)
|
||||
data["civilian_jobs"] = format_jobs(GLOB.civilian_positions)
|
||||
data["centcom_jobs"] = format_jobs(get_all_centcom_jobs())
|
||||
|
||||
|
||||
if(card_slot.stored_card)
|
||||
var/obj/item/card/id/id_card = card_slot.stored_card
|
||||
if(is_centcom)
|
||||
var/list/all_centcom_access = list()
|
||||
for(var/access in get_all_centcom_access())
|
||||
all_centcom_access.Add(list(list(
|
||||
"desc" = replacetext(get_centcom_access_desc(access), " ", " "),
|
||||
"ref" = access,
|
||||
"allowed" = (access in id_card.access) ? 1 : 0)))
|
||||
data["all_centcom_access"] = all_centcom_access
|
||||
else
|
||||
var/list/regions = list()
|
||||
for(var/i = 1; i <= 7; i++)
|
||||
if((minor || target_dept) && !(i in region_access))
|
||||
continue
|
||||
|
||||
var/list/accesses = list()
|
||||
if(i in reg_ids)
|
||||
for(var/access in get_region_accesses(i))
|
||||
if (get_access_desc(access))
|
||||
accesses.Add(list(list(
|
||||
"desc" = replacetext(get_access_desc(access), " ", " "),
|
||||
"ref" = access,
|
||||
"allowed" = (access in id_card.access) ? 1 : 0)))
|
||||
|
||||
regions.Add(list(list(
|
||||
"name" = get_region_accesses_name(i),
|
||||
"regid" = i,
|
||||
"selected" = (i in reg_ids) ? 1 : null,
|
||||
"accesses" = accesses)))
|
||||
data["regions"] = regions
|
||||
|
||||
data["minor"] = target_dept || minor ? 1 : 0
|
||||
data["authenticated"] = authenticated
|
||||
|
||||
if(computer)
|
||||
var/obj/item/card/id/id_card = card_slot.stored_card
|
||||
data["has_id"] = !!id_card
|
||||
data["id_name"] = id_card ? id_card.name : "-----"
|
||||
if(id_card)
|
||||
data["id_rank"] = id_card.assignment ? id_card.assignment : "Unassigned"
|
||||
data["id_owner"] = id_card.registered_name ? id_card.registered_name : "-----"
|
||||
data["access_on_card"] = id_card.access
|
||||
|
||||
return data
|
||||
|
||||
|
||||
/datum/computer_file/program/card_mod/proc/build_manage(datum/job,open = FALSE)
|
||||
var/out = "Denied"
|
||||
var/can_change= 0
|
||||
if(open)
|
||||
can_change = can_open_job(job)
|
||||
else
|
||||
can_change = can_close_job(job)
|
||||
var/enable = 0
|
||||
if(can_change == 1)
|
||||
out = "[open ? "Open Position" : "Close Position"]"
|
||||
enable = 1
|
||||
else if(can_change == -2)
|
||||
var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1)
|
||||
var/mins = round(time_to_wait / 60)
|
||||
var/seconds = time_to_wait - (60*mins)
|
||||
out = "Cooldown ongoing: [mins]:[(seconds < 10) ? "0[seconds]" : "[seconds]"]"
|
||||
else
|
||||
out = "Denied"
|
||||
|
||||
return list("enable" = enable, "desc" = out)
|
||||
|
||||
|
||||
/datum/computer_file/program/card_mod/proc/authorized()
|
||||
if(!authenticated && computer)
|
||||
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
|
||||
if(card_slot)
|
||||
var/obj/item/card/id/auth_card = card_slot.stored_card2
|
||||
if(auth_card)
|
||||
region_access = list()
|
||||
if(ACCESS_CHANGE_IDS in auth_card.GetAccess())
|
||||
minor = 0
|
||||
authenticated = 1
|
||||
return 1
|
||||
else
|
||||
if((ACCESS_HOP in auth_card.access) && ((target_dept==1) || !target_dept))
|
||||
region_access |= 1
|
||||
region_access |= 6
|
||||
get_subordinates("Head of Personnel")
|
||||
if((ACCESS_HOS in auth_card.access) && ((target_dept==2) || !target_dept))
|
||||
region_access |= 2
|
||||
get_subordinates("Head of Security")
|
||||
if((ACCESS_CMO in auth_card.access) && ((target_dept==3) || !target_dept))
|
||||
region_access |= 3
|
||||
get_subordinates("Chief Medical Officer")
|
||||
if((ACCESS_RD in auth_card.access) && ((target_dept==4) || !target_dept))
|
||||
region_access |= 4
|
||||
get_subordinates("Research Director")
|
||||
if((ACCESS_CE in auth_card.access) && ((target_dept==5) || !target_dept))
|
||||
region_access |= 5
|
||||
get_subordinates("Chief Engineer")
|
||||
if(region_access.len)
|
||||
minor = 1
|
||||
authenticated = 1
|
||||
return 1
|
||||
else
|
||||
return authenticated
|
||||
|
||||
/datum/computer_file/program/card_mod/proc/get_subordinates(rank)
|
||||
head_subordinates = list()
|
||||
for(var/datum/job/job in SSjob.occupations)
|
||||
if(rank in job.department_head)
|
||||
head_subordinates += job.title
|
||||
#undef CARDCON_DEPARTMENT_SERVICE
|
||||
#undef CARDCON_DEPARTMENT_SECURITY
|
||||
#undef CARDCON_DEPARTMENT_MEDICAL
|
||||
#undef CARDCON_DEPARTMENT_SCIENCE
|
||||
#undef CARDCON_DEPARTMENT_SUPPLY
|
||||
#undef CARDCON_DEPARTMENT_ENGINEERING
|
||||
#undef CARDCON_DEPARTMENT_COMMAND
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/datum/computer_file/program/shipping
|
||||
filename = "shipping"
|
||||
filedesc = "Nanotrasen Shipping Scanner"
|
||||
program_icon_state = "shipping"
|
||||
extended_desc = "A combination printer/scanner app that enables modular computers to print barcodes for easy scanning and shipping."
|
||||
network_destination = "ship scanner"
|
||||
size = 6
|
||||
tgui_id = "NtosShipping"
|
||||
ui_x = 450
|
||||
ui_y = 350
|
||||
///Account used for creating barcodes.
|
||||
var/datum/bank_account/payments_acc
|
||||
///The amount which the tagger will recieve for the sale.
|
||||
var/percent_cut = 20
|
||||
|
||||
/datum/computer_file/program/shipping/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
|
||||
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
|
||||
var/obj/item/computer_hardware/printer/printer = computer.all_components[MC_PRINT]
|
||||
var/obj/item/card/id/id_card = card_slot ? card_slot.stored_card : null
|
||||
data["has_id_slot"] = !!card_slot
|
||||
data["has_printer"] = !!printer
|
||||
data["paperamt"] = printer ? "[printer.stored_paper] / [printer.max_paper]" : null
|
||||
data["card_owner"] = card_slot && card_slot.stored_card ? id_card.registered_name : "No Card Inserted."
|
||||
data["current_user"] = payments_acc ? payments_acc.account_holder : null
|
||||
data["barcode_split"] = percent_cut
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/shipping/ui_act(action, list/params)
|
||||
if(..())
|
||||
return TRUE
|
||||
if(!computer)
|
||||
return
|
||||
|
||||
// Get components
|
||||
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
|
||||
var/obj/item/computer_hardware/printer/printer = computer.all_components[MC_PRINT]
|
||||
var/obj/item/card/id/id_card = card_slot ? card_slot.stored_card : null
|
||||
if(!card_slot || !printer) //We need both to successfully use this app.
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("ejectid")
|
||||
if(id_card)
|
||||
card_slot.try_eject(TRUE, usr)
|
||||
if("selectid")
|
||||
if(!id_card)
|
||||
return
|
||||
if(!id_card.registered_account)
|
||||
playsound(get_turf(ui_host()), 'sound/machines/buzz-sigh.ogg', 50, TRUE, -1)
|
||||
return
|
||||
payments_acc = id_card.registered_account
|
||||
playsound(get_turf(ui_host()), 'sound/machines/ping.ogg', 50, TRUE, -1)
|
||||
if("resetid")
|
||||
payments_acc = null
|
||||
if("setsplit")
|
||||
var/potential_cut = input("How much would you like to payout to the registered card?","Percentage Profit") as num|null
|
||||
percent_cut = potential_cut ? clamp(round(potential_cut, 1), 1, 50) : 20
|
||||
if("print")
|
||||
if(!printer)
|
||||
to_chat(usr, "<span class='notice'>Hardware error: A printer is required to print barcodes.</span>")
|
||||
return
|
||||
if(printer.stored_paper <= 0)
|
||||
to_chat(usr, "<span class='notice'>Hardware error: Printer is out of paper.</span>")
|
||||
return
|
||||
if(!payments_acc)
|
||||
to_chat(usr, "<span class='notice'>Software error: Please set a current user first.</span>")
|
||||
return
|
||||
var/obj/item/barcode/barcode = new /obj/item/barcode(get_turf(ui_host()))
|
||||
barcode.payments_acc = payments_acc
|
||||
barcode.percent_cut = percent_cut
|
||||
printer.stored_paper--
|
||||
to_chat(usr, "<span class='notice'>The computer prints out a barcode.</span>")
|
||||
@@ -14,7 +14,7 @@
|
||||
ui_y = 630
|
||||
available_on_ntnet = 0
|
||||
requires_ntnet = 0
|
||||
tgui_id = "ntos_configuration"
|
||||
tgui_id = "NtosConfiguration"
|
||||
|
||||
var/obj/item/modular_computer/movable = null
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user