Merge branch 'master' into various-misc

This commit is contained in:
DragonTrance
2021-05-01 10:31:15 -07:00
committed by GitHub
124 changed files with 9704 additions and 443 deletions
+5
View File
@@ -294,6 +294,7 @@
#define SPEECH_LANGUAGE 5
#define SPEECH_IGNORE_SPAM 6
#define SPEECH_FORCED 7 */
#define COMSIG_MOB_ANTAG_ON_GAIN "mob_antag_on_gain" //from base of /datum/antagonist/on_gain(): (antag_datum)
///from base of /mob/Login(): ()
#define COMSIG_MOB_LOGIN "mob_login"
@@ -378,6 +379,7 @@
///from base of mob/living/carbon/soundbang_act(): (list(intensity))
#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang"
#define COMSIG_CARBON_IDENTITY_TRANSFERRED_TO "carbon_id_transferred_to" //from datum/dna/transfer_identity(): (datum/dna, transfer_SE)
///from /item/organ/proc/Insert() (/obj/item/organ/)
#define COMSIG_CARBON_GAIN_ORGAN "carbon_gain_organ"
///from /item/organ/proc/Remove() (/obj/item/organ/)
@@ -566,6 +568,9 @@
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby"
///Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted)
#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit"
#define COMSIG_HUMAN_PREFS_COPIED_TO "human_prefs_copied_to" //from datum/preferences/copy_to(): (datum/preferences, icon_updates, roundstart_checks)
#define COMSIG_HUMAN_HARDSET_DNA "human_hardset_dna" //from mob/living/carbon/human/hardset_dna(): (ui, se, newreal_name, newblood_type, datum/species, newfeatures)
#define COMSIG_HUMAN_ON_RANDOMIZE "humman_on_randomize" //from base of proc/randomize_human()
///Whenever EquipRanked is called, called after job is set
#define COMSIG_JOB_RECEIVED "job_received"
+7
View File
@@ -187,6 +187,13 @@
#define TRAIT_NEVER_CLONE "donotclone"
#define TRAIT_COLDBLOODED "coldblooded" // Your body is literal room temperature. Does not make you immune to the temp.
#define TRAIT_FLIMSY "flimsy" //you have 20% less maxhealth
//Hyper
#define TRAIT_VIRILE "virile" //you have 20% more chance of impreg
#define TRAIT_MACROPHILE "macrophile" //likes the big
#define TRAIT_MICROPHILE "microphile" //likes the small
#define TRAIT_TOUGH "tough" //you have 10% more maxhealth
#define TRAIT_AUTO_CATCH_ITEM "auto_catch_item"
#define TRAIT_CLOWN_MENTALITY "clown_mentality" // The future is now, clownman.
-11
View File
@@ -104,17 +104,6 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
if(!src.holder) return
message_admins("[key_name_admin(usr)] manually reloaded mentors")
//Flavor Text
/mob/living/carbon/human/verb/set_flavor()
set name = "Set Flavor Text"
set desc = "Sets an extended description of your character's features."
set category = "IC"
var/new_flavor = input(src, "Enter your new flavor text:", "Flavor text", null) as message|null
if(!isnull(new_flavor))
flavor_text = html_encode(new_flavor)
to_chat(src, "Your flavor text has been updated.")
//LOOC toggles
/client/verb/listen_looc()
set name = "Show/Hide LOOC"
+1
View File
@@ -231,6 +231,7 @@
"ipc_screen" = snowflake_ipc_antenna_list ? pick(snowflake_ipc_antenna_list) : "None",
"ipc_antenna" = "None",
"flavor_text" = "",
"silicon_flavor_text" = "",
"ooc_text" = ""))
/proc/random_hair_style(gender)
+16 -5
View File
@@ -163,6 +163,7 @@
set waitfor = FALSE
to_chat(world, "<BR><BR><BR><span class='big bold'>The round has ended.</span>")
var/botmsg = "**The Round has ended!**```Round ID: [GLOB.round_id]\nRound Time: [DisplayTimeText(world.time - SSticker.round_start_time)]\nTotal Population: [GLOB.joined_player_list.len]```"
if(LAZYLEN(GLOB.round_end_notifiees))
send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.")
@@ -179,6 +180,20 @@
var/popcount = gather_roundend_feedback()
display_report(popcount)
CHECK_TICK
//Hyper bot list players
botmsg += "\n**The Crew!** ```"
for(var/p in GLOB.player_list)
var/mob/living/P = p //the living crew members
if(P)
botmsg += "[P.real_name]"
if(P.job)
botmsg += " ([P.job])"
botmsg += "\n"
botmsg += "```"
CHECK_TICK
// Add AntagHUD to everyone, see who was really evil the whole time!
@@ -208,10 +223,6 @@
if(length(CONFIG_GET(keyed_list/cross_server)))
send_news_report()
//tell the nice people on discord what went on before the salt cannon happens.
world.TgsTargetedChatBroadcast("The current round has ended. Please standby for your shift interlude Kinaris News Network's report!", FALSE)
world.TgsTargetedChatBroadcast(send_news_report(),FALSE)
CHECK_TICK
//These need update to actually reflect the real antagonists
@@ -226,7 +237,6 @@
total_antagonists[A.name] += "[key_name(A.owner)]"
CHECK_TICK
//Now print them all into the log!
log_game("Antagonists at round end were...")
for(var/antag_name in total_antagonists)
@@ -243,6 +253,7 @@
SSblackbox.Seal()
sleep(50)
world.hypermessage(botmsg)
ready_for_reboot = TRUE
standard_reboot()
+52 -5
View File
@@ -25,6 +25,12 @@
if(SSparallax.random_layer)
C.parallax_layers_cached += new SSparallax.random_layer
C.parallax_layers_cached += new /obj/screen/parallax_layer/layer_3(null, C.view)
if(SSmapping.config?.map_name == "Layenia Station")
C.parallax_layers_cached += new /obj/screen/parallax_layer/layenia/horizon(null, C.view)
C.parallax_layers_cached += new /obj/screen/parallax_layer/layenia/clouds1(null, C.view)
C.parallax_layers_cached += new /obj/screen/parallax_layer/layenia/clouds2(null, C.view)
C.parallax_layers_cached += new /obj/screen/parallax_layer/layenia/clouds3(null, C.view)
C.parallax_layers = C.parallax_layers_cached.Copy()
@@ -66,24 +72,24 @@
switch(C.prefs.parallax)
if (PARALLAX_INSANE)
C.parallax_throttle = FALSE
C.parallax_layers_max = 5
C.parallax_layers_max = 10
return TRUE
if (PARALLAX_MED)
C.parallax_throttle = PARALLAX_DELAY_MED
C.parallax_layers_max = 3
C.parallax_layers_max = 8
return TRUE
if (PARALLAX_LOW)
C.parallax_throttle = PARALLAX_DELAY_LOW
C.parallax_layers_max = 1
C.parallax_layers_max = 7
return TRUE
if (PARALLAX_DISABLE)
return FALSE
C.parallax_throttle = PARALLAX_DELAY_DEFAULT
C.parallax_layers_max = 4
C.parallax_layers_max = 10
return TRUE
/datum/hud/proc/update_parallax_pref(mob/viewmob)
@@ -320,7 +326,7 @@
blend_mode = BLEND_OVERLAY
absolute = TRUE //Status of seperation
speed = 3
layer = 30
layer = 4
/obj/screen/parallax_layer/planet/update_status(mob/M)
var/client/C = M.client
@@ -331,3 +337,44 @@
/obj/screen/parallax_layer/planet/update_o()
return //Shit wont move
//Layenia parallaxes
/obj/screen/parallax_layer/layenia
icon_state = null
blend_mode = BLEND_OVERLAY
absolute = TRUE
speed = 0.6
layer = 5
/obj/screen/parallax_layer/layenia/horizon
icon_state = "layeniahorizon"
speed = 0.3
absolute = FALSE
/obj/screen/parallax_layer/layenia/clouds1
icon_state = "layenia1"
speed = 0.6
layer = 6
/obj/screen/parallax_layer/layenia/clouds2
icon_state = "layenia2"
speed = 1
layer = 7
/obj/screen/parallax_layer/layenia/clouds3
icon_state = "layenia3"
speed = 1.4
layer = 8
/obj/screen/parallax_layer/layenia/update_status(mob/M)
var/client/C = M.client
var/turf/posobj = get_turf(C.eye)
if(!posobj)
return
invisibility = is_station_level(posobj.z) ? 0 : INVISIBILITY_ABSTRACT
/*
/obj/screen/parallax_layer/tparallax1/update_status(mob/M)
if(SSmapping.config?.map_name != "Layenia Station")
*/
+3 -1
View File
@@ -454,7 +454,9 @@ SUBSYSTEM_DEF(job)
to_chat(M, "<b>[job.custom_spawn_text]</b>")
if(CONFIG_GET(number/minimal_access_threshold))
to_chat(M, "<span class='notice'><B>As this station was initially staffed with a [CONFIG_GET(flag/jobs_have_minimal_access) ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card.</B></span>")
job.after_spawn(H, M, joined_late)
//Account ID. ID is handled by human initialization
if(ishuman(H))
var/mob/living/carbon/human/wageslave = H
+1 -1
View File
@@ -38,7 +38,7 @@
/datum/component/chasm/proc/is_safe()
//if anything matching this typecache is found in the chasm, we don't drop things
var/static/list/chasm_safeties_typecache = typecacheof(list(/obj/structure/lattice/catwalk, /obj/structure/stone_tile))
var/static/list/chasm_safeties_typecache = typecacheof(list(/obj/structure/lattice/catwalk, /obj/structure/lattice, /obj/structure/stone_tile))
var/atom/parent = src.parent
var/list/found_safeties = typecache_filter_list(parent.contents, chasm_safeties_typecache)
+6
View File
@@ -46,6 +46,12 @@
//begin playsound shenanigans//
//for big characters, add alittle boom
if(LM.size_multiplier > 1.5)
var/stompsound = pick( 'sound/effects/footstep/giant1.ogg','sound/effects/footstep/giant2.ogg')
var/giantvolume = LM.size_multiplier * 9
playsound(T, stompsound, giantvolume)
//for barefooted non-clawed mobs like monkeys
if(isbarefoot(LM))
playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
+2
View File
@@ -12,6 +12,7 @@
var/insanity_effect = 0 //is the owner being punished for low mood? If so, how much?
var/holdmyinsanityeffect = 0 //before we edit our sanity lets take a look
var/obj/screen/mood/screen_obj
var/lastupdate = 0
/datum/component/mood/Initialize()
if(!isliving(parent))
@@ -91,6 +92,7 @@
mood += event.mood_change
if(!event.hidden)
shown_mood += event.mood_change
mood *= mood_modifier
shown_mood *= mood_modifier
+5 -2
View File
@@ -54,11 +54,12 @@
if(ishuman(destination))
var/mob/living/carbon/human/H = destination
H.give_genitals(TRUE)//This gives the body the genitals of this DNA. Used for any transformations based on DNA
destination.flavor_text = destination.dna.features["flavor_text"] //Update the flavor_text to use new dna text
destination.ooc_text = destination.dna.features["ooc_text"] //Update the flavor_text to use new dna text
if(transfer_SE)
destination.dna.mutation_index = mutation_index
SEND_SIGNAL(destination, COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, src, transfer_SE)
/datum/dna/proc/copy_dna(datum/dna/new_dna)
new_dna.unique_enzymes = unique_enzymes
new_dna.mutation_index = mutation_index
@@ -356,7 +357,6 @@
if(newfeatures)
dna.features = newfeatures
flavor_text = dna.features["flavor_text"] //Update the flavor_text to use new dna text
ooc_text = dna.features["ooc_text"] //Update the flavor_text to use new dna text
if(mrace)
@@ -379,6 +379,9 @@
dna.mutation_index = mutation_index
domutcheck()
SEND_SIGNAL(src, COMSIG_HUMAN_HARDSET_DNA, ui, newreal_name, newblood_type, mrace, newfeatures)
// change to SEND_SIGNAL(src, COMSIG_HUMAN_HARDSET_DNA, ui, se, newreal_name, newblood_type, mrace, newfeatures) if we add structural enzymes.
if(mrace || newfeatures || ui)
update_body()
update_hair()
+188
View File
@@ -0,0 +1,188 @@
GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
/datum/element/flavor_text
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
id_arg_index = 3
var/flavor_name = "Flavor Text"
var/list/texts_by_atom = list()
var/addendum = ""
var/always_show = FALSE
var/max_len = MAX_FLAVOR_LEN
var/can_edit = TRUE
/// For preference/DNA saving/loading. Null to prevent. Prefs are only loaded from obviously if it exists in preferences.features.
var/save_key
/// Do not attempt to render a preview on examine. If this is on, it will display as \[flavor_name\]
var/examine_no_preview = FALSE
var/examineTabOutput = ""
/datum/element/flavor_text/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FLAVOR_LEN, _always_show = FALSE, _edit = TRUE, _save_key, _examine_no_preview = FALSE)
. = ..()
if(. == ELEMENT_INCOMPATIBLE || !isatom(target)) //no reason why this shouldn't work on atoms too.
return ELEMENT_INCOMPATIBLE
if(_max_len)
max_len = _max_len
texts_by_atom[target] = copytext(text, 1, max_len)
if(_name)
flavor_name = _name
if(!isnull(addendum))
addendum = _addendum
always_show = _always_show
can_edit = _edit
save_key = _save_key
examine_no_preview = _examine_no_preview
RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/show_flavor)
if(can_edit && ismob(target)) //but only mobs receive the proc/verb for the time being
var/mob/M = target
LAZYOR(GLOB.mobs_with_editable_flavor_text[M], src)
M.verbs |= /mob/proc/manage_flavor_tests
if(save_key && ishuman(target))
RegisterSignal(target, COMSIG_HUMAN_PREFS_COPIED_TO, .proc/update_prefs_flavor_text)
/datum/element/flavor_text/Detach(atom/A)
. = ..()
UnregisterSignal(A, list(COMSIG_PARENT_EXAMINE, COMSIG_HUMAN_PREFS_COPIED_TO))
texts_by_atom -= A
if(can_edit && ismob(A))
var/mob/M = A
LAZYREMOVE(GLOB.mobs_with_editable_flavor_text[M], src)
if(!GLOB.mobs_with_editable_flavor_text[M])
GLOB.mobs_with_editable_flavor_text -= M
M.verbs -= /mob/proc/manage_flavor_tests
/datum/element/flavor_text/proc/show_flavor(atom/target, mob/user, list/examine_list)
if(!always_show && isliving(target))
var/mob/living/L = target
var/unknown = L.get_visible_name() == "Unknown"
if(!unknown && iscarbon(target))
var/mob/living/carbon/C = L
unknown = (C.wear_mask && (C.wear_mask.flags_inv & HIDEFACE)) || (C.head && (C.head.flags_inv & HIDEFACE))
if(unknown)
if(!("...?" in examine_list)) //can't think of anything better in case of multiple flavor texts.
examine_list += "...?"
return
var/text = texts_by_atom[target]
if(!text)
return
if(examine_no_preview)
examine_list += "<span class='notice'><a href='?src=[REF(src)];show_flavor=[REF(target)]'>\[[flavor_name]\]</a></span>"
return
var/msg = replacetext(text, "\n", " ")
if(length_char(msg) <= 40)
examine_list += "<span class='notice'>[msg]</span>"
else
examine_list += "<span class='notice'>[copytext_char(msg, 1, 37)]... <a href='?src=[REF(src)];show_flavor=[REF(target)]'>More...</span></a>"
//Examine Tab stuff - Hyperstation
examineTabOutput = "<center>"
if(ishuman(target)) //user just returned, y'know, the user's own species. dumb.
var/mob/living/carbon/human/L = target
if(L.gender)
examineTabOutput += "[icon2html('hyperstation/icons/chat/gender.dmi', world, L.gender)]"
examineTabOutput += "[L.name] "
examineTabOutput += "([L.dna.custom_species ? L.dna.custom_species : L.dna.species.name])"
examineTabOutput += "</center>"
examineTabOutput += "<br>[url_encode(msg)]"
if(ismob(target))
var/mob/M = target
if(M.ooc_text)
examineTabOutput += "<br><br><i><b>OOC</b>"
examineTabOutput += "<br>[url_encode(M.ooc_text)]"
user.client << output(examineTabOutput, "statbrowser:update_examine") //open the examine window
user.client << output(null, "statbrowser:create_mobexamine") //open the examine window
/datum/element/flavor_text/Topic(href, href_list)
. = ..()
if(.)
return
if(href_list["show_flavor"])
var/atom/target = locate(href_list["show_flavor"])
var/text = texts_by_atom[target]
if(text)
usr << browse("<HTML><HEAD><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><TITLE>[target.name]</TITLE></HEAD><BODY><TT>[replacetext(texts_by_atom[target], "\n", "<BR>")]</TT></BODY></HTML>", "window=[target.name];size=500x200")
onclose(usr, "[target.name]")
return TRUE
/mob/proc/manage_flavor_tests()
set name = "Manage Flavor Texts"
set desc = "Used to manage your various flavor texts."
set category = "IC"
var/list/L = GLOB.mobs_with_editable_flavor_text[src]
if(length(L) == 1)
var/datum/element/flavor_text/F = L[1]
F.set_flavor(src)
return
var/list/choices = list()
for(var/i in L)
var/datum/element/flavor_text/F = i
choices[F.flavor_name] = F
var/chosen = input(src, "Which flavor text would you like to modify?") as null|anything in choices
if(!chosen)
return
var/datum/element/flavor_text/F = choices[chosen]
F.set_flavor(src)
/datum/element/flavor_text/proc/set_flavor(mob/user)
if(!(user in texts_by_atom))
return FALSE
var/lower_name = lowertext(flavor_name)
var/new_text = stripped_multiline_input(user, "Set the [lower_name] displayed on 'examine'. [addendum]", flavor_name, html_decode(texts_by_atom[usr]), max_len, TRUE)
if(!isnull(new_text) && (user in texts_by_atom))
texts_by_atom[user] = new_text
to_chat(src, "Your [lower_name] has been updated.")
return TRUE
return FALSE
/datum/element/flavor_text/proc/update_prefs_flavor_text(mob/living/carbon/human/H, datum/preferences/P, icon_updates = TRUE, roundstart_checks = TRUE)
if(P.features.Find(save_key))
texts_by_atom[H] = P.features[save_key]
//subtypes with additional hooks for DNA and preferences.
/datum/element/flavor_text/carbon
//list of antagonists etcetera that should have nothing to do with people's snowflakes.
var/static/list/i_dont_even_know_who_you_are = typecacheof(list(/datum/antagonist/abductor, /datum/antagonist/ert,
/datum/antagonist/nukeop, /datum/antagonist/wizard))
/datum/element/flavor_text/carbon/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FLAVOR_LEN, _always_show = FALSE, _edit = TRUE, _save_key = "flavor_text", _examine_no_preview = FALSE)
if(!iscarbon(target))
return ELEMENT_INCOMPATIBLE
. = ..()
if(. == ELEMENT_INCOMPATIBLE)
return
RegisterSignal(target, COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, .proc/update_dna_flavor_text)
RegisterSignal(target, COMSIG_MOB_ANTAG_ON_GAIN, .proc/on_antag_gain)
if(ishuman(target))
RegisterSignal(target, COMSIG_HUMAN_HARDSET_DNA, .proc/update_dna_flavor_text)
RegisterSignal(target, COMSIG_HUMAN_ON_RANDOMIZE, .proc/unset_flavor)
/datum/element/flavor_text/carbon/Detach(mob/living/carbon/C)
. = ..()
UnregisterSignal(C, list(COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, COMSIG_MOB_ANTAG_ON_GAIN, COMSIG_HUMAN_PREFS_COPIED_TO, COMSIG_HUMAN_HARDSET_DNA, COMSIG_HUMAN_ON_RANDOMIZE))
/datum/element/flavor_text/carbon/proc/update_dna_flavor_text(mob/living/carbon/C)
texts_by_atom[C] = C.dna.features[save_key]
/datum/element/flavor_text/carbon/set_flavor(mob/living/carbon/user)
. = ..()
if(. && user.dna)
user.dna.features[save_key] = texts_by_atom[user]
/datum/element/flavor_text/carbon/proc/unset_flavor(mob/living/carbon/user)
texts_by_atom[user] = ""
/datum/element/flavor_text/carbon/proc/on_antag_gain(mob/living/carbon/user, datum/antagonist/antag)
if(is_type_in_typecache(antag, i_dont_even_know_who_you_are))
texts_by_atom[user] = ""
if(user.dna)
user.dna.features[save_key] = ""
+6
View File
@@ -312,3 +312,9 @@
suffix = "advancedlab.dmm"
name = "Abductor Replication Lab"
description = "Some scientists tried and almost succeeded to recreate abductor tools. Somewhat slower and a bit less modern than their originals, these tools are the best you can get if you aren't an alien."
/datum/map_template/ruin/space/wiz_home
id = "wizhome"
suffix = "wizardden.dmm"
name = "Wizards Cabin"
description = "The wooden cabin of a wizard in space, it smells like mana in there."
@@ -0,0 +1,36 @@
/datum/weather/ash_storm/layenia //because fuck writing my own code
name = "Layenia Weather"
desc = "A subset of weather affecting Layenia"
weather_color = "white"
telegraph_message = "<span class='warning'>Thundering clouds pass overhead, swept up by a steady wind.</span>"
telegraph_duration = 300
telegraph_overlay = "light_snow"
weather_message = "<span class='boldwarning'><i>Clouds storm over the station slowly...</i></span>"
weather_duration_lower = 600
weather_duration_upper = 8200
weather_overlay = "snow_storm"
end_message = "<span class='boldannounce'>Sunlight arches over the station once more; the storm has passed.</span>"
end_duration = 300
end_overlay = "light_snow"
area_type = /area/layenia
target_trait = ZTRAIT_STATION
probability = 100
barometer_predictable = TRUE
aesthetic = TRUE
//datum/weather/layenia/telegraph()
//datum/weather/layenia/start()
//datum/weather/layenia/wind_down()
//datum/weather/layenia/end()
//datum/weather/ash_storm/layenia/weather_act
+4
View File
@@ -1380,3 +1380,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Nothing Here"
icon_state = "yellow"
ambientsounds = SPOOKY
/area/arcade
name = "Arcade"
icon_state = "yellow"
+1
View File
@@ -53,6 +53,7 @@
*/
/area/holodeck/rec_center
name = "\improper Recreational Holodeck"
has_gravity = STANDARD_GRAVITY
/area/holodeck/rec_center/offline
name = "Holodeck - Offline"
+29
View File
@@ -0,0 +1,29 @@
area/layenia
name = "Layenia"
icon_state = "mining"
has_gravity = STANDARD_GRAVITY
blob_allowed = FALSE
requires_power = TRUE
outdoors = TRUE
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
ambientsounds = MINING
atmos = FALSE
flags_1 = NONE
area/layenia/cloudlayer
name = "Laneya clouds"
icon_state = "space"
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
atmos = FALSE
area/layenia/powered
name = "Layenia Powered"
icon_state = "centcom"
requires_power = FALSE
has_gravity = STANDARD_GRAVITY
noteleport = FALSE
blob_allowed = TRUE
flags_1 = NONE
outdoors = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
atmos = FALSE
+2 -2
View File
@@ -58,8 +58,8 @@
/area/ruin/space/has_grav/powered/cat_man
name = "Kitty Den"
/area/ruin/space/has_grav/powered/wiz_home/area/ruin/space/has_grav/powered/wiz_home
name = "Wizard's Cabin"
/area/ruin/space/has_grav/powered/wiz_home
name = "Wizards Cabin"
/area/ruin/space/has_grav/powered/authorship
name = "Authorship"
@@ -15,6 +15,12 @@
var/list/list_observers = list()
/datum/dynamic_ruleset/event/acceptable(population=0, threat=0)
if(istype(controller, /datum/round_event_control))
var/datum/round_event_control/R = controller
if(R.map_blacklist.len && (SSmapping.config.map_file in R.map_blacklist)) //Apparently dynamic doesn't call a controller's canSpawnEvent :>
return FALSE
if(R.map_whitelist.len && !(SSmapping.config.map_file in R.map_whitelist))
return FALSE
return ..()
/datum/dynamic_ruleset/event/ready(forced = 0)
+15 -5
View File
@@ -133,6 +133,7 @@
/obj/machinery/door/airlock/LateInitialize()
. = ..()
autorotation() //auto rotate door
if (cyclelinkeddir)
cyclelinkairlock()
if(abandoned)
@@ -159,11 +160,20 @@
update_icon()
/obj/machinery/door/airlock/proc/getrotation() //for auto rotating doors, because im sick of doing it
for(var/turf/O in get_step(src,SOUTH))
log_mapping("[src]: [O]")
if(O.density)
log_mapping("[src]: [O] is dense")
/obj/machinery/door/airlock/proc/autorotation() //for auto rotating doors, because im sick of doing it
var/turf/N = get_step(src, NORTH)
var/turf/S = get_step(src, SOUTH)
if(istype(N, /turf/closed)) //Wall
dir = 4
if(istype(S, /turf/closed))
dir = 4
var/obj/structure/window/W = locate(/obj/structure/window, N) //Window
if(W)
dir = 4
var/obj/structure/window/R = locate(/obj/structure/window, S)
if(R)
dir = 4
/obj/machinery/door/airlock/ComponentInitialize()
. = ..()
@@ -350,7 +350,10 @@
icon = 'icons/obj/doors/airlocks/external/external.dmi'
overlays_file = 'icons/obj/doors/airlocks/external/overlays.dmi'
note_overlay_file = 'icons/obj/doors/airlocks/external/overlays.dmi'
color_overlay_file = 'icons/obj/doors/airlocks/external/color.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_ext
basecolor = "#ff0000" //red
/obj/machinery/door/airlock/external/glass
opacity = 0
@@ -319,6 +319,9 @@
new R(src)
revealed = TRUE
/obj/item/storage/backpack/satchel/flat/secret/chloe_ruin
reward_one_of_these = list(/obj/item/book/granter/spell/summonitem, /obj/item/book_of_babel)
/obj/item/storage/backpack/duffelbag
name = "duffel bag"
desc = "A large duffel bag for holding extra things."
+57
View File
@@ -656,3 +656,60 @@
if(islist(icon_states && icon_states.len))
icon_state = pick(icon_states)
/obj/structure/flora/crystal
name = "crystal"
desc = "You shouldnt see this!"
gender = PLURAL //trans rights
max_integrity = 30
/obj/structure/flora/crystal/small
name = "small crystals"
icon = 'icons/obj/flora/layeniasmall.dmi'
light_range = 2
light_power = 0.25
light_color = LIGHT_COLOR_BLUE
//Small crystal clusters
/obj/structure/flora/crystal/small/pile
name = "small crystals"
desc = "A pile of small crystals"
icon_state = "crystals"
/obj/structure/flora/crystal/small/pile/Initialize()
if(icon_state == "crystals")
icon_state = "crystals[rand(1, 4)]"
. = ..()
//Small crystal growths
/obj/structure/flora/crystal/small/growth
name = "small crystals"
desc = "A growth of small crystals"
icon_state = "crystalgrowth"
/obj/structure/flora/crystal/small/growth/Initialize()
if(icon_state == "crystalgrowth")
icon_state = "crystalgrowth[rand(1, 4)]"
. = ..()
/obj/structure/flora/crystal/medium
name = "medium crystals"
icon = 'icons/obj/flora/layeniamedium.dmi'
pixel_x = -16
pixel_y = -3
layer = ABOVE_ALL_MOB_LAYER
light_range = 4
light_power = 0.75
light_color = LIGHT_COLOR_BLUE
//Medium crystal growths
/obj/structure/flora/crystal/medium/growth
name = "medium crystals"
desc = "A growth of medium crystals"
icon_state = "crystalgrowth"
/obj/structure/flora/crystal/medium/growth/Initialize()
if(icon_state == "crystalgrowth")
icon_state = "crystalgrowth[rand(1, 3)]"
. = ..()
+2
View File
@@ -15,7 +15,9 @@
/turf/closed/wall,
/obj/structure/falsewall)
smooth = SMOOTH_MORE
obj_flags = BLOCK_Z_FALL
// flags = CONDUCT_1
//planetary_atmos = TRUE
/obj/structure/lattice/examine(mob/user)
. = ..()
+41
View File
@@ -74,6 +74,19 @@
if(istype(AM))
playsound(src,sound,50,1)
/turf/open/indestructible/concrete
name = "concrete"
icon = 'icons/turf/floors.dmi'
icon_state = "concrete"
baseturfs = /turf/open/floor/plating/asteroid/layenia
initial_gas_mix = FROZEN_ATMOS
planetary_atmos = TRUE
/turf/open/indestructible/concrete/smooth
icon_state = "concrete2"
initial_gas_mix = FROZEN_ATMOS
planetary_atmos = TRUE
/turf/open/indestructible/cobble/side
icon_state = "cobble_side"
@@ -92,6 +105,27 @@
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
tiled_dirt = FALSE
/turf/open/indestructible/layenia/crystal
name = "Lattice Crystal"
desc = "A glowing azure crystal, with strange properties to make things float."
icon = 'icons/turf/floors/crystal_floor.dmi'
baseturfs = /turf/open/indestructible/layenia/crystal
slowdown = 1
light_range = 4
light_power = 0.5
barefootstep = FOOTSTEP_HARD_BAREFOOT
clawfootstep = FOOTSTEP_HARD_CLAW
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
light_color = LIGHT_COLOR_BLUE
initial_gas_mix = FROZEN_ATMOS
planetary_atmos = TRUE
smooth = SMOOTH_TRUE | SMOOTH_BORDER | SMOOTH_MORE
canSmoothWith = list(/turf/open/indestructible/layenia/crystal)
/turf/open/indestructible/layenia/crystal/garden
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
planetary_atmos = TRUE
/turf/open/indestructible/necropolis
name = "necropolis floor"
desc = "It's regarding you suspiciously."
@@ -208,6 +242,13 @@
//testing("Active turf found. Return value of compare(): [is_active]")
excited = TRUE
SSair.active_turfs |= src
//Issues with air runtiming and you don't know where? Uncomment the following code.
/*
if(air == null)
log_game("Bad air from [src] at [src.loc]")
if(enemy_air == null)
log_game("Bad air from [enemy_tile] at [enemy_tile.loc]")
*/
/turf/open/proc/GetHeatCapacity()
. = air.heat_capacity()
+22
View File
@@ -115,3 +115,25 @@
var/turf/T = safepick(get_area_turfs(/area/fabric_of_reality))
if(T)
set_target(T)
/turf/open/chasm/cloud
name = "clouds"
gender = PLURAL
desc = "Clouds as far as the eye can see... Watch your step."
icon = 'icons/turf/space.dmi'
icon_state = "0"
plane = PLANE_SPACE
tiled_dirt = FALSE
baseturfs = /turf/open/chasm/cloud
smooth = SMOOTH_FALSE
initial_gas_mix = FROZEN_ATMOS
/turf/open/chasm/cloud/Initialize()
. = ..()
icon_state = SPACE_ICON_STATE
/turf/open/chasm/cloud/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = 'icons/turf/space.dmi'
underlay_appearance.icon_state = SPACE_ICON_STATE
underlay_appearance.plane = PLANE_SPACE
return TRUE
@@ -19,13 +19,14 @@
attachment_holes = FALSE
var/obj/item/stack/digResult = /obj/item/stack/ore/glass/basalt
var/dug
var/quantity_of_available_tiles = 12 //How many sprites do you have in the DMI? Note, consider tile 0. 12 here means = 13 titles. 13 tiles is the golden standard.
/turf/open/floor/plating/asteroid/Initialize()
var/proper_name = name
. = ..()
name = proper_name
if(prob(floor_variance))
icon_state = "[environment_type][rand(0,12)]"
icon_state = "[environment_type][rand(0,quantity_of_available_tiles)]"
/turf/open/floor/plating/asteroid/proc/getDug()
new digResult(src, 5)
@@ -363,3 +364,42 @@
/turf/open/floor/plating/asteroid/snow/atmosphere
initial_gas_mix = FROZEN_ATMOS
planetary_atmos = FALSE
//Layenia stuff
/turf/open/floor/plating/asteroid/layenia
gender = PLURAL //trans rights
name = "crimson Rock"
desc = "A cold rock, rusted scarlet in color."
icon = 'icons/turf/floors.dmi'
baseturfs = /turf/open/floor/plating/asteroid/layenia
icon_state = "layenia"
icon_plating = "layenia"
initial_gas_mix = FROZEN_ATMOS
slowdown = 1
environment_type = "layenia"
flags_1 = NONE
planetary_atmos = TRUE
burnt_states = null
bullet_sizzle = TRUE
bullet_bounce_sound = null
digResult = /obj/item/stack/ore/glass/basalt
floor_variance = 50 //This means 50% chance of variating from the default tile.
quantity_of_available_tiles = 4
//light_range = 2
//light_power = 0.15
//light_color = LIGHT_COLOR_WHITE
/turf/open/floor/plating/asteroid/layenia/Initialize()
. = ..()
//We no longer randomize the icon state here. That is done by the supercall in our parent, asteroid.
set_layenia_light(src)
/turf/open/floor/plating/asteroid/layenia/garden
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
planetary_atmos = TRUE
/proc/set_layenia_light(turf/open/floor/B)
switch(B.icon_state)
if("layenia3", "layenia4")
B.set_light(2, 0.6, LIGHT_COLOR_BLUE) //more light
@@ -240,5 +240,3 @@
/turf/open/floor/plating/snowed/temperatre
temperature = 255.37
+13 -1
View File
@@ -522,4 +522,16 @@
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
defer_change = 1
/turf/closed/mineral/layenia
name = "Crimson rock"
icon = 'icons/turf/mining.dmi'
smooth_icon = 'icons/turf/layeniarocks.dmi'
icon_state = "layenia"
smooth = SMOOTH_MORE|SMOOTH_BORDER
canSmoothWith = null
baseturfs = /turf/open/floor/plating/asteroid/layenia
initial_gas_mix = FROZEN_ATMOS
environment_type = "layenia"
turf_type = /turf/open/floor/plating/asteroid/layenia
+1
View File
@@ -72,6 +72,7 @@ GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
/client/proc/panicbunker,
/client/proc/addbunkerbypass,
/client/proc/discordmessage,
/client/proc/revokebunkerbypass,
/client/proc/stop_sounds,
/client/proc/debugstatpanel,
+4 -1
View File
@@ -37,7 +37,10 @@
H.dna.features["moth_wings"] = pick(GLOB.moth_wings_list)
H.dna.features["moth_fluff"] = pick(GLOB.moth_fluffs_list)
H.dna.features["deco_wings"] = pick(GLOB.deco_wings_list)
H.dna.features["flavor_text"] = "" //Oh no.
SEND_SIGNAL(H, COMSIG_HUMAN_ON_RANDOMIZE)
H.update_body()
H.update_hair()
H.update_body_parts()
H.update_body_parts()
@@ -72,6 +72,7 @@ GLOBAL_LIST_EMPTY(antagonists)
give_antag_moodies()
if(is_banned(owner.current) && replace_banned)
replace_banned_player()
SEND_SIGNAL(owner.current, COMSIG_MOB_ANTAG_ON_GAIN, src)
/datum/antagonist/proc/is_banned(mob/M)
if(!M)
@@ -134,6 +134,9 @@
else
to_chat(user, status())
/obj/machinery/meter/attack_ghost(mob/user)
to_chat(user, status())
/obj/machinery/meter/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
@@ -141,6 +144,7 @@
// TURF METER - REPORTS A TILE'S AIR CONTENTS
// why are you yelling?
// i hope they aren't mad
/obj/machinery/meter/turf
/obj/machinery/meter/turf/reattach_to_layer()
@@ -377,6 +377,17 @@
air_update_turf() // Update the environment if needed.
update_icon()
/obj/machinery/portable_atmospherics/canister/attack_ghost(mob/user)
if(user.client)
if(IsAdminGhost(user))
attack_ai(user)
return FALSE
else if(user.client.prefs.inquisitive_ghost)
user.examinate(src)
return FALSE
atmosanalyzer_scan(air_contents, user, src, FALSE)
return FALSE
/obj/machinery/portable_atmospherics/canister/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)
+18
View File
@@ -181,6 +181,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
"ipc_screen" = "Sunburst",
"ipc_antenna" = "None",
"flavor_text" = "",
"silicon_flavor_text" = "",
"ooc_text" = ""
)
@@ -395,6 +396,15 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "[features["flavor_text"]]"
else
dat += "[TextPreview(features["flavor_text"])]...<BR>"
dat += "<h2>Silicon Flavor Text</h2>"
dat += "<a href='?_src_=prefs;preference=silicon_flavor_text;task=input'><b>Set Silicon Examine Text</b></a><br>"
if(length(features["silicon_flavor_text"]) <= 40)
if(!length(features["silicon_flavor_text"]))
dat += "\[...\]"
else
dat += "[features["silicon_flavor_text"]]"
else
dat += "[TextPreview(features["silicon_flavor_text"])]...<BR>"
dat += "<h2>OOC Text</h2>"
dat += "<a href='?_src_=prefs;preference=ooc_text;task=input'><b>Set OOC Text</b></a><br>"
if(length(features["ooc_text"]) <= 40)
@@ -1747,6 +1757,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
msg = msg
features["flavor_text"] = msg
if("silicon_flavor_text")
var/msg = stripped_multiline_input(usr, "Set the silicon flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Silicon Flavor Text", features["silicon_flavor_text"], MAX_FLAVOR_LEN, TRUE)
if(msg)
msg = msg
features["silicon_flavor_text"] = msg
if("ooc_text")
var/msg = stripped_multiline_input(usr, "Set the OOC text in your 'examine' verb. This should be OOC only!", "OOC Text", html_decode(features["ooc_text"]), MAX_MESSAGE_LEN, TRUE)
if(msg)
@@ -2790,6 +2806,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else
character.Digitigrade_Leg_Swap(TRUE)
SEND_SIGNAL(character, COMSIG_HUMAN_PREFS_COPIED_TO, src, icon_updates, roundstart_checks)
//speech stuff
if(custom_tongue != "default")
var/new_tongue = GLOB.roundstart_tongues[custom_tongue]
@@ -436,6 +436,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
else //We have no old flavortext, default to new
S["feature_flavor_text"] >> features["flavor_text"]
S["feature_silicon_flavor_text"] >> features["silicon_flavor_text"]
if((S["ooc_text"] != "") && (S["ooc_text"] != null) && S["ooc_text"])
S["ooc_text"] >> features["ooc_text"]
@@ -513,6 +514,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")
features["flavor_text"] = copytext(features["flavor_text"], 1, MAX_FLAVOR_LEN)
features["silicon_flavor_text"] = copytext(features["silicon_flavor_text"], 1, MAX_FLAVOR_LEN)
joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole))
job_civilian_high = sanitize_integer(job_civilian_high, 0, 65535, initial(job_civilian_high))
job_civilian_med = sanitize_integer(job_civilian_med, 0, 65535, initial(job_civilian_med))
@@ -796,6 +796,7 @@
item_color = "greenplaidshirt"
body_parts_covered = CHEST|GROIN|ARMS|LEGS
can_adjust = FALSE
fitted = NO_FEMALE_UNIFORM
//yes
//Enzo_Leon patron stuff
+1
View File
@@ -4,6 +4,7 @@
max_occurrences = 1
weight = 4
earliest_start = 5 MINUTES
map_blacklist = list("LayeniaStation.dmm")
/datum/round_event_control/aurora_caelus/canSpawnEvent(players, gamemode)
if(!CONFIG_GET(flag/starlight))
+1
View File
@@ -5,6 +5,7 @@
min_players = 5 //increased min players from 2 to 5 to reduce chances of half the crew dying in a carp breach
earliest_start = 10 MINUTES
max_occurrences = 6
map_blacklist = list("LayeniaStation.dmm")
/datum/round_event/carp_migration
announceWhen = 3
+1
View File
@@ -3,6 +3,7 @@
typepath = /datum/round_event/meteor_wave/meaty
weight = 2
max_occurrences = 1
map_blacklist = list("LayeniaStation.dmm")
/datum/round_event/meteor_wave/meaty
wave_name = "meaty"
+1
View File
@@ -10,6 +10,7 @@
min_players = 20
max_occurrences = 3
earliest_start = 25 MINUTES
map_blacklist = list("LayeniaStation.dmm")
/datum/round_event/meteor_wave
startWhen = 6
+1 -1
View File
@@ -14,7 +14,7 @@
return ..()
/datum/round_event/pirates
startWhen = 60 //2 minutes to answer
startWhen = 300 //5 minutes to answer
var/datum/comm_message/threat
var/payoff = 0
var/paid_off = FALSE
+2 -1
View File
@@ -3,6 +3,7 @@
typepath = /datum/round_event/grey_tide
max_occurrences = 2
min_players = 5
map_blacklist = list("LayeniaStation.dmm")
/datum/round_event/grey_tide
announceWhen = 50
@@ -67,4 +68,4 @@
temp.prison_open()
else if(istype(O, /obj/machinery/door_timer))
var/obj/machinery/door_timer/temp = O
temp.timer_end(forced = TRUE)
temp.timer_end(forced = TRUE)
+1
View File
@@ -4,6 +4,7 @@
max_occurrences = 3
weight = 2
min_players = 2
map_blacklist = list("LayeniaStation.dmm")
/datum/round_event/wormholes
@@ -23,7 +23,7 @@
/obj/machinery/gibber/RefreshParts()
var/gib_time = 40
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
meat_produced += B.rating
meat_produced += 1.6 * B.rating
for(var/obj/item/stock_parts/manipulator/M in component_parts)
gib_time -= 5 * M.rating
gibtime = gib_time
@@ -1,6 +1,8 @@
GLOBAL_LIST_EMPTY(monkey_recyclers)
/obj/machinery/monkey_recycler
name = "monkey recycler"
desc = "A machine used for recycling dead monkeys into monkey cubes. It currently produces 1 cube for every 5 monkeys inserted." // except it literally never does
desc = "A machine used for recycling dead monkeys into monkey cubes. You can use a multitool to link it to a xenobiology console. It currently produces 0.2 cubes for every monkey inserted."
icon = 'icons/obj/kitchen.dmi'
icon_state = "grinder"
layer = BELOW_OBJ_LAYER
@@ -9,20 +11,29 @@
idle_power_usage = 5
active_power_usage = 50
circuit = /obj/item/circuitboard/machine/monkey_recycler
var/grinded = 0
var/required_grind = 5
var/cube_production = 1
var/stored_matter = 0
var/cube_production = 0.2
var/list/connected = list() //Xenobio consoles
/obj/machinery/monkey_recycler/Initialize(mapload)
. = ..()
GLOB.monkey_recyclers += src
/obj/machinery/monkey_recycler/RefreshParts()
var/req_grind = 5
var/cubes_made = 1
/obj/machinery/monkey_recycler/Destroy()
if(src in GLOB.monkey_recyclers)
GLOB.monkey_recyclers -= src
for(var/obj/machinery/computer/camera_advanced/xenobio/C in connected)
var/obj/machinery/computer/camera_advanced/xenobio/console = C
console.connected_recycler = null
return ..()
/obj/machinery/monkey_recycler/RefreshParts() //Ranges from 0.2 to 0.8 per monkey recycled
cube_production = 0
for(var/obj/item/stock_parts/manipulator/B in component_parts)
req_grind -= B.rating
cube_production += B.rating * 0.1
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
cubes_made = M.rating
cube_production = cubes_made
required_grind = req_grind
src.desc = "A machine used for recycling dead monkeys into monkey cubes. It currently produces [cubes_made] cube(s) for every [required_grind] monkey(s) inserted."
cube_production += M.rating * 0.1
desc = "A machine used for recycling dead monkeys into monkey cubes. You can use a multitool to link it to a xenobiology console. It currently produces [cube_production] cubes for every monkey inserted."
/obj/machinery/monkey_recycler/attackby(obj/item/O, mob/user, params)
if(default_deconstruction_screwdriver(user, "grinder_open", "grinder", O))
@@ -64,17 +75,23 @@
var/offset = prob(50) ? -2 : 2
animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 200) //start shaking
use_power(500)
grinded++
stored_matter += cube_production
addtimer(VARSET_CALLBACK(src, pixel_x, initial(pixel_x)))
addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, user, "<span class='notice'>The machine now has [grinded] monkey\s worth of material stored.</span>"))
addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, user, "<span class='notice'>The machine now has [stored_matter] monkey\s worth of material stored.</span>"))
/obj/machinery/monkey_recycler/interact(mob/user)
if(grinded >= required_grind)
to_chat(user, "<span class='notice'>The machine hisses loudly as it condenses the grinded monkey meat. After a moment, it dispenses a brand new monkey cube.</span>")
if(stored_matter >= 1)
to_chat(user, "<span class='notice'>The machine hisses loudly as it condenses the ground monkey meat. After a moment, it dispenses a brand new monkey cube.</span>")
playsound(src.loc, 'sound/machines/hiss.ogg', 50, 1)
grinded -= required_grind
for(var/i = 0, i < cube_production, i++)
new /obj/item/reagent_containers/food/snacks/monkeycube(src.loc)
to_chat(user, "<span class='notice'>The machine's display flashes that it has [grinded] monkeys worth of material left.</span>")
for(var/i in 1 to max(stored_matter, 1))
new /obj/item/reagent_containers/food/snacks/monkeycube(loc)
stored_matter--
to_chat(user, "<span class='notice'>The machine's display flashes that it has [stored_matter] monkeys worth of material left.</span>")
else
to_chat(user, "<span class='danger'>The machine needs at least [required_grind] monkey(s) worth of material to produce a monkey cube. It only has [grinded].</span>")
to_chat(user, "<span class='danger'>The machine needs at least 1 monkey worth of material to produce a monkey cube. It currently has [stored_matter].</span>")
/obj/machinery/monkey_recycler/multitool_act(mob/living/user, obj/item/multitool/I)
if(istype(I))
to_chat(user, "<span class='notice'>You log [src] in the multitool's buffer.</span>")
I.buffer = src
return TRUE
+1 -1
View File
@@ -368,7 +368,7 @@
C.reagents.add_reagent(/datum/reagent/fermi/eigenstate, 30)
if(5)
visible_message("<b>[src]</b> waves their arms around, <span class='spooky'>\"A new familiar for me, and you'll see it's thee!\"</span>")
C.reagents.add_reagent("secretcatchem", 30)
C.reagents.add_reagent(/datum/reagent/fermi/secretcatchem, 30)
if(6)
visible_message("<b>[src]</b> waves their arms around, <span class='spooky'>\"While you may not be a ghost, for this sheet you'll always be it's host.\"</span>")
var/mob/living/carbon/human/H = C
+2 -1
View File
@@ -18,7 +18,7 @@ Clown
minimal_access = list(ACCESS_THEATRE)
/datum/job/clown/after_spawn(mob/living/carbon/human/H, mob/M)
. = ..()
..()
H.apply_pref_name("clown", M.client)
/datum/outfit/job/clown
@@ -83,6 +83,7 @@ Mime
minimal_access = list(ACCESS_THEATRE)
/datum/job/mime/after_spawn(mob/living/carbon/human/H, mob/M)
..()
H.apply_pref_name("mime", M.client)
/datum/outfit/job/mime
+1 -1
View File
@@ -66,7 +66,7 @@
//Only override this proc
//H is usually a human unless an /equip override transformed it
/datum/job/proc/after_spawn(mob/living/H, mob/M, latejoin = FALSE)
//do actions on H but send messages to M as the key may not have been transferred_yet
//do actions on H but send messages to M as the key may not have been transferred yet
if(mind_traits)
for(var/t in mind_traits)
ADD_TRAIT(H.mind, t, JOB_TRAIT)
+1 -1
View File
@@ -21,7 +21,7 @@ AI
. = H.AIize(latejoin)
/datum/job/ai/after_spawn(mob/H, mob/M, latejoin)
. = ..()
..()
if(latejoin)
var/obj/structure/AIcore/latejoin_inactive/lateJoinCore
for(var/obj/structure/AIcore/latejoin_inactive/P in GLOB.latejoin_ai_cores)
@@ -64,6 +64,14 @@
name = "asteroid snow baseturf editor"
baseturf = /turf/open/floor/plating/asteroid/snow
/obj/effect/baseturf_helper/asteroid/layenia
name = "layenia baseturf editor"
baseturf = /turf/open/floor/plating/asteroid/layenia
/obj/effect/baseturf_helper/cloud
name = "cloud baseturf editor"
baseturf = /turf/open/chasm/cloud
/obj/effect/baseturf_helper/beach/sand
name = "beach sand baseturf editor"
baseturf = /turf/open/floor/plating/beach/sand
@@ -597,7 +597,7 @@
if (H.custom_body_size) //Do they have it set?
H.resize(H.custom_body_size * 0.01)
if (H.breedable == TRUE)
H.impregchance = 30
H.impregchance = 25
. = H
new_character = .
if(transfer_after)
@@ -17,3 +17,8 @@
name = "Round + Light"
icon_state = "roundlight"
/datum/sprite_accessory/snouts/gator
name = "Gator"
icon_state = "gator"
color_src = MATRIXED
+8 -2
View File
@@ -11,14 +11,20 @@
toggle_combat_mode(TRUE, TRUE)
. = ..()
for(var/T in get_traumas())
var/datum/brain_trauma/BT = T
BT.on_death()
if(SSticker.mode)
SSticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now
//watching someone die is traumatic
for(var/mob/living/carbon/human/H in oview(5, src))
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "death", /datum/mood_event/deathsaw)
if(prob(10)) //10% chance to pump adrenaline into their body
H.jitteriness += 5
/mob/living/carbon/gib(no_brain, no_organs, no_bodyparts)
var/atom/Tsec = drop_location()
for(var/mob/M in src)
@@ -8,7 +8,6 @@
var/t_is = p_are()
var/obscure_name
var/dispSize = round(12*size_multiplier) // gets the character's sprite size percent and converts it to the nearest half foot
var/output = ""
if(isliving(user))
var/mob/living/L = user
@@ -24,25 +23,13 @@
if (vassDesc != "")
. += vassDesc
output = "<center>"
var/list/obscured = check_obscured_slots()
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
if(ishuman(src)) //user just returned, y'know, the user's own species. dumb.
var/mob/living/carbon/human/H = src
if(gender)
output += "[icon2html('hyperstation/icons/chat/gender.dmi', world, gender)]"
output += "<b>[src.name]</b>"
var/datum/species/pref_species = H.dna.species
if(get_visible_name() == "Unknown") // same as flavor text, but hey it works.
. += "You can't make out what species they are."
else if(skipface)
. += "You can't make out what species they are."
else
. += "[t_He] [t_is] a [H.dna.custom_species ? H.dna.custom_species : pref_species.name]!"
output += "([H.dna.custom_species ? H.dna.custom_species : pref_species.name])"
output += "</center>"
if(skipface || get_visible_name() == "Unknown")
. += "You can't make out what species they are."
else
. += "[t_He] [t_is] a [dna.custom_species ? dna.custom_species : dna.species.name]!"
//uniform
if(w_uniform && !(SLOT_W_UNIFORM in obscured))
@@ -416,30 +403,9 @@
else if(isobserver(user) && traitstring)
. += "<span class='info'><b>Traits:</b> [traitstring]</span>"
if(print_flavor_text())
output += "<br><b>General</b>"
if(get_visible_name() == "Unknown") //Are we sure we know who this is? Don't show flavor text unless we can recognize them. Prevents certain metagaming with impersonation.
. += "...?"
output += "<br>...?"
else if(skipface) //Sometimes we're not unknown, but impersonating someone in a hardsuit, let's not reveal our flavor text then either.
. += "...?"
output += "<br>...?"
else
. += "[print_flavor_text()]"
output += "<br>[url_encode(flavor_text)]"
if(ooc_text)
output += "<br><br><i><b>OOC</b>"
output += "<br>[url_encode(ooc_text)]"
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, msg)
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .) //This also handles flavor texts now
. += "*---------*</span>"
//stat panel
if(ishuman(src))
user.client << output(output, "statbrowser:update_examine") //open the examine window
user.client << output(null, "statbrowser:create_mobexamine") //open the examine window
/mob/living/proc/status_effect_examines(pronoun_replacement) //You can include this in any mob's examine() to show the examine texts of status effects!
var/list/dat = list()
if(!pronoun_replacement)
@@ -37,6 +37,8 @@
if(!CONFIG_GET(flag/disable_human_mood))
AddComponent(/datum/component/mood)
AddElement(/datum/element/mob_holder/micro, "micro")
AddElement(/datum/element/flavor_text/carbon, "", "Flavor Text", "", MAX_FLAVOR_LEN, FALSE, TRUE, "flavor_text")
AddElement(/datum/element/flavor_text, "", "Temporary Flavor Text", "This should be used only for things pertaining to the current round!")
/mob/living/carbon/human/Destroy()
QDEL_NULL(physiology)
+1 -1
View File
@@ -58,7 +58,7 @@
//H13 custom body size and impregnation
var/custom_body_size = 100
var/breedable = 0
var/impregchance = 0
var/impregchance = 30
//h13 noncon settings
var/Noncon = 0
var/ERP = 0
@@ -437,11 +437,11 @@
var/obj/item/reagent_containers/spray/cyborg_drying/CD = locate(/obj/item/reagent_containers/spray/cyborg_drying) in basic_modules
if(CD)
CD.reagents.add_reagent("drying_agent", 5 * coeff)
CD.reagents.add_reagent(/datum/reagent/drying_agent, 5 * coeff)
var/obj/item/reagent_containers/spray/cyborg_lube/CL = locate(/obj/item/reagent_containers/spray/cyborg_lube) in emag_modules
if(CL)
CL.reagents.add_reagent("lube", 2 * coeff)
CL.reagents.add_reagent(/datum/reagent/lube, 2 * coeff)
/obj/item/robot_module/clown
name = "Clown"
@@ -55,6 +55,11 @@
diag_hud_set_status()
diag_hud_set_health()
/mob/living/silicon/ComponentInitialize()
. = ..()
AddElement(/datum/element/flavor_text, "", "Silicon Flavor Text", "", MAX_FLAVOR_LEN, FALSE, TRUE, "silicon_flavor_text")
AddElement(/datum/element/flavor_text, "", "Temporary Flavor Text", "This should be used only for things pertaining to the current round!")
/mob/living/silicon/med_hud_set_health()
return //we use a different hud
@@ -316,9 +316,9 @@ GLOBAL_VAR_INIT(floor_cluwnes, 0)
to_chat(H, "<span class='userdanger'>WHAT THE FUCK IS THAT?!</span>")
to_chat(H, "<i>.KNOH !nuf hcum os si uoy htiw gniyalP .KNOH KNOH KNOH</i>")
H.playsound_local(src,'sound/hallucinations/im_here1.ogg', 25)
H.reagents.add_reagent("mindbreaker", 3)
H.reagents.add_reagent("laughter", 5)
H.reagents.add_reagent("mercury", 3)
H.reagents.add_reagent(/datum/reagent/toxin/mindbreaker, 3)
H.reagents.add_reagent(/datum/reagent/consumable/laughter, 5)
H.reagents.add_reagent(/datum/reagent/mercury, 3)
Appear()
manifested = FALSE
addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Manifest), 2)
-7
View File
@@ -525,13 +525,6 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
unset_machine()
src << browse(null, t1)
if(href_list["flavor_more"])
usr << browse(text("<HTML><HEAD><TITLE>[]</TITLE></HEAD><BODY><TT>[]</TT></BODY></HTML>", name, replacetext(flavor_text, "\n", "<BR>")), text("window=[];size=500x200", name))
onclose(usr, "[name]")
if(href_list["flavor_change"])
update_flavor_text()
if(href_list["refresh"])
if(machine && in_range(src, usr))
show_inv(machine)
-2
View File
@@ -129,9 +129,7 @@
///Whether the mob is updating glide size when movespeed updates or not
var/updating_glide_size = TRUE
var/flavor_text = ""
var/ooc_text = ""
var/flavor_text_2 = "" //version of the above that only lasts for the current round.
///////TYPING INDICATORS///////
/// Set to true if we want to show typing indicators.
-25
View File
@@ -2,31 +2,6 @@
////////////////////SUBTLE COMMAND////////////////////
//////////////////////////////////////////////////////
/mob/proc/update_flavor_text()
set src in usr
if(usr != src)
to_chat(usr, "No.")
var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. IC only!", "Flavor Text", html_decode(flavor_text), MAX_MESSAGE_LEN, TRUE)
if(msg)
flavor_text = html_encode(msg)
flavor_text = msg
/mob/proc/warn_flavor_changed()
if(flavor_text && flavor_text != "") // don't spam people that don't use it!
to_chat(src, "<h2 class='alert'>OOC Warning:</h2>")
to_chat(src, "<span class='alert'>Your flavor text is likely out of date! <a href='?src=[REF(src)];flavor_change=1'>Change</a></span>")
/mob/proc/print_flavor_text()
if(flavor_text && flavor_text != "")
// We are decoding and then encoding to not only get correct amount of characters, but also to prevent partial escaping characters being shown.
var/msg = html_decode(replacetext(flavor_text, "\n", " "))
if(length_char(msg) <= 40)
return "<span class='notice'>[html_encode(msg)]</span>"
else
return "<span class='notice'>[html_encode(copytext_char(msg, 1, 37))]... <a href='?src=[REF(src)];flavor_more=1'>More...</span></a>"
/mob/proc/get_top_level_mob()
if(istype(src.loc,/mob)&&src.loc!=src)
var/mob/M=src.loc
+1 -1
View File
@@ -171,7 +171,7 @@
/turf/open/pool/attackby(obj/item/W, mob/living/user)
if(istype(W, /obj/item/mop) && filled)
W.reagents.add_reagent("water", 5)
W.reagents.add_reagent(/datum/reagent/water, 5)
to_chat(user, "<span class='notice'>You wet [W] in [src].</span>")
playsound(src, 'sound/effects/slosh.ogg', 25, TRUE)
else
+2 -2
View File
@@ -18,8 +18,8 @@
var/grumping = 0 // is the engine currently doing grumpy things
var/list/grump_prefix = list("an upsetting", "an unsettling",
"a scary", "a loud", "a sassy", "a grouchy", "a grumpy",
"an awful", "a horrible", "a despicable", "a pretty rad", "a godawful")
var/list/grump_suffix = list("noise", "racket", "ruckus", "sound", "clatter", "fracas", "hubbub")
"an awful", "a horrible", "a despicable", "a pretty rad", "a godawful, a wocky")
var/list/grump_suffix = list("noise", "racket", "ruckus", "sound", "clatter", "fracas", "hubbub, slush")
var/sound_engine1 = 'sound/machines/tractor_running.ogg'
var/sound_engine2 = 'sound/machines/engine_highpower.ogg'
var/sound_tractorrev = 'sound/machines/tractorrev.ogg'
@@ -337,70 +337,6 @@
construction_time = 600
category = list("Durand")
//H.O.N.K
/datum/design/honk_chassis
name = "Exosuit Chassis (\"H.O.N.K\")"
id = "honk_chassis"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/chassis/honker
materials = list(MAT_METAL=20000)
construction_time = 100
category = list("H.O.N.K")
/datum/design/honk_torso
name = "Exosuit Torso (\"H.O.N.K\")"
id = "honk_torso"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/honker_torso
materials = list(MAT_METAL=20000,MAT_GLASS=10000,MAT_BANANIUM=10000)
construction_time = 300
category = list("H.O.N.K")
/datum/design/honk_head
name = "Exosuit Head (\"H.O.N.K\")"
id = "honk_head"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/honker_head
materials = list(MAT_METAL=10000,MAT_GLASS=5000,MAT_BANANIUM=5000)
construction_time = 200
category = list("H.O.N.K")
/datum/design/honk_left_arm
name = "Exosuit Left Arm (\"H.O.N.K\")"
id = "honk_left_arm"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/honker_left_arm
materials = list(MAT_METAL=15000,MAT_BANANIUM=5000)
construction_time = 200
category = list("H.O.N.K")
/datum/design/honk_right_arm
name = "Exosuit Right Arm (\"H.O.N.K\")"
id = "honk_right_arm"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/honker_right_arm
materials = list(MAT_METAL=15000,MAT_BANANIUM=5000)
construction_time = 200
category = list("H.O.N.K")
/datum/design/honk_left_leg
name = "Exosuit Left Leg (\"H.O.N.K\")"
id = "honk_left_leg"
build_type = MECHFAB
build_path =/obj/item/mecha_parts/part/honker_left_leg
materials = list(MAT_METAL=20000,MAT_BANANIUM=5000)
construction_time = 200
category = list("H.O.N.K")
/datum/design/honk_right_leg
name = "Exosuit Right Leg (\"H.O.N.K\")"
id = "honk_right_leg"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/honker_right_leg
materials = list(MAT_METAL=20000,MAT_BANANIUM=5000)
construction_time = 200
category = list("H.O.N.K")
//Phazon
/datum/design/phazon_chassis
@@ -464,16 +464,6 @@
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000)
export_price = 5000
/////////////////////////Clown tech/////////////////////////
/datum/techweb_node/clown
id = "clown"
display_name = "Clown Technology"
description = "Honk?!"
prereq_ids = list("base")
design_ids = list("air_horn", "honker_main", "honker_peri", "honker_targ", "honk_chassis", "honk_head", "honk_torso", "honk_left_arm", "honk_right_arm",
"honk_left_leg", "honk_right_leg", "mech_banana_mortar", "mech_mousetrap_mortar", "mech_honker", "mech_punching_face", "implant_trombone", "borg_transform_clown")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
////////////////////////Computer tech////////////////////////
/datum/techweb_node/comptech
@@ -1,6 +1,6 @@
//Xenobio control console
/mob/camera/aiEye/remote/xenobio
visible_icon = 1
visible_icon = TRUE
icon = 'icons/obj/abductor.dmi'
icon_state = "camera_target"
var/allowed_area = null
@@ -22,15 +22,11 @@
desc = "A computer used for remotely handling slimes."
networks = list("ss13")
circuit = /obj/item/circuitboard/computer/xenobiology
var/datum/action/innate/slime_place/slime_place_action
var/datum/action/innate/slime_pick_up/slime_up_action
var/datum/action/innate/feed_slime/feed_slime_action
var/datum/action/innate/monkey_recycle/monkey_recycle_action
var/datum/action/innate/slime_scan/scan_action
var/datum/action/innate/feed_potion/potion_action
var/datum/action/innate/hotkey_help/hotkey_help
var/datum/component/redirect/listener
var/obj/machinery/monkey_recycler/connected_recycler
var/list/stored_slimes
var/obj/item/slimepotion/slime/current_potion
var/max_slimes = 5
@@ -43,14 +39,13 @@
/obj/machinery/computer/camera_advanced/xenobio/Initialize()
. = ..()
slime_place_action = new
slime_up_action = new
feed_slime_action = new
monkey_recycle_action = new
scan_action = new
potion_action = new
hotkey_help = new
stored_slimes = list()
listener = AddComponent(/datum/component/redirect, list(COMSIG_ATOM_CONTENTS_DEL = CALLBACK(src, .proc/on_contents_del)))
for(var/obj/machinery/monkey_recycler/recycler in GLOB.monkey_recyclers)
if(get_area(src) == get_area(recycler))
connected_recycler = recycler
connected_recycler.connected += src
/obj/machinery/computer/camera_advanced/xenobio/Destroy()
stored_slimes = null
@@ -61,45 +56,56 @@
S.forceMove(drop_location())
return ..()
/obj/machinery/computer/camera_advanced/xenobio/examine(mob/user)
. = ..()
var/thing = "It has "
if((upgradetier & XENOBIO_UPGRADE_SLIMEADV))
thing += "an advanced slime upgrade disk "
if((upgradetier & XENOBIO_UPGRADE_MONKEYS))
thing += "and a monkey upgrade disk "
else if((upgradetier & XENOBIO_UPGRADE_SLIMEBASIC))
thing += "a basic slime upgrade disk "
if((upgradetier & XENOBIO_UPGRADE_MONKEYS))
thing += "and a monkey upgrade disk "
else if((upgradetier & XENOBIO_UPGRADE_MONKEYS))
thing += "a monkey upgrade disk "
else
thing += "no upgrades installed."
. += thing
return
thing += "installed."
. += thing
/obj/machinery/computer/camera_advanced/xenobio/CreateEye()
eyeobj = new /mob/camera/aiEye/remote/xenobio(get_turf(src))
eyeobj.origin = src
eyeobj.visible_icon = 1
eyeobj.visible_icon = TRUE
eyeobj.icon = 'icons/obj/abductor.dmi'
eyeobj.icon_state = "camera_target"
/obj/machinery/computer/camera_advanced/xenobio/GrantActions(mob/living/user)
..()
if(slime_up_action && (upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEBASIC
slime_up_action.target = src
slime_up_action.Grant(user)
actions += slime_up_action
if(hotkey_help)
hotkey_help.target = src
hotkey_help.Grant(user)
actions += hotkey_help
if(slime_place_action && (upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEBASIC
slime_place_action.target = src
slime_place_action.Grant(user)
actions += slime_place_action
RegisterSignal(user, COMSIG_XENO_SLIME_CLICK_CTRL, .proc/XenoSlimeClickCtrl)
RegisterSignal(user, COMSIG_XENO_SLIME_CLICK_ALT, .proc/XenoSlimeClickAlt)
RegisterSignal(user, COMSIG_XENO_SLIME_CLICK_SHIFT, .proc/XenoSlimeClickShift)
RegisterSignal(user, COMSIG_XENO_TURF_CLICK_SHIFT, .proc/XenoTurfClickShift)
RegisterSignal(user, COMSIG_XENO_TURF_CLICK_CTRL, .proc/XenoTurfClickCtrl)
RegisterSignal(user, COMSIG_XENO_MONKEY_CLICK_CTRL, .proc/XenoMonkeyClickCtrl)
if(feed_slime_action && (upgradetier & XENOBIO_UPGRADE_MONKEYS)) //CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS
feed_slime_action.target = src
feed_slime_action.Grant(user)
actions += feed_slime_action
if(monkey_recycle_action && (upgradetier & XENOBIO_UPGRADE_MONKEYS)) //CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS
monkey_recycle_action.target = src
monkey_recycle_action.Grant(user)
actions += monkey_recycle_action
if(scan_action)
scan_action.target = src
scan_action.Grant(user)
actions += scan_action
if(potion_action && (upgradetier & XENOBIO_UPGRADE_SLIMEADV)) // CIT CHANGE - makes giving slimes potions via console require XENOBIO_UPGRADE_SLIMEADV
potion_action.target = src
potion_action.Grant(user)
actions += potion_action
/obj/machinery/computer/camera_advanced/xenobio/remove_eye_control(mob/living/user)
UnregisterSignal(user, COMSIG_XENO_SLIME_CLICK_CTRL)
UnregisterSignal(user, COMSIG_XENO_SLIME_CLICK_ALT)
UnregisterSignal(user, COMSIG_XENO_SLIME_CLICK_SHIFT)
UnregisterSignal(user, COMSIG_XENO_TURF_CLICK_SHIFT)
UnregisterSignal(user, COMSIG_XENO_TURF_CLICK_CTRL)
UnregisterSignal(user, COMSIG_XENO_MONKEY_CLICK_CTRL)
..()
/obj/machinery/computer/camera_advanced/xenobio/proc/on_contents_del(atom/deleted)
if(current_potion == deleted)
@@ -134,135 +140,161 @@
current_potion = O
to_chat(user, "<span class='notice'>You load [O] in the console's potion slot[replaced ? ", replacing the one that was there before" : ""].</span>")
return
else if(istype(O, /obj/item/multitool))
var/obj/item/multitool/M = O
if(istype(M.buffer))
to_chat(user, "<span class='notice'>You link [src] with [M.buffer] in [M] buffer.</span>")
connected_recycler = M.buffer
connected_recycler += src
return
else
to_chat(user, "<span class='warning'>[M] has no buffer.</span>")
return
..()
/datum/action/innate/slime_place
name = "Place Slimes"
/datum/action/innate/hotkey_help
name = "Hotkey Help"
icon_icon = 'icons/mob/actions/actions_silicon.dmi'
button_icon_state = "slime_down"
button_icon_state = "hotkey_help"
/datum/action/innate/slime_place/Activate()
/datum/action/innate/hotkey_help/Activate()
if(!target || !isliving(owner))
return
var/mob/living/C = owner
var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = target
to_chat(owner, "<b>Click shortcuts:</b>")
to_chat(owner, "Shift-click a slime to pick it up, or the floor to drop all held slimes.")
to_chat(owner, "Ctrl-click a slime to scan it.")
to_chat(owner, "Alt-click a slime to feed it a potion.")
to_chat(owner, "Ctrl-click on a dead monkey to recycle it, or the floor to place a new monkey.")
if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
for(var/mob/living/simple_animal/slime/S in X.stored_slimes)
S.forceMove(remote_eye.loc)
//
// Alternate clicks for slime, monkey and open turf if using a xenobio console
//Picks up slime
/mob/living/simple_animal/slime/ShiftClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_SHIFT, src)
..()
//Place slimes
/turf/open/ShiftClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_TURF_CLICK_SHIFT, src)
..()
//Place monkey
/turf/open/CtrlClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_TURF_CLICK_CTRL, src)
..()
//Pick up monkey
/mob/living/carbon/monkey/CtrlClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_MONKEY_CLICK_CTRL, src)
..()
// Scans slime
/mob/living/simple_animal/slime/CtrlClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_CTRL, src)
..()
//Feeds a potion to slime
/mob/living/simple_animal/slime/AltClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_ALT, src)
..()
//Picks up slime
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickShift(mob/living/user, mob/living/simple_animal/slime/S)
if(!(upgradetier & XENOBIO_UPGRADE_SLIMEBASIC))
return
if(!GLOB.cameranet.checkTurfVis(S.loc))
to_chat(user, "<span class='warning'>Target is not near a camera. Cannot proceed.</span>")
return
var/area/mobarea = get_area(S.loc)
var/mob/camera/aiEye/remote/xenobio/X = eyeobj
if(mobarea.name == X.allowed_area || mobarea.xenobiology_compatible)
if(stored_slimes.len >= max_slimes)
to_chat(user, "<span class='warning'>Slime storage is full.</span>")
return
if(S.ckey)
to_chat(user, "<span class='warning'>The slime wiggled free!</span>")
return
if(S.buckled)
S.Feedstop(silent = TRUE)
S.visible_message("[S] vanishes in a flash of light!")
S.forceMove(src)
stored_slimes += S
//Place slimes
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickShift(mob/living/user, turf/open/T)
if(!(upgradetier & XENOBIO_UPGRADE_SLIMEBASIC))
return
if(!GLOB.cameranet.checkTurfVis(T))
to_chat(user, "<span class='warning'>Target is not near a camera. Cannot proceed.</span>")
return
var/area/turfarea = get_area(T)
var/mob/camera/aiEye/remote/xenobio/X = eyeobj
if(turfarea.name == X.allowed_area || turfarea.xenobiology_compatible)
for(var/mob/living/simple_animal/slime/S in stored_slimes)
S.forceMove(T)
S.visible_message("[S] warps in!")
X.stored_slimes -= S
else
to_chat(owner, "<span class='notice'>Target is not near a camera. Cannot proceed.</span>")
stored_slimes -= S
/datum/action/innate/slime_pick_up
name = "Pick up Slime"
icon_icon = 'icons/mob/actions/actions_silicon.dmi'
button_icon_state = "slime_up"
/datum/action/innate/slime_pick_up/Activate()
if(!target || !isliving(owner))
//Place monkey
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickCtrl(mob/living/user, turf/open/T)
if(!(upgradetier & XENOBIO_UPGRADE_MONKEYS))
return
var/mob/living/C = owner
var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = target
if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
for(var/mob/living/simple_animal/slime/S in remote_eye.loc)
if(X.stored_slimes.len >= X.max_slimes)
break
if(!S.ckey)
if(S.buckled)
S.Feedstop(silent = TRUE)
S.visible_message("[S] vanishes in a flash of light!")
S.forceMove(X)
X.stored_slimes += S
else
to_chat(owner, "<span class='notice'>Target is not near a camera. Cannot proceed.</span>")
/datum/action/innate/feed_slime
name = "Feed Slimes"
icon_icon = 'icons/mob/actions/actions_silicon.dmi'
button_icon_state = "monkey_down"
/datum/action/innate/feed_slime/Activate()
if(!target || !isliving(owner))
if(!GLOB.cameranet.checkTurfVis(T))
to_chat(user, "<span class='warning'>Target is not near a camera. Cannot proceed.</span>")
return
var/mob/living/C = owner
var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = target
var/area/turfarea = get_area(T)
var/mob/camera/aiEye/remote/xenobio/X = eyeobj
if(turfarea.name == X.allowed_area || turfarea.xenobiology_compatible)
if(monkeys >= 1)
var/mob/living/carbon/monkey/food = new/mob/living/carbon/monkey(T, TRUE, user)
if(!QDELETED(food))
food.LAssailant = user
monkeys = round(monkeys-1, 0.1)
to_chat(user, "[src] now has [monkeys] monkeys stored.")
if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
if(X.monkeys >= 1)
var/mob/living/carbon/monkey/food = new /mob/living/carbon/monkey(remote_eye.loc, TRUE, owner)
if (!QDELETED(food))
food.LAssailant = C
X.monkeys --
to_chat(owner, "[X] now has [X.monkeys] monkeys left.")
else
to_chat(owner, "<span class='notice'>Target is not near a camera. Cannot proceed.</span>")
/datum/action/innate/monkey_recycle
name = "Recycle Monkeys"
icon_icon = 'icons/mob/actions/actions_silicon.dmi'
button_icon_state = "monkey_up"
/datum/action/innate/monkey_recycle/Activate()
if(!target || !isliving(owner))
//Pick up monkey
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoMonkeyClickCtrl(mob/living/user, mob/living/carbon/monkey/M)
if(!(upgradetier & XENOBIO_UPGRADE_MONKEYS))
return
var/mob/living/C = owner
var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = target
if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
for(var/mob/living/carbon/monkey/M in remote_eye.loc)
if(M.stat)
M.visible_message("[M] vanishes as [M.p_theyre()] reclaimed for recycling!")
X.monkeys = round(X.monkeys + 0.2,0.1)
qdel(M)
else
to_chat(owner, "<span class='notice'>Target is not near a camera. Cannot proceed.</span>")
/datum/action/innate/slime_scan
name = "Scan Slime"
icon_icon = 'icons/mob/actions/actions_silicon.dmi'
button_icon_state = "slime_scan"
/datum/action/innate/slime_scan/Activate()
if(!target || !isliving(owner))
if(!connected_recycler)
to_chat(user, "<span class='notice'>There is no connected monkey recycler. You can connect one with a multitool.</span>")
return
var/mob/living/C = owner
var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control
if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
for(var/mob/living/simple_animal/slime/S in remote_eye.loc)
slime_scan(S, C)
else
to_chat(owner, "<span class='notice'>Target is not near a camera. Cannot proceed.</span>")
/datum/action/innate/feed_potion
name = "Apply Potion"
icon_icon = 'icons/mob/actions/actions_silicon.dmi'
button_icon_state = "slime_potion"
/datum/action/innate/feed_potion/Activate()
if(!target || !isliving(owner))
if(!GLOB.cameranet.checkTurfVis(M.loc))
to_chat(user, "<span class='warning'>Target is not near a camera. Cannot proceed.</span>")
return
var/area/mobarea = get_area(M.loc)
var/mob/camera/aiEye/remote/xenobio/X = eyeobj
if(mobarea.name == X.allowed_area || mobarea.xenobiology_compatible)
if(!M.stat)
return
M.visible_message("[M] vanishes as [M.p_theyre()] reclaimed for recycling!")
connected_recycler.use_power(500)
monkeys += connected_recycler.cube_production
to_chat(user, "[src] now has [monkeys] monkeys available.")
qdel(M)
var/mob/living/C = owner
var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = target
if(QDELETED(X.current_potion))
to_chat(owner, "<span class='notice'>No potion loaded.</span>")
// Scans slime
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickCtrl(mob/living/user, mob/living/simple_animal/slime/S)
if(!GLOB.cameranet.checkTurfVis(S.loc))
to_chat(user, "<span class='warning'>Target is not near a camera. Cannot proceed.</span>")
return
var/area/mobarea = get_area(S.loc)
var/mob/camera/aiEye/remote/xenobio/X = eyeobj
if(mobarea.name == X.allowed_area || mobarea.xenobiology_compatible)
slime_scan(S, user)
if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
for(var/mob/living/simple_animal/slime/S in remote_eye.loc)
X.current_potion.attack(S, C)
break
else
to_chat(owner, "<span class='notice'>Target is not near a camera. Cannot proceed.</span>")
//Feeds a potion to slime
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickAlt(mob/living/user, mob/living/simple_animal/slime/S)
if(!(upgradetier & XENOBIO_UPGRADE_SLIMEBASIC))
return
if(!GLOB.cameranet.checkTurfVis(S.loc))
to_chat(user, "<span class='warning'>Target is not near a camera. Cannot proceed.</span>")
return
var/area/mobarea = get_area(S.loc)
if(QDELETED(current_potion))
to_chat(user, "<span class='warning'>No potion loaded.</span>")
return
var/mob/camera/aiEye/remote/xenobio/X = eyeobj
if(mobarea.name == X.allowed_area || mobarea.xenobiology_compatible)
current_potion.attack(S, user)