mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-10 06:34:45 +01:00
Merge branch 'master' into ghost-rad-hud
This commit is contained in:
@@ -377,7 +377,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
to_chat(usr, "Not when you're not dead!")
|
||||
return
|
||||
|
||||
var/datum/async_input/A = input_autocomplete_async(usr, "Area to jump to: ", GLOB.ghostteleportlocs)
|
||||
var/datum/async_input/A = input_autocomplete_async(usr, "Area to jump to: ", SSmapping.ghostteleportlocs)
|
||||
A.on_close(CALLBACK(src, .proc/teleport))
|
||||
|
||||
/mob/dead/observer/proc/teleport(area/thearea)
|
||||
|
||||
@@ -90,6 +90,8 @@
|
||||
M.show_message(message, m_type)
|
||||
|
||||
O.show_message(message, m_type)
|
||||
if(O.client?.prefs.toggles2 & PREFTOGGLE_2_RUNECHAT)
|
||||
O.create_chat_message(src, input, symbol = RUNECHAT_SYMBOL_EMOTE)
|
||||
|
||||
// Type 2 (Audible) emotes are sent to anyone in hear range
|
||||
// of the *LOCATION* -- this is important for pAIs to be heard
|
||||
@@ -116,7 +118,7 @@
|
||||
return
|
||||
|
||||
if(!src.client.holder)
|
||||
if(!config.dsay_allowed)
|
||||
if(!GLOB.dsay_enabled)
|
||||
to_chat(src, "<span class='warning'>Deadchat is globally muted</span>")
|
||||
return
|
||||
|
||||
|
||||
@@ -486,6 +486,14 @@
|
||||
flags = RESTRICTED | HIVEMIND | NOBABEL
|
||||
follow = TRUE
|
||||
|
||||
/datum/language/terrorspider/broadcast(mob/living/speaker, message, speaker_mask)
|
||||
if(isterrorspider(speaker))
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/T = speaker
|
||||
if(T.loudspeaker)
|
||||
..(speaker, "<font size=3><b>[message]</b></font>")
|
||||
return
|
||||
..(speaker, message)
|
||||
|
||||
/datum/language/ling
|
||||
name = "Changeling"
|
||||
desc = "Although they are normally wary and suspicious of each other, changelings can commune over a distance."
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
|
||||
/mob/living/carbon/alien/movement_delay()
|
||||
. = ..()
|
||||
. += move_delay_add + config.alien_delay //move_delay_add is used to slow aliens with stuns
|
||||
. += move_delay_add + GLOB.configuration.movement.alien_delay //move_delay_add is used to slow aliens with stuns
|
||||
|
||||
/mob/living/carbon/alien/getDNA()
|
||||
return null
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
new_xeno.mind.assigned_role = SPECIAL_ROLE_XENOMORPH
|
||||
new_xeno.mind.special_role = SPECIAL_ROLE_XENOMORPH
|
||||
new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100)//To get the player's attention
|
||||
to_chat(new_xeno, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Xenomorph)</span>")
|
||||
to_chat(new_xeno, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Xenomorph)</span>")
|
||||
|
||||
if(gib_on_success)
|
||||
owner.gib()
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
/mob/living/carbon/brain/Life()
|
||||
. = ..()
|
||||
if(.)
|
||||
if(!container && (world.time - timeofhostdeath) > config.revival_brain_life)
|
||||
if(!container && (world.time - timeofhostdeath) > GLOB.configuration.general.revival_brain_life)
|
||||
death()
|
||||
|
||||
/mob/living/carbon/brain/breathe()
|
||||
|
||||
@@ -404,6 +404,10 @@
|
||||
/mob/living/carbon/proc/tintcheck()
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/proc/create_dna()
|
||||
if(!dna)
|
||||
dna = new()
|
||||
|
||||
/mob/living/carbon/proc/getDNA()
|
||||
return dna
|
||||
|
||||
@@ -1126,8 +1130,6 @@ so that different stomachs can handle things in different ways VB*/
|
||||
|
||||
//to recalculate and update the mob's total tint from tinted equipment it's wearing.
|
||||
/mob/living/carbon/proc/update_tint()
|
||||
if(!GLOB.tinted_weldhelh)
|
||||
return
|
||||
var/tinttotal = get_total_tint()
|
||||
if(tinttotal >= TINT_BLIND)
|
||||
overlay_fullscreen("tint", /obj/screen/fullscreen/blind)
|
||||
|
||||
@@ -320,7 +320,7 @@
|
||||
for(var/current_species_name in GLOB.all_species)
|
||||
var/datum/species/current_species = GLOB.all_species[current_species_name]
|
||||
|
||||
if(check_whitelist && config.usealienwhitelist && !check_rights(R_ADMIN, 0, src)) //If we're using the whitelist, make sure to check it!
|
||||
if(check_whitelist && !check_rights(R_ADMIN, 0, src)) //If we're using the whitelist, make sure to check it!
|
||||
if(whitelist.len && !(current_species_name in whitelist))
|
||||
continue
|
||||
if(blacklist.len && (current_species_name in blacklist))
|
||||
|
||||
@@ -134,6 +134,8 @@
|
||||
on_CD = handle_emote_CD()
|
||||
if("deathgasp", "deathgasps")
|
||||
on_CD = handle_emote_CD(50)
|
||||
if("spin", "spins")
|
||||
on_CD = handle_emote_CD(50)
|
||||
if("sneeze", "sneezes")
|
||||
on_CD = handle_emote_CD()
|
||||
if("clap", "claps")
|
||||
@@ -443,6 +445,17 @@
|
||||
message = "<B>[src]</B> does a flip!"
|
||||
SpinAnimation(5,1)
|
||||
|
||||
if("spin", "spins")
|
||||
if(!restrained() && !lying)
|
||||
if(prob(5))
|
||||
spin(30, 1)
|
||||
message = "<B>[src]</B> spins too much!"
|
||||
Dizzy(12)
|
||||
Confused(12)
|
||||
else
|
||||
spin(20, 1)
|
||||
message = "<B>[src]</B> spins!"
|
||||
|
||||
if("aflap", "aflaps")
|
||||
if(!restrained())
|
||||
message = "<B>[src]</B> flaps [p_their()] wings ANGRILY!"
|
||||
@@ -950,7 +963,7 @@
|
||||
var/emotelist = "aflap(s), airguitar, blink(s), blink(s)_r, blush(es), bow(s)-none/mob, burp(s), choke(s), chuckle(s), clap(s), collapse(s), cough(s), cry, cries, custom, dance, dap(s)-none/mob," \
|
||||
+ " deathgasp(s), drool(s), eyebrow, fart(s), faint(s), flap(s), flip(s), frown(s), gasp(s), giggle(s), glare(s)-none/mob, grin(s), groan(s), grumble(s), grin(s)," \
|
||||
+ " handshake-mob, hug(s)-none/mob, hem, highfive, johnny, jump, kiss(es), laugh(s), look(s)-none/mob, moan(s), mumble(s), nod(s), pale(s), point(s)-atom, quiver(s), raise(s), salute(s)-none/mob, scream(s), shake(s)," \
|
||||
+ " shiver(s), shrug(s), sigh(s), signal(s)-#1-10, slap(s), smile(s),snap(s), sneeze(s), sniff(s), snore(s), stare(s)-none/mob, tremble(s), twitch(es), twitch(es)_s," \
|
||||
+ " shiver(s), shrug(s), sigh(s), signal(s)-#1-10, slap(s), smile(s),snap(s), sneeze(s), sniff(s), snore(s), spin(s) stare(s)-none/mob, tremble(s), twitch(es), twitch(es)_s," \
|
||||
+ " wave(s), whimper(s), wink(s), yawn(s)"
|
||||
|
||||
switch(dna.species.name)
|
||||
|
||||
@@ -14,38 +14,47 @@
|
||||
. = ..()
|
||||
|
||||
/mob/living/carbon/human/Initialize(mapload, datum/species/new_species = /datum/species/human)
|
||||
if(!dna)
|
||||
dna = new /datum/dna(null)
|
||||
// Species name is handled by set_species()
|
||||
create_dna()
|
||||
|
||||
. = ..()
|
||||
|
||||
set_species(new_species, 1, delay_icon_update = 1, skip_same_check = TRUE)
|
||||
|
||||
if(dna.species)
|
||||
real_name = dna.species.get_random_name(gender)
|
||||
name = real_name
|
||||
if(mind)
|
||||
mind.name = real_name
|
||||
|
||||
create_reagents(330)
|
||||
|
||||
handcrafting = new()
|
||||
|
||||
// Set up DNA.
|
||||
if(dna)
|
||||
dna.ready_dna(src)
|
||||
dna.real_name = real_name
|
||||
sync_organ_dna(1)
|
||||
|
||||
physiology = new()
|
||||
|
||||
AddComponent(/datum/component/footstep, FOOTSTEP_MOB_HUMAN, 1, -6)
|
||||
setup_dna(new_species)
|
||||
setup_other()
|
||||
|
||||
UpdateAppearance()
|
||||
GLOB.human_list += src
|
||||
|
||||
/**
|
||||
* Sets up DNA and species.
|
||||
*
|
||||
* Arguments:
|
||||
* * new_species - The new species to assign.
|
||||
*/
|
||||
/mob/living/carbon/human/proc/setup_dna(datum/species/new_species)
|
||||
set_species(new_species, use_default_color = TRUE, delay_icon_update = TRUE, skip_same_check = TRUE)
|
||||
// Name
|
||||
real_name = dna.species.get_random_name(gender)
|
||||
name = real_name
|
||||
if(mind)
|
||||
mind.name = real_name
|
||||
// DNA ready
|
||||
dna.ready_dna(src)
|
||||
dna.real_name = real_name
|
||||
sync_organ_dna()
|
||||
|
||||
/**
|
||||
* Sets up other variables and components that may be needed for gameplay.
|
||||
*/
|
||||
/mob/living/carbon/human/proc/setup_other()
|
||||
create_reagents(330)
|
||||
physiology = new()
|
||||
|
||||
/mob/living/carbon/human/ComponentInitialize()
|
||||
AddComponent(/datum/component/footstep, FOOTSTEP_MOB_HUMAN, 1, -6)
|
||||
|
||||
/mob/living/carbon/human/OpenCraftingMenu()
|
||||
if(!handcrafting)
|
||||
handcrafting = new()
|
||||
handcrafting.ui_interact(src)
|
||||
|
||||
/mob/living/carbon/human/prepare_data_huds()
|
||||
@@ -1211,7 +1220,7 @@
|
||||
sec_hud_set_ID()
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/set_species(datum/species/new_species, default_colour, delay_icon_update = FALSE, skip_same_check = FALSE, retain_damage = FALSE, transformation = FALSE)
|
||||
/mob/living/carbon/human/proc/set_species(datum/species/new_species, use_default_color = FALSE, delay_icon_update = FALSE, skip_same_check = FALSE, retain_damage = FALSE, transformation = FALSE)
|
||||
if(!skip_same_check)
|
||||
if(dna.species.name == initial(new_species.name))
|
||||
return
|
||||
@@ -1246,7 +1255,7 @@
|
||||
hunger_drain = dna.species.hunger_drain
|
||||
digestion_ratio = dna.species.digestion_ratio
|
||||
|
||||
if(dna.species.base_color && default_colour)
|
||||
if(dna.species.base_color && use_default_color)
|
||||
//Apply colour.
|
||||
skin_colour = dna.species.base_color
|
||||
else
|
||||
@@ -1933,3 +1942,16 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
|
||||
runechat_msg_location = loc
|
||||
else
|
||||
runechat_msg_location = src
|
||||
|
||||
/mob/living/carbon/human/verb/Examine_OOC()
|
||||
set name = "Examine Meta-Info (OOC)"
|
||||
set category = "OOC"
|
||||
set src in view()
|
||||
|
||||
if(GLOB.configuration.general.allow_character_metadata)
|
||||
if(client)
|
||||
to_chat(usr, "[src]'s Metainfo:<br>[sanitize(client.prefs.metadata)]")
|
||||
else
|
||||
to_chat(usr, "[src] does not have any stored infomation!")
|
||||
else
|
||||
to_chat(usr, "OOC Metadata is not supported by this server!")
|
||||
|
||||
@@ -37,10 +37,16 @@ emp_act
|
||||
return 2
|
||||
|
||||
if(mind?.martial_art?.deflection_chance) //Some martial arts users can deflect projectiles!
|
||||
if(!lying && !HAS_TRAIT(src, TRAIT_HULK) && prob(mind.martial_art.deflection_chance)) //But only if they're not lying down, and hulks can't do it
|
||||
if(!lying && !HAS_TRAIT(src, TRAIT_HULK) && mind.martial_art.try_deflect(src)) //But only if they're not lying down, and hulks can't do it
|
||||
add_attack_logs(P.firer, src, "hit by [P.type] but got deflected by martial arts '[mind.martial_art]'")
|
||||
visible_message("<span class='danger'>[src] deflects the projectile; [p_they()] can't be hit with ranged weapons!</span>", "<span class='userdanger'>You deflect the projectile!</span>")
|
||||
return FALSE
|
||||
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, TRUE)
|
||||
if(mind.martial_art.reroute_deflection)
|
||||
P.firer = src
|
||||
P.setAngle(rand(0, 360))
|
||||
return -1
|
||||
else
|
||||
return FALSE
|
||||
|
||||
var/obj/item/organ/external/organ = get_organ(check_zone(def_zone))
|
||||
if(isnull(organ))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/mob/living/carbon/human/movement_delay()
|
||||
. = 0
|
||||
. += ..()
|
||||
. += config.human_delay
|
||||
. += GLOB.configuration.movement.human_delay
|
||||
. += dna.species.movement_delay(src)
|
||||
|
||||
/mob/living/carbon/human/Process_Spacemove(movement_dir = 0)
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
player_logged++
|
||||
if(istype(loc, /obj/machinery/cryopod))
|
||||
return
|
||||
if(config.auto_cryo_ssd_mins && (player_logged >= (config.auto_cryo_ssd_mins * 30)) && player_logged % 30 == 0)
|
||||
if(GLOB.configuration.afk.ssd_auto_cryo_minutes && (player_logged >= (GLOB.configuration.afk.ssd_auto_cryo_minutes * 30)) && player_logged % 30 == 0)
|
||||
var/turf/T = get_turf(src)
|
||||
if(!is_station_level(T.z))
|
||||
return
|
||||
|
||||
@@ -129,17 +129,11 @@
|
||||
if((head_organ.dna.species.name in tmp_hair.species_allowed) && (robohead.company in tmp_hair.models_allowed)) //Populate the list of available monitor styles only with styles that the monitor-head is allowed to use.
|
||||
hair += i
|
||||
|
||||
var/file = file2text("config/custom_sprites.txt") //Pulls up the custom_sprites list
|
||||
var/lines = splittext(file, "\n")
|
||||
|
||||
for(var/line in lines) // Looks for lines set up as screen:ckey:screen_name
|
||||
var/list/Entry = splittext(line, ":") // split lines
|
||||
for(var/i = 1 to Entry.len)
|
||||
Entry[i] = trim(Entry[i]) // Cleans up lines
|
||||
if(Entry.len != 3 || Entry[1] != "screen") // Ignore entries that aren't for screens
|
||||
continue
|
||||
if(Entry[2] == H.ckey) // They're in the list? Custom sprite time, var and icon change required
|
||||
hair += Entry[3] // Adds custom screen to list
|
||||
if(H.ckey in GLOB.configuration.custom_sprites.ipc_screen_map)
|
||||
// key: ckey | value: list of icon states
|
||||
for(var/style in GLOB.configuration.custom_sprites.ipc_screen_map[H.ckey])
|
||||
hair += style
|
||||
|
||||
var/new_style = input(H, "Select a monitor display", "Monitor Display", head_organ.h_style) as null|anything in hair
|
||||
var/new_color = input("Please select hair color.", "Monitor Color", head_organ.hair_colour) as null|color
|
||||
|
||||
@@ -572,9 +572,22 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
|
||||
standing.alpha = w_uniform.alpha
|
||||
standing.color = w_uniform.color
|
||||
overlays_standing[UNIFORM_LAYER] = standing
|
||||
else
|
||||
else if(!dna.species.nojumpsuit)
|
||||
var/list/uniform_slots = list()
|
||||
var/obj/item/organ/external/L = get_organ(BODY_ZONE_L_LEG)
|
||||
if(!(L?.status & ORGAN_ROBOT))
|
||||
uniform_slots += l_store
|
||||
var/obj/item/organ/external/R = get_organ(BODY_ZONE_R_LEG)
|
||||
if(!(R?.status & ORGAN_ROBOT))
|
||||
uniform_slots += r_store
|
||||
var/obj/item/organ/external/C = get_organ(BODY_ZONE_CHEST)
|
||||
if(!(C?.status & ORGAN_ROBOT))
|
||||
uniform_slots += wear_id
|
||||
uniform_slots += wear_pda
|
||||
uniform_slots += belt
|
||||
|
||||
// Automatically drop anything in store / id / belt if you're not wearing a uniform. //CHECK IF NECESARRY
|
||||
for(var/obj/item/thing in list(r_store, l_store, wear_id, wear_pda, belt)) // whoever made this
|
||||
for(var/obj/item/thing in uniform_slots) // whoever made this
|
||||
if(thing) // you're a piece of fucking garbage
|
||||
unEquip(thing) // why the fuck would you goddamn do this motherfucking shit
|
||||
if(client) // INVENTORY CODE IN FUCKING ICON CODE
|
||||
|
||||
@@ -92,6 +92,9 @@
|
||||
to_chat(src, "<span class='warning'>[L] is restrained, you cannot push past.</span>")
|
||||
return TRUE
|
||||
|
||||
if(pulledby == L && a_intent != INTENT_HELP) //prevents boosting the person pulling you, but you can still move through them on help intent
|
||||
return TRUE
|
||||
|
||||
if(L.pulling)
|
||||
if(ismob(L.pulling))
|
||||
var/mob/P = L.pulling
|
||||
@@ -519,22 +522,6 @@
|
||||
/mob/living/proc/UpdateDamageIcon()
|
||||
return
|
||||
|
||||
|
||||
/mob/living/proc/Examine_OOC()
|
||||
set name = "Examine Meta-Info (OOC)"
|
||||
set category = "OOC"
|
||||
set src in view()
|
||||
|
||||
if(config.allow_Metadata)
|
||||
if(client)
|
||||
to_chat(usr, "[src]'s Metainfo:<br>[client.prefs.metadata]")
|
||||
else
|
||||
to_chat(usr, "[src] does not have any stored infomation!")
|
||||
else
|
||||
to_chat(usr, "OOC Metadata is not supported by this server!")
|
||||
|
||||
return
|
||||
|
||||
/mob/living/Move(atom/newloc, direct, movetime)
|
||||
if(buckled && buckled.loc != newloc) //not updating position
|
||||
if(!buckled.anchored)
|
||||
@@ -928,15 +915,15 @@
|
||||
if(forced_look)
|
||||
. += 3
|
||||
if(ignorewalk)
|
||||
. += config.run_speed
|
||||
. += GLOB.configuration.movement.base_run_speed
|
||||
else
|
||||
switch(m_intent)
|
||||
if(MOVE_INTENT_RUN)
|
||||
if(drowsyness > 0)
|
||||
. += 6
|
||||
. += config.run_speed
|
||||
. += GLOB.configuration.movement.base_run_speed
|
||||
if(MOVE_INTENT_WALK)
|
||||
. += config.walk_speed
|
||||
. += GLOB.configuration.movement.base_walk_speed
|
||||
|
||||
|
||||
/mob/living/proc/can_use_guns(obj/item/gun/G)
|
||||
|
||||
@@ -53,7 +53,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
|
||||
var/list/connected_robots = list()
|
||||
var/aiRestorePowerRoutine = 0
|
||||
//var/list/laws = list()
|
||||
alarms_listend_for = list("Motion", "Fire", "Atmosphere", "Power", "Camera", "Burglar")
|
||||
alarms_listend_for = list("Motion", "Fire", "Atmosphere", "Power", "Burglar")
|
||||
var/viewalerts = 0
|
||||
var/icon/holo_icon//Default is assigned when AI is created.
|
||||
var/obj/mecha/controlled_mech //For controlled_mech a mech, to determine whether to relaymove or use the AI eye.
|
||||
@@ -365,20 +365,8 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
|
||||
if(stat || aiRestorePowerRoutine)
|
||||
return
|
||||
if(!custom_sprite) //Check to see if custom sprite time, checking the appopriate file to change a var
|
||||
var/file = file2text("config/custom_sprites.txt")
|
||||
var/lines = splittext(file, "\n")
|
||||
|
||||
for(var/line in lines)
|
||||
// split & clean up
|
||||
var/list/Entry = splittext(line, ":")
|
||||
for(var/i = 1 to Entry.len)
|
||||
Entry[i] = trim(Entry[i])
|
||||
|
||||
if(Entry.len < 2 || Entry[1] != "ai") //ignore incorrectly formatted entries or entries that aren't marked for AI
|
||||
continue
|
||||
|
||||
if(Entry[2] == ckey) //They're in the list? Custom sprite time, var and icon change required
|
||||
custom_sprite = 1
|
||||
if(ckey in GLOB.configuration.custom_sprites.ai_core_ckeys)
|
||||
custom_sprite = TRUE
|
||||
|
||||
var/display_choices = list(
|
||||
"Monochrome",
|
||||
@@ -963,21 +951,9 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
|
||||
|
||||
if(check_unable())
|
||||
return
|
||||
if(!custom_hologram) //Check to see if custom sprite time, checking the appopriate file to change a var
|
||||
var/file = file2text("config/custom_sprites.txt")
|
||||
var/lines = splittext(file, "\n")
|
||||
|
||||
for(var/line in lines)
|
||||
// split & clean up
|
||||
var/list/Entry = splittext(line, ":")
|
||||
for(var/i = 1 to Entry.len)
|
||||
Entry[i] = trim(Entry[i])
|
||||
|
||||
if(Entry.len < 2 || Entry[1] != "hologram")
|
||||
continue
|
||||
|
||||
if (Entry[2] == ckey) //Custom holograms
|
||||
custom_hologram = 1 // option is given in hologram menu
|
||||
if(!custom_hologram)
|
||||
if(ckey in GLOB.configuration.custom_sprites.ai_hologram_ckeys)
|
||||
custom_hologram = TRUE
|
||||
|
||||
var/input
|
||||
switch(alert("Would you like to select a hologram based on a crew member, an animal, or switch to a unique avatar?",,"Crew Member","Unique","Animal"))
|
||||
@@ -1319,7 +1295,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
|
||||
/mob/living/silicon/ai/proc/open_nearest_door(mob/living/target)
|
||||
if(!istype(target))
|
||||
return
|
||||
|
||||
|
||||
if(check_unable(AI_CHECK_WIRELESS))
|
||||
return
|
||||
|
||||
|
||||
@@ -9,8 +9,9 @@ GLOBAL_LIST_EMPTY(empty_playable_ai_cores)
|
||||
if(alert("WARNING: This will immediately wipe your core and ghost you, removing your character from the round permanently (similar to cryo and robotic storage). Are you entirely sure you want to do this?",
|
||||
"Wipe Core", "No", "No", "Yes") != "Yes")
|
||||
return
|
||||
cryo_AI()
|
||||
|
||||
// We warned you.
|
||||
/mob/living/silicon/ai/proc/cryo_AI()
|
||||
GLOB.empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(loc)
|
||||
GLOB.global_announcer.autosay("[src] has been moved to intelligence storage.", "Artificial Intelligence Oversight")
|
||||
|
||||
|
||||
@@ -125,11 +125,10 @@
|
||||
laws.sort_laws()
|
||||
|
||||
/mob/living/silicon/proc/make_laws()
|
||||
switch(config.default_laws)
|
||||
if(0)
|
||||
laws = new /datum/ai_laws/crewsimov()
|
||||
else
|
||||
laws = get_random_lawset()
|
||||
if(GLOB.configuration.general.random_ai_lawset)
|
||||
laws = get_random_lawset()
|
||||
else
|
||||
laws = new /datum/ai_laws/crewsimov()
|
||||
|
||||
/mob/living/silicon/proc/get_random_lawset()
|
||||
var/list/law_options[0]
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
. = ..()
|
||||
. += slowdown
|
||||
. += 1 //A bit slower than humans, so they're easier to smash
|
||||
. += config.robot_delay
|
||||
. += GLOB.configuration.movement.robot_delay
|
||||
|
||||
/mob/living/silicon/pai/update_icons()
|
||||
if(stat == DEAD)
|
||||
@@ -286,21 +286,9 @@
|
||||
|
||||
//check for custom_sprite
|
||||
if(!custom_sprite)
|
||||
var/file = file2text("config/custom_sprites.txt")
|
||||
var/lines = splittext(file, "\n")
|
||||
|
||||
for(var/line in lines)
|
||||
// split & clean up
|
||||
var/list/Entry = splittext(line, ":")
|
||||
for(var/i = 1 to Entry.len)
|
||||
Entry[i] = trim(Entry[i])
|
||||
|
||||
if(Entry.len < 2 || Entry[1] != "pai") //ignore incorrectly formatted entries or entries that aren't marked for pAI
|
||||
continue
|
||||
|
||||
if(Entry[2] == ckey) //They're in the list? Custom sprite time, var and icon change required
|
||||
custom_sprite = 1
|
||||
my_choices["Custom"] = "[ckey]-pai"
|
||||
if(ckey in GLOB.configuration.custom_sprites.pai_holoform_ckeys)
|
||||
custom_sprite = TRUE
|
||||
my_choices["Custom"] = "[ckey]-pai"
|
||||
|
||||
my_choices = possible_chassis.Copy()
|
||||
if(custom_sprite)
|
||||
|
||||
@@ -48,6 +48,8 @@
|
||||
if(brute_damage + electronics_damage >= max_damage)
|
||||
destroy()
|
||||
|
||||
SStgui.update_uis(owner.self_diagnosis)
|
||||
|
||||
/datum/robot_component/proc/heal_damage(brute, electronics, updating_health = TRUE)
|
||||
if(installed != 1)
|
||||
// If it's not installed, can't repair it.
|
||||
@@ -59,6 +61,8 @@
|
||||
brute_damage = max(0, brute_damage - brute)
|
||||
electronics_damage = max(0, electronics_damage - electronics)
|
||||
|
||||
SStgui.update_uis(owner.self_diagnosis)
|
||||
|
||||
/datum/robot_component/proc/is_powered()
|
||||
return (installed == 1) && (brute_damage + electronics_damage < max_damage) && (powered)
|
||||
|
||||
@@ -68,6 +72,8 @@
|
||||
return
|
||||
powered = 1
|
||||
|
||||
SStgui.update_uis(owner.self_diagnosis)
|
||||
|
||||
/datum/robot_component/proc/disable()
|
||||
if(!component_disabled)
|
||||
go_offline()
|
||||
@@ -85,6 +91,8 @@
|
||||
else
|
||||
go_offline()
|
||||
|
||||
SStgui.update_uis(owner.self_diagnosis)
|
||||
|
||||
/datum/robot_component/proc/go_online()
|
||||
return
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
return FALSE
|
||||
notransform = 1
|
||||
canmove = 0
|
||||
icon = null
|
||||
invisibility = 101
|
||||
dust_animation()
|
||||
if(mmi)
|
||||
qdel(mmi) //Delete the MMI first so that it won't go popping out.
|
||||
GLOB.dead_mob_list -= src
|
||||
|
||||
@@ -133,6 +133,16 @@
|
||||
if(emagged)
|
||||
return FALSE
|
||||
|
||||
/mob/living/silicon/robot/drone/detailed_examine()
|
||||
return "Drones are player-controlled synthetics which are lawed to maintain the station and not \
|
||||
interact with anyone else, except for other drones. They hold a wide array of tools to build, repair, maintain, and clean. \
|
||||
They function similarly to other synthetics, in that they require recharging regularly, have laws, and are resilient to many hazards, \
|
||||
such as fire, radiation, vacuum, and more. Ghosts can join the round as a maintenance drone by using the appropriate verb in the 'ghost' tab. \
|
||||
An inactive drone can be rebooted by swiping an ID card on it with engineering or robotics access."
|
||||
|
||||
/mob/living/silicon/robot/drone/detailed_examine_antag()
|
||||
return "An Electromagnetic Sequencer can be used to subvert the drone to your cause."
|
||||
|
||||
//Drones cannot be upgraded with borg modules so we need to catch some items before they get used in ..().
|
||||
/mob/living/silicon/robot/drone/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/borg/upgrade))
|
||||
|
||||
@@ -49,35 +49,6 @@
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/silicon/robot/drone/verb/customize()
|
||||
set name = "Customize Chassis"
|
||||
set desc = "Reconfigure your chassis into a customized version."
|
||||
set category = "Drone"
|
||||
|
||||
if(!custom_sprite) //Check to see if custom sprite time, checking the appopriate file to change a var
|
||||
var/file = file2text("config/custom_sprites.txt")
|
||||
var/lines = splittext(file, "\n")
|
||||
|
||||
for(var/line in lines)
|
||||
// split & clean up
|
||||
var/list/Entry = splittext(line, ":")
|
||||
for(var/i = 1 to Entry.len)
|
||||
Entry[i] = trim(Entry[i])
|
||||
|
||||
if(Entry.len < 2 || Entry[1] != "drone")
|
||||
continue
|
||||
|
||||
if (Entry[2] == ckey) //Custom holograms
|
||||
custom_sprite = 1 // option is given in hologram menu
|
||||
|
||||
if(!custom_sprite)
|
||||
to_chat(src, "<span class='warning'>Error 404: Custom chassis not found. Revoking customization option.</span>")
|
||||
else
|
||||
icon = 'icons/mob/custom_synthetic/custom-synthetic.dmi'
|
||||
icon_state = "[ckey]-drone"
|
||||
to_chat(src, "<span class='notice'>You reconfigure your chassis and improve the station through your new aesthetics.</span>")
|
||||
verbs -= /mob/living/silicon/robot/drone/verb/customize
|
||||
|
||||
/mob/living/silicon/robot/drone/get_scooped(mob/living/carbon/grabber)
|
||||
var/obj/item/holder/H = ..()
|
||||
if(!istype(H))
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#define DRONE_BUILD_TIME 2 MINUTES
|
||||
#define MAX_MAINT_DRONES 5
|
||||
|
||||
/obj/machinery/drone_fabricator
|
||||
name = "drone fabricator"
|
||||
desc = "A large automated factory for producing maintenance drones."
|
||||
@@ -37,14 +40,14 @@
|
||||
|
||||
icon_state = "drone_fab_active"
|
||||
var/elapsed = world.time - time_last_drone
|
||||
drone_progress = clamp(round((elapsed / config.drone_build_time) * 100), 0, 100)
|
||||
drone_progress = clamp(round((elapsed / DRONE_BUILD_TIME) * 100), 0, 100)
|
||||
|
||||
if(drone_progress >= 100)
|
||||
visible_message("[src] voices a strident beep, indicating a drone chassis is prepared.")
|
||||
|
||||
/obj/machinery/drone_fabricator/examine(mob/user)
|
||||
. = ..()
|
||||
if(produce_drones && drone_progress >= 100 && isobserver(user) && config.allow_drone_spawn && count_drones() < config.max_maint_drones)
|
||||
if(produce_drones && drone_progress >= 100 && isobserver(user) && count_drones() < MAX_MAINT_DRONES)
|
||||
. += "<BR><B>A drone is prepared. Select 'Join As Drone' from the Ghost tab to spawn as a maintenance drone.</B>"
|
||||
|
||||
/obj/machinery/drone_fabricator/proc/count_drones()
|
||||
@@ -58,7 +61,7 @@
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
|
||||
if(!produce_drones || !config.allow_drone_spawn || count_drones() >= config.max_maint_drones)
|
||||
if(!produce_drones || count_drones() >= MAX_MAINT_DRONES)
|
||||
return
|
||||
|
||||
if(!player || !isobserver(player.mob))
|
||||
@@ -80,10 +83,6 @@
|
||||
set name = "Join As Drone"
|
||||
set desc = "If there is a powered, enabled fabricator in the game world with a prepared chassis, join as a maintenance drone."
|
||||
|
||||
if(!(config.allow_drone_spawn))
|
||||
to_chat(src, "<span class='warning'>That verb is not currently permitted.</span>")
|
||||
return
|
||||
|
||||
if(stat != DEAD)
|
||||
return
|
||||
|
||||
@@ -99,7 +98,7 @@
|
||||
return
|
||||
|
||||
var/player_age_check = check_client_age(usr.client, 14) // 14 days to play as a drone
|
||||
if(player_age_check && config.use_age_restriction_for_antags)
|
||||
if(player_age_check && GLOB.configuration.gamemode.antag_account_age_restriction)
|
||||
to_chat(usr, "<span class='warning'>This role is not yet available to you. You need to wait another [player_age_check] days.</span>")
|
||||
return
|
||||
|
||||
@@ -141,7 +140,7 @@
|
||||
if(DF.stat & NOPOWER || !DF.produce_drones)
|
||||
continue
|
||||
|
||||
if(DF.count_drones() >= config.max_maint_drones)
|
||||
if(DF.count_drones() >= MAX_MAINT_DRONES)
|
||||
to_chat(src, "<span class='warning'>There are too many active drones in the world for you to spawn.</span>")
|
||||
return
|
||||
|
||||
@@ -150,3 +149,6 @@
|
||||
return
|
||||
|
||||
to_chat(src, "<span class='warning'>There are no available drone spawn points, sorry.</span>")
|
||||
|
||||
#undef DRONE_BUILD_TIME
|
||||
#undef MAX_MAINT_DRONES
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
//Cooldown-inducing emotes
|
||||
if("law","flip","flips","halt") //halt is exempt because it's used to stop criminal scum //WHOEVER THOUGHT THAT WAS A GOOD IDEA IS GOING TO GET SHOT.
|
||||
on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm
|
||||
if("spin","spins")
|
||||
on_CD = handle_emote_CD(5 SECONDS)
|
||||
//Everything else, including typos of the above emotes
|
||||
else
|
||||
on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown
|
||||
@@ -157,8 +159,12 @@
|
||||
message = "<B>[src]</B> does a flip!"
|
||||
src.SpinAnimation(5,1)
|
||||
|
||||
if("spin","spins")
|
||||
spin(20, 1)
|
||||
message = "<B>[src]</B> spins!"
|
||||
|
||||
if("help")
|
||||
to_chat(src, "salute, bow-(none)/mob, clap, flap, aflap, twitch, twitches, nod, deathgasp, glare-(none)/mob, stare-(none)/mob, look,\n law, halt")
|
||||
to_chat(src, "salute, bow-(none)/mob, clap, flap, aflap, twitch, twitches, nod, deathgasp, glare-(none)/mob, stare-(none)/mob, look,\n law, halt, flip, spin")
|
||||
|
||||
..()
|
||||
|
||||
|
||||
@@ -138,6 +138,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
radio = new /obj/item/radio/borg(src)
|
||||
common_radio = radio
|
||||
|
||||
if(!cell) // Make sure a new cell gets created *before* executing initialize_components(). The cell component needs an existing cell for it to get set up properly
|
||||
cell = new default_cell_type(src)
|
||||
|
||||
init(alien, connect_to_AI, ai_to_sync_to)
|
||||
|
||||
if(has_camera && !camera)
|
||||
@@ -151,9 +154,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
mmi = new /obj/item/mmi/robotic_brain(src) //Give the borg an MMI if he spawns without for some reason. (probably not the correct way to spawn a robotic brain, but it works)
|
||||
mmi.icon_state = "boris"
|
||||
|
||||
if(!cell) // Make sure a new cell gets created *before* executing initialize_components(). The cell component needs an existing cell for it to get set up properly
|
||||
cell = new default_cell_type(src)
|
||||
|
||||
initialize_components()
|
||||
//if(!unfinished)
|
||||
// Create all the robot parts.
|
||||
@@ -215,20 +215,8 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
|
||||
//Check for custom sprite
|
||||
if(!custom_sprite)
|
||||
var/file = file2text("config/custom_sprites.txt")
|
||||
var/lines = splittext(file, "\n")
|
||||
|
||||
for(var/line in lines)
|
||||
// split & clean up
|
||||
var/list/Entry = splittext(line, ":")
|
||||
for(var/i = 1 to Entry.len)
|
||||
Entry[i] = trim(Entry[i])
|
||||
|
||||
if(Entry.len < 2 || Entry[1] != "cyborg") //ignore incorrectly formatted entries or entries that aren't marked for cyborg
|
||||
continue
|
||||
|
||||
if(Entry[2] == ckey) //They're in the list? Custom sprite time, var and icon change required
|
||||
custom_sprite = 1
|
||||
if(ckey in GLOB.configuration.custom_sprites.cyborg_ckeys)
|
||||
custom_sprite = TRUE
|
||||
|
||||
if(mmi && mmi.brainmob)
|
||||
mmi.brainmob.name = newname
|
||||
@@ -296,7 +284,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
else
|
||||
to_chat(src, "<span class='boldannounce'>Oops! Something went very wrong, your MMI was unable to receive your mind. You have been ghosted. Please make a bug report so we can fix this bug.</span>")
|
||||
ghostize()
|
||||
error("A borg has been destroyed, but its MMI lacked a brainmob, so the mind could not be transferred. Player: [ckey].")
|
||||
log_runtime(EXCEPTION("A borg has been destroyed, but its MMI lacked a brainmob, so the mind could not be transferred. Player: [ckey]."), src)
|
||||
mmi = null
|
||||
if(connected_ai)
|
||||
connected_ai.connected_robots -= src
|
||||
@@ -306,6 +294,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
QDEL_NULL(cell)
|
||||
QDEL_NULL(robot_suit)
|
||||
QDEL_NULL(spark_system)
|
||||
QDEL_NULL(self_diagnosis)
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/proc/pick_module()
|
||||
@@ -506,30 +495,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
set name = "Show Station Manifest"
|
||||
show_station_manifest()
|
||||
|
||||
/mob/living/silicon/robot/proc/self_diagnosis()
|
||||
if(!is_component_functioning("diagnosis unit"))
|
||||
return null
|
||||
|
||||
var/dat = "<HEAD><TITLE>[src.name] Self-Diagnosis Report</TITLE></HEAD><BODY>\n"
|
||||
for(var/V in components)
|
||||
var/datum/robot_component/C = components[V]
|
||||
if(C.installed == 0)
|
||||
dat += "<b>[C.name]</b><br>MISSING<br>"
|
||||
else
|
||||
dat += "<b>[C.name]</b>[C.installed == -1 ? "<br>DESTROYED" : ""]<br><table><tr><td>Brute Damage:</td><td>[C.brute_damage]</td></tr><tr><td>Electronics Damage:</td><td>[C.electronics_damage]</td></tr><tr><td>Powered:</td><td>[C.is_powered() ? "Yes" : "No"]</td></tr><tr><td>Toggled:</td><td>[ C.toggled ? "Yes" : "No"]</td></table><br>"
|
||||
return dat
|
||||
|
||||
/mob/living/silicon/robot/verb/self_diagnosis_verb()
|
||||
set category = "Robot Commands"
|
||||
set name = "Self Diagnosis"
|
||||
|
||||
if(!is_component_functioning("diagnosis unit"))
|
||||
to_chat(src, "<span class='warning'>Your self-diagnosis component isn't functioning.</span>")
|
||||
|
||||
var/dat = self_diagnosis()
|
||||
src << browse(dat, "window=robotdiagnosis")
|
||||
|
||||
|
||||
/mob/living/silicon/robot/verb/toggle_component()
|
||||
set category = "Robot Commands"
|
||||
set name = "Toggle Component"
|
||||
|
||||
@@ -385,7 +385,7 @@
|
||||
/obj/item/holosign_creator/engineering,
|
||||
/obj/item/gripper,
|
||||
/obj/item/matter_decompiler,
|
||||
/obj/item/floor_painter,
|
||||
/obj/item/painter,
|
||||
/obj/item/areaeditor/blueprints/cyborg,
|
||||
/obj/item/stack/sheet/metal/cyborg,
|
||||
/obj/item/stack/rods/cyborg,
|
||||
@@ -416,7 +416,11 @@
|
||||
/obj/item/clothing/mask/gas/sechailer/cyborg
|
||||
)
|
||||
emag_modules = list(/obj/item/gun/energy/laser/cyborg)
|
||||
special_rechargables = list(/obj/item/melee/baton/loaded, /obj/item/gun/energy/disabler/cyborg)
|
||||
special_rechargables = list(
|
||||
/obj/item/melee/baton/loaded,
|
||||
/obj/item/gun/energy/disabler/cyborg,
|
||||
/obj/item/gun/energy/laser/cyborg
|
||||
)
|
||||
|
||||
/obj/item/robot_module/security/update_cells(unlink_cell = FALSE)
|
||||
var/obj/item/melee/baton/B = locate(/obj/item/melee/baton/loaded) in modules
|
||||
@@ -566,6 +570,7 @@
|
||||
/obj/item/gun/energy/pulse/cyborg,
|
||||
/obj/item/crowbar/cyborg
|
||||
)
|
||||
special_rechargables = list(/obj/item/gun/energy/pulse/cyborg)
|
||||
|
||||
// Sydicate assault cyborg module.
|
||||
/obj/item/robot_module/syndicate
|
||||
@@ -658,7 +663,10 @@
|
||||
/obj/item/pickaxe/drill/jackhammer, // for breaking walls to execute flanking moves
|
||||
/obj/item/borg/destroyer/mobility
|
||||
)
|
||||
special_rechargables = list(/obj/item/melee/baton/loaded)
|
||||
special_rechargables = list(
|
||||
/obj/item/melee/baton/loaded,
|
||||
/obj/item/gun/energy/immolator/multi/cyborg
|
||||
)
|
||||
|
||||
/obj/item/robot_module/combat
|
||||
name = "combat robot module"
|
||||
@@ -674,7 +682,10 @@
|
||||
/obj/item/restraints/handcuffs/cable/zipties/cyborg,
|
||||
/obj/item/pickaxe/drill/jackhammer // for breaking walls to execute flanking moves
|
||||
)
|
||||
special_rechargables = list(/obj/item/melee/baton/loaded)
|
||||
special_rechargables = list(
|
||||
/obj/item/melee/baton/loaded,
|
||||
/obj/item/gun/energy/immolator/multi/cyborg
|
||||
)
|
||||
|
||||
// Xenomorph cyborg module.
|
||||
/obj/item/robot_module/alien/hunter
|
||||
@@ -716,6 +727,7 @@
|
||||
/obj/item/soap,
|
||||
/obj/item/t_scanner,
|
||||
/obj/item/rpd,
|
||||
/obj/item/analyzer,
|
||||
/obj/item/stack/sheet/metal/cyborg,
|
||||
/obj/item/stack/rods/cyborg,
|
||||
/obj/item/stack/tile/plasteel/cyborg,
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
. += speed
|
||||
if(module_active && istype(module_active,/obj/item/borg/destroyer/mobility))
|
||||
. -= 3
|
||||
. += config.robot_delay
|
||||
. += GLOB.configuration.movement.robot_delay
|
||||
|
||||
/mob/living/silicon/robot/mob_negates_gravity()
|
||||
return magpulse
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
var/list/stating_laws = list()// Channels laws are currently being stated on
|
||||
var/list/alarms_to_show = list()
|
||||
var/list/alarms_to_clear = list()
|
||||
var/list/alarm_types_show = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0)
|
||||
var/list/alarm_types_clear = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0)
|
||||
var/list/alarms_listend_for = list("Motion", "Fire", "Atmosphere", "Power", "Camera")
|
||||
var/list/alarm_types_show = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0)
|
||||
var/list/alarm_types_clear = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0)
|
||||
var/list/alarms_listend_for = list("Motion", "Fire", "Atmosphere", "Power")
|
||||
//var/list/hud_list[10]
|
||||
var/list/speech_synthesizer_langs = list() //which languages can be vocalized by the speech synthesizer
|
||||
var/designation = ""
|
||||
@@ -61,6 +61,10 @@
|
||||
|
||||
/mob/living/silicon/Destroy()
|
||||
GLOB.silicon_mob_list -= src
|
||||
QDEL_NULL(atmos_control)
|
||||
QDEL_NULL(crew_monitor)
|
||||
QDEL_NULL(law_manager)
|
||||
QDEL_NULL(power_monitor)
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/proc/alarm_triggered(src, class, area/A, list/O, obj/alarmsource)
|
||||
@@ -106,9 +110,6 @@
|
||||
if(alarm_types_show["Power"])
|
||||
msg += "POWER: [alarm_types_show["Power"]] alarms detected. - "
|
||||
|
||||
if(alarm_types_show["Camera"])
|
||||
msg += "CAMERA: [alarm_types_show["Camera"]] alarms detected. - "
|
||||
|
||||
msg += "<A href=?src=[UID()];showalerts=1'>\[Show Alerts\]</a>"
|
||||
var/msg_text = msg.Join("")
|
||||
to_chat(src, msg_text)
|
||||
@@ -132,9 +133,6 @@
|
||||
if(alarm_types_clear["Power"])
|
||||
msg += "POWER: [alarm_types_clear["Power"]] alarms cleared. - "
|
||||
|
||||
if(alarm_types_show["Camera"])
|
||||
msg += "CAMERA: [alarm_types_clear["Camera"]] alarms cleared. - "
|
||||
|
||||
msg += "<A href=?src=[UID()];showalerts=1'>\[Show Alerts\]</a>"
|
||||
|
||||
var/msg_text = msg.Join("")
|
||||
|
||||
@@ -18,8 +18,16 @@
|
||||
/mob/living/silicon/proc/subsystem_power_monitor
|
||||
)
|
||||
|
||||
/mob/living/silicon/robot
|
||||
var/datum/ui_module/robot_self_diagnosis/self_diagnosis
|
||||
silicon_subsystems = list(
|
||||
/mob/living/silicon/robot/proc/self_diagnosis,
|
||||
/mob/living/silicon/proc/subsystem_law_manager
|
||||
)
|
||||
|
||||
/mob/living/silicon/robot/drone
|
||||
silicon_subsystems = list(
|
||||
/mob/living/silicon/robot/proc/self_diagnosis,
|
||||
/mob/living/silicon/proc/subsystem_law_manager,
|
||||
/mob/living/silicon/proc/subsystem_power_monitor
|
||||
)
|
||||
@@ -33,6 +41,10 @@
|
||||
law_manager = new(src)
|
||||
power_monitor = new(src)
|
||||
|
||||
/mob/living/silicon/robot/init_subsystems()
|
||||
. = ..()
|
||||
self_diagnosis = new(src)
|
||||
|
||||
/********************
|
||||
* Atmos Control *
|
||||
********************/
|
||||
@@ -68,3 +80,12 @@
|
||||
|
||||
power_monitor.ui_interact(usr, state = GLOB.self_state)
|
||||
|
||||
/mob/living/silicon/robot/proc/self_diagnosis()
|
||||
set category = "Robot Commands"
|
||||
set name = "Self Diagnosis"
|
||||
|
||||
if(!is_component_functioning("diagnosis unit"))
|
||||
to_chat(src, "<span class='warning'>Your self-diagnosis component isn't functioning.</span>")
|
||||
return
|
||||
|
||||
self_diagnosis.ui_interact(src)
|
||||
|
||||
@@ -139,12 +139,22 @@
|
||||
update_controls()
|
||||
|
||||
/mob/living/simple_animal/bot/New()
|
||||
/*
|
||||
HEY! LISTEN!
|
||||
|
||||
I see you're poking the the bot/New() proc
|
||||
Assuming you are converting this to Initialize() [yay], please see my note in
|
||||
code\game\jobs\job\job.dm | /datum/job/proc/get_access()
|
||||
|
||||
Theres a useless check that bugs me but needs to exist because these things New()
|
||||
-AA07
|
||||
*/
|
||||
..()
|
||||
GLOB.bots_list += src
|
||||
icon_living = icon_state
|
||||
icon_dead = icon_state
|
||||
access_card = new /obj/item/card/id(src)
|
||||
//This access is so bots can be immediately set to patrol and leave Robotics, instead of having to be let out first.
|
||||
//This access is so bots can be immediately set to patrol and leave Robotics, instead of having to be let out first.
|
||||
access_card.access += ACCESS_ROBOTICS
|
||||
set_custom_texts()
|
||||
Radio = new/obj/item/radio/headset/bot(src)
|
||||
|
||||
@@ -94,6 +94,17 @@
|
||||
/mob/living/simple_animal/hostile/construct/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/Life(seconds, times_fired)
|
||||
if(holy_check(src))
|
||||
throw_alert("holy_fire", /obj/screen/alert/holy_fire, override = TRUE)
|
||||
visible_message("<span class='danger'>[src] slowly crumbles to dust in this holy place!</span>", \
|
||||
"<span class='danger'>Your shell burns as you crumble to dust in this holy place!</span>")
|
||||
playsound(loc, 'sound/items/welder.ogg', 150, TRUE)
|
||||
adjustBruteLoss(maxHealth/8)
|
||||
else
|
||||
clear_alert("holy_fire", clear_override = TRUE)
|
||||
return ..()
|
||||
|
||||
/////////////////Juggernaut///////////////
|
||||
|
||||
|
||||
|
||||
@@ -21,13 +21,16 @@
|
||||
var/yelp_sound = 'sound/creatures/dog_yelp.ogg' //Used on death.
|
||||
var/last_eaten = 0
|
||||
footstep_type = FOOTSTEP_MOB_CLAW
|
||||
var/next_spin_message = 0
|
||||
|
||||
/mob/living/simple_animal/pet/dog/verb/chasetail()
|
||||
set name = "Chase your tail"
|
||||
set desc = "d'awwww."
|
||||
set category = "Dog"
|
||||
|
||||
visible_message("[src] [pick("dances around", "chases [p_their()] tail")].", "[pick("You dance around", "You chase your tail")].")
|
||||
if(next_spin_message <= world.time)
|
||||
visible_message("[src] [pick("dances around", "chases [p_their()] tail")].", "[pick("You dance around", "You chase your tail")].")
|
||||
next_spin_message = world.time + 5 SECONDS
|
||||
spin(20, 1)
|
||||
|
||||
/mob/living/simple_animal/pet/dog/death(gibbed)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
can_collar = 1
|
||||
blood_volume = BLOOD_VOLUME_NORMAL
|
||||
var/obj/item/udder/udder = null
|
||||
gender = FEMALE
|
||||
footstep_type = FOOTSTEP_MOB_SHOE
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/New()
|
||||
@@ -114,7 +115,7 @@
|
||||
icon_living = "cow"
|
||||
icon_dead = "cow_dead"
|
||||
icon_gib = "cow_gib"
|
||||
speak = list("moo?","moo","MOOOOOO")
|
||||
speak = list("Moo?","Moo","MOOOOOO")
|
||||
speak_emote = list("moos","moos hauntingly")
|
||||
emote_hear = list("brays")
|
||||
emote_see = list("shakes its head")
|
||||
|
||||
@@ -81,8 +81,8 @@
|
||||
pixel_y = 8
|
||||
|
||||
if(is_type_in_typecache(get_area(loc), invalid_area_typecache))
|
||||
var/area = pick(GLOB.teleportlocs)
|
||||
var/area/tp = GLOB.teleportlocs[area]
|
||||
var/area = pick(SSmapping.teleportlocs)
|
||||
var/area/tp = SSmapping.teleportlocs[area]
|
||||
forceMove(pick(get_area_turfs(tp.type)))
|
||||
|
||||
if((!current_victim && !admincluwne) || QDELETED(current_victim))
|
||||
|
||||
@@ -56,6 +56,12 @@
|
||||
for(var/obj/structure/spider/S in range(1, get_turf(src)))
|
||||
return S
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/giant_spider/death(gibbed)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
SSmobs.giant_spiders--
|
||||
|
||||
//nursemaids - these create webs and eggs
|
||||
/mob/living/simple_animal/hostile/poison/giant_spider/nurse
|
||||
desc = "Furry and black, it makes you shudder to look at it. This one has brilliant green eyes."
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
/mob/living/simple_animal/hostile/headcrab
|
||||
name = "headcrab"
|
||||
desc = "A small parasitic creature that would like to connect with your brain stem."
|
||||
icon = 'icons/mob/headcrab.dmi'
|
||||
icon_state = "headcrab"
|
||||
icon_living = "headcrab"
|
||||
icon_dead = "headcrab_dead"
|
||||
health = 60
|
||||
maxHealth = 60
|
||||
dodging = 1
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 10
|
||||
ranged = 1
|
||||
ranged_message = "leaps"
|
||||
ranged_cooldown_time = 40
|
||||
var/jumpdistance = 4
|
||||
var/jumpspeed = 1
|
||||
attacktext = "bites"
|
||||
attack_sound = 'sound/creatures/headcrab_attack.ogg'
|
||||
speak_emote = list("hisses")
|
||||
var/is_zombie = 0
|
||||
stat_attack = DEAD // Necessary for them to attack (zombify) dead humans
|
||||
robust_searching = 1
|
||||
var/host_species = ""
|
||||
var/list/human_overlays = list()
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/Life(seconds, times_fired)
|
||||
if(..() && !stat)
|
||||
if(!is_zombie && isturf(src.loc))
|
||||
for(var/mob/living/carbon/human/H in oview(src, 1)) //Only for corpse right next to/on same tile
|
||||
if(H.stat == DEAD || (!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD))
|
||||
Zombify(H)
|
||||
break
|
||||
if(times_fired % 4 == 0)
|
||||
for(var/mob/living/simple_animal/K in oview(src, 1)) //Only for corpse right next to/on same tile
|
||||
if(K.stat == DEAD || (!K.check_death_method() && K.health <= HEALTH_THRESHOLD_DEAD))
|
||||
visible_message("<span class='danger'>[src] consumes [K] whole!</span>")
|
||||
if(health < maxHealth)
|
||||
health += 10
|
||||
qdel(K)
|
||||
break
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/OpenFire(atom/A)
|
||||
if(check_friendly_fire)
|
||||
for(var/turf/T in getline(src,A)) // Not 100% reliable but this is faster than simulating actual trajectory
|
||||
for(var/mob/living/L in T)
|
||||
if(L == src || L == A)
|
||||
continue
|
||||
if(faction_check_mob(L) && !attack_same)
|
||||
return
|
||||
visible_message("<span class='danger'><b>[src]</b> [ranged_message] at [A]!</span>")
|
||||
throw_at(A, jumpdistance, jumpspeed, spin = FALSE, diagonals_first = TRUE)
|
||||
ranged_cooldown = world.time + ranged_cooldown_time
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/proc/Zombify(mob/living/carbon/human/H)
|
||||
if(!H.check_death_method())
|
||||
H.death()
|
||||
var/obj/item/organ/external/head/head_organ = H.get_organ("head")
|
||||
is_zombie = TRUE
|
||||
if(H.wear_suit)
|
||||
var/obj/item/clothing/suit/armor/A = H.wear_suit
|
||||
if(A.armor && A.armor.getRating("melee"))
|
||||
maxHealth += A.armor.getRating("melee") //That zombie's got armor, I want armor!
|
||||
maxHealth += 200
|
||||
health = maxHealth
|
||||
name = "zombie"
|
||||
desc = "A corpse animated by the alien being on its head."
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 15
|
||||
ranged = 0
|
||||
stat_attack = CONSCIOUS // Disables their targeting of dead mobs once they're already a zombie
|
||||
icon = H.icon
|
||||
speak = list('sound/creatures/zombie_idle1.ogg','sound/creatures/zombie_idle2.ogg','sound/creatures/zombie_idle3.ogg')
|
||||
speak_chance = 50
|
||||
speak_emote = list("groans")
|
||||
attacktext = "bites"
|
||||
attack_sound = 'sound/creatures/zombie_attack.ogg'
|
||||
icon_state = "zombie2_s"
|
||||
if(head_organ && !(NO_HAIR in H.dna.species.species_traits))
|
||||
head_organ.h_style = null
|
||||
H.update_hair()
|
||||
host_species = H.dna.species.name
|
||||
human_overlays = H.overlays
|
||||
update_icons()
|
||||
H.forceMove(src)
|
||||
visible_message("<span class='warning'>The corpse of [H.name] suddenly rises!</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/death()
|
||||
..()
|
||||
if(is_zombie)
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/handle_automated_speech() // This way they have different screams when attacking, sometimes. Might be seen as sphagetthi code though.
|
||||
if(speak_chance)
|
||||
if(rand(0,200) < speak_chance)
|
||||
if(speak && speak.len)
|
||||
playsound(get_turf(src), pick(speak), 200, 1)
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/Destroy()
|
||||
if(contents)
|
||||
for(var/mob/M in contents)
|
||||
M.loc = get_turf(src)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/update_icons()
|
||||
. = ..()
|
||||
if(is_zombie)
|
||||
overlays.Cut()
|
||||
overlays = human_overlays
|
||||
var/image/I = image('icons/mob/headcrab.dmi', icon_state = "headcrabpod")
|
||||
if(host_species == "Vox")
|
||||
I = image('icons/mob/headcrab.dmi', icon_state = "headcrabpod_vox")
|
||||
else if(host_species == "Gray")
|
||||
I = image('icons/mob/headcrab.dmi', icon_state = "headcrabpod_gray")
|
||||
overlays += I
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/CanAttack(atom/the_target)
|
||||
if(stat_attack == DEAD && isliving(the_target) && !ishuman(the_target))
|
||||
var/mob/living/L = the_target
|
||||
if(L.stat == DEAD)
|
||||
// Override default behavior of stat_attack, to stop headcrabs targeting dead mobs they cannot infect, such as silicons.
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/fast
|
||||
name = "fast headcrab"
|
||||
desc = "A fast parasitic creature that would like to connect with your brain stem."
|
||||
icon = 'icons/mob/headcrab.dmi'
|
||||
icon_state = "fast_headcrab"
|
||||
icon_living = "fast_headcrab"
|
||||
icon_dead = "fast_headcrab_dead"
|
||||
health = 40
|
||||
maxHealth = 40
|
||||
ranged_cooldown_time = 30
|
||||
jumpdistance = 8
|
||||
jumpspeed = 2
|
||||
speak_emote = list("screech")
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/fast/update_icons()
|
||||
. = ..()
|
||||
if(is_zombie)
|
||||
overlays.Cut()
|
||||
overlays = human_overlays
|
||||
var/image/I = image('icons/mob/headcrab.dmi', icon_state = "fast_headcrabpod")
|
||||
if(host_species == "Vox")
|
||||
I = image('icons/mob/headcrab.dmi', icon_state = "fast_headcrabpod_vox")
|
||||
else if(host_species == "Gray")
|
||||
I = image('icons/mob/headcrab.dmi', icon_state = "fast_headcrabpod_gray")
|
||||
overlays += I
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/fast/Zombify(mob/living/carbon/human/H)
|
||||
. = ..()
|
||||
speak = list('sound/creatures/fast_zombie_idle1.ogg','sound/creatures/fast_zombie_idle2.ogg','sound/creatures/fast_zombie_idle3.ogg')
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/poison
|
||||
name = "poison headcrab"
|
||||
desc = "A poison parasitic creature that would like to connect with your brain stem."
|
||||
icon = 'icons/mob/headcrab.dmi'
|
||||
icon_state = "poison_headcrab"
|
||||
icon_living = "poison_headcrab"
|
||||
icon_dead = "poison_headcrab_dead"
|
||||
health = 80
|
||||
maxHealth = 80
|
||||
ranged_cooldown_time = 50
|
||||
jumpdistance = 3
|
||||
jumpspeed = 1
|
||||
melee_damage_lower = 8
|
||||
melee_damage_upper = 20
|
||||
attack_sound = 'sound/creatures/ph_scream1.ogg'
|
||||
speak_emote = list("screech")
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/poison/update_icons()
|
||||
. = ..()
|
||||
if(is_zombie)
|
||||
overlays.Cut()
|
||||
overlays = human_overlays
|
||||
var/image/I = image('icons/mob/headcrab.dmi', icon_state = "poison_headcrabpod")
|
||||
if(host_species == "Vox")
|
||||
I = image('icons/mob/headcrab.dmi', icon_state = "poison_headcrabpod_vox")
|
||||
else if(host_species == "Gray")
|
||||
I = image('icons/mob/headcrab.dmi', icon_state = "poison_headcrabpod_gray")
|
||||
overlays += I
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/headcrab/poison/AttackingTarget()
|
||||
. = ..()
|
||||
if(iscarbon(target) && target.reagents)
|
||||
var/inject_target = pick("chest", "head")
|
||||
var/mob/living/carbon/C = target
|
||||
if(C.stunned || C.can_inject(null, FALSE, inject_target, FALSE))
|
||||
if(C.eye_blurry < 60)
|
||||
C.AdjustEyeBlurry(10)
|
||||
visible_message("<span class='danger'>[src] buries its fangs deep into the [inject_target] of [target]!</span>")
|
||||
@@ -408,7 +408,7 @@ Difficulty: Hard
|
||||
/obj/effect/decal/cleanable/blood/gibs/bubblegum/can_bloodcrawl_in()
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A, visual_effect_icon)
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
|
||||
if(!charging)
|
||||
..()
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@
|
||||
M.Weaken(4) // 8 seconds.
|
||||
if(iscarbon(M))
|
||||
web_special_ability(M)
|
||||
addtimer(CALLBACK(src, .proc/after_carbon_crossed, M), 0.7 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
|
||||
addtimer(CALLBACK(src, .proc/after_carbon_crossed, M), 7 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
|
||||
|
||||
/**
|
||||
* Called some time after a carbon mob crossed the terror web.
|
||||
|
||||
@@ -42,6 +42,6 @@
|
||||
to_chat(user, "<span class='notice'>Someone else already took this spider.</span>")
|
||||
return
|
||||
key = user.key
|
||||
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Terror_Spider)</span>")
|
||||
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Terror_Spider)</span>")
|
||||
for(var/mob/dead/observer/G in GLOB.player_list)
|
||||
G.show_message("<i>A ghost has taken control of <b>[src]</b>. ([ghost_follow_link(src, ghost=G)]).</i>")
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
regen_points_per_kill = 200 // >2x normal, since they're food reprocessors
|
||||
idle_ventcrawl_chance = 5
|
||||
spider_tier = TS_TIER_3
|
||||
loudspeaker = TRUE
|
||||
spider_opens_doors = 2
|
||||
web_type = /obj/structure/spider/terrorweb/mother
|
||||
var/datum/action/innate/terrorspider/ventsmash/ventsmash_action
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
environment_smash = ENVIRONMENT_SMASH_RWALLS
|
||||
idle_ventcrawl_chance = 0
|
||||
spider_tier = TS_TIER_3
|
||||
loudspeaker = TRUE
|
||||
spider_opens_doors = 2
|
||||
web_type = /obj/structure/spider/terrorweb/purple
|
||||
ai_spins_webs = FALSE
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
projectilesound = 'sound/weapons/pierce.ogg'
|
||||
projectiletype = /obj/item/projectile/terrorqueenspit
|
||||
spider_tier = TS_TIER_4
|
||||
loudspeaker = TRUE
|
||||
spider_opens_doors = 2
|
||||
web_type = /obj/structure/spider/terrorweb/queen
|
||||
var/spider_spawnfrequency = 1200 // 120 seconds. Default for player queens and NPC queens on station. Awaymission queens have this changed in New()
|
||||
|
||||
@@ -137,6 +137,8 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
|
||||
var/killcount = 0
|
||||
var/busy = 0 // leave this alone!
|
||||
var/spider_tier = TS_TIER_1 // 1 for red,gray,green. 2 for purple,black,white, 3 for prince, mother. 4 for queen
|
||||
/// Does this terror speak loudly on the terror hivemind?
|
||||
var/loudspeaker = FALSE
|
||||
var/hasdied = 0
|
||||
var/list/spider_special_drops = list()
|
||||
var/attackstep = 0
|
||||
@@ -312,6 +314,8 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/Destroy()
|
||||
GLOB.ts_spiderlist -= src
|
||||
var/datum/atom_hud/U = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
U.remove_hud_from(src)
|
||||
handle_dying()
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 15
|
||||
spider_tier = TS_TIER_2
|
||||
loudspeaker = TRUE
|
||||
web_type = /obj/structure/spider/terrorweb/white
|
||||
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
name = "venus human trap"
|
||||
desc = "Now you know how the fly feels."
|
||||
icon_state = "venus_human_trap"
|
||||
icon_living = "venus_human_trap"
|
||||
mob_biotypes = MOB_ORGANIC | MOB_PLANT
|
||||
layer = MOB_LAYER + 0.9
|
||||
health = 50
|
||||
|
||||
@@ -332,7 +332,7 @@
|
||||
. = speed
|
||||
if(forced_look)
|
||||
. += 3
|
||||
. += config.animal_delay
|
||||
. += GLOB.configuration.movement.animal_delay
|
||||
|
||||
/mob/living/simple_animal/Stat()
|
||||
..()
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
if(health <= 0) // if damaged, the slime moves twice as slow
|
||||
. *= 2
|
||||
|
||||
. += config.slime_delay
|
||||
. += GLOB.configuration.movement.slime_delay
|
||||
|
||||
/mob/living/simple_animal/slime/update_health_hud()
|
||||
if(hud_used)
|
||||
|
||||
@@ -211,11 +211,12 @@
|
||||
|
||||
/mob/living/SetEyeBlurry(amount, updating = TRUE)
|
||||
. = STATUS_UPDATE_BLURRY
|
||||
if((!!amount) == (!!eye_blurry)) // We're not changing from + to 0 or vice versa
|
||||
//if they're both above max or equal that means we won't change the blur filter
|
||||
if(amount > MAX_EYE_BLURRY_FILTER_SIZE / EYE_BLUR_TO_FILTER_SIZE_MULTIPLIER && eye_blurry > MAX_EYE_BLURRY_FILTER_SIZE / EYE_BLUR_TO_FILTER_SIZE_MULTIPLIER || eye_blurry == amount)
|
||||
updating = FALSE
|
||||
. = STATUS_UPDATE_NONE
|
||||
|
||||
eye_blurry = max(amount, 0)
|
||||
// We transitioned to/from 0, so update the eye blur overlays
|
||||
if(updating)
|
||||
update_blurry_effects()
|
||||
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
return 0
|
||||
|
||||
/mob/living/update_blurry_effects()
|
||||
if(eyes_blurred())
|
||||
overlay_fullscreen("blurry", /obj/screen/fullscreen/blurry)
|
||||
return 1
|
||||
var/atom/movable/plane_master_controller/game_plane_master_controller = hud_used?.plane_master_controllers[PLANE_MASTERS_GAME]
|
||||
if(!game_plane_master_controller)
|
||||
return
|
||||
if(eye_blurry)
|
||||
game_plane_master_controller.add_filter("eye_blur", 1, gauss_blur_filter(clamp(eye_blurry * EYE_BLUR_TO_FILTER_SIZE_MULTIPLIER, 0.6, MAX_EYE_BLURRY_FILTER_SIZE)))
|
||||
else
|
||||
clear_fullscreen("blurry")
|
||||
return 0
|
||||
game_plane_master_controller.remove_filter("eye_blur")
|
||||
|
||||
/mob/living/update_druggy_effects()
|
||||
if(druggy)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
log_access_in(client)
|
||||
create_attack_log("<font color='red'>Logged in at [atom_loc_line(get_turf(src))]</font>")
|
||||
create_log(MISC_LOG, "Logged in")
|
||||
if(config.log_access)
|
||||
if(GLOB.configuration.logging.access_logging)
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M == src) continue
|
||||
if( M.key && (M.key != key) )
|
||||
@@ -16,7 +16,7 @@
|
||||
if( (M.computer_id == client.computer_id) )
|
||||
if(matches) matches += " and "
|
||||
matches += "ID ([client.computer_id])"
|
||||
if(!config.disable_cid_warn_popup)
|
||||
if(!GLOB.configuration.general.disable_cid_warning_popup)
|
||||
spawn() alert("You have logged in already with another key this round, please log out of this one NOW or risk being banned!")
|
||||
if(matches)
|
||||
if(M.client)
|
||||
@@ -68,9 +68,5 @@
|
||||
for(var/datum/alternate_appearance/AA in viewing_alternate_appearances)
|
||||
AA.display_to(list(src))
|
||||
|
||||
if(!fexists("config/config.txt") || !fexists("config/game_options.txt"))
|
||||
to_chat(src, "<span class='biggerdanger'>The game config files have not been properly set!\n Please copy ALL files from '/config/example' into the parent folder, '/config'.</span>")
|
||||
log_world("The game config files have not been properly set! Please copy ALL files from /config/example into the parent folder, /config.")
|
||||
|
||||
update_client_colour(0)
|
||||
update_morgue()
|
||||
|
||||
@@ -7,14 +7,18 @@
|
||||
create_log(MISC_LOG, "Logged out")
|
||||
// `holder` is nil'd out by now, so we check the `admin_datums` array directly
|
||||
//Only report this stuff if we are currently playing.
|
||||
if(GLOB.admin_datums[ckey] && SSticker && SSticker.current_state == GAME_STATE_PLAYING)
|
||||
if(GLOB.admin_datums[ckey] && SSticker.current_state == GAME_STATE_PLAYING)
|
||||
var/datum/admins/temp_admin = GLOB.admin_datums[ckey]
|
||||
// Triggers on people with banhammer power only - no mentors tripping the alarm
|
||||
if(temp_admin.rights & R_BAN)
|
||||
if(temp_admin.rights & R_MENTOR)
|
||||
var/list/mentorcounter = staff_countup(R_MENTOR)
|
||||
if(mentorcounter[1] == 0) // No active mentors
|
||||
SSdiscord.send2discord_simple(DISCORD_WEBHOOK_MENTOR, "[key_name(src)] logged out - 0 active mentors, [mentorcounter[2]] non-mentor staff, [mentorcounter[3]] inactive mentors.")
|
||||
|
||||
else if(temp_admin.rights & R_BAN)
|
||||
message_admins("Admin logout: [key_name_admin(src)]")
|
||||
var/list/admincounter = staff_countup(R_BAN)
|
||||
if(admincounter[1] == 0) // No active admins
|
||||
SSdiscord.send2discord_simple(DISCORD_WEBHOOK_ADMIN, "[key_name(src)] logged out - No active admins, [admincounter[2]] non-admin staff, [admincounter[3]] inactive staff.")
|
||||
SSdiscord.send2discord_simple(DISCORD_WEBHOOK_ADMIN, "[key_name(src)] logged out - 0 active admins, [admincounter[2]] non-admin staff, [admincounter[3]] inactive staff.")
|
||||
|
||||
..()
|
||||
update_morgue()
|
||||
|
||||
+41
-15
@@ -8,6 +8,7 @@
|
||||
spellremove(src)
|
||||
mobspellremove(src)
|
||||
QDEL_LIST(viruses)
|
||||
QDEL_LIST(actions)
|
||||
ghostize()
|
||||
QDEL_LIST_ASSOC_VAL(tkgrabbed_objects)
|
||||
for(var/I in tkgrabbed_objects)
|
||||
@@ -20,6 +21,7 @@
|
||||
AA.viewers -= src
|
||||
viewing_alternate_appearances = null
|
||||
LAssailant = null
|
||||
runechat_msg_location = null
|
||||
return ..()
|
||||
|
||||
/mob/Initialize(mapload)
|
||||
@@ -749,7 +751,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
|
||||
set name = "Respawn"
|
||||
set category = "OOC"
|
||||
|
||||
if(!GLOB.abandon_allowed)
|
||||
if(!GLOB.configuration.general.respawn_enabled)
|
||||
to_chat(usr, "<span class='warning'>Respawning is disabled.</span>")
|
||||
return
|
||||
|
||||
@@ -1007,7 +1009,8 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
|
||||
|
||||
// this function displays the station time in the status panel
|
||||
/mob/proc/show_stat_station_time()
|
||||
stat(null, "Round Time: [worldtime2text()]")
|
||||
stat(null, "Server Uptime: [worldtime2text()]")
|
||||
stat(null, "Round Time: [ROUND_TIME ? time2text(ROUND_TIME, "hh:mm:ss") : "N/A"]")
|
||||
stat(null, "Station Time: [station_time_timestamp()]")
|
||||
|
||||
// this function displays the shuttles ETA in the status panel if the shuttle has been called
|
||||
@@ -1352,20 +1355,14 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
|
||||
set waitfor = 0
|
||||
if(!spintime || !speed || spintime > 100)
|
||||
CRASH("Aborted attempted call of /mob/proc/spin with invalid args ([spintime],[speed]) which could have frozen the server.")
|
||||
var/D = dir
|
||||
while(spintime >= speed)
|
||||
var/end_time = world.time + spintime
|
||||
var/spin_dir = prob(50)
|
||||
while(world.time <= end_time)
|
||||
sleep(speed)
|
||||
switch(D)
|
||||
if(NORTH)
|
||||
D = EAST
|
||||
if(SOUTH)
|
||||
D = WEST
|
||||
if(EAST)
|
||||
D = SOUTH
|
||||
if(WEST)
|
||||
D = NORTH
|
||||
setDir(D)
|
||||
spintime -= speed
|
||||
if(spin_dir)
|
||||
dir = turn(dir, 90)
|
||||
else
|
||||
dir = turn(dir, -90)
|
||||
|
||||
/mob/proc/is_literate()
|
||||
return FALSE
|
||||
@@ -1481,3 +1478,32 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
|
||||
MA.plane = GAME_PLANE
|
||||
pic.appearance = MA
|
||||
flick_overlay(pic, list(client), 10)
|
||||
|
||||
|
||||
GLOBAL_LIST_INIT(holy_areas, typecacheof(list(
|
||||
/area/chapel
|
||||
)))
|
||||
|
||||
/mob/proc/holy_check()
|
||||
if(!is_type_in_typecache(loc.loc, GLOB.holy_areas))
|
||||
return FALSE
|
||||
|
||||
if(!mind)
|
||||
return FALSE
|
||||
|
||||
//Allows fullpower vampires to bypass holy areas
|
||||
var/datum/vampire/vampire = mind.vampire
|
||||
if(vampire && vampire.get_ability(/datum/vampire_passive/full))
|
||||
return FALSE
|
||||
|
||||
//Allows cult to bypass holy areas once they summon
|
||||
var/datum/game_mode/gamemode = SSticker.mode
|
||||
if(iscultist(src) && gamemode.cult_objs.cult_status == NARSIE_HAS_RISEN)
|
||||
return FALSE
|
||||
|
||||
//Execption for Holy Constructs
|
||||
if(isconstruct(src) && !iscultist(src))
|
||||
return FALSE
|
||||
|
||||
to_chat(src, "<span class='warning'>Your powers are useless on this holy ground.</span>")
|
||||
return TRUE
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
|
||||
/proc/cannotPossess(A)
|
||||
var/mob/dead/observer/G = A
|
||||
if(G.has_enabled_antagHUD && config.antag_hud_restricted)
|
||||
if(G.has_enabled_antagHUD && GLOB.configuration.general.restrict_antag_hud_rejoin)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -116,7 +116,9 @@
|
||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("[question]?", poll_time = 10 SECONDS, min_hours = minhours, source = M)
|
||||
var/mob/dead/observer/theghost = null
|
||||
|
||||
if(LAZYLEN(candidates))
|
||||
if(length(candidates))
|
||||
if(QDELETED(M))
|
||||
return
|
||||
theghost = pick(candidates)
|
||||
to_chat(M, "Your mob has been taken over by a ghost!")
|
||||
message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)])")
|
||||
|
||||
@@ -169,7 +169,10 @@
|
||||
n = get_step(mob, direct)
|
||||
|
||||
. = mob.SelfMove(n, direct, delay)
|
||||
mob.setDir(direct)
|
||||
if(mob.pulling?.face_while_pulling)
|
||||
mob.setDir(get_dir(mob, mob.pulling)) // Face welding tanks and stuff when pulling
|
||||
else
|
||||
mob.setDir(direct)
|
||||
|
||||
if((direct & (direct - 1)) && mob.loc == n) //moved diagonally successfully
|
||||
delay = mob.movement_delay() * 2 //Will prevent mob diagonal moves from smoothing accurately, sadly
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
if(client)
|
||||
client.playtitlemusic()
|
||||
|
||||
if(config.player_overflow_cap && config.overflow_server_url) //Overflow rerouting, if set, forces players to be moved to a different server once a player cap is reached. Less rough than a pure kick.
|
||||
if(src.client.holder) return //admins are immune to overflow rerouting
|
||||
if(config.overflow_whitelist.Find(lowertext(src.ckey))) return //Whitelisted people are immune to overflow rerouting.
|
||||
var/tally = 0
|
||||
for(var/client/C in GLOB.clients)
|
||||
tally++
|
||||
if(tally > config.player_overflow_cap)
|
||||
src << link(config.overflow_server_url)
|
||||
//Overflow rerouting, if set, forces players to be moved to a different server once a player cap is reached. Less rough than a pure kick.
|
||||
if(GLOB.configuration.overflow.reroute_cap && GLOB.configuration.overflow.overflow_server_location)
|
||||
if(client.holder)
|
||||
return //admins are immune to overflow rerouting
|
||||
if(ckey in GLOB.configuration.overflow.overflow_whitelist)
|
||||
return //Whitelisted people are immune to overflow rerouting.
|
||||
if(length(GLOB.clients) > GLOB.configuration.overflow.reroute_cap)
|
||||
src << link(GLOB.configuration.overflow.overflow_server_location)
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
return FALSE
|
||||
|
||||
if(href_list["consent_signed"])
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("REPLACE INTO [format_table_name("privacy")] (ckey, datetime, consent) VALUES (:ckey, Now(), 1)", list(
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("REPLACE INTO privacy (ckey, datetime, consent) VALUES (:ckey, Now(), 1)", list(
|
||||
"ckey" = ckey
|
||||
))
|
||||
// If the query fails we dont want them permenantly stuck on being unable to accept TOS
|
||||
@@ -129,7 +129,7 @@
|
||||
if(href_list["consent_rejected"])
|
||||
client.tos_consent = FALSE
|
||||
to_chat(usr, "<span class='warning'>You must consent to the terms of service before you can join!</span>")
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("REPLACE INTO [format_table_name("privacy")] (ckey, datetime, consent) VALUES (:ckey, Now(), 0)", list(
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("REPLACE INTO privacy (ckey, datetime, consent) VALUES (:ckey, Now(), 0)", list(
|
||||
"ckey" = ckey
|
||||
))
|
||||
// If the query fails we dont want them permenantly stuck on being unable to accept TOS
|
||||
@@ -214,7 +214,7 @@
|
||||
return
|
||||
if(client.prefs.species in GLOB.whitelisted_species)
|
||||
|
||||
if(!is_alien_whitelisted(src, client.prefs.species) && config.usealienwhitelist)
|
||||
if(!is_alien_whitelisted(src, client.prefs.species))
|
||||
to_chat(src, alert("You are currently not whitelisted to play [client.prefs.species]."))
|
||||
return FALSE
|
||||
|
||||
@@ -233,7 +233,7 @@
|
||||
client.prefs.load_random_character_slot(client)
|
||||
|
||||
if(client.prefs.species in GLOB.whitelisted_species)
|
||||
if(!is_alien_whitelisted(src, client.prefs.species) && config.usealienwhitelist)
|
||||
if(!is_alien_whitelisted(src, client.prefs.species))
|
||||
to_chat(src, alert("You are currently not whitelisted to play [client.prefs.species]."))
|
||||
return FALSE
|
||||
|
||||
@@ -257,14 +257,14 @@
|
||||
if(job.available_in_playtime(client))
|
||||
return 0
|
||||
|
||||
if(config.assistantlimit)
|
||||
if(GLOB.configuration.jobs.assistant_limit)
|
||||
if(job.title == "Civilian")
|
||||
var/count = 0
|
||||
var/datum/job/officer = SSjobs.GetJob("Security Officer")
|
||||
var/datum/job/warden = SSjobs.GetJob("Warden")
|
||||
var/datum/job/hos = SSjobs.GetJob("Head of Security")
|
||||
count += (officer.current_positions + warden.current_positions + hos.current_positions)
|
||||
if(job.current_positions > (config.assistantratio * count))
|
||||
if(job.current_positions > (GLOB.configuration.jobs.assistant_security_ratio * count))
|
||||
if(count >= 5) // if theres more than 5 security on the station just let assistants join regardless, they should be able to handle the tide
|
||||
return 1
|
||||
return 0
|
||||
@@ -603,7 +603,7 @@
|
||||
|
||||
/mob/new_player/proc/is_species_whitelisted(datum/species/S)
|
||||
if(!S) return 1
|
||||
return is_alien_whitelisted(src, S.name) || !config.usealienwhitelist || !(IS_WHITELISTED in S.species_traits)
|
||||
return is_alien_whitelisted(src, S.name) || !(IS_WHITELISTED in S.species_traits)
|
||||
|
||||
/mob/new_player/get_gender()
|
||||
if(!client || !client.prefs) ..()
|
||||
|
||||
@@ -616,3 +616,35 @@
|
||||
/datum/sprite_accessory/socks/black_fishnet
|
||||
name = "Black Fishnet"
|
||||
icon_state = "black_fishnet"
|
||||
|
||||
/datum/sprite_accessory/socks/stockings_lpink
|
||||
name = "Stockings (Programmer)"
|
||||
icon_state = "stockings_lpink"
|
||||
|
||||
/datum/sprite_accessory/socks/stockings_purple
|
||||
name = "Stockings (Purple)"
|
||||
icon_state = "stockings_purple"
|
||||
|
||||
/datum/sprite_accessory/socks/stockings_green
|
||||
name = "Stockings (Green)"
|
||||
icon_state = "stockings_green"
|
||||
|
||||
/datum/sprite_accessory/socks/stockings_cyan
|
||||
name = "Stockings (Cyan)"
|
||||
icon_state = "stockings_cyan"
|
||||
|
||||
/datum/sprite_accessory/socks/stockings_orange
|
||||
name = "Stockings (Orange)"
|
||||
icon_state = "stockings_orange"
|
||||
|
||||
/datum/sprite_accessory/socks/stockings_yellow
|
||||
name = "Stockings (Yellow)"
|
||||
icon_state = "stockings_yellow"
|
||||
|
||||
/datum/sprite_accessory/socks/stockings_dpink
|
||||
name = "Stockings (Dark Pink)"
|
||||
icon_state = "stockings_dpink"
|
||||
|
||||
/datum/sprite_accessory/socks/stockings_blue
|
||||
name = "Stockings (Blue)"
|
||||
icon_state = "stockings_blue"
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
/mob/proc/say_dead(message)
|
||||
if(client)
|
||||
if(!client.holder)
|
||||
if(!config.dsay_allowed)
|
||||
if(!GLOB.dsay_enabled)
|
||||
to_chat(src, "<span class='danger'>Deadchat is globally muted.</span>")
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user