merge from master
This commit is contained in:
@@ -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*/
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
if(AH)
|
||||
message_admins("[key_name_admin(src)] has started replying to [key_name(C, 0, 0)]'s admin help.")
|
||||
var/msg = input(src,"Message:", "Private message to [key_name(C, 0, 0)]") as message|null
|
||||
var/msg = stripped_multiline_input(src,"Message:", "Private message to [key_name(C, 0, 0)]")
|
||||
if (!msg)
|
||||
message_admins("[key_name_admin(src)] has cancelled their reply to [key_name(C, 0, 0)]'s admin help.")
|
||||
return
|
||||
@@ -87,10 +87,10 @@
|
||||
|
||||
|
||||
if(irc)
|
||||
if(!ircreplyamount) //to prevent people from spamming irc
|
||||
if(!ircreplyamount) //to prevent people from spamming irc/discord
|
||||
return
|
||||
if(!msg)
|
||||
msg = input(src,"Message:", "Private message to Administrator") as text|null
|
||||
msg = stripped_multiline_input(src,"Message:", "Private message to Administrator")
|
||||
|
||||
if(!msg)
|
||||
return
|
||||
@@ -112,7 +112,7 @@
|
||||
|
||||
//get message text, limit it's length.and clean/escape html
|
||||
if(!msg)
|
||||
msg = input(src,"Message:", "Private message to [key_name(recipient, 0, 0)]") as message|null
|
||||
msg = stripped_multiline_input(src,"Message:", "Private message to [key_name(recipient, 0, 0)]")
|
||||
msg = trim(msg)
|
||||
if(!msg)
|
||||
return
|
||||
@@ -191,7 +191,7 @@
|
||||
spawn() //so we don't hold the caller proc up
|
||||
var/sender = src
|
||||
var/sendername = key
|
||||
var/reply = input(recipient, msg,"Admin PM from-[sendername]", "") as text|null //show message and await a reply
|
||||
var/reply = stripped_multiline_input(recipient, msg,"Admin PM from-[sendername]", "") //show message and await a reply
|
||||
if(recipient && reply)
|
||||
if(sender)
|
||||
recipient.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them
|
||||
|
||||
@@ -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"
|
||||
@@ -1276,7 +1269,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
|
||||
if(!check_rights(R_ADMIN) || !check_rights(R_FUN))
|
||||
return
|
||||
|
||||
var/list/punishment_list = list(ADMIN_PUNISHMENT_PIE, ADMIN_PUNISHMENT_CUSTOM_PIE, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_SUPPLYPOD_QUICK, ADMIN_PUNISHMENT_SUPPLYPOD, ADMIN_PUNISHMENT_MAZING, ADMIN_PUNISHMENT_ROD)
|
||||
var/list/punishment_list = list(ADMIN_PUNISHMENT_PIE, ADMIN_PUNISHMENT_CUSTOM_PIE, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_SUPPLYPOD_QUICK, ADMIN_PUNISHMENT_SUPPLYPOD, ADMIN_PUNISHMENT_MAZING, ADMIN_PUNISHMENT_ROD, ADMIN_PUNISHMENT_PICKLE)
|
||||
|
||||
var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
|
||||
|
||||
@@ -1341,7 +1334,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
|
||||
if(ADMIN_PUNISHMENT_PIE)
|
||||
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/creamy = new(get_turf(target))
|
||||
creamy.splat(target)
|
||||
if (ADMIN_PUNISHMENT_CUSTOM_PIE)
|
||||
if(ADMIN_PUNISHMENT_CUSTOM_PIE)
|
||||
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/A = new()
|
||||
if(!A.reagents)
|
||||
var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num|null
|
||||
@@ -1354,6 +1347,8 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
|
||||
if(amount)
|
||||
A.reagents.add_reagent(chosen_id, amount)
|
||||
A.splat(target)
|
||||
if(ADMIN_PUNISHMENT_PICKLE)
|
||||
target.turn_into_pickle()
|
||||
|
||||
punish_log(target, punishment)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
var/obj/machinery/computer/camera_advanced/abductor/camera
|
||||
var/list/datum/icon_snapshot/disguises = list()
|
||||
|
||||
/obj/machinery/abductor/console/attack_hand(mob/user)
|
||||
/obj/machinery/abductor/console/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
gland_colors[i] = random_color()
|
||||
amounts[i] = rand(1,5)
|
||||
|
||||
/obj/machinery/abductor/gland_dispenser/attack_hand(mob/user)
|
||||
/obj/machinery/abductor/gland_dispenser/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
/obj/machinery/abductor/experiment/attack_hand(mob/user)
|
||||
/obj/machinery/abductor/experiment/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -217,7 +217,7 @@
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/structure/bloodsucker/vassalrack/attack_hand(mob/user)
|
||||
/obj/structure/bloodsucker/vassalrack/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
//. = ..() // Taken from sacrificial altar in divine.dm
|
||||
//if(.)
|
||||
// return
|
||||
@@ -469,7 +469,7 @@
|
||||
. += {"<span class='cult'>This is a magical candle which drains at the sanity of the fools who havent yet accepted your master, as long as it is active.\n
|
||||
You can turn it on and off by clicking on it while you are next to it</span>"} */
|
||||
|
||||
/obj/structure/bloodsucker/candelabrum/attack_hand(mob/user)
|
||||
/obj/structure/bloodsucker/candelabrum/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
var/datum/antagonist/vassal/T = user.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
if(AmBloodsucker(user) || istype(T))
|
||||
toggle()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/glasses/changeling/attack_hand(mob/user)
|
||||
/obj/item/clothing/glasses/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/under/changeling/attack_hand(mob/user)
|
||||
/obj/item/clothing/under/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
@@ -51,7 +51,7 @@
|
||||
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/suit/changeling/attack_hand(mob/user)
|
||||
/obj/item/clothing/suit/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
@@ -66,7 +66,7 @@
|
||||
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/head/changeling/attack_hand(mob/user)
|
||||
/obj/item/clothing/head/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
@@ -82,7 +82,7 @@
|
||||
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/shoes/changeling/attack_hand(mob/user)
|
||||
/obj/item/clothing/shoes/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
@@ -98,7 +98,7 @@
|
||||
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/gloves/changeling/attack_hand(mob/user)
|
||||
/obj/item/clothing/gloves/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
@@ -114,7 +114,7 @@
|
||||
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/mask/changeling/attack_hand(mob/user)
|
||||
/obj/item/clothing/mask/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/changeling/attack_hand(mob/user)
|
||||
/obj/item/changeling/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
return //you can't tk stomp sigils, but you can hit them with something
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/effect/clockwork/sigil/attack_hand(mob/user)
|
||||
/obj/effect/clockwork/sigil/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(iscarbon(user) && !user.stat)
|
||||
if(is_servant_of_ratvar(user) && user.a_intent != INTENT_HARM)
|
||||
return ..()
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
..()
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/effect/clockwork/spatial_gateway/attack_hand(mob/living/user)
|
||||
/obj/effect/clockwork/spatial_gateway/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!uses)
|
||||
return FALSE
|
||||
if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling))
|
||||
|
||||
@@ -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
|
||||
@@ -55,7 +58,7 @@
|
||||
return ..()
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clockwork/slab/debug/attack_hand(mob/living/user)
|
||||
/obj/item/clockwork/slab/debug/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!is_servant_of_ratvar(user))
|
||||
add_servant_of_ratvar(user)
|
||||
return ..()
|
||||
@@ -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))
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
clockwork_desc = initial(clockwork_desc)
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clockwork/construct_chassis/attack_hand(mob/living/user)
|
||||
/obj/item/clockwork/construct_chassis/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(w_class >= WEIGHT_CLASS_HUGE)
|
||||
to_chat(user, "<span class='warning'>[src] is too cumbersome to carry! Drag it around instead!</span>")
|
||||
return
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
affected += try_use_power(MIN_CLOCKCULT_POWER*4)
|
||||
return affected
|
||||
|
||||
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/attack_hand(mob/living/user)
|
||||
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
var/selection_timer //Timer ID; this is canceled if the vote is canceled
|
||||
var/kingmaking
|
||||
|
||||
/obj/structure/destructible/clockwork/eminence_spire/attack_hand(mob/living/user)
|
||||
/obj/structure/destructible/clockwork/eminence_spire/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
. += "<span class='brass'>There are <b>[time_remaining]</b> second[time_remaining != 1 ? "s" : ""] remaining to vote.</span>"
|
||||
. += "<span class='big brass'>There are <b>[voters.len]/[votes_needed]</b> votes to activate the beacon!</span>"
|
||||
|
||||
/obj/structure/destructible/clockwork/heralds_beacon/attack_hand(mob/living/user)
|
||||
/obj/structure/destructible/clockwork/heralds_beacon/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
toggle()
|
||||
return TRUE
|
||||
|
||||
/obj/structure/destructible/clockwork/powered/mania_motor/attack_hand(mob/living/user)
|
||||
/obj/structure/destructible/clockwork/powered/mania_motor/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
max_integrity = 75
|
||||
icon_state = "lever"
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/trigger/lever/attack_hand(mob/living/user)
|
||||
/obj/structure/destructible/clockwork/trap/trigger/lever/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
max_integrity = 15 //Fragile!
|
||||
icon_state = "repeater"
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/trigger/repeater/attack_hand(mob/living/user)
|
||||
/obj/structure/destructible/clockwork/trap/trigger/repeater/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -67,7 +67,7 @@ Runes can either be invoked by one's self or with many different cultists. Each
|
||||
to_chat(user, "<span class='danger'>You disrupt the magic of [src] with [I].</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/rune/attack_hand(mob/living/user)
|
||||
/obj/effect/rune/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
if(A)
|
||||
notify_ghosts("A swarmer shell has been created in [A.name].", 'sound/effects/bin_close.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
|
||||
|
||||
/obj/effect/mob_spawn/swarmer/attack_hand(mob/living/user)
|
||||
/obj/effect/mob_spawn/swarmer/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
@@ -400,13 +400,13 @@
|
||||
return FALSE
|
||||
|
||||
/obj/structure/lattice/catwalk/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
|
||||
. = ..()
|
||||
var/turf/here = get_turf(src)
|
||||
for(var/A in here.contents)
|
||||
var/obj/structure/cable/C = A
|
||||
if(istype(C))
|
||||
to_chat(S, "<span class='warning'>Disrupting the power grid would bring no benefit to us. Aborting.</span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/deactivated_swarmer/IntegrateAmount()
|
||||
return 50
|
||||
|
||||
@@ -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>
|
||||
@@ -16,6 +16,8 @@ GLOBAL_LIST_INIT(meta_gas_dangers, meta_gas_danger_list())
|
||||
GLOBAL_LIST_INIT(meta_gas_ids, meta_gas_id_list())
|
||||
GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
/datum/gas_mixture
|
||||
/// Never ever set this variable, hooked into vv_get_var for view variables viewing.
|
||||
var/gas_list_view_only
|
||||
var/initial_volume = CELL_VOLUME //liters
|
||||
var/list/reaction_results
|
||||
var/list/analyzer_results //used for analyzer feedback - not initialized until its used
|
||||
@@ -29,9 +31,75 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
reaction_results = new
|
||||
|
||||
/datum/gas_mixture/vv_edit_var(var_name, var_value)
|
||||
if(var_name == "_extools_pointer_gasmixture")
|
||||
if(var_name == NAMEOF(src, _extools_pointer_gasmixture))
|
||||
return FALSE // please no. segfaults bad.
|
||||
if(var_name == NAMEOF(src, gas_list_view_only))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/gas_mixture/vv_get_var(var_name)
|
||||
. = ..()
|
||||
if(var_name == NAMEOF(src, gas_list_view_only))
|
||||
var/list/dummy = get_gases()
|
||||
for(var/gas in dummy)
|
||||
dummy[gas] = get_moles(gas)
|
||||
return debug_variable("gases (READ ONLY)", dummy, 0, src)
|
||||
|
||||
/datum/gas_mixture/vv_get_dropdown()
|
||||
. = ..()
|
||||
VV_DROPDOWN_OPTION("", "---")
|
||||
VV_DROPDOWN_OPTION(VV_HK_PARSE_GASSTRING, "Parse Gas String")
|
||||
VV_DROPDOWN_OPTION(VV_HK_EMPTY, "Empty")
|
||||
VV_DROPDOWN_OPTION(VV_HK_SET_MOLES, "Set Moles")
|
||||
VV_DROPDOWN_OPTION(VV_HK_SET_TEMPERATURE, "Set Temperature")
|
||||
VV_DROPDOWN_OPTION(VV_HK_SET_VOLUME, "Set Volume")
|
||||
|
||||
/datum/gas_mixture/vv_do_topic(list/href_list)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(href_list[VV_HK_PARSE_GASSTRING])
|
||||
var/gasstring = input(usr, "Input Gas String (WARNING: Advanced. Don't use this unless you know how these work.", "Gas String Parse") as text|null
|
||||
if(!istext(gasstring))
|
||||
return
|
||||
log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Set to gas string [gasstring].")
|
||||
message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Set to gas string [gasstring].")
|
||||
parse_gas_string(gasstring)
|
||||
if(href_list[VV_HK_EMPTY])
|
||||
log_admin("[key_name(usr)] emptied gas mixture [REF(src)].")
|
||||
message_admins("[key_name(usr)] emptied gas mixture [REF(src)].")
|
||||
clear()
|
||||
if(href_list[VV_HK_SET_MOLES])
|
||||
var/list/gases = get_gases()
|
||||
for(var/gas in gases)
|
||||
gases[gas] = get_moles(gas)
|
||||
var/gastype = input(usr, "What kind of gas?", "Set Gas") as null|anything in subtypesof(/datum/gas)
|
||||
if(!ispath(gastype, /datum/gas))
|
||||
return
|
||||
var/amount = input(usr, "Input amount", "Set Gas", gases[gastype] || 0) as num|null
|
||||
if(!isnum(amount))
|
||||
return
|
||||
amount = max(0, amount)
|
||||
log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Set gas type [gastype] to [amount] moles.")
|
||||
message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Set gas type [gastype] to [amount] moles.")
|
||||
set_moles(gastype, amount)
|
||||
if(href_list[VV_HK_SET_TEMPERATURE])
|
||||
var/temp = input(usr, "Set the temperature of this mixture to?", "Set Temperature", return_temperature()) as num|null
|
||||
if(!isnum(temp))
|
||||
return
|
||||
temp = max(2.7, temp)
|
||||
log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Changed temperature to [temp].")
|
||||
message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Changed temperature to [temp].")
|
||||
set_temperature(temp)
|
||||
if(href_list[VV_HK_SET_VOLUME])
|
||||
var/volume = input(usr, "Set the volume of this mixture to?", "Set Volume", return_volume()) as num|null
|
||||
if(!isnum(volume))
|
||||
return
|
||||
volume = max(0, volume)
|
||||
log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Changed volume to [volume].")
|
||||
message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Changed volume to [volume].")
|
||||
set_volume(volume)
|
||||
|
||||
/*
|
||||
/datum/gas_mixture/Del()
|
||||
__gasmixture_unregister()
|
||||
@@ -169,7 +237,7 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
set_moles(path, text2num(gas[id]))
|
||||
archive()
|
||||
return 1
|
||||
|
||||
|
||||
/datum/gas_mixture/react(datum/holder)
|
||||
. = NO_REACTION
|
||||
if(!total_moles())
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -322,7 +322,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()
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/ctf/attack_hand(mob/living/user)
|
||||
/obj/item/ctf/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!is_ctf_target(user) && !anyonecanpickup)
|
||||
to_chat(user, "Non players shouldn't be moving the flag!")
|
||||
return
|
||||
@@ -679,7 +679,7 @@
|
||||
/obj/machinery/control_point/attackby(mob/user, params)
|
||||
capture(user)
|
||||
|
||||
/obj/machinery/control_point/attack_hand(mob/user)
|
||||
/obj/machinery/control_point/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -595,7 +595,7 @@
|
||||
job_description = "Space Bar Patron"
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/effect/mob_spawn/human/alive/space_bar_patron/attack_hand(mob/user)
|
||||
/obj/effect/mob_spawn/human/alive/space_bar_patron/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
var/despawn = alert("Return to cryosleep? (Warning, Your mob will be deleted!)",,"Yes","No")
|
||||
if(despawn == "No" || !loc || !Adjacent(user))
|
||||
return
|
||||
|
||||
@@ -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)
|
||||
@@ -894,13 +893,13 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
||||
|
||||
/client/vv_edit_var(var_name, var_value)
|
||||
switch (var_name)
|
||||
if ("holder")
|
||||
if (NAMEOF(src, holder))
|
||||
return FALSE
|
||||
if ("ckey")
|
||||
if (NAMEOF(src, ckey))
|
||||
return FALSE
|
||||
if ("key")
|
||||
if (NAMEOF(src, key))
|
||||
return FALSE
|
||||
if("view")
|
||||
if(NAMEOF(src, view))
|
||||
change_view(var_value)
|
||||
return TRUE
|
||||
. = ..()
|
||||
|
||||
@@ -165,6 +165,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/custom_speech_verb = "default" //if your say_mod is to be something other than your races
|
||||
var/custom_tongue = "default" //if your tongue is to be something other than your races
|
||||
|
||||
/// Security record note section
|
||||
var/security_records
|
||||
/// Medical record note section
|
||||
var/medical_records
|
||||
|
||||
var/list/custom_names = list()
|
||||
var/preferred_ai_core_display = "Blue"
|
||||
var/prefered_security_department = SEC_DEPT_RANDOM
|
||||
@@ -340,6 +345,24 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<b>Custom job preferences:</b><BR>"
|
||||
dat += "<a href='?_src_=prefs;preference=ai_core_icon;task=input'><b>Preferred AI Core Display:</b> [preferred_ai_core_display]</a><br>"
|
||||
dat += "<a href='?_src_=prefs;preference=sec_dept;task=input'><b>Preferred Security Department:</b> [prefered_security_department]</a><BR></td>"
|
||||
dat += "<br>Records</b><br>"
|
||||
dat += "<br><a href='?_src_=prefs;preference=security_records;task=input'><b>Security Records</b></a><br>"
|
||||
if(length_char(security_records) <= 40)
|
||||
if(!length(security_records))
|
||||
dat += "\[...\]"
|
||||
else
|
||||
dat += "[security_records]"
|
||||
else
|
||||
dat += "[TextPreview(security_records)]...<BR>"
|
||||
|
||||
dat += "<br><a href='?_src_=prefs;preference=medical_records;task=input'><b>Medical Records</b></a><br>"
|
||||
if(length_char(medical_records) <= 40)
|
||||
if(!length(medical_records))
|
||||
dat += "\[...\]<br>"
|
||||
else
|
||||
dat += "[medical_records]"
|
||||
else
|
||||
dat += "[TextPreview(medical_records)]...<BR>"
|
||||
dat += "</tr></table>"
|
||||
|
||||
//Character Appearance
|
||||
@@ -1646,6 +1669,16 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_age)
|
||||
age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN)
|
||||
|
||||
if("security_records")
|
||||
var/rec = stripped_multiline_input(usr, "Set your security record note section. This should be IC!", "Security Records", html_decode(security_records), MAX_FLAVOR_LEN, TRUE)
|
||||
if(!isnull(rec))
|
||||
security_records = rec
|
||||
|
||||
if("medical_records")
|
||||
var/rec = stripped_multiline_input(usr, "Set your medical record note section. This should be IC!", "Security Records", html_decode(medical_records), MAX_FLAVOR_LEN, TRUE)
|
||||
if(!isnull(rec))
|
||||
medical_records = rec
|
||||
|
||||
if("flavor_text")
|
||||
var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", html_decode(features["flavor_text"]), MAX_FLAVOR_LEN, TRUE)
|
||||
if(!isnull(msg))
|
||||
|
||||
@@ -515,6 +515,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
//Quirks
|
||||
S["all_quirks"] >> all_quirks
|
||||
|
||||
//Records
|
||||
S["security_records"] >> security_records
|
||||
S["medical_records"] >> medical_records
|
||||
|
||||
//Citadel code
|
||||
S["feature_genitals_use_skintone"] >> features["genitals_use_skintone"]
|
||||
S["feature_mcolor2"] >> features["mcolor2"]
|
||||
@@ -698,6 +702,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
custom_speech_verb = sanitize_inlist(custom_speech_verb, GLOB.speech_verbs, "default")
|
||||
custom_tongue = sanitize_inlist(custom_tongue, GLOB.roundstart_tongues, "default")
|
||||
|
||||
security_records = copytext(security_records, 1, MAX_FLAVOR_LEN)
|
||||
medical_records = copytext(medical_records, 1, MAX_FLAVOR_LEN)
|
||||
|
||||
features["flavor_text"] = copytext(features["flavor_text"], 1, MAX_FLAVOR_LEN)
|
||||
features["silicon_flavor_text"] = copytext(features["silicon_flavor_text"], 1, MAX_FLAVOR_LEN)
|
||||
features["ooc_notes"] = copytext(features["ooc_notes"], 1, MAX_FLAVOR_LEN)
|
||||
@@ -762,6 +769,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["species"] , pref_species.id)
|
||||
WRITE_FILE(S["custom_speech_verb"] , custom_speech_verb)
|
||||
WRITE_FILE(S["custom_tongue"] , custom_tongue)
|
||||
|
||||
// records
|
||||
WRITE_FILE(S["security_records"] , security_records)
|
||||
WRITE_FILE(S["medical_records"] , medical_records)
|
||||
|
||||
WRITE_FILE(S["feature_mcolor"] , features["mcolor"])
|
||||
WRITE_FILE(S["feature_lizard_tail"] , features["tail_lizard"])
|
||||
WRITE_FILE(S["feature_human_tail"] , features["tail_human"])
|
||||
|
||||
@@ -287,7 +287,7 @@
|
||||
if(!target.IsUnconscious())
|
||||
to_chat(target, "<span class='warning'>Your zealous conspirationism rapidly dissipates as the donned hat warps up into a ruined mess. All those theories starting to sound like nothing but a ridicolous fanfare.</span>")
|
||||
|
||||
/obj/item/clothing/head/foilhat/attack_hand(mob/user)
|
||||
/obj/item/clothing/head/foilhat/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!warped && iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
if(src == C.head)
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
lock = TRUE
|
||||
return
|
||||
|
||||
/obj/item/clothing/neck/petcollar/locked/attack_hand(mob/user)
|
||||
/obj/item/clothing/neck/petcollar/locked/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(loc == user && user.get_item_by_slot(SLOT_NECK) && lock != FALSE)
|
||||
to_chat(user, "<span class='warning'>The collar is locked! You'll need unlock the collar before you can take it off!</span>")
|
||||
return
|
||||
|
||||
@@ -85,12 +85,10 @@
|
||||
item_state = "w_suit"
|
||||
permeability_coefficient = 0.5
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/rank/medical/paramedic/light
|
||||
desc = "It's made of a special fiber that provides minor protection against biohazards. It has a dark blue cross on the chest denoting that the wearer is a trained paramedic."
|
||||
icon_state = "paramedic-light"
|
||||
can_adjust = TRUE
|
||||
|
||||
/obj/item/clothing/under/rank/medical/paramedic/skirt
|
||||
name = "paramedic jumpskirt"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -143,7 +143,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
|
||||
if(L && (L.density || prob(10)))
|
||||
L.ex_act(EXPLODE_HEAVY)
|
||||
|
||||
obj/effect/immovablerod/attack_hand(mob/living/user)
|
||||
obj/effect/immovablerod/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/U = user
|
||||
if(U.job in list("Research Director"))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -346,7 +346,7 @@
|
||||
SM.on_cross(src, AM)
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/structure/spacevine/attack_hand(mob/user)
|
||||
/obj/structure/spacevine/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
SM.on_hit(src, user)
|
||||
user_unbuckle_mob(user, user)
|
||||
|
||||
@@ -0,0 +1,330 @@
|
||||
/datum/round_event_control/travelling_trader
|
||||
name = "Travelling Trader"
|
||||
typepath = /datum/round_event/travelling_trader
|
||||
weight = 10
|
||||
max_occurrences = 3
|
||||
earliest_start = 0 MINUTES
|
||||
|
||||
/datum/round_event/travelling_trader
|
||||
startWhen = 0
|
||||
endWhen = 900 //you effectively have 15 minutes to complete the traders request, before they disappear
|
||||
var/mob/living/carbon/human/dummy/travelling_trader/trader
|
||||
var/atom/spawn_location //where the trader appears
|
||||
|
||||
/datum/round_event/travelling_trader/setup()
|
||||
if(GLOB.generic_event_spawns)
|
||||
spawn_location = pick(GLOB.generic_event_spawns)
|
||||
else
|
||||
message_admins("No event spawn landmarks exist on the map while placing a travelling trader, resorting to random station turf. (go yell at a mapper)")
|
||||
spawn_location = get_random_station_turf()
|
||||
|
||||
/datum/round_event/travelling_trader/start()
|
||||
//spawn a type of trader
|
||||
var/trader_type = pick(subtypesof(/mob/living/carbon/human/dummy/travelling_trader))
|
||||
trader = new trader_type(get_turf(spawn_location))
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(1, spawn_location)
|
||||
smoke.start()
|
||||
trader.visible_message("<b>[src]</b> suddenly appears in a puff of smoke!")
|
||||
|
||||
/datum/round_event/travelling_trader/announce(fake)
|
||||
priority_announce("A mysterious figure has been detected on sensors at [get_area(spawn_location)]", "Mysterious Figure")
|
||||
|
||||
/datum/round_event/travelling_trader/end()
|
||||
if(trader)
|
||||
trader.visible_message("The <b>[src]</b> has given up on waiting!")
|
||||
qdel(trader)
|
||||
|
||||
//the actual trader mob
|
||||
/mob/living/carbon/human/dummy/travelling_trader //similar to a dummy because we want to be resource-efficient
|
||||
var/trader_name = "Debug Travelling Trader"
|
||||
status_flags = GODMODE //avoid scenarios of people trying to kill the trader
|
||||
move_resist = MOVE_FORCE_VERY_STRONG //you can't bluespace bodybag them!
|
||||
var/datum/outfit/trader_outfit
|
||||
var/list/possible_wanted_items //weighted list of possible things to request
|
||||
var/list/possible_rewards //weighted list of possible things to give in return for the requested item
|
||||
var/atom/requested_item //the thing they chose from possible_wanted_items
|
||||
var/last_speech //last time someone tried interacting with them using their hand
|
||||
var/last_refusal //last time they vocally refused an item given to them
|
||||
var/initial_speech = "It looks like the coders did a mishap!" //first thing they say when interacted with, like a description
|
||||
var/speech_verb = "says"
|
||||
var/request_speech = "Please bring me a requested_item you shall be greatly rewarded!" //second thing they say when interacted with
|
||||
var/acceptance_speech = "This is exactly what I wanted! I shall be on my way now, thank you.!"
|
||||
var/refusal_speech = "A given_item? I wanted a requested_item!" //what they say when refusing an item
|
||||
var/active = TRUE
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/proc/setup_speech(var/input_speech, var/obj/item/given_item)
|
||||
if(requested_item)
|
||||
input_speech = replacetext(input_speech, "requested_item", initial(requested_item.name))
|
||||
if(given_item)
|
||||
input_speech = replacetext(input_speech, "given_item", given_item.name)
|
||||
return input_speech
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/attack_hand(mob/living/carbon/human/H)
|
||||
if(active && last_speech + 3 < world.realtime) //can only talk once per 3 seconds, to avoid spam
|
||||
last_speech = world.realtime
|
||||
if(initial_speech)
|
||||
visible_message("<b>[src]</b> [speech_verb] \"[setup_speech(initial_speech)]\"")
|
||||
sleep(15)
|
||||
if(active && request_speech) //they might not be active anymore because of the prior sleep!
|
||||
visible_message("<b>[src]</b> [speech_verb] \"[setup_speech(request_speech)]\"")
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/attackby(obj/item/I, mob/user)
|
||||
if(active)
|
||||
if(check_item(I))
|
||||
active = FALSE
|
||||
visible_message("<b>[src]</b> [speech_verb] \"[setup_speech(acceptance_speech, I)]\"")
|
||||
qdel(I)
|
||||
sleep(15)
|
||||
give_reward(user)
|
||||
qdel(src)
|
||||
else
|
||||
if(last_refusal + 3 < world.realtime)
|
||||
last_refusal = world.realtime
|
||||
visible_message("<b>[src]</b> [speech_verb] \"[setup_speech(refusal_speech, I)]\"")
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/proc/check_item(var/obj/item/supplied_item) //sometimes we might want to care about the properties of the item, etc
|
||||
return istype(supplied_item, requested_item)
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/proc/give_reward()
|
||||
var/reward = pickweight(possible_rewards)
|
||||
new reward(get_turf(src))
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/Initialize()
|
||||
..()
|
||||
ADD_TRAIT(src,TRAIT_PIERCEIMMUNE, "trader_pierce_immune") //don't let people take their blood
|
||||
equipOutfit(trader_outfit, TRUE)
|
||||
for(var/obj/item/item in src.get_equipped_items())
|
||||
ADD_TRAIT(item, TRAIT_NODROP, "trader_no_drop") //don't let people steal the travellers clothes!
|
||||
item.resistance_flags |= INDESTRUCTIBLE //don't let people burn their clothes off, either.
|
||||
if(!requested_item) //sometimes we already picked one
|
||||
requested_item = pickweight(possible_wanted_items)
|
||||
name = trader_name //gets changed in humans initialisation so we set it here
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/Destroy()
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(1, loc)
|
||||
smoke.start()
|
||||
visible_message("<b>[src]</b> disappears in a puff of smoke, leaving something on the ground!")
|
||||
..()
|
||||
|
||||
//travelling trader subtypes (the types that can actually spawn)
|
||||
//so far there's: cook / botanist / bartender / animal hunter / artifact dealer / surgeon (6 types!)
|
||||
|
||||
//cook
|
||||
/mob/living/carbon/human/dummy/travelling_trader/cook
|
||||
trader_name = "Otherworldly Chef"
|
||||
trader_outfit = /datum/outfit/job/cook
|
||||
initial_speech = "Mama-mia! I have came to this plane of existence, searching the greatest of foods!"
|
||||
request_speech = "Can you fetch me the delicacy known as requested_item? I would pay you for your service!"
|
||||
acceptance_speech = "Grazie! You have done me a service, my friend."
|
||||
refusal_speech = "A given_item? Surely you must be joking!"
|
||||
possible_rewards = list(/obj/item/paper/secretrecipe = 1,
|
||||
/obj/item/pizzabox/infinite = 1,
|
||||
/obj/item/kitchen/fork/throwing = 1,
|
||||
/mob/living/simple_animal/cow/random = 1)
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/cook/Initialize()
|
||||
//pick a random crafted food item as the requested item
|
||||
var/datum/crafting_recipe/food_recipe = pick(subtypesof(/datum/crafting_recipe/food))
|
||||
var/result = initial(food_recipe.result)
|
||||
if(ispath(result, /obj/item/reagent_containers/food)) //not all food recipes make food objects (like cak/butterbear)
|
||||
requested_item = result
|
||||
else
|
||||
requested_item = /obj/item/reagent_containers/food/snacks/copypasta
|
||||
..()
|
||||
|
||||
//botanist
|
||||
/mob/living/carbon/human/dummy/travelling_trader/gardener
|
||||
trader_name = "Otherworldly Gardener"
|
||||
trader_outfit = /datum/outfit/job/botanist
|
||||
initial_speech = "I have come across this realm in search of rare plants and believe this station may be able to help me.."
|
||||
request_speech = "Are you able to bring me the plant known to you as: 'requested_item'? I could see that you get some reward for this task."
|
||||
acceptance_speech = "Amazing! Ill finally be able to make that salad. Goodbye for now!"
|
||||
refusal_speech = "A given_item? Did nobody ever teach you the basics of gardening?"
|
||||
possible_rewards = list(/obj/item/seeds/cherry/bomb = 1,
|
||||
/obj/item/storage/box/strange_seeds_5pack = 6,
|
||||
/obj/item/clothing/suit/hooded/bee_costume = 2,
|
||||
/obj/item/seeds/gatfruit = 1) //overall you have less chance of seeing them than a lifebringer just bringing the seeds to you directly
|
||||
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/gardener/Initialize()
|
||||
requested_item = pick(subtypesof(/obj/item/reagent_containers/food/snacks/grown) - list(/obj/item/reagent_containers/food/snacks/grown/shell,
|
||||
/obj/item/reagent_containers/food/snacks/grown/shell/gatfruit,
|
||||
/obj/item/reagent_containers/food/snacks/grown/cherry_bomb))
|
||||
..()
|
||||
|
||||
//animal hunter
|
||||
/mob/living/carbon/human/dummy/travelling_trader/animal_hunter
|
||||
trader_name = "Otherworldly Animal Specialist"
|
||||
trader_outfit = /datum/outfit/job/doctor
|
||||
initial_speech = "Greetings, lifeform. I am here to locate a special creature aboard your station."
|
||||
request_speech = "Find me the creature known as 'requested_item' and you shall be rewarded for your efforts."
|
||||
refusal_speech = "Do you think me to be a fool, lifeform? I know a requested_item when I see one."
|
||||
possible_wanted_items = list(/mob/living/simple_animal/pet/dog/corgi/Ian = 1,
|
||||
/mob/living/simple_animal/sloth/paperwork = 1,
|
||||
/mob/living/carbon/monkey/punpun = 1,
|
||||
/mob/living/simple_animal/pet/fox/Renault = 1,
|
||||
/mob/living/simple_animal/hostile/carp/cayenne = 1,
|
||||
/mob/living/simple_animal/pet/bumbles = 1,
|
||||
/mob/living/simple_animal/parrot/Poly = 1)
|
||||
possible_rewards = list(/mob/living/simple_animal/pet/dog/corgi/exoticcorgi = 1, //rewards are animals, friendly to only the person who handed the reward in!
|
||||
/mob/living/simple_animal/cockroach = 1,
|
||||
/mob/living/simple_animal/hostile/skeleton = 1,
|
||||
/mob/living/simple_animal/hostile/stickman = 1,
|
||||
/mob/living/simple_animal/hostile/stickman/dog = 1,
|
||||
/mob/living/simple_animal/hostile/asteroid/fugu = 1,
|
||||
/mob/living/simple_animal/hostile/bear = 1,
|
||||
/mob/living/simple_animal/hostile/retaliate/clown/fleshclown = 1,
|
||||
/mob/living/simple_animal/hostile/tree = 1,
|
||||
/mob/living/simple_animal/hostile/mimic = 1,
|
||||
/mob/living/simple_animal/hostile/shark = 1,
|
||||
/mob/living/simple_animal/hostile/netherworld/blankbody = 1,
|
||||
/mob/living/simple_animal/hostile/retaliate/goose = 1)
|
||||
|
||||
mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize()
|
||||
acceptance_speech = pick(list("This lifeform shall make for a great stew, thank you.", "This lifeform shall be of a true use to our cause, thank you.", "The lifeform is adequate. Goodbye.", "This lifeform shall make a great addition to my collection."))
|
||||
//make sure they only ask for animals that are still alive
|
||||
for(var/mob/living/animal in possible_wanted_items)
|
||||
if(!(animal in GLOB.mob_living_list))
|
||||
possible_wanted_items -= animal
|
||||
if(!possible_wanted_items)
|
||||
//all the pets are dead, so ask for a monkey, or sometimes a corgi (corgis are more annoying to get a hold of)
|
||||
possible_wanted_items = list(/mob/living/simple_animal/pet/dog/corgi = 1, /mob/living/carbon/monkey = 3)
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/animal_hunter/check_item(var/obj/item/supplied_item) //item is likely to be in contents of whats supplied
|
||||
for(var/atom/something in supplied_item.contents)
|
||||
if(istype(something, requested_item))
|
||||
qdel(something) //typically things holding mobs release the mob when the container is deleted, so delete the mob first here
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/animal_hunter/give_reward(var/mob/giver) //the reward is actually given in a jar, because releasing it onto the station might be a bad idea
|
||||
var/obj/item/pet_carrier/bluespace/jar = new(get_turf(src))
|
||||
var/chosen_animal = pickweight(possible_rewards)
|
||||
var/mob/living/new_animal = new chosen_animal(jar)
|
||||
if(giver && giver.tag)
|
||||
new_animal.faction += "\[[giver.tag]\]"
|
||||
jar.add_occupant(new_animal)
|
||||
jar.name = "WARNING: [new_animal]"
|
||||
|
||||
//bartender
|
||||
/mob/living/carbon/human/dummy/travelling_trader/bartender
|
||||
trader_name = "Otherworldly Bartender"
|
||||
trader_outfit = /datum/outfit/job/bartender
|
||||
initial_speech = "Greetings, station inhabitor. I came to this dimension in the pursuit of a particular drink."
|
||||
request_speech = "Bring me thirty units of the beverage known as 'requested_item'."
|
||||
acceptance_speech = "This is truly the drink I have been seeking. Thank you."
|
||||
refusal_speech = "Do not mess with me, simpleton, I do not wish for that which you are trying to give me."
|
||||
possible_rewards = list(/obj/structure/reagent_dispensers/keg/neurotoxin = 1, //all kegs have 250u aside from neurotoxin/hearty punch which have 100u
|
||||
/obj/structure/reagent_dispensers/keg/hearty_punch = 3,
|
||||
/obj/structure/reagent_dispensers/keg/red_queen = 3,
|
||||
/obj/structure/reagent_dispensers/keg/narsour = 3,
|
||||
/obj/structure/reagent_dispensers/keg/quintuple_sec = 3)
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/bartender/Initialize() //pick a subtype of ethanol that isn't found in the default set of the booze dispensers reagents
|
||||
requested_item = pick(subtypesof(/datum/reagent/consumable/ethanol) - list(/datum/reagent/consumable/ethanol/beer,
|
||||
/datum/reagent/consumable/ethanol/kahlua,
|
||||
/datum/reagent/consumable/ethanol/whiskey,
|
||||
/datum/reagent/consumable/ethanol/wine,
|
||||
/datum/reagent/consumable/ethanol/vodka,
|
||||
/datum/reagent/consumable/ethanol/gin,
|
||||
/datum/reagent/consumable/ethanol/rum,
|
||||
/datum/reagent/consumable/ethanol/tequila,
|
||||
/datum/reagent/consumable/ethanol/vermouth,
|
||||
/datum/reagent/consumable/ethanol/cognac,
|
||||
/datum/reagent/consumable/ethanol/ale,
|
||||
/datum/reagent/consumable/ethanol/absinthe,
|
||||
/datum/reagent/consumable/ethanol/hcider,
|
||||
/datum/reagent/consumable/ethanol/creme_de_menthe,
|
||||
/datum/reagent/consumable/ethanol/creme_de_cacao,
|
||||
/datum/reagent/consumable/ethanol/creme_de_coconut,
|
||||
/datum/reagent/consumable/ethanol/triple_sec,
|
||||
/datum/reagent/consumable/ethanol/sake,
|
||||
/datum/reagent/consumable/ethanol/applejack))
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/bartender/check_item(var/obj/item/supplied_item) //you need to check its reagents
|
||||
if(istype(supplied_item, /obj/item/reagent_containers))
|
||||
var/obj/item/reagent_containers/supplied_container = supplied_item
|
||||
if(supplied_container.reagents.has_reagent(requested_item, 30))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
//artifact dealer
|
||||
/mob/living/carbon/human/dummy/travelling_trader/artifact_dealer
|
||||
trader_name = "Otherworldly Artifact Dealer"
|
||||
trader_outfit = /datum/outfit/artifact_dealer //he's cool enough to get his own outfit
|
||||
initial_speech = "I have come here due to sensing the existence of an object of great power and importance."
|
||||
request_speech = "Give to me the great object known as: requested_item and I shall make it worth your while, traveller."
|
||||
acceptance_speech = "This is truly an artifact worthy of my collection, thank you."
|
||||
refusal_speech = "A given_item? Hah! Worthless."
|
||||
possible_wanted_items = list(/obj/item/pen/fountain/captain = 1, //various rare things and high risk but not useful things (i.e. champion belt, bedsheet, pen)
|
||||
/obj/item/storage/belt/champion = 1,
|
||||
/obj/item/clothing/shoes/wheelys = 1,
|
||||
/obj/item/relic = 1,
|
||||
/obj/item/flashlight/lamp/bananalamp = 1,
|
||||
/obj/item/storage/box/hug = 1,
|
||||
/obj/item/clothing/gloves/color/yellow = 1,
|
||||
/obj/item/instrument/saxophone = 1,
|
||||
/obj/item/bedsheet/captain = 1,
|
||||
/obj/item/slime_extract/green = 1,
|
||||
/obj/item/chainsaw = 1,
|
||||
/obj/item/clothing/head/crown = 1)
|
||||
possible_rewards = list(/obj/item/storage/bag/money/c5000 = 5,
|
||||
/obj/item/circuitboard/computer/arcade/amputation = 2,
|
||||
/obj/item/stack/sticky_tape/infinite = 2,
|
||||
/obj/item/clothing/suit/hooded/wintercoat/cosmic = 2)
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/artifact_dealer/Initialize()
|
||||
possible_rewards += list(pick(subtypesof(/obj/item/clothing/head/collectable)) = 1) //this is slightly lower because it's absolutely useless
|
||||
..()
|
||||
|
||||
/datum/outfit/artifact_dealer
|
||||
uniform = /obj/item/clothing/under/suit/black_really
|
||||
shoes = /obj/item/clothing/shoes/combat
|
||||
head = /obj/item/clothing/head/that
|
||||
glasses = /obj/item/clothing/glasses/monocle
|
||||
|
||||
//surgeon
|
||||
/mob/living/carbon/human/dummy/travelling_trader/surgeon
|
||||
trader_name = "Otherworldly Surgeon"
|
||||
trader_outfit = /datum/outfit/otherworldly_surgeon
|
||||
initial_speech = "Hello there, meatbag. You can provide me with something I want."
|
||||
request_speech = "Find me the appendage you call 'requested_item'. I shall make sure it's worth your efforts."
|
||||
acceptance_speech = "This shall do. Goodbye, meatbag."
|
||||
refusal_speech = "That is not what I wish for. Give me a requested_item, or I shall take one by force."
|
||||
possible_wanted_items = list(/obj/item/bodypart/l_arm = 4,
|
||||
/obj/item/bodypart/r_arm = 4,
|
||||
/obj/item/bodypart/l_leg = 4,
|
||||
/obj/item/bodypart/r_leg = 4,
|
||||
/obj/item/organ/tongue = 2,
|
||||
/obj/item/organ/liver = 2,
|
||||
/obj/item/organ/lungs = 2,
|
||||
/obj/item/organ/heart = 2,
|
||||
/obj/item/organ/eyes = 1,
|
||||
/obj/item/organ/brain = 1,
|
||||
/obj/item/bodypart/head = 1)
|
||||
possible_rewards = list(/obj/item/organ/cyberimp/mouth/breathing_tube = 1,
|
||||
/obj/item/organ/eyes/robotic/thermals = 1,
|
||||
/obj/item/organ/cyberimp/arm/toolset = 1,
|
||||
/obj/item/organ/cyberimp/arm/surgery = 1,
|
||||
/obj/item/organ/cyberimp/arm/janitor = 1,
|
||||
/obj/item/organ/cyberimp/arm/flash = 1,
|
||||
/obj/item/organ/cyberimp/arm/shield = 1,
|
||||
/obj/item/organ/cyberimp/eyes/hud/medical = 1,
|
||||
/obj/item/organ/cyberimp/arm/baton = 1)
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/surgeon/give_reward()
|
||||
var/chosen_implant = pickweight(possible_rewards)
|
||||
var/new_implant = new chosen_implant
|
||||
var/obj/item/autosurgeon/reward = new(get_turf(src))
|
||||
reward.insert_organ(new_implant)
|
||||
|
||||
/datum/outfit/otherworldly_surgeon
|
||||
uniform = /obj/item/clothing/under/pants/white
|
||||
shoes = /obj/item/clothing/shoes/sneakers/white
|
||||
gloves = /obj/item/clothing/gloves/color/latex
|
||||
mask = /obj/item/clothing/mask/surgical
|
||||
suit = /obj/item/clothing/suit/apron/surgical
|
||||
@@ -13,15 +13,31 @@ The nutriment reagent and bitesize variable replace the old heal_amt and amount
|
||||
bitesize of 2, then it'll take 3 bites to eat. Unlike the old system, the contained reagents are evenly spread among all
|
||||
the bites. No more contained reagents = no more bites.
|
||||
|
||||
Here is an example of the new formatting for anyone who wants to add more food items.
|
||||
Food formatting and crafting examples.
|
||||
```
|
||||
/obj/item/reagent_containers/food/snacks/xenoburger //Identification path for the object.
|
||||
name = "Xenoburger" //Name that displays in the UI.
|
||||
desc = "Smells caustic. Tastes like heresy." //Duh
|
||||
icon_state = "xburger" //Refers to an icon in food.dmi
|
||||
list_reagents = list(/datum/reagent/xenomicrobes = 10,
|
||||
/datum/reagent/consumable/nutriment = 2) //What's inside the snack.
|
||||
bitesize = 3 //This is the amount each bite consumes.
|
||||
/obj/item/reagent_containers/food/snacks/saltedcornchips //Identification path for the object.
|
||||
name = "salted corn chips" //Name that displays when hovered over.
|
||||
desc = "Manufactured in a far away factory." //Description on examine.
|
||||
icon_state = "saltychip" //Refers to an icon, usually in food.dmi
|
||||
bitesize = 3 //How many reagents are consumed in each bite.
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 6, //What's inside the snack, but only if spawned. For example, from a chemical reaction, vendor, or slime core spawn.
|
||||
/datum/reagent/consumable/nutriment/vitamin = 2)
|
||||
bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, //What's -added- to the food, in addition to the reagents contained inside the foods used to craft it. Basically, a reward for cooking.
|
||||
/datum/reagent/consumable/nutriment/vitamin = 1) ^^For example. Egg+Egg = 2Egg + Bonus Reagents.
|
||||
filling_color = "#F4A460" //What color it will use if put in a custom food.
|
||||
tastes = list("salt" = 1, "oil" = 1) //Descriptive flavoring displayed when eaten. IE: "You taste a bit of salt and a bit of oil."
|
||||
foodtype = GRAIN | JUNKFOOD //Tag for racial or custom food preferences. IE: Most Lizards cannot have GRAIN.
|
||||
|
||||
Crafting Recipe (See files in code/modules/food_and_drinks/recipes/tablecraft/)
|
||||
|
||||
/datum/crafting_recipe/food/nachos
|
||||
name ="Salted Corn Chips" //Name that displays in the Crafting UI
|
||||
reqs = list( //The list of ingredients to make the food.
|
||||
/obj/item/reagent_containers/food/snacks/tortilla = 1,
|
||||
/datum/reagent/consumable/sodiumchloride = 1 //As a note, reagents and non-food items don't get added to the food. If you
|
||||
) ^^want the reagents, make sure the food item has it listed under bonus_reagents.
|
||||
result = /obj/item/reagent_containers/food/snacks/saltedcornchips //Resulting object.
|
||||
subcategory = CAT_MISCFOOD //Subcategory the food falls under in the Food Tab of the crafting menu.
|
||||
```
|
||||
|
||||
All foods are distributed among various categories. Use common sense.
|
||||
|
||||
@@ -134,7 +134,7 @@ God bless America.
|
||||
/obj/machinery/deepfryer/attack_ai(mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/deepfryer/attack_hand(mob/user)
|
||||
/obj/machinery/deepfryer/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(frying)
|
||||
if(frying.loc == src)
|
||||
to_chat(user, "<span class='notice'>You eject [frying] from [src].</span>")
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
/obj/machinery/gibber/relaymove(mob/living/user)
|
||||
go_out()
|
||||
|
||||
/obj/machinery/gibber/attack_hand(mob/user)
|
||||
/obj/machinery/gibber/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
/obj/machinery/grill/attack_ai(mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/grill/attack_hand(mob/user)
|
||||
/obj/machinery/grill/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(grilled_item)
|
||||
to_chat(user, "<span class='notice'>You take out [grilled_item] from [src].</span>")
|
||||
grilled_item.forceMove(drop_location())
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
update_icon()
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/pizzabox/attack_hand(mob/user)
|
||||
/obj/item/pizzabox/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(user.get_inactive_held_item() != src)
|
||||
return ..()
|
||||
if(open)
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
return
|
||||
say("It doesn't seem like that's magical enough!")
|
||||
|
||||
/obj/item/barthpot/attack_hand(mob/user)
|
||||
/obj/item/barthpot/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!active)
|
||||
say("Meow!")
|
||||
return
|
||||
|
||||
@@ -406,14 +406,14 @@
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, GLUED_ITEM_TRAIT)
|
||||
|
||||
/obj/item/clothing/suit/ghost_sheet/sticky/attack_hand(mob/user)
|
||||
/obj/item/clothing/suit/ghost_sheet/sticky/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(iscarbon(user))
|
||||
to_chat(user, "<span class='spooky'><i>Boooooo~!</i></span>")
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/clothing/suit/ghost_sheet/sticky/attack_hand(mob/user)
|
||||
/obj/item/clothing/suit/ghost_sheet/sticky/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(iscarbon(user))
|
||||
to_chat(user, "<span class='spooky'><i>Boooooo~!</i></span>")
|
||||
return
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
if(user.transferItemToLoc(W, drop_location()))
|
||||
visible_message("<span class='warning'> [user] dunks [W] into \the [src]!</span>")
|
||||
|
||||
/obj/structure/holohoop/attack_hand(mob/user)
|
||||
/obj/structure/holohoop/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
@@ -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"
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
tiled_dirt = FALSE
|
||||
baseturfs = /turf/open/floor/holofloor/snow
|
||||
|
||||
/turf/open/floor/holofloor/snow/attack_hand(mob/living/user)
|
||||
/turf/open/floor/holofloor/snow/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/structure/fermenting_barrel/attack_hand(mob/user)
|
||||
/obj/structure/fermenting_barrel/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
open = !open
|
||||
if(open)
|
||||
DISABLE_BITFIELD(reagents.reagents_holder_flags, DRAINABLE)
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
foodtype = FRUIT
|
||||
wine_power = 50
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/ghost_chili/attack_hand(mob/user)
|
||||
/obj/item/reagent_containers/food/snacks/grown/ghost_chili/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user