April sync (#360)
* Maps and things no code/icons * helpers defines globalvars * Onclick world.dm orphaned_procs * subsystems Round vote and shuttle autocall done here too * datums * Game folder * Admin - chatter modules * clothing - mining * modular computers - zambies * client * mob level 1 * mob stage 2 + simple_animal * silicons n brains * mob stage 3 + Alien/Monkey * human mobs * icons updated * some sounds * emitter y u no commit * update tgstation.dme * compile fixes * travis fixes Also removes Fast digest mode, because reasons. * tweaks for travis Mentors are broke again Also fixes Sizeray guns * oxygen loss fix for vore code. * removes unused code * some code updates * bulk fixes * further fixes * outside things * whoops. * Maint bar ported * GLOBs.
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
/obj/item/device/mmi
|
||||
name = "Man-Machine Interface"
|
||||
desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity, that nevertheless has become standard-issue on Nanotrasen stations."
|
||||
@@ -66,8 +64,8 @@
|
||||
brainmob.container = src
|
||||
if(!newbrain.damaged_brain) // the brain organ hasn't been beaten to death.
|
||||
brainmob.stat = CONSCIOUS //we manually revive the brain mob
|
||||
dead_mob_list -= brainmob
|
||||
living_mob_list += brainmob
|
||||
GLOB.dead_mob_list -= brainmob
|
||||
GLOB.living_mob_list += brainmob
|
||||
|
||||
brainmob.reset_perspective()
|
||||
brain = newbrain
|
||||
@@ -99,8 +97,8 @@
|
||||
brainmob.stat = DEAD
|
||||
brainmob.emp_damage = 0
|
||||
brainmob.reset_perspective() //so the brainmob follows the brain organ instead of the mmi. And to update our vision
|
||||
living_mob_list -= brainmob //Get outta here
|
||||
dead_mob_list += brainmob
|
||||
GLOB.living_mob_list -= brainmob //Get outta here
|
||||
GLOB.dead_mob_list += brainmob
|
||||
brain.brainmob = brainmob //Set the brain to use the brainmob
|
||||
brainmob = null //Set mmi brainmob var to null
|
||||
if(user)
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
|
||||
|
||||
/mob/living/brain
|
||||
languages_spoken = HUMAN
|
||||
languages_understood = HUMAN
|
||||
var/obj/item/device/mmi/container = null
|
||||
var/timeofhostdeath = 0
|
||||
var/emp_damage = 0//Handles a type of MMI damage
|
||||
@@ -64,4 +62,4 @@
|
||||
/mob/living/brain/fully_replace_character_name(oldname,newname)
|
||||
..()
|
||||
if(stored_dna)
|
||||
stored_dna.real_name = real_name
|
||||
stored_dna.real_name = real_name
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
/datum/emote/brain/flash
|
||||
key = "flash"
|
||||
message = "lights' blink."
|
||||
message = "blinks their lights."
|
||||
|
||||
/datum/emote/brain/notice
|
||||
key = "notice"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var/global/posibrain_notif_cooldown = 0
|
||||
GLOBAL_VAR(posibrain_notify_cooldown)
|
||||
|
||||
/obj/item/device/mmi/posibrain
|
||||
name = "positronic brain"
|
||||
@@ -7,11 +7,11 @@ var/global/posibrain_notif_cooldown = 0
|
||||
icon_state = "posibrain"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
origin_tech = "biotech=3;programming=3;plasmatech=2"
|
||||
var/notified = 0
|
||||
var/next_ask
|
||||
var/askDelay = 600 //one minute
|
||||
var/used = 0 //Prevents split personality virus. May be reset if personality deletion code is added.
|
||||
var/searching = FALSE
|
||||
brainmob = null
|
||||
req_access = list(access_robotics)
|
||||
req_access = list(GLOB.access_robotics)
|
||||
mecha = null//This does not appear to be used outside of reference in mecha.dm.
|
||||
braintype = "Android"
|
||||
var/autoping = TRUE //if it pings on creation immediately
|
||||
@@ -25,9 +25,8 @@ var/global/posibrain_notif_cooldown = 0
|
||||
Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm.</b>"
|
||||
var/new_mob_message = "<span class='notice'>The positronic brain chimes quietly.</span>"
|
||||
var/dead_message = "<span class='deadsay'>It appears to be completely inactive. The reset light is blinking.</span>"
|
||||
var/list/fluff_names = list("PBU","HIU","SINA","ARMA","OSI","HBL","MSO","RR","CHRI","CDB","HG","XSI","ORNG","GUN","KOR","MET","FRE","XIS","SLI","PKP","HOG","RZH","GOOF","MRPR","JJR","FIRC","INC","PHL","BGB","ANTR","MIW","WJ","JRD","CHOC","ANCL","JLLO","JNLG","KOS","TKRG","XAL","STLP","CBOS","DUNC","FXMC","DRSD")
|
||||
var/picked_fluff_name //which fluff name we picked
|
||||
|
||||
var/list/possible_names //If you leave this blank, it will use the global posibrain names
|
||||
var/picked_name
|
||||
|
||||
/obj/item/device/mmi/posibrain/Topic(href, href_list)
|
||||
if(href_list["activate"])
|
||||
@@ -36,42 +35,42 @@ var/global/posibrain_notif_cooldown = 0
|
||||
activate(ghost)
|
||||
|
||||
/obj/item/device/mmi/posibrain/proc/ping_ghosts(msg, newlymade)
|
||||
if(newlymade || !posibrain_notif_cooldown)
|
||||
if(newlymade || GLOB.posibrain_notify_cooldown <= world.time)
|
||||
notify_ghosts("[name] [msg] in [get_area(src)]!", ghost_sound = !newlymade ? 'sound/effects/ghost2.ogg':null, enter_link = "<a href=?src=\ref[src];activate=1>(Click to enter)</a>", source = src, action = NOTIFY_ATTACK, flashwindow = FALSE)
|
||||
if(!newlymade)
|
||||
posibrain_notif_cooldown = 1
|
||||
addtimer(CALLBACK(src, .proc/reset_posibrain_cooldown), askDelay)
|
||||
|
||||
/obj/item/device/mmi/posibrain/proc/reset_posibrain_cooldown()
|
||||
posibrain_notif_cooldown = 0
|
||||
GLOB.posibrain_notify_cooldown = world.time + askDelay
|
||||
|
||||
/obj/item/device/mmi/posibrain/attack_self(mob/user)
|
||||
if(brainmob && !brainmob.key && !notified)
|
||||
//Start the process of requesting a new ghost.
|
||||
to_chat(user, begin_activation_message)
|
||||
ping_ghosts("requested", FALSE)
|
||||
notified = 1
|
||||
used = 0
|
||||
update_icon()
|
||||
spawn(askDelay) //Seperate from the global cooldown.
|
||||
notified = 0
|
||||
update_icon()
|
||||
if(brainmob.client)
|
||||
visible_message(success_message)
|
||||
else
|
||||
visible_message(fail_message)
|
||||
|
||||
return //Code for deleting personalities recommended here.
|
||||
if(!brainmob || brainmob.key)
|
||||
return
|
||||
if(next_ask > world.time)
|
||||
return
|
||||
//Start the process of requesting a new ghost.
|
||||
to_chat(user, begin_activation_message)
|
||||
ping_ghosts("requested", FALSE)
|
||||
next_ask = world.time + askDelay
|
||||
searching = TRUE
|
||||
addtimer(CALLBACK(src, .proc/check_success), askDelay)
|
||||
|
||||
/obj/item/device/mmi/posibrain/proc/check_success()
|
||||
searching = FALSE
|
||||
update_icon()
|
||||
if(QDELETED(brainmob))
|
||||
return
|
||||
if(brainmob.client)
|
||||
visible_message(success_message)
|
||||
else
|
||||
visible_message(fail_message)
|
||||
|
||||
/obj/item/device/mmi/posibrain/attack_ghost(mob/user)
|
||||
activate(user)
|
||||
|
||||
//Two ways to activate a positronic brain. A clickable link in the ghost notif, or simply clicking the object itself.
|
||||
/obj/item/device/mmi/posibrain/proc/activate(mob/user)
|
||||
if(used || (brainmob && brainmob.key) || jobban_isbanned(user,"posibrain"))
|
||||
if(QDELETED(brainmob))
|
||||
return
|
||||
if(brainmob.key || jobban_isbanned(user,"posibrain"))
|
||||
return
|
||||
|
||||
var/posi_ask = alert("Become a [name]? (Warning, You can no longer be cloned, and all past lives will be forgotten!)","Are you positive?","Yes","No")
|
||||
if(posi_ask == "No" || QDELETED(src))
|
||||
return
|
||||
@@ -97,10 +96,11 @@ var/global/posibrain_notif_cooldown = 0
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/mmi/posibrain/proc/transfer_personality(mob/candidate)
|
||||
if(used || (brainmob && brainmob.key)) //Prevents hostile takeover if two ghosts get the prompt or link for the same brain.
|
||||
if(QDELETED(brainmob))
|
||||
return
|
||||
if(brainmob.key) //Prevents hostile takeover if two ghosts get the prompt or link for the same brain.
|
||||
to_chat(candidate, "This brain has already been taken! Please try your possession again later!")
|
||||
return FALSE
|
||||
notified = 0
|
||||
if(candidate.mind && !isobserver(candidate))
|
||||
candidate.mind.transfer_to(brainmob)
|
||||
else
|
||||
@@ -109,12 +109,11 @@ var/global/posibrain_notif_cooldown = 0
|
||||
to_chat(brainmob, welcome_message)
|
||||
brainmob.mind.assigned_role = new_role
|
||||
brainmob.stat = CONSCIOUS
|
||||
dead_mob_list -= brainmob
|
||||
living_mob_list += brainmob
|
||||
GLOB.dead_mob_list -= brainmob
|
||||
GLOB.living_mob_list += brainmob
|
||||
|
||||
visible_message(new_mob_message)
|
||||
update_icon()
|
||||
used = 1
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -124,7 +123,7 @@ var/global/posibrain_notif_cooldown = 0
|
||||
if(brainmob && brainmob.key)
|
||||
switch(brainmob.stat)
|
||||
if(CONSCIOUS)
|
||||
if(!src.brainmob.client)
|
||||
if(!brainmob.client)
|
||||
msg = "It appears to be in stand-by mode." //afk
|
||||
if(DEAD)
|
||||
msg = "<span class='deadsay'>It appears to be completely inactive.</span>"
|
||||
@@ -133,24 +132,27 @@ var/global/posibrain_notif_cooldown = 0
|
||||
|
||||
to_chat(user, msg)
|
||||
|
||||
/obj/item/device/mmi/posibrain/New()
|
||||
/obj/item/device/mmi/posibrain/Initialize()
|
||||
..()
|
||||
brainmob = new(src)
|
||||
picked_fluff_name = pick(fluff_names)
|
||||
brainmob.name = "[picked_fluff_name]-[rand(100, 999)]"
|
||||
var/new_name
|
||||
if(!LAZYLEN(possible_names))
|
||||
new_name = pick(GLOB.posibrain_names)
|
||||
else
|
||||
new_name = pick(possible_names)
|
||||
brainmob.name = "[new_name]-[rand(100, 999)]"
|
||||
brainmob.real_name = brainmob.name
|
||||
brainmob.loc = src
|
||||
brainmob.container = src
|
||||
if(autoping)
|
||||
ping_ghosts("created", TRUE)
|
||||
..()
|
||||
|
||||
|
||||
/obj/item/device/mmi/posibrain/attackby(obj/item/O, mob/user)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/device/mmi/posibrain/update_icon()
|
||||
if(notified)
|
||||
if(searching)
|
||||
icon_state = "[initial(icon_state)]-searching"
|
||||
return
|
||||
if(brainmob && brainmob.key)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/living/brain/say(message)
|
||||
/mob/living/brain/say(message, language)
|
||||
if(!(container && istype(container, /obj/item/device/mmi)))
|
||||
return //No MMI, can't speak, bucko./N
|
||||
else
|
||||
@@ -7,16 +7,17 @@
|
||||
return
|
||||
else
|
||||
message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher
|
||||
|
||||
..()
|
||||
|
||||
/mob/living/brain/get_spans()
|
||||
return ..() | SPAN_ROBOT
|
||||
|
||||
/mob/living/brain/radio(message, message_mode, list/spans)
|
||||
/mob/living/brain/radio(message, message_mode, list/spans, language)
|
||||
if(message_mode && istype(container, /obj/item/device/mmi))
|
||||
var/obj/item/device/mmi/R = container
|
||||
if(R.radio)
|
||||
R.radio.talk_into(src, message, , spans)
|
||||
R.radio.talk_into(src, message, , get_spans(), language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
/mob/living/brain/lingcheck()
|
||||
@@ -24,4 +25,12 @@
|
||||
|
||||
/mob/living/brain/treat_message(message)
|
||||
message = capitalize(message)
|
||||
return message
|
||||
return message
|
||||
|
||||
/mob/living/brain/can_speak_in_language(datum/language/dt)
|
||||
if(HAS_SECONDARY_FLAG(src, OMNITONGUE))
|
||||
. = has_language(dt)
|
||||
else if(istype(container, /obj/item/device/mmi/posibrain/soul_vessel))
|
||||
. = has_language(dt) && ispath(dt, /datum/language/ratvar)
|
||||
else
|
||||
. = ..()
|
||||
|
||||
@@ -11,15 +11,13 @@
|
||||
dna = null
|
||||
faction = list("alien")
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
languages_spoken = ALIEN
|
||||
languages_understood = ALIEN
|
||||
sight = SEE_MOBS
|
||||
see_in_dark = 4
|
||||
verb_say = "hisses"
|
||||
initial_languages = list(/datum/language/xenocommon)
|
||||
bubble_icon = "alien"
|
||||
type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno
|
||||
var/nightvision = 1
|
||||
devourable = 1
|
||||
|
||||
var/obj/item/weapon/card/id/wear_id = null // Fix for station bounced radios -- Skie
|
||||
var/has_fine_manipulation = 0
|
||||
@@ -111,7 +109,7 @@ Des: Gives the client of the alien an image on each infected mob.
|
||||
----------------------------------------*/
|
||||
/mob/living/carbon/alien/proc/AddInfectionImages()
|
||||
if (client)
|
||||
for (var/mob/living/C in mob_list)
|
||||
for (var/mob/living/C in GLOB.mob_list)
|
||||
if(C.status_flags & XENO_HOST)
|
||||
var/obj/item/organ/body_egg/alien_embryo/A = C.getorgan(/obj/item/organ/body_egg/alien_embryo)
|
||||
if(A)
|
||||
|
||||
@@ -74,7 +74,8 @@ In all, this is a lot like the monkey code. /N
|
||||
|
||||
|
||||
/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
switch(M.melee_damage_type)
|
||||
if(BRUTE)
|
||||
@@ -89,7 +90,6 @@ In all, this is a lot like the monkey code. /N
|
||||
adjustCloneLoss(damage)
|
||||
if(STAMINA)
|
||||
adjustStaminaLoss(damage)
|
||||
updatehealth()
|
||||
|
||||
/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/datum/emote/living/alien
|
||||
mob_type_allowed_typecache = list(/mob/living/carbon/alien)
|
||||
|
||||
/datum/emote/living/alien/gnarl
|
||||
key = "gnarl"
|
||||
key_third_person = "gnarls"
|
||||
message = "gnarls and shows its teeth..."
|
||||
|
||||
/datum/emote/living/alien/hiss
|
||||
key = "hiss"
|
||||
key_third_person = "hisses"
|
||||
message_alien = "hisses."
|
||||
message_larva = "hisses softly."
|
||||
|
||||
/datum/emote/living/alien/hiss/run_emote(mob/user, params)
|
||||
. = ..()
|
||||
if(. && isalienadult(user))
|
||||
playsound(user.loc, "hiss", 40, 1, 1)
|
||||
|
||||
/datum/emote/living/alien/roar
|
||||
key = "roar"
|
||||
key_third_person = "roars"
|
||||
message_alien = "roars"
|
||||
message_larva = "softly roars"
|
||||
emote_type = EMOTE_AUDIBLE
|
||||
|
||||
/datum/emote/living/alien/roar/run_emote(mob/user, params)
|
||||
. = ..()
|
||||
if(. && isalienadult(user))
|
||||
playsound(user.loc, 'sound/voice/hiss5.ogg', 40, 1, 1)
|
||||
@@ -87,7 +87,7 @@ Doesn't work on other aliens/AI.*/
|
||||
log_say("AlienWhisper: [key_name(user)]->[M.key] : [msg]")
|
||||
to_chat(M, "<span class='noticealien'>You hear a strange, alien voice in your head...</span>[msg]")
|
||||
to_chat(user, "<span class='noticealien'>You said: \"[msg]\" to [M]</span>")
|
||||
for(var/ded in dead_mob_list)
|
||||
for(var/ded in GLOB.dead_mob_list)
|
||||
if(!isobserver(ded))
|
||||
continue
|
||||
var/follow_link_user = FOLLOW_LINK(ded, user)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
if(stat == DEAD)
|
||||
return
|
||||
|
||||
for(var/mob/living/carbon/C in living_mob_list)
|
||||
for(var/mob/living/carbon/C in GLOB.living_mob_list)
|
||||
if(C == src) //Make sure not to proc it on ourselves.
|
||||
continue
|
||||
var/obj/item/organ/alien/hivenode/node = C.getorgan(/obj/item/organ/alien/hivenode)
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
|
||||
//For alien evolution/promotion/queen finder procs. Checks for an active alien of that type
|
||||
/proc/get_alien_type(var/alienpath)
|
||||
for(var/mob/living/carbon/alien/humanoid/A in living_mob_list)
|
||||
for(var/mob/living/carbon/alien/humanoid/A in GLOB.living_mob_list)
|
||||
if(!istype(A, alienpath))
|
||||
continue
|
||||
if(!A.key || A.stat == DEAD) //Only living aliens with a ckey are valid.
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
/mob/living/carbon/alien/humanoid/royal/queen/Initialize()
|
||||
//there should only be one queen
|
||||
for(var/mob/living/carbon/alien/humanoid/royal/queen/Q in living_mob_list)
|
||||
for(var/mob/living/carbon/alien/humanoid/royal/queen/Q in GLOB.living_mob_list)
|
||||
if(Q == src)
|
||||
continue
|
||||
if(Q.stat == DEAD)
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
var/message_a = say_quote(message, get_spans())
|
||||
var/rendered = "<i><span class='alien'>Hivemind, <span class='name'>[shown_name]</span> <span class='message'>[message_a]</span></span></i>"
|
||||
for(var/mob/S in player_list)
|
||||
for(var/mob/S in GLOB.player_list)
|
||||
if(!S.stat && S.hivecheck())
|
||||
to_chat(S, rendered)
|
||||
if(S in dead_mob_list)
|
||||
if(S in GLOB.dead_mob_list)
|
||||
var/link = FOLLOW_LINK(S, src)
|
||||
to_chat(S, "[link] [rendered]")
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ Proc: AddInfectionImages(C)
|
||||
Des: Adds the infection image to all aliens for this embryo
|
||||
----------------------------------------*/
|
||||
/obj/item/organ/body_egg/alien_embryo/AddInfectionImages()
|
||||
for(var/mob/living/carbon/alien/alien in player_list)
|
||||
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
|
||||
if(alien.client)
|
||||
var/I = image('icons/mob/alien.dmi', loc = owner, icon_state = "infected[stage]")
|
||||
alien.client.images += I
|
||||
@@ -127,7 +127,7 @@ Proc: RemoveInfectionImage(C)
|
||||
Des: Removes all images from the mob infected by this embryo
|
||||
----------------------------------------*/
|
||||
/obj/item/organ/body_egg/alien_embryo/RemoveInfectionImages()
|
||||
for(var/mob/living/carbon/alien/alien in player_list)
|
||||
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
|
||||
if(alien.client)
|
||||
for(var/image/I in alien.client.images)
|
||||
if(dd_hasprefix_case(I.icon_state, "infected") && I.loc == owner)
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
//TODO: Make these simple_animals
|
||||
|
||||
var/const/MIN_IMPREGNATION_TIME = 100 //time it takes to impregnate someone
|
||||
var/const/MAX_IMPREGNATION_TIME = 150
|
||||
#define MIN_IMPREGNATION_TIME 100 //time it takes to impregnate someone
|
||||
#define MAX_IMPREGNATION_TIME 150
|
||||
|
||||
var/const/MIN_ACTIVE_TIME = 200 //time between being dropped and going idle
|
||||
var/const/MAX_ACTIVE_TIME = 400
|
||||
#define MIN_ACTIVE_TIME 200 //time between being dropped and going idle
|
||||
#define MAX_ACTIVE_TIME 400
|
||||
|
||||
/obj/item/clothing/mask/facehugger
|
||||
name = "alien"
|
||||
@@ -152,14 +152,6 @@ var/const/MAX_ACTIVE_TIME = 400
|
||||
// probiscis-blocker handling
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/target = M
|
||||
if(target.wear_mask)
|
||||
var/obj/item/clothing/W = target.wear_mask
|
||||
if(W.flags & NODROP)
|
||||
return FALSE
|
||||
if(!istype(W,/obj/item/clothing/mask/facehugger))
|
||||
target.dropItemToGround(W)
|
||||
target.visible_message("<span class='danger'>[src] tears [W] off of [target]'s face!</span>", \
|
||||
"<span class='userdanger'>[src] tears [W] off of [target]'s face!</span>")
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
@@ -168,6 +160,12 @@ var/const/MAX_ACTIVE_TIME = 400
|
||||
"<span class='userdanger'>[src] smashes against [H]'s [H.head]!</span>")
|
||||
Die()
|
||||
return FALSE
|
||||
|
||||
if(target.wear_mask)
|
||||
var/obj/item/clothing/W = target.wear_mask
|
||||
if(!istype(W,/obj/item/clothing/mask/facehugger) && target.dropItemToGround(W))
|
||||
target.visible_message("<span class='danger'>[src] tears [W] off of [target]'s face!</span>", \
|
||||
"<span class='userdanger'>[src] tears [W] off of [target]'s face!</span>")
|
||||
forceMove(target)
|
||||
target.equip_to_slot_if_possible(src, slot_wear_mask, 0, 1, 1)
|
||||
// early returns and validity checks done: attach.
|
||||
|
||||
@@ -522,6 +522,7 @@
|
||||
return
|
||||
|
||||
sight = initial(sight)
|
||||
lighting_alpha = initial(lighting_alpha)
|
||||
var/obj/item/organ/eyes/E = getorganslot("eye_sight")
|
||||
if(!E)
|
||||
update_tint()
|
||||
@@ -529,6 +530,8 @@
|
||||
see_invisible = E.see_invisible
|
||||
see_in_dark = E.see_in_dark
|
||||
sight |= E.sight_flags
|
||||
if(!isnull(E.lighting_alpha))
|
||||
lighting_alpha = E.lighting_alpha
|
||||
|
||||
if(client.eye != src)
|
||||
var/atom/A = client.eye
|
||||
@@ -543,6 +546,8 @@
|
||||
see_invisible = G.invis_override
|
||||
else
|
||||
see_invisible = min(G.invis_view, see_invisible)
|
||||
if(!isnull(G.lighting_alpha))
|
||||
lighting_alpha = min(lighting_alpha, G.lighting_alpha)
|
||||
if(dna)
|
||||
for(var/X in dna.mutations)
|
||||
var/datum/mutation/M = X
|
||||
@@ -552,11 +557,12 @@
|
||||
|
||||
if(see_override)
|
||||
see_invisible = see_override
|
||||
. = ..()
|
||||
|
||||
|
||||
//to recalculate and update the mob's total tint from tinted equipment it's wearing.
|
||||
/mob/living/carbon/proc/update_tint()
|
||||
if(!tinted_weldhelh)
|
||||
if(!GLOB.tinted_weldhelh)
|
||||
return
|
||||
tinttotal = get_total_tint()
|
||||
if(tinttotal >= TINT_BLIND)
|
||||
|
||||
@@ -44,4 +44,7 @@
|
||||
/obj/item/bodypart/r_arm, /obj/item/bodypart/r_leg, /obj/item/bodypart/l_leg)
|
||||
//Gets filled up in create_bodyparts()
|
||||
|
||||
var/list/hand_bodyparts = list() //a collection of arms (or actually whatever the fug /bodyparts you monsters use to wreck my systems)
|
||||
var/list/hand_bodyparts = list() //a collection of arms (or actually whatever the fug /bodyparts you monsters use to wreck my systems)
|
||||
|
||||
var/icon_render_key = ""
|
||||
var/static/list/limb_icon_cache = list()
|
||||
@@ -19,12 +19,6 @@
|
||||
if(legcuffed)
|
||||
. += legcuffed.slowdown
|
||||
|
||||
|
||||
var/const/NO_SLIP_WHEN_WALKING = 1
|
||||
var/const/SLIDE = 2
|
||||
var/const/GALOSHES_DONT_HELP = 4
|
||||
var/const/SLIDE_ICE = 8
|
||||
|
||||
/mob/living/carbon/slip(s_amount, w_amount, obj/O, lube)
|
||||
if(movement_type & FLYING)
|
||||
return 0
|
||||
|
||||
@@ -147,8 +147,8 @@
|
||||
parts -= picked
|
||||
if(updating_health)
|
||||
updatehealth()
|
||||
if(update)
|
||||
update_damage_overlays()
|
||||
if(update)
|
||||
update_damage_overlays()
|
||||
|
||||
// damage MANY bodyparts, in random order
|
||||
/mob/living/carbon/take_overall_damage(brute, burn, updating_health = 1)
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
emote("deathgasp")
|
||||
|
||||
. = ..()
|
||||
if(ticker && ticker.mode)
|
||||
ticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now
|
||||
if(SSticker && SSticker.mode)
|
||||
SSticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now
|
||||
|
||||
/mob/living/carbon/gib(no_brain, no_organs, no_bodyparts)
|
||||
for(var/mob/M in src)
|
||||
@@ -35,7 +35,7 @@
|
||||
if(org_zone == "chest")
|
||||
O.Remove(src)
|
||||
O.forceMove(get_turf(src))
|
||||
O.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
|
||||
O.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
|
||||
else
|
||||
for(var/X in internal_organs)
|
||||
var/obj/item/organ/I = X
|
||||
@@ -44,11 +44,11 @@
|
||||
continue
|
||||
I.Remove(src)
|
||||
I.forceMove(get_turf(src))
|
||||
I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
|
||||
I.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
|
||||
|
||||
|
||||
/mob/living/carbon/spread_bodyparts()
|
||||
for(var/X in bodyparts)
|
||||
var/obj/item/bodypart/BP = X
|
||||
BP.drop_limb()
|
||||
BP.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
|
||||
BP.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
|
||||
@@ -10,8 +10,11 @@
|
||||
else
|
||||
new /obj/effect/gibspawner/humanbodypartless(loc, viruses, dna)
|
||||
|
||||
/mob/living/carbon/human/spawn_dust()
|
||||
new /obj/effect/decal/remains/human(loc)
|
||||
/mob/living/carbon/human/spawn_dust(just_ash = FALSE)
|
||||
if(just_ash)
|
||||
new /obj/effect/decal/cleanable/ash(loc)
|
||||
else
|
||||
new /obj/effect/decal/remains/human(loc)
|
||||
|
||||
/mob/living/carbon/human/death(gibbed)
|
||||
if(stat == DEAD)
|
||||
@@ -29,7 +32,7 @@
|
||||
|
||||
dna.species.spec_death(gibbed, src)
|
||||
|
||||
if(ticker && ticker.mode)
|
||||
if(SSticker && SSticker.mode)
|
||||
sql_report_death(src)
|
||||
if(mind && mind.devilinfo)
|
||||
INVOKE_ASYNC(mind.devilinfo, /datum/devilinfo.proc/beginResurrectionCheck, src)
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
if(!key)
|
||||
var/foundghost = 0
|
||||
if(mind)
|
||||
for(var/mob/dead/observer/G in player_list)
|
||||
for(var/mob/dead/observer/G in GLOB.player_list)
|
||||
if(G.mind == mind)
|
||||
foundghost = 1
|
||||
if (G.can_reenter_corpse == 0)
|
||||
@@ -257,9 +257,6 @@
|
||||
msg += "[t_He] looks like a drunken mess.\n"
|
||||
if(91.01 to INFINITY)
|
||||
msg += "[t_He] [t_is] a shitfaced, slobbering wreck.\n"
|
||||
for (var/I in src.vore_organs)
|
||||
var/datum/belly/B = vore_organs[I]
|
||||
msg += B.get_examine_msg()
|
||||
|
||||
msg += "</span>"
|
||||
|
||||
@@ -292,7 +289,7 @@
|
||||
if(istype(H.glasses, /obj/item/clothing/glasses/hud) || CIH)
|
||||
var/perpname = get_face_name(get_id_name(""))
|
||||
if(perpname)
|
||||
var/datum/data/record/R = find_record("name", perpname, data_core.general)
|
||||
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.general)
|
||||
if(R)
|
||||
msg += "<span class='deptradio'>Rank:</span> [R.fields["rank"]]<br>"
|
||||
msg += "<a href='?src=\ref[src];hud=1;photo_front=1'>\[Front photo\]</a> "
|
||||
@@ -310,7 +307,7 @@
|
||||
msg += "<a href='?src=\ref[src];hud=m;p_stat=1'>\[[health_r]\]</a>"
|
||||
health_r = R.fields["m_stat"]
|
||||
msg += "<a href='?src=\ref[src];hud=m;m_stat=1'>\[[health_r]\]</a><br>"
|
||||
R = find_record("name", perpname, data_core.medical)
|
||||
R = find_record("name", perpname, GLOB.data_core.medical)
|
||||
if(R)
|
||||
msg += "<a href='?src=\ref[src];hud=m;evaluation=1'>\[Medical evaluation\]</a><br>"
|
||||
|
||||
@@ -320,7 +317,7 @@
|
||||
//|| !user.canmove || user.restrained()) Fluff: Sechuds have eye-tracking technology and sets 'arrest' to people that the wearer looks and blinks at.
|
||||
var/criminal = "None"
|
||||
|
||||
R = find_record("name", perpname, data_core.security)
|
||||
R = find_record("name", perpname, GLOB.data_core.security)
|
||||
if(R)
|
||||
criminal = R.fields["criminal"]
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/mob/living/carbon/human/proc/examine_nutrition()
|
||||
var/message = ""
|
||||
var/nutrition_examine = round(nutrition)
|
||||
var/t_He = "It" //capitalised for use at the start of each line.
|
||||
var/t_His = "Its"
|
||||
var/t_his = "its"
|
||||
var/t_is = "is"
|
||||
var/t_has = "has"
|
||||
switch(gender)
|
||||
if(MALE)
|
||||
t_He = "He"
|
||||
t_his = "his"
|
||||
t_His = "His"
|
||||
if(FEMALE)
|
||||
t_He = "She"
|
||||
t_his = "her"
|
||||
t_His = "Her"
|
||||
if(PLURAL)
|
||||
t_He = "They"
|
||||
t_his = "their"
|
||||
t_His = "Their"
|
||||
t_is = "are"
|
||||
t_has = "have"
|
||||
if(NEUTER)
|
||||
t_He = "It"
|
||||
t_his = "its"
|
||||
t_His = "Its"
|
||||
switch(nutrition_examine)
|
||||
if(0 to 49)
|
||||
message = "<span class='warning'>[t_He] [t_is] starving! You can hear [t_his] stomach snarling from across the room!</span>\n"
|
||||
if(50 to 99)
|
||||
message = "<span class='warning'>[t_He] [t_is] extremely hungry. A deep growl occasionally rumbles from [t_his] empty stomach.</span>\n"
|
||||
if(100 to 499)
|
||||
return message //Well that's pretty normal, really.
|
||||
if(500 to 864) // Fat.
|
||||
message = "[t_He] [t_has] a stuffed belly, bloated fat and round from eating too much.\n"
|
||||
if(1200 to 1934) // One person fully digested.
|
||||
message = "<span class='warning'>[t_He] [t_is] sporting a large, round, sagging stomach. It's contains at least their body weight worth of glorping slush.</span>\n"
|
||||
if(1935 to 3004) // Two people.
|
||||
message = "<span class='warning'>[t_He] [t_is] engorged with a huge stomach that sags and wobbles as they move. [t_He] must have consumed at least twice their body weight. It looks incredibly soft.</span>\n"
|
||||
if(3005 to 4074) // Three people.
|
||||
message = "<span class='warning'>[t_His] stomach is firmly packed with digesting slop. [t_He] must have eaten at least a few times worth their body weight! It looks hard for them to stand, and [t_his] gut jiggles when they move.</span>\n"
|
||||
if(4075 to 10000) // Four or more people.
|
||||
message = "<span class='warning'>[t_He] [t_is] so absolutely stuffed that you aren't sure how it's possible to move. [t_He] can't seem to swell any bigger. The surface of [t_his] belly looks sorely strained!</span>\n"
|
||||
return message
|
||||
|
||||
/mob/living/carbon/human/proc/examine_bellies()
|
||||
var/message = ""
|
||||
|
||||
for (var/I in src.vore_organs)
|
||||
var/datum/belly/B = vore_organs[I]
|
||||
message += B.get_examine_msg()
|
||||
|
||||
return message
|
||||
@@ -17,6 +17,9 @@
|
||||
args[1] = FALSE
|
||||
Initialize(arglist(args))
|
||||
|
||||
/mob/living/carbon/human/dummy/Life()
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/Initialize()
|
||||
verbs += /mob/living/proc/mob_sleep
|
||||
verbs += /mob/living/proc/lay_down
|
||||
@@ -39,6 +42,8 @@
|
||||
|
||||
handcrafting = new()
|
||||
|
||||
grant_language(/datum/language/common) // ME TARZAN, YOU JANEBOT
|
||||
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/create_internal_organs()
|
||||
@@ -298,7 +303,7 @@
|
||||
var/mob/living/carbon/human/H = usr
|
||||
var/perpname = get_face_name(get_id_name(""))
|
||||
if(istype(H.glasses, /obj/item/clothing/glasses/hud) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud))
|
||||
var/datum/data/record/R = find_record("name", perpname, data_core.general)
|
||||
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.general)
|
||||
if(href_list["photo_front"] || href_list["photo_side"])
|
||||
if(R)
|
||||
if(!H.canUseHUD())
|
||||
@@ -388,7 +393,7 @@
|
||||
if (!G.emagged)
|
||||
if(H.wear_id)
|
||||
var/list/access = H.wear_id.GetAccess()
|
||||
if(access_sec_doors in access)
|
||||
if(GLOB.access_sec_doors in access)
|
||||
allowed_access = H.get_authentification_name()
|
||||
else
|
||||
allowed_access = "@%&ERROR_%$*"
|
||||
@@ -399,7 +404,7 @@
|
||||
return
|
||||
|
||||
if(perpname)
|
||||
R = find_record("name", perpname, data_core.security)
|
||||
R = find_record("name", perpname, GLOB.data_core.security)
|
||||
if(R)
|
||||
if(href_list["status"])
|
||||
var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", R.fields["criminal"]) in list("None", "*Arrest*", "Incarcerated", "Parolled", "Discharged", "Cancel")
|
||||
@@ -447,8 +452,8 @@
|
||||
return
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
return
|
||||
var/crime = data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text())
|
||||
data_core.addMinorCrime(R.fields["id"], crime)
|
||||
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text())
|
||||
GLOB.data_core.addMinorCrime(R.fields["id"], crime)
|
||||
to_chat(usr, "<span class='notice'>Successfully added a minor crime.</span>")
|
||||
return
|
||||
if("Major Crime")
|
||||
@@ -462,8 +467,8 @@
|
||||
return
|
||||
else if (!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
return
|
||||
var/crime = data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text())
|
||||
data_core.addMajorCrime(R.fields["id"], crime)
|
||||
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text())
|
||||
GLOB.data_core.addMajorCrime(R.fields["id"], crime)
|
||||
to_chat(usr, "<span class='notice'>Successfully added a major crime.</span>")
|
||||
return
|
||||
|
||||
@@ -494,7 +499,7 @@
|
||||
var/counter = 1
|
||||
while(R.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
R.fields[text("com_[]", counter)] = text("Made by [] on [] [], []<BR>[]", allowed_access, worldtime2text(), time2text(world.realtime, "MMM DD"), year_integer+540, t1)
|
||||
R.fields[text("com_[]", counter)] = text("Made by [] on [] [], []<BR>[]", allowed_access, worldtime2text(), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
|
||||
to_chat(usr, "<span class='notice'>Successfully added comment.</span>")
|
||||
return
|
||||
to_chat(usr, "<span class='warning'>Unable to locate a data core entry for this person.</span>")
|
||||
@@ -581,7 +586,7 @@
|
||||
|
||||
//Check for weapons
|
||||
if(judgebot.weaponscheck)
|
||||
if(!idcard || !(access_weapons in idcard.access))
|
||||
if(!idcard || !(GLOB.access_weapons in idcard.access))
|
||||
for(var/obj/item/I in held_items)
|
||||
if(judgebot.check_for_weapons(I))
|
||||
threatcount += 4
|
||||
@@ -591,7 +596,7 @@
|
||||
//Check for arrest warrant
|
||||
if(judgebot.check_records)
|
||||
var/perpname = get_face_name(get_id_name())
|
||||
var/datum/data/record/R = find_record("name", perpname, data_core.security)
|
||||
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
|
||||
if(R && R.fields["criminal"])
|
||||
switch(R.fields["criminal"])
|
||||
if("*Arrest*")
|
||||
@@ -765,7 +770,7 @@
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/replace_records_name(oldname,newname) // Only humans have records right now, move this up if changed.
|
||||
for(var/list/L in list(data_core.general,data_core.medical,data_core.security,data_core.locked))
|
||||
for(var/list/L in list(GLOB.data_core.general,GLOB.data_core.medical,GLOB.data_core.security,GLOB.data_core.locked))
|
||||
var/datum/data/record/R = find_record("name", oldname, L)
|
||||
if(R)
|
||||
R.fields["name"] = newname
|
||||
@@ -855,7 +860,7 @@
|
||||
if(7) // Pride
|
||||
log_game("[src] was influenced by the sin of pride.")
|
||||
O = new /datum/objective/sintouched/pride
|
||||
ticker.mode.sintouched += src.mind
|
||||
SSticker.mode.sintouched += src.mind
|
||||
src.mind.objectives += O
|
||||
src.mind.announce_objectives()
|
||||
|
||||
@@ -920,12 +925,15 @@
|
||||
return
|
||||
if(buckled) //NO INFINITE STACKING!!
|
||||
return
|
||||
if(M.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE))
|
||||
M.visible_message("<span class='boldwarning'>[M] can't hang onto [src]!</span>")
|
||||
return
|
||||
if(iscarbon(M) && (!riding_datum.equip_buckle_inhands(M, 2))) //MAKE SURE THIS IS LAST!!
|
||||
M.visible_message("<span class='boldwarning'>[M] can't climb onto [src] because [M.p_their()] hands are full!</span>")
|
||||
if(M.stat != CONSCIOUS)
|
||||
return
|
||||
if(iscarbon(M))
|
||||
if(M.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE))
|
||||
M.visible_message("<span class='boldwarning'>[M] can't hang onto [src]!</span>")
|
||||
return
|
||||
if(!riding_datum.equip_buckle_inhands(M, 2)) //MAKE SURE THIS IS LAST!!
|
||||
M.visible_message("<span class='boldwarning'>[M] can't climb onto [src] because [M.p_their()] hands are full!</span>")
|
||||
return
|
||||
. = ..(M, force, check_loc)
|
||||
stop_pulling()
|
||||
|
||||
|
||||
@@ -160,8 +160,8 @@
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0)
|
||||
if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && isliving(pulling))
|
||||
vore_attack(user, pulling)
|
||||
if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && (disabilities & FAT) && ismonkey(pulling))
|
||||
devour_mob(pulling)
|
||||
else
|
||||
..()
|
||||
|
||||
@@ -302,13 +302,14 @@
|
||||
|
||||
|
||||
/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
if(check_shields(damage, "the [M.name]", null, MELEE_ATTACK, M.armour_penetration))
|
||||
return 0
|
||||
return FALSE
|
||||
var/dam_zone = dismembering_strike(M, pick("chest", "l_hand", "r_hand", "l_leg", "r_leg"))
|
||||
if(!dam_zone) //Dismemberment successful
|
||||
return 1
|
||||
return TRUE
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart("chest")
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
var/global/default_martial_art = new/datum/martial_art
|
||||
/mob/living/carbon/human
|
||||
languages_spoken = HUMAN
|
||||
languages_understood = HUMAN
|
||||
initial_languages = list(/datum/language/common)
|
||||
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD)
|
||||
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
|
||||
pressure_resistance = 25
|
||||
@@ -43,6 +41,7 @@ var/global/default_martial_art = new/datum/martial_art
|
||||
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
|
||||
|
||||
var/datum/martial_art/martial_art = null
|
||||
var/static/default_martial_art = new/datum/martial_art
|
||||
|
||||
var/name_override //For temporary visible name changes
|
||||
|
||||
@@ -50,4 +49,4 @@ var/global/default_martial_art = new/datum/martial_art
|
||||
var/datum/personal_crafting/handcrafting
|
||||
can_buckle = TRUE
|
||||
buckle_lying = FALSE
|
||||
can_ride_typecache = list(/mob/living/carbon/human, /mob/living/simple_animal/slime)
|
||||
can_ride_typecache = list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -102,7 +102,7 @@
|
||||
update_tint()
|
||||
if(G.vision_correction)
|
||||
clear_fullscreen("nearsighted")
|
||||
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view)
|
||||
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view || !isnull(G.lighting_alpha))
|
||||
update_sight()
|
||||
update_inv_glasses()
|
||||
if(slot_gloves)
|
||||
@@ -141,13 +141,13 @@
|
||||
|
||||
return not_handled //For future deeper overrides
|
||||
|
||||
/mob/living/carbon/human/doUnEquip(obj/item/I, force)
|
||||
/mob/living/carbon/human/doUnEquip(obj/item/I, force, newloc, no_move, invdrop)
|
||||
. = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should.
|
||||
if(!. || !I)
|
||||
return
|
||||
|
||||
if(I == wear_suit)
|
||||
if(s_store)
|
||||
if(s_store && invdrop)
|
||||
dropItemToGround(s_store, TRUE) //It makes no sense for your suit storage to stay on you if you drop your suit.
|
||||
if(wear_suit.breakouttime) //when unequipping a straightjacket
|
||||
update_action_buttons_icon() //certain action buttons may be usable again.
|
||||
@@ -156,17 +156,18 @@
|
||||
update_inv_w_uniform()
|
||||
update_inv_wear_suit()
|
||||
else if(I == w_uniform)
|
||||
if(r_store)
|
||||
dropItemToGround(r_store, TRUE) //Again, makes sense for pockets to drop.
|
||||
if(l_store)
|
||||
dropItemToGround(l_store, TRUE)
|
||||
if(wear_id)
|
||||
dropItemToGround(wear_id)
|
||||
if(belt)
|
||||
dropItemToGround(belt)
|
||||
if(invdrop)
|
||||
if(r_store)
|
||||
dropItemToGround(r_store, TRUE) //Again, makes sense for pockets to drop.
|
||||
if(l_store)
|
||||
dropItemToGround(l_store, TRUE)
|
||||
if(wear_id)
|
||||
dropItemToGround(wear_id)
|
||||
if(belt)
|
||||
dropItemToGround(belt)
|
||||
w_uniform = null
|
||||
update_suit_sensors()
|
||||
update_inv_w_uniform()
|
||||
update_inv_w_uniform(invdrop)
|
||||
else if(I == gloves)
|
||||
gloves = null
|
||||
update_inv_gloves()
|
||||
@@ -180,7 +181,7 @@
|
||||
if(G.vision_correction)
|
||||
if(disabilities & NEARSIGHT)
|
||||
overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1)
|
||||
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view)
|
||||
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view || !isnull(G.lighting_alpha))
|
||||
update_sight()
|
||||
update_inv_glasses()
|
||||
else if(I == ears)
|
||||
|
||||
@@ -57,8 +57,6 @@
|
||||
/mob/living/carbon/human/calculate_affecting_pressure(pressure)
|
||||
if((wear_suit && (wear_suit.flags & STOPSPRESSUREDMAGE)) && (head && (head.flags & STOPSPRESSUREDMAGE)))
|
||||
return ONE_ATMOSPHERE
|
||||
if(ismob(loc))
|
||||
return ONE_ATMOSPHERE //hopefully won't murderficate people in your guts by going for a spacewalk
|
||||
else
|
||||
return pressure
|
||||
|
||||
@@ -98,7 +96,7 @@
|
||||
if(!dna.species.breathe(src))
|
||||
..()
|
||||
#define HUMAN_MAX_OXYLOSS 3
|
||||
#define HUMAN_CRIT_MAX_OXYLOSS (SSmob.wait/30)
|
||||
#define HUMAN_CRIT_MAX_OXYLOSS (SSmobs.wait/30)
|
||||
/mob/living/carbon/human/check_breath(datum/gas_mixture/breath)
|
||||
|
||||
var/L = getorganslot("lungs")
|
||||
@@ -141,8 +139,6 @@
|
||||
|
||||
/mob/living/carbon/human/proc/get_thermal_protection()
|
||||
var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures
|
||||
if(ismob(loc))
|
||||
thermal_protection = FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT //because lazy and insulated by being inside someone
|
||||
if(wear_suit)
|
||||
if(wear_suit.max_heat_protection_temperature >= FIRE_SUIT_MAX_TEMP_PROTECT)
|
||||
thermal_protection += (wear_suit.max_heat_protection_temperature*0.7)
|
||||
@@ -252,9 +248,6 @@
|
||||
if(dna.check_mutation(COLDRES))
|
||||
return 1 //Fully protected from the cold.
|
||||
|
||||
if(ismob(loc))
|
||||
return 1 //because lazy and being inside somemone insulates you from space
|
||||
|
||||
if(dna && (RESISTCOLD in dna.species.species_traits))
|
||||
return 1
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
/mob/living/carbon/human/say_quote(input, spans)
|
||||
if(!input)
|
||||
return "says, \"...\"" //not the best solution, but it will stop a large number of runtimes. The cause is somewhere in the Tcomms code
|
||||
/mob/living/carbon/human/say_quote(input, spans, message_mode)
|
||||
verb_say = dna.species.say_mod
|
||||
. = ..()
|
||||
if(src.slurring)
|
||||
input = attach_spans(input, spans)
|
||||
return "slurs, \"[input]\""
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/treat_message(message)
|
||||
message = dna.species.handle_speech(message,src)
|
||||
@@ -75,7 +73,7 @@
|
||||
if(!istype(dongle)) return 0
|
||||
if(dongle.translate_binary) return 1
|
||||
|
||||
/mob/living/carbon/human/radio(message, message_mode, list/spans)
|
||||
/mob/living/carbon/human/radio(message, message_mode, list/spans, language)
|
||||
. = ..()
|
||||
if(. != 0)
|
||||
return .
|
||||
@@ -83,17 +81,17 @@
|
||||
switch(message_mode)
|
||||
if(MODE_HEADSET)
|
||||
if (ears)
|
||||
ears.talk_into(src, message, , spans)
|
||||
ears.talk_into(src, message, , spans, language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
if(MODE_DEPARTMENT)
|
||||
if (ears)
|
||||
ears.talk_into(src, message, message_mode, spans)
|
||||
ears.talk_into(src, message, message_mode, spans, language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
if(message_mode in radiochannels)
|
||||
if(message_mode in GLOB.radiochannels)
|
||||
if(ears)
|
||||
ears.talk_into(src, message, message_mode, spans)
|
||||
ears.talk_into(src, message, message_mode, spans, language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
return 0
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race
|
||||
|
||||
var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows
|
||||
|
||||
var/face_y_offset = 0
|
||||
var/hair_y_offset = 0
|
||||
|
||||
var/hair_color = null // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color
|
||||
var/hair_alpha = 255 // the alpha used by the hair. 255 is completely solid, 0 is transparent.
|
||||
var/use_skintones = 0 // does it use skintones or not? (spoiler alert this is only used by humans)
|
||||
@@ -69,8 +73,6 @@
|
||||
var/fixed_mut_color3 = ""
|
||||
var/whitelisted = 0 //Is this species restricted to certain players?
|
||||
var/whitelist = list() //List the ckeys that can use this species, if it's whitelisted.: list("John Doe", "poopface666", "SeeALiggerPullTheTrigger") Spaces & capitalization can be included or ignored entirely for each key as it checks for both.
|
||||
var/lang_spoken = HUMAN
|
||||
var/lang_understood = HUMAN
|
||||
|
||||
///////////
|
||||
// PROCS //
|
||||
@@ -90,21 +92,21 @@
|
||||
|
||||
var/randname
|
||||
if(gender == MALE)
|
||||
randname = pick(first_names_male)
|
||||
randname = pick(GLOB.first_names_male)
|
||||
else
|
||||
randname = pick(first_names_female)
|
||||
randname = pick(GLOB.first_names_female)
|
||||
|
||||
if(lastname)
|
||||
randname += " [lastname]"
|
||||
else
|
||||
randname += " [pick(last_names)]"
|
||||
randname += " [pick(GLOB.last_names)]"
|
||||
|
||||
return randname
|
||||
|
||||
|
||||
//Please override this locally if you want to define when what species qualifies for what rank if human authority is enforced.
|
||||
/datum/species/proc/qualifies_for_rank(rank, list/features)
|
||||
if(rank in command_positions)
|
||||
if(rank in GLOB.command_positions)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
@@ -205,7 +207,7 @@
|
||||
facialhair_hidden = TRUE
|
||||
|
||||
if(H.facial_hair_style && (FACEHAIR in species_traits) && (!facialhair_hidden || dynamic_fhair_suffix))
|
||||
S = facial_hair_styles_list[H.facial_hair_style]
|
||||
S = GLOB.facial_hair_styles_list[H.facial_hair_style]
|
||||
if(S)
|
||||
|
||||
//List of all valid dynamic_fhair_suffixes
|
||||
@@ -262,7 +264,7 @@
|
||||
standing += image("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained", "layer" = -HAIR_LAYER)
|
||||
|
||||
else if(H.hair_style && (HAIR in species_traits))
|
||||
S = hair_styles_list[H.hair_style]
|
||||
S = GLOB.hair_styles_list[H.hair_style]
|
||||
if(S)
|
||||
|
||||
//List of all valid dynamic_hair_suffixes
|
||||
@@ -295,6 +297,7 @@
|
||||
img_hair.color = forced_colour
|
||||
img_hair.alpha = hair_alpha
|
||||
|
||||
img_hair.pixel_y += hair_y_offset
|
||||
standing += img_hair
|
||||
|
||||
if(standing.len)
|
||||
@@ -311,33 +314,36 @@
|
||||
|
||||
|
||||
// eyes
|
||||
var/has_eyes = (H.getorgan(/obj/item/organ/eyes) && HD)
|
||||
var/has_eyes = TRUE
|
||||
|
||||
if(!has_eyes)
|
||||
if(!H.getorgan(/obj/item/organ/eyes) && HD)
|
||||
standing += image("icon"='icons/mob/human_face.dmi', "icon_state" = "eyes_missing", "layer" = -BODY_LAYER)
|
||||
has_eyes = FALSE
|
||||
|
||||
if(!HUSK)
|
||||
if(!(H.disabilities & HUSK))
|
||||
// lipstick
|
||||
if(H.lip_style && (LIPS in species_traits) && HD)
|
||||
var/image/lips = image("icon"='icons/mob/human_face.dmi', "icon_state"="lips_[H.lip_style]", "layer" = -BODY_LAYER)
|
||||
lips.color = H.lip_color
|
||||
lips.pixel_y += face_y_offset
|
||||
standing += lips
|
||||
|
||||
// eyes
|
||||
if((EYECOLOR in species_traits) && HD && has_eyes)
|
||||
var/image/img_eyes = image("icon" = 'icons/mob/human_face.dmi', "icon_state" = "eyes", "layer" = -BODY_LAYER)
|
||||
img_eyes.color = "#" + H.eye_color
|
||||
img_eyes.pixel_y += face_y_offset
|
||||
standing += img_eyes
|
||||
|
||||
//Underwear, Undershirts & Socks
|
||||
/*This will be refactored at a later date
|
||||
if(H.underwear)
|
||||
var/datum/sprite_accessory/underwear/underwear = underwear_list[H.underwear]
|
||||
var/datum/sprite_accessory/underwear/underwear = GLOB.underwear_list[H.underwear]
|
||||
if(underwear)
|
||||
standing += image("icon"=underwear.icon, "icon_state"="[underwear.icon_state]", "layer"=-BODY_LAYER)
|
||||
|
||||
if(H.undershirt)
|
||||
var/datum/sprite_accessory/undershirt/undershirt = undershirt_list[H.undershirt]
|
||||
var/datum/sprite_accessory/undershirt/undershirt = GLOB.undershirt_list[H.undershirt]
|
||||
if(undershirt)
|
||||
if(H.dna.species.sexes && H.gender == FEMALE)
|
||||
standing += wear_female_version("[undershirt.icon_state]", undershirt.icon, BODY_LAYER)
|
||||
@@ -345,7 +351,7 @@
|
||||
standing += image("icon"=undershirt.icon, "icon_state"="[undershirt.icon_state]", "layer"=-BODY_LAYER)
|
||||
|
||||
if(H.socks && H.get_num_legs() >= 2 && !(DIGITIGRADE in species_traits))
|
||||
var/datum/sprite_accessory/socks/socks = socks_list[H.socks]
|
||||
var/datum/sprite_accessory/socks/socks = GLOB.socks_list[H.socks]
|
||||
if(socks)
|
||||
standing += image("icon"=socks.icon, "icon_state"="[socks.icon_state]", "layer"=-BODY_LAYER)
|
||||
*/
|
||||
@@ -495,53 +501,53 @@
|
||||
var/datum/sprite_accessory/S
|
||||
switch(bodypart)
|
||||
if("tail_lizard")
|
||||
S = tails_list_lizard[H.dna.features["tail_lizard"]]
|
||||
S = GLOB.tails_list_lizard[H.dna.features["tail_lizard"]]
|
||||
if("waggingtail_lizard")
|
||||
S.= animated_tails_list_lizard[H.dna.features["tail_lizard"]]
|
||||
S.= GLOB.animated_tails_list_lizard[H.dna.features["tail_lizard"]]
|
||||
if("tail_human")
|
||||
S = tails_list_human[H.dna.features["tail_human"]]
|
||||
S = GLOB.tails_list_human[H.dna.features["tail_human"]]
|
||||
if("waggingtail_human")
|
||||
S.= animated_tails_list_human[H.dna.features["tail_human"]]
|
||||
S.= GLOB.animated_tails_list_human[H.dna.features["tail_human"]]
|
||||
if("spines")
|
||||
S = spines_list[H.dna.features["spines"]]
|
||||
S = GLOB.spines_list[H.dna.features["spines"]]
|
||||
if("waggingspines")
|
||||
S.= animated_spines_list[H.dna.features["spines"]]
|
||||
S.= GLOB.animated_spines_list[H.dna.features["spines"]]
|
||||
if("snout")
|
||||
S = snouts_list[H.dna.features["snout"]]
|
||||
S = GLOB.snouts_list[H.dna.features["snout"]]
|
||||
if("frills")
|
||||
S = frills_list[H.dna.features["frills"]]
|
||||
S = GLOB.frills_list[H.dna.features["frills"]]
|
||||
if("horns")
|
||||
S = horns_list[H.dna.features["horns"]]
|
||||
S = GLOB.horns_list[H.dna.features["horns"]]
|
||||
if("ears")
|
||||
S = ears_list[H.dna.features["ears"]]
|
||||
S = GLOB.ears_list[H.dna.features["ears"]]
|
||||
if("body_markings")
|
||||
S = body_markings_list[H.dna.features["body_markings"]]
|
||||
S = GLOB.body_markings_list[H.dna.features["body_markings"]]
|
||||
if("wings")
|
||||
S = wings_list[H.dna.features["wings"]]
|
||||
S = GLOB.wings_list[H.dna.features["wings"]]
|
||||
if("wingsopen")
|
||||
S = wings_open_list[H.dna.features["wings"]]
|
||||
S = GLOB.wings_open_list[H.dna.features["wings"]]
|
||||
if("legs")
|
||||
S = legs_list[H.dna.features["legs"]]
|
||||
S = GLOB.legs_list[H.dna.features["legs"]]
|
||||
|
||||
//Mammal Bodyparts (Canid/Felid, others maybe in the future)
|
||||
if("mam_tail")
|
||||
S = mam_tails_list[H.dna.features["mam_tail"]]
|
||||
S = GLOB.mam_tails_list[H.dna.features["mam_tail"]]
|
||||
if("mam_waggingtail")
|
||||
S.= mam_tails_animated_list[H.dna.features["mam_tail"]]
|
||||
S.= GLOB.mam_tails_animated_list[H.dna.features["mam_tail"]]
|
||||
if("mam_body_markings")
|
||||
S = mam_body_markings_list[H.dna.features["mam_body_markings"]]
|
||||
S = GLOB.mam_body_markings_list[H.dna.features["mam_body_markings"]]
|
||||
if("mam_ears")
|
||||
S = mam_ears_list[H.dna.features["mam_ears"]]
|
||||
S = GLOB.mam_ears_list[H.dna.features["mam_ears"]]
|
||||
if("taur")
|
||||
S = taur_list[H.dna.features["taur"]]
|
||||
S = GLOB.taur_list[H.dna.features["taur"]]
|
||||
|
||||
//Xeno Bodyparts
|
||||
if("xenodorsal")
|
||||
S = xeno_dorsal_list[H.dna.features["xenodorsal"]]
|
||||
S = GLOB.xeno_dorsal_list[H.dna.features["xenodorsal"]]
|
||||
if("xenohead")
|
||||
S = xeno_head_list[H.dna.features["xenohead"]]
|
||||
S = GLOB.xeno_head_list[H.dna.features["xenohead"]]
|
||||
if("xenotail")
|
||||
S = xeno_tail_list[H.dna.features["xenotail"]]
|
||||
S = GLOB.xeno_tail_list[H.dna.features["xenotail"]]
|
||||
|
||||
//Slimecoon Bodyparts
|
||||
/* if("slimecoontail")
|
||||
@@ -1035,6 +1041,8 @@
|
||||
return 1
|
||||
|
||||
/datum/species/proc/go_bald(mob/living/carbon/human/H)
|
||||
if(QDELETED(H)) //may be called from a timer
|
||||
return
|
||||
H.facial_hair_style = "Shaved"
|
||||
H.hair_style = "Bald"
|
||||
H.update_hair()
|
||||
@@ -1198,9 +1206,9 @@
|
||||
target.visible_message("<span class='danger'>[user] has weakened [target]!</span>", \
|
||||
"<span class='userdanger'>[user] has weakened [target]!</span>")
|
||||
target.apply_effect(4, WEAKEN, armor_block)
|
||||
target.forcesay(hit_appends)
|
||||
target.forcesay(GLOB.hit_appends)
|
||||
else if(target.lying)
|
||||
target.forcesay(hit_appends)
|
||||
target.forcesay(GLOB.hit_appends)
|
||||
|
||||
|
||||
|
||||
@@ -1223,7 +1231,6 @@
|
||||
return 1
|
||||
else
|
||||
user.do_attack_animation(target, ATTACK_EFFECT_DISARM)
|
||||
add_logs(user, target, "disarmed")
|
||||
|
||||
if(target.w_uniform)
|
||||
target.w_uniform.add_fingerprint(user)
|
||||
@@ -1234,24 +1241,26 @@
|
||||
target.visible_message("<span class='danger'>[user] has pushed [target]!</span>",
|
||||
"<span class='userdanger'>[user] has pushed [target]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
target.apply_effect(2, WEAKEN, target.run_armor_check(affecting, "melee", "Your armor prevents your fall!", "Your armor softens your fall!"))
|
||||
target.forcesay(hit_appends)
|
||||
target.forcesay(GLOB.hit_appends)
|
||||
add_logs(user, target, "disarmed", " pushing them to the ground")
|
||||
|
||||
return
|
||||
|
||||
var/talked = 0 // BubbleWrap
|
||||
|
||||
if(randn <= 60)
|
||||
//BubbleWrap: Disarming breaks a pull
|
||||
var/obj/item/I = null
|
||||
if(target.pulling)
|
||||
to_chat(target, "<span class='warning'>[user] has broken [target]'s grip on [target.pulling]!</span>")
|
||||
talked = 1
|
||||
target.stop_pulling()
|
||||
//End BubbleWrap
|
||||
|
||||
if(!talked) //BubbleWrap
|
||||
else
|
||||
I = target.get_active_held_item()
|
||||
if(target.drop_item())
|
||||
target.visible_message("<span class='danger'>[user] has disarmed [target]!</span>", \
|
||||
"<span class='userdanger'>[user] has disarmed [target]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
I = null
|
||||
playsound(target, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
add_logs(user, target, "disarmed", "[I ? " removing \the [I]" : ""]")
|
||||
return
|
||||
|
||||
|
||||
@@ -1347,7 +1356,7 @@
|
||||
H.adjust_blurriness(10)
|
||||
|
||||
if(prob(I.force + ((100 - H.health)/2)) && H != user)
|
||||
ticker.mode.remove_revolutionary(H.mind)
|
||||
SSticker.mode.remove_revolutionary(H.mind)
|
||||
|
||||
if(bloody) //Apply blood
|
||||
if(H.wear_mask)
|
||||
@@ -1376,7 +1385,7 @@
|
||||
H.update_inv_w_uniform()
|
||||
|
||||
if(Iforce > 10 || Iforce >= 5 && prob(33))
|
||||
H.forcesay(hit_appends) //forcesay checks stat already.
|
||||
H.forcesay(GLOB.hit_appends) //forcesay checks stat already.
|
||||
return TRUE
|
||||
|
||||
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H)
|
||||
@@ -1480,7 +1489,7 @@
|
||||
H.apply_damage(HEAT_DAMAGE_LEVEL_3*heatmod, BURN)
|
||||
else
|
||||
H.apply_damage(HEAT_DAMAGE_LEVEL_2*heatmod, BURN)
|
||||
else if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !(mutations_list[COLDRES] in H.dna.mutations))
|
||||
else if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !(GLOB.mutations_list[COLDRES] in H.dna.mutations))
|
||||
switch(H.bodytemperature)
|
||||
if(200 to 260)
|
||||
H.throw_alert("temp", /obj/screen/alert/cold, 1)
|
||||
|
||||
@@ -14,6 +14,8 @@ datum/species/mammal
|
||||
if(H)
|
||||
H.endTailWag()
|
||||
|
||||
/datum/species/mammal/qualifies_for_rank(rank, list/features)
|
||||
return TRUE
|
||||
|
||||
//AVIAN//
|
||||
/datum/species/avian
|
||||
@@ -32,6 +34,9 @@ datum/species/mammal
|
||||
if(H)
|
||||
H.endTailWag()
|
||||
|
||||
/datum/species/avian/qualifies_for_rank(rank, list/features)
|
||||
return TRUE
|
||||
|
||||
//AQUATIC//
|
||||
/datum/species/aquatic
|
||||
name = "Aquatic"
|
||||
@@ -48,6 +53,10 @@ datum/species/mammal
|
||||
/datum/species/aquatic/spec_death(gibbed, mob/living/carbon/human/H)
|
||||
if(H)
|
||||
H.endTailWag()
|
||||
|
||||
/datum/species/aquatic/qualifies_for_rank(rank, list/features)
|
||||
return TRUE
|
||||
|
||||
//INSECT//
|
||||
/datum/species/insect
|
||||
name = "Insect"
|
||||
@@ -65,6 +74,8 @@ datum/species/mammal
|
||||
if(H)
|
||||
H.endTailWag()
|
||||
|
||||
/datum/species/insect/qualifies_for_rank(rank, list/features)
|
||||
return TRUE
|
||||
//HERBIVOROUS//
|
||||
|
||||
//EXOTIC//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/datum/species/golem
|
||||
// Animated beings of stone. They have increased defenses, and do not need to breathe. They're also slow as fuuuck.
|
||||
name = "Golem"
|
||||
id = "iron"
|
||||
id = "iron golem"
|
||||
species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOFIRE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS)
|
||||
speedmod = 2
|
||||
armor = 55
|
||||
@@ -12,6 +12,7 @@
|
||||
no_equip = list(slot_wear_mask, slot_wear_suit, slot_gloves, slot_shoes, slot_w_uniform)
|
||||
nojumpsuit = 1
|
||||
sexes = 1
|
||||
damage_overlay_type = ""
|
||||
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/golem
|
||||
// To prevent golem subtypes from overwhelming the odds when random species
|
||||
// changes, only the Random Golem type can be chosen
|
||||
@@ -21,6 +22,21 @@
|
||||
fixed_mut_color = "aaa"
|
||||
var/info_text = "As an <span class='danger'>Iron Golem</span>, you don't have any special traits."
|
||||
|
||||
var/prefix = "Iron"
|
||||
var/list/special_names
|
||||
|
||||
/datum/species/golem/random_name(gender,unique,lastname)
|
||||
var/golem_surname = pick(GLOB.golem_names)
|
||||
// 3% chance that our golem has a human surname, because
|
||||
// cultural contamination
|
||||
if(prob(3))
|
||||
golem_surname = pick(GLOB.last_names)
|
||||
else if(special_names && prob(5))
|
||||
golem_surname = pick(special_names)
|
||||
|
||||
var/golem_name = "[prefix] [golem_surname]"
|
||||
return golem_name
|
||||
|
||||
/datum/species/golem/random
|
||||
name = "Random Golem"
|
||||
blacklisted = FALSE
|
||||
@@ -36,21 +52,24 @@
|
||||
|
||||
/datum/species/golem/adamantine
|
||||
name = "Adamantine Golem"
|
||||
id = "adamantine"
|
||||
id = "adamantine golem"
|
||||
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/golem/adamantine
|
||||
fixed_mut_color = "4ed"
|
||||
info_text = "As an <span class='danger'>Adamantine Golem</span>, you don't have any special traits."
|
||||
prefix = "Adamantine"
|
||||
|
||||
//Explodes on death
|
||||
/datum/species/golem/plasma
|
||||
name = "Plasma Golem"
|
||||
id = "plasma"
|
||||
id = "plasma golem"
|
||||
fixed_mut_color = "a3d"
|
||||
meat = /obj/item/weapon/ore/plasma
|
||||
//Can burn and takes damage from heat
|
||||
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS)
|
||||
info_text = "As a <span class='danger'>Plasma Golem</span>, you explode on death!"
|
||||
burnmod = 1.5
|
||||
prefix = "Plasma"
|
||||
special_names = list("Flood","Fire","Bar","Man")
|
||||
|
||||
/datum/species/golem/plasma/spec_death(gibbed, mob/living/carbon/human/H)
|
||||
explosion(get_turf(H),0,1,2,flame_range = 5)
|
||||
@@ -60,35 +79,40 @@
|
||||
//Harder to hurt
|
||||
/datum/species/golem/diamond
|
||||
name = "Diamond Golem"
|
||||
id = "diamond"
|
||||
id = "diamond golem"
|
||||
fixed_mut_color = "0ff"
|
||||
armor = 70 //up from 55
|
||||
meat = /obj/item/weapon/ore/diamond
|
||||
info_text = "As a <span class='danger'>Diamond Golem</span>, you are more resistant than the average golem."
|
||||
prefix = "Diamond"
|
||||
special_names = list("Back")
|
||||
|
||||
//Faster but softer and less armoured
|
||||
/datum/species/golem/gold
|
||||
name = "Gold Golem"
|
||||
id = "gold"
|
||||
id = "gold golem"
|
||||
fixed_mut_color = "cc0"
|
||||
speedmod = 1
|
||||
armor = 25 //down from 55
|
||||
meat = /obj/item/weapon/ore/gold
|
||||
info_text = "As a <span class='danger'>Gold Golem</span>, you are faster but less resistant than the average golem."
|
||||
prefix = "Golden"
|
||||
|
||||
//Heavier, thus higher chance of stunning when punching
|
||||
/datum/species/golem/silver
|
||||
name = "Silver Golem"
|
||||
id = "silver"
|
||||
id = "silver golem"
|
||||
fixed_mut_color = "ddd"
|
||||
punchstunthreshold = 9 //60% chance, from 40%
|
||||
meat = /obj/item/weapon/ore/silver
|
||||
info_text = "As a <span class='danger'>Silver Golem</span>, your attacks are heavier and have a higher chance of stunning."
|
||||
prefix = "Silver"
|
||||
special_names = list("Surfer", "Chariot", "Lining")
|
||||
|
||||
//Harder to stun, deals more damage, but it's even slower
|
||||
/datum/species/golem/plasteel
|
||||
name = "Plasteel Golem"
|
||||
id = "plasteel"
|
||||
id = "plasteel golem"
|
||||
fixed_mut_color = "bbb"
|
||||
stunmod = 0.40
|
||||
punchdamagelow = 12
|
||||
@@ -99,15 +123,17 @@
|
||||
info_text = "As a <span class='danger'>Plasteel Golem</span>, you are slower, but harder to stun, and hit very hard when punching."
|
||||
attack_verb = "smash"
|
||||
attack_sound = 'sound/effects/meteorimpact.ogg' //hits pretty hard
|
||||
prefix = "Plasteel"
|
||||
|
||||
//Immune to ash storms
|
||||
/datum/species/golem/titanium
|
||||
name = "Titanium Golem"
|
||||
id = "titanium"
|
||||
id = "titanium golem"
|
||||
fixed_mut_color = "fff"
|
||||
meat = /obj/item/weapon/ore/titanium
|
||||
info_text = "As a <span class='danger'>Titanium Golem</span>, you are immune to ash storms, and slightly more resistant to burn damage."
|
||||
burnmod = 0.9
|
||||
prefix = "Titanium"
|
||||
|
||||
/datum/species/golem/titanium/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
. = ..()
|
||||
@@ -120,11 +146,12 @@
|
||||
//Immune to ash storms and lava
|
||||
/datum/species/golem/plastitanium
|
||||
name = "Plastitanium Golem"
|
||||
id = "plastitanium"
|
||||
id = "plastitanium golem"
|
||||
fixed_mut_color = "888"
|
||||
meat = /obj/item/weapon/ore/titanium
|
||||
info_text = "As a <span class='danger'>Plastitanium Golem</span>, you are immune to both ash storms and lava, and slightly more resistant to burn damage."
|
||||
burnmod = 0.8
|
||||
prefix = "Plastitanium"
|
||||
|
||||
/datum/species/golem/plastitanium/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
. = ..()
|
||||
@@ -139,12 +166,14 @@
|
||||
//Fast and regenerates... but can only speak like an abductor
|
||||
/datum/species/golem/alloy
|
||||
name = "Alien Alloy Golem"
|
||||
id = "alloy"
|
||||
id = "alloy golem"
|
||||
fixed_mut_color = "333"
|
||||
meat = /obj/item/stack/sheet/mineral/abductor
|
||||
mutant_organs = list(/obj/item/organ/tongue/abductor) //abductor tongue
|
||||
speedmod = 1 //faster
|
||||
info_text = "As an <span class='danger'>Alloy Golem</span>, you are made of advanced alien materials: you are faster and regenerate over time. You are, however, only able to be heard by other alloy golems."
|
||||
prefix = "Alien"
|
||||
special_names = list("Outsider", "Technology", "Watcher", "Stranger") //ominous and unknown
|
||||
|
||||
//Regenerates because self-repairing super-advanced alien tech
|
||||
/datum/species/golem/alloy/spec_life(mob/living/carbon/human/H)
|
||||
@@ -157,7 +186,7 @@
|
||||
//Since this will usually be created from a collaboration between podpeople and free golems, wood golems are a mix between the two races
|
||||
/datum/species/golem/wood
|
||||
name = "Wood Golem"
|
||||
id = "wood"
|
||||
id = "wood golem"
|
||||
fixed_mut_color = "49311c"
|
||||
meat = /obj/item/stack/sheet/mineral/wood
|
||||
//Can burn and take damage from heat
|
||||
@@ -166,6 +195,13 @@
|
||||
burnmod = 1.25
|
||||
heatmod = 1.5
|
||||
info_text = "As a <span class='danger'>Wooden Golem</span>, you have plant-like traits: you take damage from extreme temperatures, can be set on fire, and have lower armor than a normal golem. You regenerate when in the light and wither in the darkness."
|
||||
prefix = "Wooden"
|
||||
|
||||
/datum/species/golem/wood/random_name(gender,unique,lastname)
|
||||
var/plant_name = pick("Tomato", "Potato", "Broccoli", "Carrot", "Ambrosia", "Pumpkin", "Ivy", "Kudzu", "Banana", "Moss", "Flower", "Bloom", "Root", "Bark", "Glowshroom", "Petal", "Leaf", \
|
||||
"Venus", "Sprout","Cocoa", "Strawberry", "Citrus", "Oak", "Cactus", "Pepper", "Juniper")
|
||||
var/golem_name = "[prefix] [plant_name]"
|
||||
return golem_name
|
||||
|
||||
/datum/species/golem/wood/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
. = ..()
|
||||
@@ -204,13 +240,14 @@
|
||||
//Radioactive
|
||||
/datum/species/golem/uranium
|
||||
name = "Uranium Golem"
|
||||
id = "uranium"
|
||||
id = "uranium golem"
|
||||
fixed_mut_color = "7f0"
|
||||
meat = /obj/item/weapon/ore/uranium
|
||||
info_text = "As an <span class='danger'>Uranium Golem</span>, you emit radiation pulses every once in a while. It won't harm fellow golems, but organic lifeforms will be affected."
|
||||
|
||||
var/last_event = 0
|
||||
var/active = null
|
||||
prefix = "Uranium"
|
||||
|
||||
/datum/species/golem/uranium/spec_life(mob/living/carbon/human/H)
|
||||
if(!active)
|
||||
@@ -224,7 +261,7 @@
|
||||
//Immune to physical bullets and resistant to brute, but very vulnerable to burn damage. Dusts on death.
|
||||
/datum/species/golem/sand
|
||||
name = "Sand Golem"
|
||||
id = "sand"
|
||||
id = "sand golem"
|
||||
fixed_mut_color = "ffdc8f"
|
||||
meat = /obj/item/weapon/ore/glass //this is sand
|
||||
armor = 0
|
||||
@@ -232,6 +269,7 @@
|
||||
brutemod = 0.25
|
||||
info_text = "As a <span class='danger'>Sand Golem</span>, you are immune to physical bullets and take very little brute damage, but are extremely vulnerable to burn damage. You will also turn to sand when dying, preventing any form of recovery."
|
||||
attack_sound = 'sound/effects/shovel_dig.ogg'
|
||||
prefix = "Sand"
|
||||
|
||||
/datum/species/golem/sand/spec_death(gibbed, mob/living/carbon/human/H)
|
||||
H.visible_message("<span class='danger'>[H] turns into a pile of sand!</span>")
|
||||
@@ -253,7 +291,7 @@
|
||||
//Reflects lasers and resistant to burn damage, but very vulnerable to brute damage. Shatters on death.
|
||||
/datum/species/golem/glass
|
||||
name = "Glass Golem"
|
||||
id = "glass"
|
||||
id = "glass golem"
|
||||
fixed_mut_color = "5a96b4aa" //transparent body
|
||||
meat = /obj/item/weapon/shard
|
||||
armor = 0
|
||||
@@ -261,6 +299,7 @@
|
||||
burnmod = 0.25
|
||||
info_text = "As a <span class='danger'>Glass Golem</span>, you reflect lasers and energy weapons, and are very resistant to burn damage, but you are extremely vulnerable to brute damage. On death, you'll shatter beyond any hope of recovery."
|
||||
attack_sound = 'sound/effects/Glassbr2.ogg'
|
||||
prefix = "Glass"
|
||||
|
||||
/datum/species/golem/glass/spec_death(gibbed, mob/living/carbon/human/H)
|
||||
playsound(H, "shatter", 70, 1)
|
||||
@@ -295,12 +334,14 @@
|
||||
//Teleports when hit or when it wants to
|
||||
/datum/species/golem/bluespace
|
||||
name = "Bluespace Golem"
|
||||
id = "bluespace"
|
||||
id = "bluespace golem"
|
||||
fixed_mut_color = "33f"
|
||||
meat = /obj/item/weapon/ore/bluespace_crystal
|
||||
info_text = "As a <span class='danger'>Bluespace Golem</span>, are spatially unstable: you will teleport when hit, and you can teleport manually at a long distance."
|
||||
attack_verb = "bluespace punch"
|
||||
attack_sound = 'sound/effects/phasein.ogg'
|
||||
prefix = "Bluespace"
|
||||
special_names = list("Crystal", "Polycrystal")
|
||||
|
||||
var/datum/action/innate/unstable_teleport/unstable_teleport
|
||||
var/teleport_cooldown = 100
|
||||
@@ -384,7 +425,7 @@
|
||||
//honk
|
||||
/datum/species/golem/bananium
|
||||
name = "Bananium Golem"
|
||||
id = "bananium"
|
||||
id = "bananium golem"
|
||||
fixed_mut_color = "ff0"
|
||||
say_mod = "honks"
|
||||
punchdamagelow = 0
|
||||
@@ -394,6 +435,7 @@
|
||||
info_text = "As a <span class='danger'>Bananium Golem</span>, you are made for pranking. Your body emits natural honks, and you cannot hurt people when punching them. Your skin also emits bananas when damaged."
|
||||
attack_verb = "honk"
|
||||
attack_sound = 'sound/items/AirHorn2.ogg'
|
||||
prefix = "Bananium"
|
||||
|
||||
var/last_honk = 0
|
||||
var/honkooldown = 0
|
||||
@@ -401,6 +443,11 @@
|
||||
var/banana_cooldown = 100
|
||||
var/active = null
|
||||
|
||||
/datum/species/golem/bananium/random_name(gender,unique,lastname)
|
||||
var/clown_name = pick(GLOB.clown_names)
|
||||
var/golem_name = "[uppertext(clown_name)]"
|
||||
return golem_name
|
||||
|
||||
/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style = M.martial_art)
|
||||
..()
|
||||
if(world.time > last_banana + banana_cooldown && M != H && M.a_intent != INTENT_HELP)
|
||||
@@ -449,7 +496,7 @@
|
||||
|
||||
/datum/species/golem/runic
|
||||
name = "Runic Golem"
|
||||
id = "runic"
|
||||
id = "runic golem"
|
||||
limbs_id = "cultgolem"
|
||||
sexes = FALSE
|
||||
info_text = "As a <span class='danger'>Runic Golem</span>, you possess eldritch powers granted by the Elder God Nar'Sie."
|
||||
@@ -459,6 +506,12 @@
|
||||
var/obj/effect/proc_holder/spell/targeted/abyssal_gaze/abyssal_gaze
|
||||
var/obj/effect/proc_holder/spell/targeted/dominate/dominate
|
||||
|
||||
/datum/species/golem/runic/random_name(gender,unique,lastname)
|
||||
var/edgy_first_name = pick("Razor","Blood","Dark","Evil","Cold","Pale","Black","Silent","Chaos","Deadly")
|
||||
var/edgy_last_name = pick("Edge","Night","Death","Razor","Blade","Steel","Calamity","Twilight","Shadow","Nightmare") //dammit Razor Razor
|
||||
var/golem_name = "[edgy_first_name] [edgy_last_name]"
|
||||
return golem_name
|
||||
|
||||
/datum/species/golem/runic/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
. = ..()
|
||||
C.faction |= "cult"
|
||||
@@ -489,3 +542,100 @@
|
||||
H.adjustFireLoss(-4)
|
||||
H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM)
|
||||
|
||||
/datum/species/golem/cloth
|
||||
name = "Cloth Golem"
|
||||
id = "cloth golem"
|
||||
limbs_id = "clothgolem"
|
||||
sexes = FALSE
|
||||
info_text = "As a <span class='danger'>Cloth Golem</span>, you are able to reform yourself after death, provided your remains aren't burned or destroyed. You are, of course, very flammable."
|
||||
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER) //no mutcolors, and can burn
|
||||
armor = 15 //feels no pain, but not too resistant
|
||||
burnmod = 2 // don't get burned
|
||||
speedmod = 1 // not as heavy as stone
|
||||
punchdamagelow = 4
|
||||
punchstunthreshold = 7
|
||||
punchdamagehigh = 8 // not as heavy as stone
|
||||
prefix = "Cloth"
|
||||
|
||||
/datum/species/golem/cloth/random_name(gender,unique,lastname)
|
||||
var/pharaoh_name = pick("Neferkare", "Hudjefa", "Khufu", "Mentuhotep", "Ahmose", "Amenhotep", "Thutmose", "Hatshepsut", "Tutankhamun", "Ramses", "Seti", \
|
||||
"Merenptah", "Djer", "Semerkhet", "Nynetjer", "Khafre", "Pepi", "Intef", "Ay") //yes, Ay was an actual pharaoh
|
||||
var/golem_name = "[pharaoh_name] \Roman[rand(1,99)]"
|
||||
return golem_name
|
||||
|
||||
/datum/species/golem/cloth/spec_life(mob/living/carbon/human/H)
|
||||
if(H.fire_stacks < 1)
|
||||
H.adjust_fire_stacks(1) //always prone to burning
|
||||
..()
|
||||
|
||||
/datum/species/golem/cloth/spec_death(gibbed, mob/living/carbon/human/H)
|
||||
if(gibbed)
|
||||
return
|
||||
if(H.on_fire)
|
||||
H.visible_message("<span class='danger'>[H] burns into ash!</span>")
|
||||
H.dust(just_ash = TRUE)
|
||||
return
|
||||
|
||||
H.visible_message("<span class='danger'>[H] falls apart into a pile of bandages!</span>")
|
||||
new /obj/structure/cloth_pile(get_turf(H), H)
|
||||
..()
|
||||
|
||||
/obj/structure/cloth_pile
|
||||
name = "pile of bandages"
|
||||
desc = "It emits a strange aura, as if there was still life within it..."
|
||||
obj_integrity = 50
|
||||
max_integrity = 50
|
||||
armor = list(melee = 90, bullet = 90, laser = 25, energy = 80, bomb = 50, bio = 100, fire = -50, acid = -50)
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "pile_bandages"
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
var/revive_time = 900
|
||||
var/mob/living/carbon/human/cloth_golem
|
||||
|
||||
/obj/structure/cloth_pile/Initialize(mapload, mob/living/carbon/human/H)
|
||||
if(!QDELETED(H) && is_species(H, /datum/species/golem/cloth))
|
||||
H.unequip_everything()
|
||||
H.forceMove(src)
|
||||
cloth_golem = H
|
||||
to_chat(cloth_golem, "<span class='notice'>You start gathering your life energy, preparing to rise again...</span>")
|
||||
addtimer(CALLBACK(src, .proc/revive), revive_time)
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/cloth_pile/Destroy()
|
||||
if(cloth_golem)
|
||||
QDEL_NULL(cloth_golem)
|
||||
return ..()
|
||||
|
||||
/obj/structure/cloth_pile/burn()
|
||||
visible_message("<span class='danger'>[src] burns into ash!</span>")
|
||||
new /obj/effect/decal/cleanable/ash(get_turf(src))
|
||||
..()
|
||||
|
||||
/obj/structure/cloth_pile/proc/revive()
|
||||
if(QDELETED(src) || QDELETED(cloth_golem)) //QDELETED also checks for null, so if no cloth golem is set this won't runtime
|
||||
return
|
||||
if(cloth_golem.suiciding || cloth_golem.disabilities & NOCLONE)
|
||||
QDEL_NULL(cloth_golem)
|
||||
return
|
||||
|
||||
invisibility = INVISIBILITY_MAXIMUM //disappear before the animation
|
||||
new /obj/effect/overlay/temp/mummy_animation(get_turf(src))
|
||||
if(cloth_golem.revive(full_heal = TRUE, admin_revive = TRUE))
|
||||
cloth_golem.grab_ghost() //won't pull if it's a suicide
|
||||
sleep(20)
|
||||
cloth_golem.forceMove(get_turf(src))
|
||||
cloth_golem.visible_message("<span class='danger'>[src] rises and reforms into [cloth_golem]!</span>","<span class='userdanger'>You reform into yourself!</span>")
|
||||
cloth_golem = null
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/cloth_pile/attackby(obj/item/weapon/P, mob/living/carbon/human/user, params)
|
||||
. = ..()
|
||||
|
||||
if(resistance_flags & ON_FIRE)
|
||||
return
|
||||
|
||||
if(P.is_hot())
|
||||
visible_message("<span class='danger'>[src] bursts into flames!</span>")
|
||||
fire_act()
|
||||
@@ -10,9 +10,7 @@
|
||||
|
||||
|
||||
/datum/species/human/qualifies_for_rank(rank, list/features)
|
||||
if((!features["tail_human"] || features["tail_human"] == "None") && (!features["ears"] || features["ears"] == "None"))
|
||||
return TRUE //Pure humans are always allowed in all roles.
|
||||
return ..()
|
||||
return TRUE
|
||||
|
||||
//Curiosity killed the cat's wagging tail.
|
||||
/datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,NOBLOOD,VIRUSIMMUNE,TOXINLOVER)
|
||||
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/slime
|
||||
exotic_blood = "slimejelly"
|
||||
damage_overlay_type = ""
|
||||
var/datum/action/innate/regenerate_limbs/regenerate_limbs
|
||||
|
||||
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
|
||||
@@ -226,7 +227,7 @@
|
||||
else
|
||||
ui_interact(owner)
|
||||
|
||||
/datum/action/innate/swap_body/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = conscious_state)
|
||||
/datum/action/innate/swap_body/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.conscious_state)
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,FACEHAIR)
|
||||
mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs", "taur")
|
||||
mutant_organs = list(/obj/item/organ/tongue/lizard)
|
||||
coldmod = 1.5
|
||||
heatmod = 0.67
|
||||
default_features = list("mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0", "tail" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Normal Legs", "taur" = "None")
|
||||
attack_verb = "slash"
|
||||
attack_sound = 'sound/weapons/slash.ogg'
|
||||
@@ -26,6 +28,9 @@
|
||||
|
||||
return randname
|
||||
|
||||
/datum/species/lizard/qualifies_for_rank(rank, list/features)
|
||||
return TRUE
|
||||
|
||||
//I wag in death
|
||||
/datum/species/lizard/spec_death(gibbed, mob/living/carbon/human/H)
|
||||
if(H)
|
||||
@@ -38,4 +43,4 @@
|
||||
name = "Ash Walker"
|
||||
id = "ashlizard"
|
||||
limbs_id = "lizard"
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,NOBREATH,NOGUNS,DIGITIGRADE)
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,NOBREATH,NOGUNS,DIGITIGRADE)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
var/global/image/plasmaman_on_fire = image("icon"='icons/mob/OnFire.dmi', "icon_state"="plasmaman")
|
||||
|
||||
/datum/species/plasmaman
|
||||
name = "Plasmaman"
|
||||
id = "plasmaman"
|
||||
@@ -52,7 +50,7 @@ var/global/image/plasmaman_on_fire = image("icon"='icons/mob/OnFire.dmi', "icon_
|
||||
return 0
|
||||
|
||||
/datum/species/plasmaman/qualifies_for_rank(rank, list/features)
|
||||
if(rank in security_positions)
|
||||
if(rank in GLOB.security_positions)
|
||||
return 0
|
||||
if(rank == "Clown" || rank == "Mime")//No funny bussiness
|
||||
return 0
|
||||
|
||||
@@ -99,7 +99,7 @@ There are several things that need to be remembered:
|
||||
/* --------------------------------------- */
|
||||
//vvvvvv UPDATE_INV PROCS vvvvvv
|
||||
|
||||
/mob/living/carbon/human/update_inv_w_uniform()
|
||||
/mob/living/carbon/human/update_inv_w_uniform(invdrop = TRUE)
|
||||
remove_overlay(UNIFORM_LAYER)
|
||||
|
||||
if(client && hud_used)
|
||||
@@ -138,7 +138,7 @@ There are several things that need to be remembered:
|
||||
|
||||
overlays_standing[UNIFORM_LAYER] = standing
|
||||
|
||||
else if(!(dna && dna.species.nojumpsuit))
|
||||
else if(!(dna && dna.species.nojumpsuit) && invdrop)
|
||||
// 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, belt)) //
|
||||
dropItemToGround(thing)
|
||||
@@ -274,7 +274,7 @@ There are several things that need to be remembered:
|
||||
client.screen += shoes //add it to client's screen
|
||||
update_observer_view(shoes,1)
|
||||
var/image/standing = shoes.build_worn_icon(state = shoes.icon_state, default_layer = SHOES_LAYER, default_icon_file = 'icons/mob/feet.dmi')
|
||||
overlays_standing[SHOES_LAYER] = standing
|
||||
overlays_standing[SHOES_LAYER] = standing
|
||||
|
||||
apply_overlay(SHOES_LAYER)
|
||||
|
||||
@@ -392,10 +392,10 @@ There are several things that need to be remembered:
|
||||
|
||||
/proc/wear_female_version(t_color, icon, layer, type)
|
||||
var/index = t_color
|
||||
var/icon/female_clothing_icon = female_clothing_icons[index]
|
||||
var/icon/female_clothing_icon = GLOB.female_clothing_icons[index]
|
||||
if(!female_clothing_icon) //Create standing/laying icons if they don't exist
|
||||
generate_female_clothing(index,t_color,icon,type)
|
||||
var/standing = image("icon"=female_clothing_icons["[t_color]"], "layer"=-layer)
|
||||
var/standing = image("icon"=GLOB.female_clothing_icons["[t_color]"], "layer"=-layer)
|
||||
return(standing)
|
||||
|
||||
/mob/living/carbon/human/proc/get_overlays_copy(list/unwantedLayers)
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
/mob/living/carbon/human/whisper(message as text)
|
||||
/mob/living/carbon/human/whisper_verb(message as text)
|
||||
whisper(message)
|
||||
|
||||
/mob/living/carbon/human/whisper(message, datum/language/language=null)
|
||||
if(!IsVocal())
|
||||
return
|
||||
if(!message)
|
||||
return
|
||||
if(!language)
|
||||
language = get_default_language()
|
||||
|
||||
if(say_disabled) //This is here to try to identify lag problems
|
||||
if(GLOB.say_disabled) //This is here to try to identify lag problems
|
||||
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
|
||||
return
|
||||
|
||||
@@ -44,9 +49,11 @@
|
||||
message = Ellipsis(message, 10, 1)
|
||||
|
||||
message = treat_message(message)
|
||||
if(!message)
|
||||
return
|
||||
|
||||
var/list/listening_dead = list()
|
||||
for(var/mob/M in player_list)
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.stat == DEAD && M.client && ((M.client.prefs.chat_toggles & CHAT_GHOSTWHISPER) || (get_dist(M, src) <= 7)))
|
||||
listening_dead |= M
|
||||
|
||||
@@ -71,14 +78,14 @@
|
||||
for(var/atom/movable/AM in listening)
|
||||
if(istype(AM,/obj/item/device/radio))
|
||||
continue
|
||||
AM.Hear(rendered, src, languages_spoken, message, , spans)
|
||||
AM.Hear(rendered, src, language, message, , spans)
|
||||
|
||||
message = stars(message)
|
||||
rendered = "<span class='game say'><span class='name'>[GetVoice()]</span>[alt_name] [whispers], <span class='message'>\"[attach_spans(message, spans)]\"</span></span>"
|
||||
for(var/atom/movable/AM in eavesdropping)
|
||||
if(istype(AM,/obj/item/device/radio))
|
||||
continue
|
||||
AM.Hear(rendered, src, languages_spoken, message, , spans)
|
||||
AM.Hear(rendered, src, language, message, , spans)
|
||||
|
||||
if(critical) //Dying words.
|
||||
succumb(1)
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
//Start of a breath chain, calls breathe()
|
||||
/mob/living/carbon/handle_breathing()
|
||||
if(SSmob.times_fired%4==2 || failed_last_breath)
|
||||
if(SSmobs.times_fired%4==2 || failed_last_breath)
|
||||
breathe() //Breathe per 4 ticks, unless suffocating
|
||||
else
|
||||
if(istype(loc, /obj/))
|
||||
@@ -47,8 +47,6 @@
|
||||
if(loc)
|
||||
environment = loc.return_air()
|
||||
|
||||
if(ismob(loc)) return
|
||||
|
||||
var/datum/gas_mixture/breath
|
||||
|
||||
if(health <= HEALTH_THRESHOLD_CRIT || (pulledby && pulledby.grab_state >= GRAB_KILL && !getorganslot("breathing_tube")))
|
||||
@@ -132,7 +130,7 @@
|
||||
if(prob(20))
|
||||
emote("gasp")
|
||||
if(O2_partialpressure > 0)
|
||||
var/ratio = safe_oxy_min/O2_partialpressure
|
||||
var/ratio = 1 - O2_partialpressure/safe_oxy_min
|
||||
adjustOxyLoss(min(5*ratio, 3))
|
||||
failed_last_breath = 1
|
||||
oxygen_used = breath_gases["o2"][MOLES]*ratio
|
||||
@@ -255,7 +253,7 @@
|
||||
dna.previous.Remove("blood_type")
|
||||
dna.temporary_mutations.Remove(mut)
|
||||
continue
|
||||
HM = mutations_list[mut]
|
||||
HM = GLOB.mutations_list[mut]
|
||||
HM.force_lose(src)
|
||||
dna.temporary_mutations.Remove(mut)
|
||||
|
||||
@@ -294,7 +292,7 @@
|
||||
stomach_contents.Remove(M)
|
||||
qdel(M)
|
||||
continue
|
||||
if(SSmob.times_fired%3==1)
|
||||
if(SSmobs.times_fired%3==1)
|
||||
if(!(M.status_flags & GODMODE))
|
||||
M.adjustBruteLoss(5)
|
||||
nutrition += 10
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
var/pickpocketing = FALSE
|
||||
var/disposing_body = FALSE
|
||||
var/obj/machinery/disposal/bodyDisposal = null
|
||||
var/next_battle_screech = 0
|
||||
var/battle_screech_cooldown = 50
|
||||
|
||||
/mob/living/carbon/monkey/proc/IsStandingStill()
|
||||
return resisting || pickpocketing || disposing_body
|
||||
@@ -59,6 +61,12 @@
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/monkey/proc/battle_screech()
|
||||
if(next_battle_screech < world.time)
|
||||
emote(pick("roar","screech"))
|
||||
for(var/mob/living/carbon/monkey/M in view(7,src))
|
||||
M.next_battle_screech = world.time + battle_screech_cooldown
|
||||
|
||||
/mob/living/carbon/monkey/proc/equip_item(var/obj/item/I)
|
||||
|
||||
if(I.loc == src)
|
||||
@@ -197,7 +205,7 @@
|
||||
for(var/mob/living/L in around)
|
||||
if( should_target(L) )
|
||||
if(L.stat == CONSCIOUS)
|
||||
emote(pick("roar","screech"))
|
||||
battle_screech()
|
||||
retaliate(L)
|
||||
return TRUE
|
||||
else if(bodyDisposal)
|
||||
@@ -241,7 +249,7 @@
|
||||
var/list/around = view(src, MONKEY_ENEMY_VISION)
|
||||
for(var/mob/living/carbon/monkey/M in around)
|
||||
if(M.mode == MONKEY_IDLE && prob(MONKEY_RECRUIT_PROB))
|
||||
M.emote(pick("roar","screech"))
|
||||
M.battle_screech()
|
||||
M.target = target
|
||||
M.mode = MONKEY_HUNT
|
||||
|
||||
@@ -406,7 +414,7 @@
|
||||
enemies[L] += MONKEY_HATRED_AMOUNT
|
||||
|
||||
if(a_intent != INTENT_HARM)
|
||||
emote(pick("roar","screech"))
|
||||
battle_screech()
|
||||
a_intent = INTENT_HARM
|
||||
|
||||
/mob/living/carbon/monkey/attack_hand(mob/living/L)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
if(stat == CONSCIOUS)
|
||||
if(!handle_combat())
|
||||
if(prob(33) && canmove && isturf(loc) && !pulledby)
|
||||
step(src, pick(cardinal))
|
||||
step(src, pick(GLOB.cardinal))
|
||||
if(prob(1))
|
||||
emote(pick("scratch","jump","roll","tail"))
|
||||
else
|
||||
|
||||
@@ -2,18 +2,16 @@
|
||||
name = "monkey"
|
||||
voice_name = "monkey"
|
||||
verb_say = "chimpers"
|
||||
initial_languages = list(/datum/language/monkey)
|
||||
icon = 'icons/mob/monkey.dmi'
|
||||
icon_state = ""
|
||||
gender = NEUTER
|
||||
pass_flags = PASSTABLE
|
||||
languages_spoken = MONKEY
|
||||
languages_understood = MONKEY
|
||||
ventcrawler = VENTCRAWLER_NUDE
|
||||
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
|
||||
type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey
|
||||
gib_type = /obj/effect/decal/cleanable/blood/gibs
|
||||
unique_name = 1
|
||||
devourable = 1
|
||||
bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey,
|
||||
/obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
|
||||
|
||||
@@ -160,4 +158,4 @@
|
||||
if(prob(10))
|
||||
var/obj/item/clothing/head/helmet/justice/escape/helmet = new(src)
|
||||
equip_to_slot_or_del(helmet,slot_head)
|
||||
helmet.attack_self(src) // todo encapsulate toggle
|
||||
helmet.attack_self(src) // todo encapsulate toggle
|
||||
|
||||
@@ -117,26 +117,33 @@
|
||||
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has attempted to lunge at [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has attempted to lunge at [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
if (M.a_intent == INTENT_DISARM)
|
||||
var/obj/item/I = null
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
|
||||
if(prob(95))
|
||||
Weaken(10)
|
||||
visible_message("<span class='danger'>[M] has tackled down [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has tackled down [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
I = get_active_held_item()
|
||||
if(drop_item())
|
||||
visible_message("<span class='danger'>[M] has disarmed [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has disarmed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
add_logs(M, src, "disarmed")
|
||||
else
|
||||
I = null//did not manage to actually disarm the item, gross but no time to refactor
|
||||
|
||||
add_logs(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
|
||||
updatehealth()
|
||||
|
||||
|
||||
/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
var/dam_zone = dismembering_strike(M, pick("chest", "l_hand", "r_hand", "l_leg", "r_leg"))
|
||||
if(!dam_zone) //Dismemberment successful
|
||||
return 1
|
||||
return TRUE
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart("chest")
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
equip_to_slot_or_del(new relic_mask, slot_wear_mask)
|
||||
|
||||
/mob/living/carbon/monkey/punpun/Life()
|
||||
if(ticker.current_state == GAME_STATE_FINISHED && !memory_saved)
|
||||
if(SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
|
||||
Write_Memory(0)
|
||||
..()
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
//update whether our neck item appears on our hud.
|
||||
/mob/living/carbon/monkey/update_hud_neck(obj/item/I)
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
I.screen_loc = ui_monkey_mask
|
||||
I.screen_loc = ui_monkey_neck
|
||||
client.screen += I
|
||||
|
||||
//update whether our back item appears on our hud.
|
||||
|
||||
@@ -28,3 +28,15 @@
|
||||
var/obj/item/I = get_active_held_item()
|
||||
if(I)
|
||||
. |= I.get_held_item_speechspans(src)
|
||||
|
||||
/mob/living/carbon/can_speak_in_language(datum/language/dt)
|
||||
if(HAS_SECONDARY_FLAG(src, OMNITONGUE))
|
||||
. = has_language(dt)
|
||||
else if(has_language(dt))
|
||||
var/obj/item/organ/tongue/T = getorganslot("tongue")
|
||||
if(T)
|
||||
. = T.can_speak_in_language(dt)
|
||||
else
|
||||
. = initial(dt.flags) & TONGUELESS_SPEECH
|
||||
else
|
||||
. = FALSE
|
||||
|
||||
@@ -276,12 +276,6 @@
|
||||
See RemieRichards on irc.rizon.net #coderbus
|
||||
*/
|
||||
|
||||
var/global/list/limb_icon_cache = list()
|
||||
|
||||
/mob/living/carbon
|
||||
var/icon_render_key = ""
|
||||
|
||||
|
||||
//produces a key based on the mob's limbs
|
||||
|
||||
/mob/living/carbon/proc/generate_icon_render_key()
|
||||
|
||||
@@ -26,20 +26,20 @@
|
||||
/mob/living/proc/spread_bodyparts()
|
||||
return
|
||||
|
||||
/mob/living/dust()
|
||||
/mob/living/dust(just_ash = FALSE)
|
||||
death(1)
|
||||
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob(src,force=1)
|
||||
|
||||
dust_animation()
|
||||
spawn_dust()
|
||||
spawn_dust(just_ash)
|
||||
qdel(src)
|
||||
|
||||
/mob/living/proc/dust_animation()
|
||||
return
|
||||
|
||||
/mob/living/proc/spawn_dust()
|
||||
/mob/living/proc/spawn_dust(just_ash = FALSE)
|
||||
new /obj/effect/decal/cleanable/ash(loc)
|
||||
|
||||
|
||||
@@ -55,9 +55,9 @@
|
||||
deadchat_broadcast(rendered, follow_target = src, turf_target = T, message_type=DEADCHAT_DEATHRATTLE)
|
||||
if(mind)
|
||||
mind.store_memory("Time of death: [tod]", 0)
|
||||
living_mob_list -= src
|
||||
GLOB.living_mob_list -= src
|
||||
if(!gibbed)
|
||||
dead_mob_list += src
|
||||
GLOB.dead_mob_list += src
|
||||
paralysis = 0
|
||||
stunned = 0
|
||||
weakened = 0
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
param = copytext(act, custom_param + 1, length(act) + 1)
|
||||
act = copytext(act, 1, custom_param)
|
||||
|
||||
var/datum/emote/E = emote_list[act]
|
||||
var/datum/emote/E
|
||||
E = E.emote_list[act]
|
||||
if(!E)
|
||||
to_chat(src, "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>")
|
||||
return
|
||||
@@ -426,10 +427,12 @@
|
||||
var/list/keys = list()
|
||||
var/list/message = list("Available emotes, you can use them with say \"*emote\": ")
|
||||
|
||||
var/datum/emote/E
|
||||
var/list/emote_list = E.emote_list
|
||||
for(var/e in emote_list)
|
||||
if(e in keys)
|
||||
continue
|
||||
var/datum/emote/E = emote_list[e]
|
||||
E = emote_list[e]
|
||||
if(E.can_run_emote(user, TRUE))
|
||||
keys += E.key
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
return
|
||||
if(!loc)
|
||||
if(client)
|
||||
for(var/obj/effect/landmark/error/E in landmarks_list)
|
||||
for(var/obj/effect/landmark/error/E in GLOB.landmarks_list)
|
||||
loc = E.loc
|
||||
break
|
||||
message_admins("[key_name_admin(src)] was found to have no .loc with an attached client, if the cause is unknown it would be wise to ask how this was accomplished.")
|
||||
@@ -40,9 +40,6 @@
|
||||
//stuff in the stomach
|
||||
handle_stomach()
|
||||
|
||||
// Vore code for belly processes
|
||||
handle_internal_contents()
|
||||
|
||||
update_gravity(mob_has_gravity())
|
||||
|
||||
if(machine)
|
||||
@@ -70,7 +67,7 @@
|
||||
if(!digitaldisguise)
|
||||
src.digitaldisguise = image(loc = src)
|
||||
src.digitaldisguise.override = 1
|
||||
for(var/mob/living/silicon/ai/AI in player_list)
|
||||
for(var/mob/living/silicon/ai/AI in GLOB.player_list)
|
||||
AI.client.images |= src.digitaldisguise
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
. = ..()
|
||||
generateStaticOverlay()
|
||||
if(staticOverlays.len)
|
||||
for(var/mob/living/simple_animal/drone/D in player_list)
|
||||
for(var/mob/living/simple_animal/drone/D in GLOB.player_list)
|
||||
if(D && D.seeStatic)
|
||||
if(D.staticChoice in staticOverlays)
|
||||
D.staticOverlays |= staticOverlays[D.staticChoice]
|
||||
@@ -13,10 +13,12 @@
|
||||
if(unique_name)
|
||||
name = "[name] ([rand(1, 1000)])"
|
||||
real_name = name
|
||||
var/datum/atom_hud/data/human/medical/advanced/medhud = huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
var/datum/atom_hud/data/human/medical/advanced/medhud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
medhud.add_to_hud(src)
|
||||
faction += "\ref[src]"
|
||||
|
||||
language_menu = new(src)
|
||||
|
||||
|
||||
/mob/living/prepare_huds()
|
||||
..()
|
||||
@@ -33,7 +35,7 @@
|
||||
buckled.unbuckle_mob(src,force=1)
|
||||
QDEL_NULL(riding_datum)
|
||||
|
||||
for(var/mob/living/simple_animal/drone/D in player_list)
|
||||
for(var/mob/living/simple_animal/drone/D in GLOB.player_list)
|
||||
for(var/image/I in staticOverlays)
|
||||
D.staticOverlays.Remove(I)
|
||||
D.client.images.Remove(I)
|
||||
@@ -41,6 +43,8 @@
|
||||
staticOverlays.len = 0
|
||||
remove_from_all_data_huds()
|
||||
|
||||
QDEL_NULL(language_menu)
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/ghostize(can_reenter_corpse = 1)
|
||||
@@ -342,8 +346,8 @@
|
||||
if(full_heal)
|
||||
fully_heal(admin_revive)
|
||||
if(stat == DEAD && can_be_revived()) //in some cases you can't revive (e.g. no brain)
|
||||
dead_mob_list -= src
|
||||
living_mob_list += src
|
||||
GLOB.dead_mob_list -= src
|
||||
GLOB.living_mob_list += src
|
||||
suiciding = 0
|
||||
stat = UNCONSCIOUS //the mob starts unconscious,
|
||||
blind_eyes(1)
|
||||
@@ -480,7 +484,7 @@
|
||||
newdir = NORTH
|
||||
else if(newdir == 12) //E + W
|
||||
newdir = EAST
|
||||
if((newdir in cardinal) && (prob(50)))
|
||||
if((newdir in GLOB.cardinal) && (prob(50)))
|
||||
newdir = turn(get_dir(T, src.loc), 180)
|
||||
if(!blood_exists)
|
||||
new /obj/effect/decal/cleanable/trail_holder(src.loc)
|
||||
@@ -546,9 +550,6 @@
|
||||
if(buckled && last_special <= world.time)
|
||||
resist_buckle()
|
||||
|
||||
// climbing out of a gut
|
||||
if(attempt_vr(src,"vore_process_resist",args)) return TRUE
|
||||
|
||||
//Breaking out of a container (Locker, sleeper, cryo...)
|
||||
else if(isobj(loc))
|
||||
var/obj/C = loc
|
||||
@@ -598,7 +599,7 @@
|
||||
return name
|
||||
|
||||
/mob/living/update_gravity(has_gravity,override = 0)
|
||||
if(!ticker || !ticker.mode)
|
||||
if(!SSticker || !SSticker.mode)
|
||||
return
|
||||
if(has_gravity)
|
||||
clear_alert("weightless")
|
||||
@@ -668,7 +669,8 @@
|
||||
if(what && Adjacent(who) && what.mob_can_equip(who, src, final_where, TRUE))
|
||||
if(temporarilyRemoveItemFromInventory(what))
|
||||
if(where_list)
|
||||
who.put_in_hand(what, where_list[2])
|
||||
if(!who.put_in_hand(what, where_list[2]))
|
||||
what.forceMove(get_turf(who))
|
||||
else
|
||||
who.equip_to_slot(what, where, TRUE)
|
||||
|
||||
@@ -725,14 +727,14 @@
|
||||
..()
|
||||
|
||||
if(statpanel("Status"))
|
||||
if(ticker && ticker.mode)
|
||||
for(var/datum/gang/G in ticker.mode.gangs)
|
||||
if(SSticker && SSticker.mode)
|
||||
for(var/datum/gang/G in SSticker.mode.gangs)
|
||||
if(G.is_dominating)
|
||||
stat(null, "[G.name] Gang Takeover: [max(G.domination_time_remaining(), 0)]")
|
||||
if(istype(ticker.mode, /datum/game_mode/blob))
|
||||
var/datum/game_mode/blob/B = ticker.mode
|
||||
if(istype(SSticker.mode, /datum/game_mode/blob))
|
||||
var/datum/game_mode/blob/B = SSticker.mode
|
||||
if(B.message_sent)
|
||||
stat(null, "Blobs to Blob Win: [blobs_legit.len]/[B.blobwincount]")
|
||||
stat(null, "Blobs to Blob Win: [GLOB.blobs_legit.len]/[B.blobwincount]")
|
||||
|
||||
/mob/living/cancel_camera()
|
||||
..()
|
||||
@@ -802,9 +804,6 @@
|
||||
setStaminaLoss(health - 2)
|
||||
update_health_hud()
|
||||
|
||||
/mob/proc/update_sight()
|
||||
return
|
||||
|
||||
/mob/living/proc/owns_soul()
|
||||
if(mind)
|
||||
return mind.soulOwner == mind
|
||||
@@ -910,13 +909,14 @@
|
||||
|
||||
// used by secbot and monkeys Crossed
|
||||
/mob/living/proc/knockOver(var/mob/living/carbon/C)
|
||||
C.visible_message("<span class='warning'>[pick( \
|
||||
"[C] dives out of [src]'s way!", \
|
||||
"[C] stumbles over [src]!", \
|
||||
"[C] jumps out of [src]'s path!", \
|
||||
"[C] trips over [src] and falls!", \
|
||||
"[C] topples over [src]!", \
|
||||
"[C] leaps out of [src]'s way!")]</span>")
|
||||
if(C.key) //save us from monkey hordes
|
||||
C.visible_message("<span class='warning'>[pick( \
|
||||
"[C] dives out of [src]'s way!", \
|
||||
"[C] stumbles over [src]!", \
|
||||
"[C] jumps out of [src]'s path!", \
|
||||
"[C] trips over [src] and falls!", \
|
||||
"[C] topples over [src]!", \
|
||||
"[C] leaps out of [src]'s way!")]</span>")
|
||||
C.Weaken(2)
|
||||
|
||||
/mob/living/post_buckle_mob(mob/living/M)
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
IgniteMob()
|
||||
|
||||
/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = 0)
|
||||
if(user == src || anchored)
|
||||
if(user == src || anchored || !isturf(user.loc))
|
||||
return 0
|
||||
if(!user.pulling || user.pulling != src)
|
||||
user.start_pulling(src, supress_message)
|
||||
@@ -172,7 +172,7 @@
|
||||
|
||||
|
||||
/mob/living/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(!ticker || !ticker.mode)
|
||||
if(!SSticker || !SSticker.mode)
|
||||
to_chat(M, "You cannot attack people before the game has started.")
|
||||
return
|
||||
|
||||
@@ -244,10 +244,6 @@
|
||||
return 0
|
||||
|
||||
/mob/living/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(isturf(loc) && istype(loc.loc, /area/start))
|
||||
to_chat(M, "No attacking people at spawn, you jackass.")
|
||||
return 0
|
||||
|
||||
switch(M.a_intent)
|
||||
if ("help")
|
||||
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/mob/living
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
languages_spoken = HUMAN
|
||||
languages_understood = HUMAN
|
||||
sight = 0
|
||||
see_in_dark = 2
|
||||
hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD)
|
||||
@@ -74,4 +72,7 @@
|
||||
var/list/implants = null
|
||||
var/tesla_ignore = FALSE
|
||||
|
||||
var/datum/riding/riding_datum
|
||||
var/datum/riding/riding_datum
|
||||
|
||||
var/datum/language/selected_default_language
|
||||
var/datum/language_menu/language_menu
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
mind.show_memory(src, 0)
|
||||
|
||||
//Round specific stuff
|
||||
if(ticker && ticker.mode)
|
||||
switch(ticker.mode.name)
|
||||
if(SSticker && SSticker.mode)
|
||||
switch(SSticker.mode.name)
|
||||
if("sandbox")
|
||||
CanBuild()
|
||||
|
||||
|
||||
+198
-100
@@ -1,70 +1,69 @@
|
||||
var/list/department_radio_keys = list(
|
||||
":r" = "right hand", "#r" = "right hand", ".r" = "right hand",
|
||||
":l" = "left hand", "#l" = "left hand", ".l" = "left hand",
|
||||
":i" = "intercom", "#i" = "intercom", ".i" = "intercom",
|
||||
":h" = "department", "#h" = "department", ".h" = "department",
|
||||
":c" = "Command", "#c" = "Command", ".c" = "Command",
|
||||
":n" = "Science", "#n" = "Science", ".n" = "Science",
|
||||
":m" = "Medical", "#m" = "Medical", ".m" = "Medical",
|
||||
":e" = "Engineering", "#e" = "Engineering", ".e" = "Engineering",
|
||||
":s" = "Security", "#s" = "Security", ".s" = "Security",
|
||||
":w" = "whisper", "#w" = "whisper", ".w" = "whisper",
|
||||
":b" = "binary", "#b" = "binary", ".b" = "binary",
|
||||
":a" = "alientalk", "#a" = "alientalk", ".a" = "alientalk",
|
||||
":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate",
|
||||
":u" = "Supply", "#u" = "Supply", ".u" = "Supply",
|
||||
":v" = "Service", "#v" = "Service", ".v" = "Service",
|
||||
":o" = "AI Private", "#o" = "AI Private", ".o" = "AI Private",
|
||||
":g" = "changeling", "#g" = "changeling", ".g" = "changeling",
|
||||
":y" = "Centcom", "#y" = "Centcom", ".y" = "Centcom",
|
||||
":x" = "cords", "#x" = "cords", ".x" = "cords",
|
||||
":p" = "admin", "#p" = "admin", ".p" = "admin",
|
||||
":d" = "deadmin", "#d" = "deadmin", ".d" = "deadmin",
|
||||
GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
":r" = "right hand", ".r" = "right hand",
|
||||
":l" = "left hand", ".l" = "left hand",
|
||||
":i" = "intercom", ".i" = "intercom",
|
||||
":h" = "department", ".h" = "department",
|
||||
":c" = "Command", ".c" = "Command",
|
||||
":n" = "Science", ".n" = "Science",
|
||||
":m" = "Medical", ".m" = "Medical",
|
||||
":e" = "Engineering", ".e" = "Engineering",
|
||||
":s" = "Security", ".s" = "Security",
|
||||
":b" = "binary", ".b" = "binary",
|
||||
":a" = "alientalk", ".a" = "alientalk",
|
||||
":t" = "Syndicate", ".t" = "Syndicate",
|
||||
":u" = "Supply", ".u" = "Supply",
|
||||
":v" = "Service", ".v" = "Service",
|
||||
":o" = "AI Private", ".o" = "AI Private",
|
||||
":g" = "changeling", ".g" = "changeling",
|
||||
":y" = "Centcom", ".y" = "Centcom",
|
||||
":x" = "cords", ".x" = "cords",
|
||||
":p" = "admin", ".p" = "admin",
|
||||
":d" = "deadmin", ".d" = "deadmin",
|
||||
|
||||
":R" = "right hand", "#R" = "right hand", ".R" = "right hand",
|
||||
":L" = "left hand", "#L" = "left hand", ".L" = "left hand",
|
||||
":I" = "intercom", "#I" = "intercom", ".I" = "intercom",
|
||||
":H" = "department", "#H" = "department", ".H" = "department",
|
||||
":C" = "Command", "#C" = "Command", ".C" = "Command",
|
||||
":N" = "Science", "#N" = "Science", ".N" = "Science",
|
||||
":M" = "Medical", "#M" = "Medical", ".M" = "Medical",
|
||||
":E" = "Engineering", "#E" = "Engineering", ".E" = "Engineering",
|
||||
":S" = "Security", "#S" = "Security", ".S" = "Security",
|
||||
":W" = "whisper", "#W" = "whisper", ".W" = "whisper",
|
||||
":B" = "binary", "#B" = "binary", ".B" = "binary",
|
||||
":A" = "alientalk", "#A" = "alientalk", ".A" = "alientalk",
|
||||
":T" = "Syndicate", "#T" = "Syndicate", ".T" = "Syndicate",
|
||||
":U" = "Supply", "#U" = "Supply", ".U" = "Supply",
|
||||
":V" = "Service", "#V" = "Service", ".V" = "Service",
|
||||
":O" = "AI Private", "#O" = "AI Private", ".O" = "AI Private",
|
||||
":G" = "changeling", "#G" = "changeling", ".G" = "changeling",
|
||||
":Y" = "Centcom", "#Y" = "Centcom", ".Y" = "Centcom",
|
||||
":X" = "cords", "#X" = "cords", ".X" = "cords",
|
||||
":P" = "admin", "#P" = "admin", ".P" = "admin",
|
||||
":D" = "deadmin", "#D" = "deadmin", ".D" = "deadmin",
|
||||
":R" = "right hand", ".R" = "right hand",
|
||||
":L" = "left hand", ".L" = "left hand",
|
||||
":I" = "intercom", ".I" = "intercom",
|
||||
":H" = "department", ".H" = "department",
|
||||
":C" = "Command", ".C" = "Command",
|
||||
":N" = "Science", ".N" = "Science",
|
||||
":M" = "Medical", ".M" = "Medical",
|
||||
":E" = "Engineering", ".E" = "Engineering",
|
||||
":S" = "Security", ".S" = "Security",
|
||||
":B" = "binary", ".B" = "binary",
|
||||
":A" = "alientalk", ".A" = "alientalk",
|
||||
":T" = "Syndicate", ".T" = "Syndicate",
|
||||
":U" = "Supply", ".U" = "Supply",
|
||||
":V" = "Service", ".V" = "Service",
|
||||
":O" = "AI Private", ".O" = "AI Private",
|
||||
":G" = "changeling", ".G" = "changeling",
|
||||
":Y" = "Centcom", ".Y" = "Centcom",
|
||||
":X" = "cords", ".X" = "cords",
|
||||
":P" = "admin", ".P" = "admin",
|
||||
":D" = "deadmin", ".D" = "deadmin",
|
||||
|
||||
//kinda localization -- rastaf0
|
||||
//same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding.
|
||||
":ê" = "right hand", "#ê" = "right hand", ".ê" = "right hand",
|
||||
":ä" = "left hand", "#ä" = "left hand", ".ä" = "left hand",
|
||||
":ø" = "intercom", "#ø" = "intercom", ".ø" = "intercom",
|
||||
":ð" = "department", "#ð" = "department", ".ð" = "department",
|
||||
":ñ" = "Command", "#ñ" = "Command", ".ñ" = "Command",
|
||||
":ò" = "Science", "#ò" = "Science", ".ò" = "Science",
|
||||
":ü" = "Medical", "#ü" = "Medical", ".ü" = "Medical",
|
||||
":ó" = "Engineering", "#ó" = "Engineering", ".ó" = "Engineering",
|
||||
":û" = "Security", "#û" = "Security", ".û" = "Security",
|
||||
":ö" = "whisper", "#ö" = "whisper", ".ö" = "whisper",
|
||||
":è" = "binary", "#è" = "binary", ".è" = "binary",
|
||||
":ô" = "alientalk", "#ô" = "alientalk", ".ô" = "alientalk",
|
||||
":å" = "Syndicate", "#å" = "Syndicate", ".å" = "Syndicate",
|
||||
":é" = "Supply", "#é" = "Supply", ".é" = "Supply",
|
||||
":ï" = "changeling", "#ï" = "changeling", ".ï" = "changeling"
|
||||
)
|
||||
":ê" = "right hand", ".ê" = "right hand",
|
||||
":ä" = "left hand", ".ä" = "left hand",
|
||||
":ø" = "intercom", ".ø" = "intercom",
|
||||
":ð" = "department", ".ð" = "department",
|
||||
":ñ" = "Command", ".ñ" = "Command",
|
||||
":ò" = "Science", ".ò" = "Science",
|
||||
":ü" = "Medical", ".ü" = "Medical",
|
||||
":ó" = "Engineering", ".ó" = "Engineering",
|
||||
":û" = "Security", ".û" = "Security",
|
||||
":è" = "binary", ".è" = "binary",
|
||||
":ô" = "alientalk", ".ô" = "alientalk",
|
||||
":å" = "Syndicate", ".å" = "Syndicate",
|
||||
":é" = "Supply", ".é" = "Supply",
|
||||
":ï" = "changeling", ".ï" = "changeling"))
|
||||
|
||||
var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
|
||||
/mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null)
|
||||
var/static/list/crit_allowed_modes = list(MODE_WHISPER = TRUE, MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
|
||||
var/static/list/unconscious_allowed_modes = list(MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
|
||||
|
||||
var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE)
|
||||
|
||||
/mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE)
|
||||
if(sanitize)
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
if(!message || message == "")
|
||||
@@ -72,8 +71,9 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
|
||||
|
||||
var/message_mode = get_message_mode(message)
|
||||
var/original_message = message
|
||||
var/in_critical = InCritical()
|
||||
|
||||
if(message_mode == MODE_HEADSET || message_mode == MODE_ROBOT)
|
||||
if(one_character_prefix[message_mode])
|
||||
message = copytext(message, 2)
|
||||
else if(message_mode)
|
||||
message = copytext(message, 3)
|
||||
@@ -94,34 +94,79 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
|
||||
say_dead(original_message)
|
||||
return
|
||||
|
||||
if(check_emote(original_message))
|
||||
if(check_emote(original_message) || !can_speak_basic(original_message))
|
||||
return
|
||||
|
||||
if(!can_speak_basic(original_message)) //Stat is seperate so I can handle whispers properly.
|
||||
return
|
||||
if(in_critical)
|
||||
if(!(crit_allowed_modes[message_mode]))
|
||||
return
|
||||
else if(stat == UNCONSCIOUS)
|
||||
if(!(unconscious_allowed_modes[message_mode]))
|
||||
return
|
||||
|
||||
if(stat && !(message_mode in crit_allowed_modes))
|
||||
return
|
||||
// language comma detection.
|
||||
var/datum/language/message_language = get_message_language(message)
|
||||
if(message_language)
|
||||
// No, you cannot speak in xenocommon just because you know the key
|
||||
if(can_speak_in_language(message_language))
|
||||
language = message_language
|
||||
message = copytext(message, 3)
|
||||
|
||||
if(handle_inherent_channels(message, message_mode)) //Hiveminds, binary chat & holopad.
|
||||
// Trim the space if they said ",0 I LOVE LANGUAGES"
|
||||
if(findtext(message, " ", 1, 2))
|
||||
message = copytext(message, 2)
|
||||
|
||||
if(!language)
|
||||
language = get_default_language()
|
||||
|
||||
// Detection of language needs to be before inherent channels, because
|
||||
// AIs use inherent channels for the holopad. Most inherent channels
|
||||
// ignore the language argument however.
|
||||
|
||||
if(handle_inherent_channels(message, message_mode, language)) //Hiveminds, binary chat & holopad.
|
||||
return
|
||||
|
||||
if(!can_speak_vocal(message))
|
||||
to_chat(src, "<span class='warning'>You find yourself unable to speak!</span>")
|
||||
return
|
||||
|
||||
if(message_mode != MODE_WHISPER) //whisper() calls treat_message(); double process results in "hisspering"
|
||||
message = treat_message(message)
|
||||
var/message_range = 7
|
||||
|
||||
var/succumbed = FALSE
|
||||
|
||||
if(message_mode == MODE_WHISPER)
|
||||
message_range = 1
|
||||
spans |= SPAN_ITALICS
|
||||
log_whisper("[src.name]/[src.key] : [message]")
|
||||
if(in_critical)
|
||||
var/health_diff = round(-HEALTH_THRESHOLD_DEAD + health)
|
||||
// If we cut our message short, abruptly end it with a-..
|
||||
var/message_len = length(message)
|
||||
message = copytext(message, 1, health_diff) + "[message_len > health_diff ? "-.." : "..."]"
|
||||
message = Ellipsis(message, 10, 1)
|
||||
message_mode = MODE_WHISPER_CRIT
|
||||
succumbed = TRUE
|
||||
else
|
||||
log_say("[name]/[key] : [message]")
|
||||
|
||||
message = treat_message(message)
|
||||
if(!message)
|
||||
return
|
||||
|
||||
spans += get_spans()
|
||||
|
||||
if(language)
|
||||
var/datum/language/L = GLOB.language_datums[language]
|
||||
if(!istype(L))
|
||||
L = new language
|
||||
GLOB.language_datums[language] = L
|
||||
|
||||
spans |= L.spans
|
||||
|
||||
//Log what we've said with an associated timestamp, using the list's len for safety/to prevent overwriting messages
|
||||
log_message(message, INDIVIDUAL_SAY_LOG)
|
||||
|
||||
var/message_range = 7
|
||||
var/radio_return = radio(message, message_mode, spans)
|
||||
if(radio_return & NOPASS) //There's a whisper() message_mode, no need to continue the proc if that is called
|
||||
return
|
||||
if(radio_return & ITALICS)
|
||||
spans |= SPAN_ITALICS
|
||||
if(radio_return & REDUCE_RANGE)
|
||||
@@ -137,12 +182,15 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
|
||||
if(pressure < ONE_ATMOSPHERE*0.4) //Thin air, let's italicise the message
|
||||
spans |= SPAN_ITALICS
|
||||
|
||||
send_speech(message, message_range, src, bubble_type, spans)
|
||||
send_speech(message, message_range, src, bubble_type, spans, language, message_mode)
|
||||
|
||||
if(succumbed)
|
||||
succumb(1)
|
||||
to_chat(src, compose_message(src, language, message, , spans, message_mode))
|
||||
|
||||
log_say("[name]/[key] : [message]")
|
||||
return 1
|
||||
|
||||
/mob/living/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
|
||||
/mob/living/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
if(!client)
|
||||
return
|
||||
var/deaf_message
|
||||
@@ -154,20 +202,38 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
|
||||
else
|
||||
deaf_message = "<span class='notice'>You can't hear yourself!</span>"
|
||||
deaf_type = 2 // Since you should be able to hear yourself without looking
|
||||
if(!(message_langs & languages_understood) || force_compose) //force_compose is so AIs don't end up without their hrefs.
|
||||
message = compose_message(speaker, message_langs, raw_message, radio_freq, spans)
|
||||
|
||||
// Recompose message for AI hrefs, language incomprehension.
|
||||
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
show_message(message, 2, deaf_message, deaf_type)
|
||||
return message
|
||||
|
||||
/mob/living/send_speech(message, message_range = 7, obj/source = src, bubble_type = bubble_icon, list/spans)
|
||||
var/list/listening = get_hearers_in_view(message_range, source)
|
||||
for(var/mob/M in player_list)
|
||||
/mob/living/send_speech(message, message_range = 6, obj/source = src, bubble_type = bubble_icon, list/spans, datum/language/message_language=null, message_mode)
|
||||
var/static/list/eavesdropping_modes = list(MODE_WHISPER = TRUE, MODE_WHISPER_CRIT = TRUE)
|
||||
var/eavesdrop_range = 0
|
||||
if(eavesdropping_modes[message_mode])
|
||||
eavesdrop_range = EAVESDROP_EXTRA_RANGE
|
||||
var/list/listening = get_hearers_in_view(message_range+eavesdrop_range, source)
|
||||
var/list/the_dead = list()
|
||||
for(var/_M in GLOB.player_list)
|
||||
var/mob/M = _M
|
||||
if(M.stat == DEAD && M.client && ((M.client.prefs.chat_toggles & CHAT_GHOSTEARS) || (get_dist(M, src) <= 7 && M.z == z)) && client) // client is so that ghosts don't have to listen to mice
|
||||
listening |= M
|
||||
the_dead[M] = TRUE
|
||||
|
||||
var/rendered = compose_message(src, languages_spoken, message, , spans)
|
||||
for(var/atom/movable/AM in listening)
|
||||
AM.Hear(rendered, src, languages_spoken, message, , spans)
|
||||
var/eavesdropping
|
||||
var/eavesrendered
|
||||
if(eavesdrop_range)
|
||||
eavesdropping = stars(message)
|
||||
eavesrendered = compose_message(src, message_language, eavesdropping, , spans, message_mode)
|
||||
|
||||
var/rendered = compose_message(src, message_language, message, , spans, message_mode)
|
||||
for(var/_AM in listening)
|
||||
var/atom/movable/AM = _AM
|
||||
if(eavesdrop_range && get_dist(source, AM) > message_range && !(the_dead[AM]))
|
||||
AM.Hear(eavesrendered, src, message_language, eavesdropping, , spans, message_mode)
|
||||
else
|
||||
AM.Hear(rendered, src, message_language, message, , spans, message_mode)
|
||||
|
||||
//speech bubble
|
||||
var/list/speech_bubble_recipients = list()
|
||||
@@ -176,8 +242,7 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
|
||||
speech_bubble_recipients.Add(M.client)
|
||||
var/image/I = image('icons/mob/talk.dmi', src, "[bubble_type][say_test(message)]", FLY_LAYER)
|
||||
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
|
||||
spawn(0)
|
||||
flick_overlay(I, speech_bubble_recipients, 30)
|
||||
INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_recipients, 30)
|
||||
|
||||
/mob/proc/binarycheck()
|
||||
return 0
|
||||
@@ -216,16 +281,32 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
|
||||
/mob/living/proc/get_message_mode(message)
|
||||
if(copytext(message, 1, 2) == ";")
|
||||
return MODE_HEADSET
|
||||
else if(copytext(message, 1, 2) == "#")
|
||||
return MODE_WHISPER
|
||||
else if(length(message) > 2)
|
||||
return department_radio_keys[copytext(message, 1, 3)]
|
||||
return GLOB.department_radio_keys[copytext(message, 1, 3)]
|
||||
|
||||
/mob/living/proc/get_message_language(message)
|
||||
var/static/list/langlist
|
||||
if(!langlist)
|
||||
langlist = subtypesof(/datum/language)
|
||||
|
||||
if(copytext(message, 1, 2) == ",")
|
||||
var/key = copytext(message, 2, 3)
|
||||
for(var/ld in langlist)
|
||||
var/datum/language/LD = ld
|
||||
if(initial(LD.key) == key)
|
||||
return LD
|
||||
return null
|
||||
|
||||
/mob/living/proc/handle_inherent_channels(message, message_mode)
|
||||
if(message_mode == MODE_CHANGELING)
|
||||
switch(lingcheck())
|
||||
if(3)
|
||||
var/msg = "<i><font color=#800040><b>[src.mind]:</b> [message]</font></i>"
|
||||
for(var/mob/M in mob_list)
|
||||
if(M in dead_mob_list)
|
||||
for(var/_M in GLOB.mob_list)
|
||||
var/mob/M = _M
|
||||
if(M in GLOB.dead_mob_list)
|
||||
var/link = FOLLOW_LINK(M, src)
|
||||
to_chat(M, "[link] [msg]")
|
||||
else
|
||||
@@ -240,8 +321,9 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
|
||||
if(2)
|
||||
var/msg = "<i><font color=#800080><b>[mind.changeling.changelingID]:</b> [message]</font></i>"
|
||||
log_say("[mind.changeling.changelingID]/[src.key] : [message]")
|
||||
for(var/mob/M in mob_list)
|
||||
if(M in dead_mob_list)
|
||||
for(var/_M in GLOB.mob_list)
|
||||
var/mob/M = _M
|
||||
if(M in GLOB.dead_mob_list)
|
||||
var/link = FOLLOW_LINK(M, src)
|
||||
to_chat(M, "[link] [msg]")
|
||||
else
|
||||
@@ -287,32 +369,28 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
|
||||
|
||||
return message
|
||||
|
||||
/mob/living/proc/radio(message, message_mode, list/spans)
|
||||
/mob/living/proc/radio(message, message_mode, list/spans, language)
|
||||
switch(message_mode)
|
||||
if(MODE_R_HAND)
|
||||
for(var/obj/item/r_hand in get_held_items_for_side("r", all = TRUE))
|
||||
if (r_hand)
|
||||
return r_hand.talk_into(src, message, , spans)
|
||||
return r_hand.talk_into(src, message, , spans, language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
if(MODE_L_HAND)
|
||||
for(var/obj/item/l_hand in get_held_items_for_side("l", all = TRUE))
|
||||
if (l_hand)
|
||||
return l_hand.talk_into(src, message, , spans)
|
||||
return l_hand.talk_into(src, message, , spans, language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
if(MODE_INTERCOM)
|
||||
for (var/obj/item/device/radio/intercom/I in view(1, null))
|
||||
I.talk_into(src, message, , spans)
|
||||
I.talk_into(src, message, , spans, language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
if(MODE_BINARY)
|
||||
if(binarycheck())
|
||||
robot_talk(message)
|
||||
return ITALICS | REDUCE_RANGE //Does not return 0 since this is only reached by humans, not borgs or AIs.
|
||||
|
||||
if(MODE_WHISPER)
|
||||
whisper(message)
|
||||
return NOPASS
|
||||
return 0
|
||||
|
||||
/mob/living/lingcheck() //1 is ling w/ no hivemind. 2 is ling w/hivemind. 3 is ling victim being linked into hivemind.
|
||||
@@ -324,10 +402,30 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
|
||||
return 3
|
||||
return 0
|
||||
|
||||
/mob/living/say_quote(input, list/spans)
|
||||
/mob/living/say_quote(input, list/spans, message_mode)
|
||||
var/tempinput = attach_spans(input, spans)
|
||||
if(message_mode == MODE_WHISPER)
|
||||
return "[verb_whisper], \"[tempinput]\""
|
||||
if(message_mode == MODE_WHISPER_CRIT)
|
||||
return "[verb_whisper] in [p_their()] last breath, \"[tempinput]\""
|
||||
if (stuttering)
|
||||
return "stammers, \"[tempinput]\""
|
||||
if (getBrainLoss() >= 60)
|
||||
return "gibbers, \"[tempinput]\""
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/get_default_language()
|
||||
if(selected_default_language)
|
||||
if(has_language(selected_default_language))
|
||||
return selected_default_language
|
||||
else
|
||||
selected_default_language = null
|
||||
|
||||
. = ..()
|
||||
|
||||
/mob/living/proc/open_language_menu(mob/user)
|
||||
language_menu.ui_interact(user)
|
||||
|
||||
/mob/living/whisper(message as text)
|
||||
say("#[message]")
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#define CALL_BOT_COOLDOWN 900
|
||||
var/list/ai_list = list()
|
||||
|
||||
//Not sure why this is necessary...
|
||||
/proc/AutoUpdateAI(obj/subject)
|
||||
var/is_in_use = 0
|
||||
if (subject!=null)
|
||||
for(var/A in ai_list)
|
||||
for(var/A in GLOB.ai_list)
|
||||
var/mob/living/silicon/ai/M = A
|
||||
if ((M.client && M.machine == subject))
|
||||
is_in_use = 1
|
||||
@@ -22,7 +21,6 @@ var/list/ai_list = list()
|
||||
canmove = 0
|
||||
status_flags = CANSTUN|CANPUSH
|
||||
a_intent = INTENT_HARM //so we always get pushed instead of trying to swap
|
||||
force_compose = 1 //This ensures that the AI always composes it's own hear message. Needed for hrefs and job display.
|
||||
sight = SEE_TURFS | SEE_MOBS | SEE_OBJS
|
||||
see_in_dark = 8
|
||||
med_hud = DATA_HUD_MEDICAL_BASIC
|
||||
@@ -84,6 +82,10 @@ var/list/ai_list = list()
|
||||
var/obj/machinery/camera/portable/builtInCamera
|
||||
|
||||
var/obj/structure/AIcore/deactivated/linked_core //For exosuit control
|
||||
var/mob/living/silicon/robot/deployed_shell = null //For shell control
|
||||
var/datum/action/innate/deploy_shell/deploy_action = new
|
||||
var/datum/action/innate/deploy_last_shell/redeploy_action = new
|
||||
var/chnotify = 0
|
||||
|
||||
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
|
||||
..()
|
||||
@@ -138,22 +140,24 @@ var/list/ai_list = list()
|
||||
radio = new /obj/item/device/radio/headset/ai(src)
|
||||
aicamera = new/obj/item/device/camera/siliconcam/ai_camera(src)
|
||||
|
||||
deploy_action.Grant(src)
|
||||
|
||||
if(isturf(loc))
|
||||
verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \
|
||||
/mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \
|
||||
/mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall,\
|
||||
/mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/set_automatic_say_channel)
|
||||
|
||||
ai_list += src
|
||||
shuttle_caller_list += src
|
||||
GLOB.ai_list += src
|
||||
GLOB.shuttle_caller_list += src
|
||||
|
||||
builtInCamera = new /obj/machinery/camera/portable(src)
|
||||
builtInCamera.network = list("SS13")
|
||||
|
||||
|
||||
/mob/living/silicon/ai/Destroy()
|
||||
ai_list -= src
|
||||
shuttle_caller_list -= src
|
||||
GLOB.ai_list -= src
|
||||
GLOB.shuttle_caller_list -= src
|
||||
SSshuttle.autoEvac()
|
||||
qdel(eyeobj) // No AI, no Eye
|
||||
malfhack = null
|
||||
@@ -247,13 +251,16 @@ var/list/ai_list = list()
|
||||
for(var/mob/living/silicon/robot/R in connected_robots)
|
||||
borg_area = get_area(R)
|
||||
var/robot_status = "Nominal"
|
||||
if(R.stat || !R.client)
|
||||
if(R.shell)
|
||||
robot_status = "AI SHELL"
|
||||
else if(R.stat || !R.client)
|
||||
robot_status = "OFFLINE"
|
||||
else if(!R.cell || R.cell.charge <= 0)
|
||||
robot_status = "DEPOWERED"
|
||||
//Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies!
|
||||
stat(null, text("[R.name] | S.Integrity: [R.health]% | Cell: [R.cell ? "[R.cell.charge]/[R.cell.maxcharge]" : "Empty"] | \
|
||||
Module: [R.designation] | Loc: [borg_area.name] | Status: [robot_status]"))
|
||||
Module: [R.designation] | Loc: [borg_area.name] | Status: [robot_status]"))
|
||||
stat(null, text("AI shell beacons detected: [LAZYLEN(GLOB.available_ai_shells)]")) //Count of total AI shells
|
||||
else
|
||||
stat(null, text("Systems nonfunctional"))
|
||||
|
||||
@@ -293,7 +300,7 @@ var/list/ai_list = list()
|
||||
/mob/living/silicon/ai/proc/ai_roster()
|
||||
var/dat = "<html><head><title>Crew Roster</title></head><body><b>Crew Roster:</b><br><br>"
|
||||
|
||||
dat += data_core.get_manifest()
|
||||
dat += GLOB.data_core.get_manifest()
|
||||
dat += "</body></html>"
|
||||
|
||||
src << browse(dat, "window=airoster")
|
||||
@@ -315,7 +322,7 @@ var/list/ai_list = list()
|
||||
|
||||
// hack to display shuttle timer
|
||||
if(!EMERGENCY_IDLE_OR_RECALLED)
|
||||
var/obj/machinery/computer/communications/C = locate() in machines
|
||||
var/obj/machinery/computer/communications/C = locate() in GLOB.machines
|
||||
if(C)
|
||||
C.post_status("shuttle")
|
||||
|
||||
@@ -363,7 +370,7 @@ var/list/ai_list = list()
|
||||
unset_machine()
|
||||
src << browse(null, t1)
|
||||
if (href_list["switchcamera"])
|
||||
switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras
|
||||
switchCamera(locate(href_list["switchcamera"])) in GLOB.cameranet.cameras
|
||||
if (href_list["showalerts"])
|
||||
ai_alerts()
|
||||
#ifdef AI_VOX
|
||||
@@ -403,14 +410,14 @@ var/list/ai_list = list()
|
||||
if(call_bot_cooldown > world.time)
|
||||
to_chat(src, "<span class='danger'>Error: Your last call bot command is still processing, please wait for the bot to finish calculating a route.</span>")
|
||||
return
|
||||
Bot = locate(href_list["callbot"]) in living_mob_list
|
||||
Bot = locate(href_list["callbot"]) in GLOB.living_mob_list
|
||||
if(!Bot || Bot.remote_disabled || src.control_disabled)
|
||||
return //True if there is no bot found, the bot is manually emagged, or the AI is carded with wireless off.
|
||||
waypoint_mode = 1
|
||||
to_chat(src, "<span class='notice'>Set your waypoint by clicking on a valid location free of obstructions.</span>")
|
||||
return
|
||||
if(href_list["interface"]) //Remotely connect to a bot!
|
||||
Bot = locate(href_list["interface"]) in living_mob_list
|
||||
Bot = locate(href_list["interface"]) in GLOB.living_mob_list
|
||||
if(!Bot || Bot.remote_disabled || src.control_disabled)
|
||||
return
|
||||
Bot.attack_ai(src)
|
||||
@@ -423,7 +430,7 @@ var/list/ai_list = list()
|
||||
if(controlled_mech)
|
||||
to_chat(src, "<span class='warning'>You are already loaded into an onboard computer!</span>")
|
||||
return
|
||||
if(!cameranet.checkCameraVis(M))
|
||||
if(!GLOB.cameranet.checkCameraVis(M))
|
||||
to_chat(src, "<span class='warning'>Exosuit is no longer near active cameras.</span>")
|
||||
return
|
||||
if(lacks_power())
|
||||
@@ -470,7 +477,7 @@ var/list/ai_list = list()
|
||||
d += "<A HREF=?src=\ref[src];botrefresh=1>Query network status</A><br>"
|
||||
d += "<table width='100%'><tr><td width='40%'><h3>Name</h3></td><td width='30%'><h3>Status</h3></td><td width='30%'><h3>Location</h3></td><td width='10%'><h3>Control</h3></td></tr>"
|
||||
|
||||
for (Bot in living_mob_list)
|
||||
for (Bot in GLOB.living_mob_list)
|
||||
if(Bot.z == ai_Zlevel && !Bot.remote_disabled) //Only non-emagged bots on the same Z-level are detected!
|
||||
bot_area = get_area(Bot)
|
||||
var/bot_mode = Bot.get_mode()
|
||||
@@ -492,7 +499,7 @@ var/list/ai_list = list()
|
||||
//The target must be in view of a camera or near the core.
|
||||
if(turf_check in range(get_turf(src)))
|
||||
call_bot(turf_check)
|
||||
else if(cameranet && cameranet.checkTurfVis(turf_check))
|
||||
else if(GLOB.cameranet && GLOB.cameranet.checkTurfVis(turf_check))
|
||||
call_bot(turf_check)
|
||||
else
|
||||
to_chat(src, "<span class='danger'>Selected location is not visible.</span>")
|
||||
@@ -582,7 +589,7 @@ var/list/ai_list = list()
|
||||
|
||||
var/mob/living/silicon/ai/U = usr
|
||||
|
||||
for (var/obj/machinery/camera/C in cameranet.cameras)
|
||||
for (var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
if(!C.can_use())
|
||||
continue
|
||||
|
||||
@@ -601,7 +608,7 @@ var/list/ai_list = list()
|
||||
if(isnull(network))
|
||||
network = old_network // If nothing is selected
|
||||
else
|
||||
for(var/obj/machinery/camera/C in cameranet.cameras)
|
||||
for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
if(!C.can_use())
|
||||
continue
|
||||
if(network in C.network)
|
||||
@@ -625,7 +632,7 @@ var/list/ai_list = list()
|
||||
return //won't work if dead
|
||||
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer", "Dorfy", "Blue Glow", "Red Glow")
|
||||
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
|
||||
for (var/obj/machinery/M in machines) //change status
|
||||
for (var/obj/machinery/M in GLOB.machines) //change status
|
||||
if(istype(M, /obj/machinery/ai_status_display))
|
||||
var/obj/machinery/ai_status_display/AISD = M
|
||||
AISD.emotion = emote
|
||||
@@ -652,7 +659,7 @@ var/list/ai_list = list()
|
||||
if("Crew Member")
|
||||
var/list/personnel_list = list()
|
||||
|
||||
for(var/datum/data/record/t in data_core.locked)//Look in data core locked.
|
||||
for(var/datum/data/record/t in GLOB.data_core.locked)//Look in data core locked.
|
||||
personnel_list["[t.fields["name"]]: [t.fields["rank"]]"] = t.fields["image"]//Pull names, rank, and image.
|
||||
|
||||
if(personnel_list.len)
|
||||
@@ -791,12 +798,13 @@ var/list/ai_list = list()
|
||||
if(!..())
|
||||
return
|
||||
if(interaction == AI_TRANS_TO_CARD)//The only possible interaction. Upload AI mob to a card.
|
||||
if(!mind)
|
||||
to_chat(user, "<span class='warning'>No intelligence patterns detected.</span>" )
|
||||
return
|
||||
if(!can_be_carded)
|
||||
to_chat(user, "<span class='boldwarning'>Transfer failed.</span>")
|
||||
return
|
||||
disconnect_shell() //If the AI is controlling a borg, force the player back to core!
|
||||
if(!mind)
|
||||
to_chat(user, "<span class='warning'>No intelligence patterns detected.</span>" )
|
||||
return
|
||||
ShutOffDoomsdayDevice()
|
||||
new /obj/structure/AIcore/deactivated(loc)//Spawns a deactivated terminal at AI location.
|
||||
ai_restore_power()//So the AI initially has power.
|
||||
@@ -818,12 +826,12 @@ var/list/ai_list = list()
|
||||
//stop AIs from leaving windows open and using then after they lose vision
|
||||
//apc_override is needed here because AIs use their own APC when powerless
|
||||
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
|
||||
if(M && cameranet && !cameranet.checkTurfVis(get_turf_pixel(M)) && !apc_override)
|
||||
if(M && GLOB.cameranet && !GLOB.cameranet.checkTurfVis(get_turf_pixel(M)) && !apc_override)
|
||||
return
|
||||
return 1
|
||||
|
||||
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
|
||||
raw_message = lang_treat(speaker, message_langs, raw_message, spans)
|
||||
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
raw_message = lang_treat(speaker, message_language, raw_message, spans, message_mode)
|
||||
var/name_used = speaker.GetVoice()
|
||||
var/rendered = "<i><span class='game say'>Relayed Speech: <span class='name'>[name_used]</span> <span class='message'>[raw_message]</span></span></i>"
|
||||
show_message(rendered, 2)
|
||||
@@ -907,6 +915,69 @@ var/list/ai_list = list()
|
||||
to_chat(src, "Hack complete. \The [apc] is now under your exclusive control.")
|
||||
apc.update_icon()
|
||||
|
||||
/mob/living/silicon/ai/verb/deploy_to_shell(var/mob/living/silicon/robot/target)
|
||||
set category = "AI Commands"
|
||||
set name = "Deploy to Shell"
|
||||
|
||||
if(stat || lacks_power() || control_disabled)
|
||||
to_chat(src, "<span class='danger'>Wireless networking module is offline.</span>")
|
||||
return
|
||||
|
||||
var/list/possible = list()
|
||||
|
||||
for(var/borgie in GLOB.available_ai_shells)
|
||||
var/mob/living/silicon/robot/R = borgie
|
||||
if(R.shell && !R.deployed && (R.stat != DEAD) && (!R.connected_ai ||(R.connected_ai == src)))
|
||||
possible += R
|
||||
|
||||
if(!LAZYLEN(possible))
|
||||
to_chat(src, "No usable AI shell beacons detected.")
|
||||
|
||||
if(!target || !(target in possible)) //If the AI is looking for a new shell, or its pre-selected shell is no longer valid
|
||||
target = input(src, "Which body to control?") as null|anything in possible
|
||||
|
||||
if (!target || target.stat == DEAD || target.deployed || !(!target.connected_ai ||(target.connected_ai == src)))
|
||||
return
|
||||
|
||||
else if(mind)
|
||||
soullink(/datum/soullink/sharedbody, src, target)
|
||||
deployed_shell = target
|
||||
target.deploy_init(src)
|
||||
mind.transfer_to(target)
|
||||
diag_hud_set_deployed()
|
||||
|
||||
/datum/action/innate/deploy_shell
|
||||
name = "Deploy to AI Shell"
|
||||
desc = "Wirelessly control a specialized cyborg shell."
|
||||
button_icon_state = "ai_shell"
|
||||
|
||||
/datum/action/innate/deploy_shell/Trigger()
|
||||
var/mob/living/silicon/ai/AI = owner
|
||||
if(!AI)
|
||||
return
|
||||
AI.deploy_to_shell()
|
||||
|
||||
/datum/action/innate/deploy_last_shell
|
||||
name = "Reconnect to shell"
|
||||
desc = "Reconnect to the most recently used AI shell."
|
||||
button_icon_state = "ai_last_shell"
|
||||
var/mob/living/silicon/robot/last_used_shell
|
||||
|
||||
/datum/action/innate/deploy_last_shell/Trigger()
|
||||
if(!owner)
|
||||
return
|
||||
if(last_used_shell)
|
||||
var/mob/living/silicon/ai/AI = owner
|
||||
AI.deploy_to_shell(last_used_shell)
|
||||
else
|
||||
Remove(owner) //If the last shell is blown, destroy it.
|
||||
|
||||
/mob/living/silicon/ai/proc/disconnect_shell()
|
||||
if(deployed_shell) //Forcibly call back AI in event of things such as damage, EMP or power loss.
|
||||
to_chat(src, "<span class='danger'>Your remote connection has been reset!</span>")
|
||||
deployed_shell.undeploy()
|
||||
diag_hud_set_deployed()
|
||||
|
||||
/mob/living/silicon/ai/resist()
|
||||
return
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
|
||||
/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(!ticker || !ticker.mode)
|
||||
if(!SSticker || !SSticker.mode)
|
||||
to_chat(M, "You cannot attack people before the game has started.")
|
||||
return
|
||||
..()
|
||||
@@ -22,6 +22,7 @@
|
||||
return 0
|
||||
|
||||
/mob/living/silicon/ai/emp_act(severity)
|
||||
disconnect_shell()
|
||||
if (prob(30))
|
||||
switch(pick(1,2))
|
||||
if(1)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
if(eyeobj)
|
||||
eyeobj.setLoc(get_turf(src))
|
||||
|
||||
shuttle_caller_list -= src
|
||||
GLOB.shuttle_caller_list -= src
|
||||
SSshuttle.autoEvac()
|
||||
|
||||
ShutOffDoomsdayDevice()
|
||||
@@ -35,7 +35,7 @@
|
||||
if(nuking)
|
||||
set_security_level("red")
|
||||
nuking = FALSE
|
||||
for(var/obj/item/weapon/pinpointer/P in pinpointer_list)
|
||||
for(var/obj/item/weapon/pinpointer/P in GLOB.pinpointer_list)
|
||||
P.switch_mode_to(TRACK_NUKE_DISK) //Party's over, back to work, everyone
|
||||
P.nuke_warning = FALSE
|
||||
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/mob/living/silicon/ai/examine(mob/user)
|
||||
var/msg = "<span class='info'>*---------*\nThis is \icon[src] <EM>[src]</EM>!\n"
|
||||
if (src.stat == DEAD)
|
||||
if (stat == DEAD)
|
||||
msg += "<span class='deadsay'>It appears to be powered-down.</span>\n"
|
||||
else
|
||||
msg += "<span class='warning'>"
|
||||
if (src.getBruteLoss())
|
||||
if (src.getBruteLoss() < 30)
|
||||
if (getBruteLoss())
|
||||
if (getBruteLoss() < 30)
|
||||
msg += "It looks slightly dented.\n"
|
||||
else
|
||||
msg += "<B>It looks severely dented!</B>\n"
|
||||
if (src.getFireLoss())
|
||||
if (src.getFireLoss() < 30)
|
||||
if (getFireLoss())
|
||||
if (getFireLoss() < 30)
|
||||
msg += "It looks slightly charred.\n"
|
||||
else
|
||||
msg += "<B>Its casing is melted and heat-warped!</B>\n"
|
||||
msg += "</span>"
|
||||
if (shunted == 0 && !src.client)
|
||||
if(deployed_shell)
|
||||
msg += "The wireless networking light is blinking.\n"
|
||||
else if (!shunted && !client)
|
||||
msg += "[src]Core.exe has stopped responding! NTOS is searching for a solution to the problem...\n"
|
||||
msg += "*---------*</span>"
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
//
|
||||
// The datum containing all the chunks.
|
||||
|
||||
var/const/CHUNK_SIZE = 16 // Only chunk sizes that are to the power of 2. E.g: 2, 4, 8, 16, etc..
|
||||
#define CHUNK_SIZE 16 // Only chunk sizes that are to the power of 2. E.g: 2, 4, 8, 16, etc..
|
||||
|
||||
var/datum/cameranet/cameranet = new()
|
||||
GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
|
||||
|
||||
/datum/cameranet
|
||||
var/name = "Camera Net" // Name to show for VV and stat()
|
||||
@@ -66,7 +66,7 @@ var/datum/cameranet/cameranet = new()
|
||||
|
||||
/datum/cameranet/proc/updateVisibility(atom/A, opacity_check = 1)
|
||||
|
||||
if(!ticker || (opacity_check && !A.opacity))
|
||||
if(!SSticker || (opacity_check && !A.opacity))
|
||||
return
|
||||
majorChunkChange(A, 2)
|
||||
|
||||
@@ -151,7 +151,7 @@ var/datum/cameranet/cameranet = new()
|
||||
if(!statclick)
|
||||
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
|
||||
|
||||
stat(name, statclick.update("Cameras: [cameranet.cameras.len] | Chunks: [cameranet.chunks.len]"))
|
||||
stat(name, statclick.update("Cameras: [GLOB.cameranet.cameras.len] | Chunks: [GLOB.cameranet.chunks.len]"))
|
||||
|
||||
// Debug verb for VVing the chunk that the turf is in.
|
||||
/*
|
||||
|
||||
@@ -173,4 +173,5 @@
|
||||
t.obscured.plane = LIGHTING_PLANE+1
|
||||
obscured += t.obscured
|
||||
|
||||
#undef UPDATE_BUFFER
|
||||
#undef UPDATE_BUFFER
|
||||
#undef CHUNK_SIZE
|
||||
@@ -21,7 +21,7 @@
|
||||
return
|
||||
T = get_turf(T)
|
||||
loc = T
|
||||
cameranet.visibility(src)
|
||||
GLOB.cameranet.visibility(src)
|
||||
if(ai.client)
|
||||
ai.client.eye = src
|
||||
update_parallax_contents()
|
||||
@@ -104,6 +104,6 @@
|
||||
acceleration = !acceleration
|
||||
to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].")
|
||||
|
||||
/mob/camera/aiEye/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
|
||||
/mob/camera/aiEye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
if(relay_speech && speaker && ai && !radio_freq && speaker != ai && near_camera(speaker))
|
||||
ai.relay_speech(message, speaker, message_langs, raw_message, radio_freq, spans)
|
||||
ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans)
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
health = maxHealth - getOxyLoss() - getToxLoss() - getBruteLoss() - getFireLoss()
|
||||
update_stat()
|
||||
diag_hud_set_health()
|
||||
disconnect_shell()
|
||||
|
||||
/mob/living/silicon/ai/update_stat()
|
||||
if(status_flags & GODMODE)
|
||||
@@ -90,6 +91,7 @@
|
||||
|
||||
if(see_override)
|
||||
see_invisible = see_override
|
||||
sync_lighting_plane_alpha()
|
||||
|
||||
|
||||
/mob/living/silicon/ai/proc/start_RestorePowerRoutine()
|
||||
@@ -146,7 +148,7 @@
|
||||
to_chat(src, "Receiving control information from APC.")
|
||||
sleep(2)
|
||||
apc_override = 1
|
||||
theAPC.ui_interact(src, state = conscious_state)
|
||||
theAPC.ui_interact(src, state = GLOB.conscious_state)
|
||||
apc_override = 0
|
||||
aiRestorePowerRoutine = POWER_RESTORATION_APC_FOUND
|
||||
sleep(50)
|
||||
@@ -163,6 +165,7 @@
|
||||
update_sight()
|
||||
|
||||
/mob/living/silicon/ai/proc/ai_lose_power()
|
||||
disconnect_shell()
|
||||
aiRestorePowerRoutine = POWER_RESTORATION_START
|
||||
blind_eyes(1)
|
||||
update_sight()
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
client.images += blood
|
||||
|
||||
if(stat != DEAD)
|
||||
for(var/obj/machinery/ai_status_display/O in machines) //change status
|
||||
for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
|
||||
O.mode = 1
|
||||
O.emotion = "Neutral"
|
||||
view_core()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/mob/living/silicon/ai/say(message)
|
||||
/mob/living/silicon/ai/say(message, language)
|
||||
if(parent && istype(parent) && parent.stat != 2) //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead.
|
||||
parent.say(message)
|
||||
parent.say(message, language)
|
||||
return
|
||||
..(message)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
/mob/living/silicon/ai/IsVocal()
|
||||
return !config.silent_ai
|
||||
|
||||
/mob/living/silicon/ai/radio(message, message_mode, list/spans)
|
||||
/mob/living/silicon/ai/radio(message, message_mode, list/spans, language)
|
||||
if(!radio_enabled || aiRestorePowerRoutine || stat) //AI cannot speak if radio is disabled (via intellicard) or depowered.
|
||||
to_chat(src, "<span class='danger'>Your radio transmitter is offline!</span>")
|
||||
return 0
|
||||
@@ -29,17 +29,17 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/ai/handle_inherent_channels(message, message_mode)
|
||||
/mob/living/silicon/ai/handle_inherent_channels(message, message_mode, language)
|
||||
. = ..()
|
||||
if(.)
|
||||
return .
|
||||
|
||||
if(message_mode == MODE_HOLOPAD)
|
||||
holopad_talk(message)
|
||||
holopad_talk(message, language)
|
||||
return 1
|
||||
|
||||
//For holopads only. Usable by AI.
|
||||
/mob/living/silicon/ai/proc/holopad_talk(message)
|
||||
/mob/living/silicon/ai/proc/holopad_talk(message, language)
|
||||
log_say("[key_name(src)] : [message]")
|
||||
|
||||
message = trim(message)
|
||||
@@ -49,20 +49,15 @@
|
||||
|
||||
var/obj/machinery/holopad/T = current
|
||||
if(istype(T) && T.masters[src])//If there is a hologram and its master is the user.
|
||||
send_speech(message, 7, T, "robot", get_spans())
|
||||
send_speech(message, 7, T, "robot", get_spans(), language)
|
||||
to_chat(src, "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> <span class='message robot'>\"[message]\"</span></span></i>")
|
||||
else
|
||||
to_chat(src, "No holopad connected.")
|
||||
return
|
||||
|
||||
|
||||
// Make sure that the code compiles with AI_VOX undefined
|
||||
#ifdef AI_VOX
|
||||
|
||||
var/announcing_vox = 0 // Stores the time of the last announcement
|
||||
var/const/VOX_CHANNEL = 200
|
||||
var/const/VOX_DELAY = 600
|
||||
|
||||
#define VOX_DELAY 600
|
||||
/mob/living/silicon/ai/verb/announcement_help()
|
||||
|
||||
set name = "Announcement Help"
|
||||
@@ -79,10 +74,10 @@ var/const/VOX_DELAY = 600
|
||||
<font class='bad'>WARNING:</font><BR>Misuse of the announcement system will get you job banned.<HR>"
|
||||
|
||||
var/index = 0
|
||||
for(var/word in vox_sounds)
|
||||
for(var/word in GLOB.vox_sounds)
|
||||
index++
|
||||
dat += "<A href='?src=\ref[src];say_word=[word]'>[capitalize(word)]</A>"
|
||||
if(index != vox_sounds.len)
|
||||
if(index != GLOB.vox_sounds.len)
|
||||
dat += " / "
|
||||
|
||||
var/datum/browser/popup = new(src, "announce_help", "Announcement Help", 500, 400)
|
||||
@@ -91,6 +86,7 @@ var/const/VOX_DELAY = 600
|
||||
|
||||
|
||||
/mob/living/silicon/ai/proc/announcement()
|
||||
var/static/announcing_vox = 0 // Stores the time of the last announcement
|
||||
if(announcing_vox > world.time)
|
||||
to_chat(src, "<span class='notice'>Please wait [round((announcing_vox - world.time) / 10)] seconds.</span>")
|
||||
return
|
||||
@@ -120,7 +116,7 @@ var/const/VOX_DELAY = 600
|
||||
if(!word)
|
||||
words -= word
|
||||
continue
|
||||
if(!vox_sounds[word])
|
||||
if(!GLOB.vox_sounds[word])
|
||||
incorrect_words += word
|
||||
|
||||
if(incorrect_words.len)
|
||||
@@ -147,16 +143,16 @@ var/const/VOX_DELAY = 600
|
||||
|
||||
word = lowertext(word)
|
||||
|
||||
if(vox_sounds[word])
|
||||
if(GLOB.vox_sounds[word])
|
||||
|
||||
var/sound_file = vox_sounds[word]
|
||||
var/sound/voice = sound(sound_file, wait = 1, channel = VOX_CHANNEL)
|
||||
var/sound_file = GLOB.vox_sounds[word]
|
||||
var/sound/voice = sound(sound_file, wait = 1, channel = CHANNEL_VOX)
|
||||
voice.status = SOUND_STREAM
|
||||
|
||||
// If there is no single listener, broadcast to everyone in the same z level
|
||||
if(!only_listener)
|
||||
// Play voice for all mobs in the z level
|
||||
for(var/mob/M in player_list)
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.client && !M.ear_deaf && (M.client.prefs.toggles & SOUND_ANNOUNCEMENTS))
|
||||
var/turf/T = get_turf(M)
|
||||
if(T.z == z_level)
|
||||
@@ -167,3 +163,12 @@ var/const/VOX_DELAY = 600
|
||||
return 0
|
||||
|
||||
#endif
|
||||
|
||||
/mob/living/silicon/ai/can_speak_in_language(datum/language/dt)
|
||||
if(HAS_SECONDARY_FLAG(src, OMNITONGUE))
|
||||
. = has_language(dt)
|
||||
else if(is_servant_of_ratvar(src))
|
||||
// Ratvarian AIs can only speak Ratvarian
|
||||
. = ispath(dt, /datum/language/ratvar) && has_language(dt)
|
||||
else
|
||||
. = ..()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Dynamically loading it has bad results with sounds overtaking each other, even with the wait variable.
|
||||
#ifdef AI_VOX
|
||||
|
||||
var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg',
|
||||
GLOBAL_LIST_INIT(vox_sounds, list("," = 'sound/vox_fem/,.ogg',
|
||||
"." = 'sound/vox_fem/..ogg',
|
||||
"a" = 'sound/vox_fem/a.ogg',
|
||||
"abortions" = 'sound/vox_fem/abortions.ogg',
|
||||
@@ -713,6 +713,5 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg',
|
||||
"z" = 'sound/vox_fem/z.ogg',
|
||||
"zero" = 'sound/vox_fem/zero.ogg',
|
||||
"zone" = 'sound/vox_fem/zone.ogg',
|
||||
"zulu" = 'sound/vox_fem/zulu.ogg',
|
||||
)
|
||||
"zulu" = 'sound/vox_fem/zulu.ogg'))
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
/mob/living/silicon/Login()
|
||||
if(mind && ticker && ticker.mode)
|
||||
ticker.mode.remove_cultist(mind, 0, 0)
|
||||
ticker.mode.remove_revolutionary(mind, 0)
|
||||
ticker.mode.remove_gangster(mind, remove_bosses=1)
|
||||
if(mind && SSticker && SSticker.mode)
|
||||
SSticker.mode.remove_cultist(mind, 0, 0)
|
||||
SSticker.mode.remove_revolutionary(mind, 0)
|
||||
SSticker.mode.remove_gangster(mind, remove_bosses=1)
|
||||
..()
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
stat = DEAD
|
||||
canmove = 0
|
||||
card.removePersonality()
|
||||
if(holoform)
|
||||
card.forceMove(loc)
|
||||
update_sight()
|
||||
clear_fullscreens()
|
||||
|
||||
//New pAI's get a brand new mind to prevent meta stuff from their previous life. This new mind causes problems down the line if it's not deleted here.
|
||||
living_mob_list -= src
|
||||
GLOB.living_mob_list -= src
|
||||
ghostize()
|
||||
qdel(src)
|
||||
@@ -78,13 +78,13 @@
|
||||
. += slowdown
|
||||
|
||||
/mob/living/silicon/pai/Destroy()
|
||||
pai_list -= src
|
||||
GLOB.pai_list -= src
|
||||
..()
|
||||
|
||||
/mob/living/silicon/pai/Initialize()
|
||||
var/obj/item/device/paicard/P = loc
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
pai_list += src
|
||||
GLOB.pai_list += src
|
||||
make_laws()
|
||||
canmove = 0
|
||||
if(!istype(P)) //when manually spawning a pai, we create a card to put it into.
|
||||
@@ -110,10 +110,13 @@
|
||||
var/datum/action/innate/pai/chassis/AC = new /datum/action/innate/pai/chassis
|
||||
var/datum/action/innate/pai/rest/AR = new /datum/action/innate/pai/rest
|
||||
var/datum/action/innate/pai/light/AL = new /datum/action/innate/pai/light
|
||||
|
||||
var/datum/action/language_menu/ALM = new
|
||||
AS.Grant(src)
|
||||
AC.Grant(src)
|
||||
AR.Grant(src)
|
||||
AL.Grant(src)
|
||||
ALM.Grant(src)
|
||||
emittersemicd = TRUE
|
||||
addtimer(CALLBACK(src, .proc/emittercool), 600)
|
||||
|
||||
|
||||
@@ -102,4 +102,4 @@
|
||||
|
||||
/mob/living/silicon/pai/movement_delay()
|
||||
. = ..()
|
||||
. += 1 //A bit slower than humans, so they're easier to smash
|
||||
. += 1 //A bit slower than humans, so they're easier to smash
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
if(temp)
|
||||
left_part = temp
|
||||
else if(src.stat == 2) // Show some flavor text if the pAI is dead
|
||||
left_part = "<b><font color=red>ÈRrÖR Ða†Ä ÇÖRrÚþ†Ìoñ</font></b>"
|
||||
left_part = "<b><font color=red>�Rr�R �a�� ��Rr����o�</font></b>"
|
||||
right_part = "<pre>Program index hash not found</pre>"
|
||||
|
||||
else
|
||||
@@ -220,18 +220,18 @@
|
||||
// Accessing medical records
|
||||
if("medicalrecord")
|
||||
if(subscreen == 1)
|
||||
medicalActive1 = find_record("id", href_list["med_rec"], data_core.general)
|
||||
medicalActive1 = find_record("id", href_list["med_rec"], GLOB.data_core.general)
|
||||
if(medicalActive1)
|
||||
medicalActive2 = find_record("id", href_list["med_rec"], data_core.medical)
|
||||
medicalActive2 = find_record("id", href_list["med_rec"], GLOB.data_core.medical)
|
||||
if(!medicalActive2)
|
||||
medicalActive1 = null
|
||||
temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
|
||||
|
||||
if("securityrecord")
|
||||
if(subscreen == 1)
|
||||
securityActive1 = find_record("id", href_list["sec_rec"], data_core.general)
|
||||
securityActive1 = find_record("id", href_list["sec_rec"], GLOB.data_core.general)
|
||||
if(securityActive1)
|
||||
securityActive2 = find_record("id", href_list["sec_rec"], data_core.security)
|
||||
securityActive2 = find_record("id", href_list["sec_rec"], GLOB.data_core.security)
|
||||
if(!securityActive2)
|
||||
securityActive1 = null
|
||||
temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
|
||||
@@ -241,7 +241,7 @@
|
||||
if(secHUD)
|
||||
add_sec_hud()
|
||||
else
|
||||
var/datum/atom_hud/sec = huds[sec_hud]
|
||||
var/datum/atom_hud/sec = GLOB.huds[sec_hud]
|
||||
sec.remove_hud_from(src)
|
||||
if("medicalhud")
|
||||
if(href_list["toggle"])
|
||||
@@ -249,13 +249,13 @@
|
||||
if(medHUD)
|
||||
add_med_hud()
|
||||
else
|
||||
var/datum/atom_hud/med = huds[med_hud]
|
||||
var/datum/atom_hud/med = GLOB.huds[med_hud]
|
||||
med.remove_hud_from(src)
|
||||
if("translator")
|
||||
if(href_list["toggle"])
|
||||
var/on_already = ((languages_understood == ALL) && (languages_spoken == ALL))
|
||||
languages_spoken = on_already ? (HUMAN | ROBOT) : ALL
|
||||
languages_understood = on_already ? (HUMAN | ROBOT) : ALL
|
||||
if(!HAS_SECONDARY_FLAG(src, OMNITONGUE))
|
||||
grant_all_languages(TRUE)
|
||||
// this is PERMAMENT.
|
||||
if("doorjack")
|
||||
if(href_list["jack"])
|
||||
if(src.cable && src.cable.machine)
|
||||
@@ -313,7 +313,8 @@
|
||||
if(s == "medical HUD")
|
||||
dat += "<a href='byond://?src=\ref[src];software=medicalhud;sub=0'>Medical Analysis Suite</a>[(src.medHUD) ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
|
||||
if(s == "universal translator")
|
||||
dat += "<a href='byond://?src=\ref[src];software=translator;sub=0'>Universal Translator</a>[((languages_spoken == ALL) && (languages_understood == ALL)) ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
|
||||
var/translator_on = HAS_SECONDARY_FLAG(src, OMNITONGUE)
|
||||
dat += "<a href='byond://?src=\ref[src];software=translator;sub=0'>Universal Translator</a>[translator_on ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
|
||||
if(s == "projection array")
|
||||
dat += "<a href='byond://?src=\ref[src];software=projectionarray;sub=0'>Projection Array</a> <br>"
|
||||
if(s == "camera jack")
|
||||
@@ -413,8 +414,8 @@
|
||||
// Crew Manifest
|
||||
/mob/living/silicon/pai/proc/softwareManifest()
|
||||
. += "<h2>Crew Manifest</h2><br><br>"
|
||||
if(data_core.general)
|
||||
for(var/datum/data/record/t in sortRecord(data_core.general))
|
||||
if(GLOB.data_core.general)
|
||||
for(var/datum/data/record/t in sortRecord(GLOB.data_core.general))
|
||||
. += "[t.fields["name"]] - [t.fields["rank"]]<BR>"
|
||||
. += "</body></html>"
|
||||
return .
|
||||
@@ -424,16 +425,16 @@
|
||||
switch(subscreen)
|
||||
if(0)
|
||||
. += "<h3>Medical Records</h3><HR>"
|
||||
if(data_core.general)
|
||||
for(var/datum/data/record/R in sortRecord(data_core.general))
|
||||
if(GLOB.data_core.general)
|
||||
for(var/datum/data/record/R in sortRecord(GLOB.data_core.general))
|
||||
. += "<A href='?src=\ref[src];med_rec=[R.fields["id"]];software=medicalrecord;sub=1'>[R.fields["id"]]: [R.fields["name"]]<BR>"
|
||||
if(1)
|
||||
. += "<CENTER><B>Medical Record</B></CENTER><BR>"
|
||||
if(medicalActive1 in data_core.general)
|
||||
if(medicalActive1 in GLOB.data_core.general)
|
||||
. += "Name: [medicalActive1.fields["name"]] ID: [medicalActive1.fields["id"]]<BR>\nSex: [medicalActive1.fields["sex"]]<BR>\nAge: [medicalActive1.fields["age"]]<BR>\nFingerprint: [medicalActive1.fields["fingerprint"]]<BR>\nPhysical Status: [medicalActive1.fields["p_stat"]]<BR>\nMental Status: [medicalActive1.fields["m_stat"]]<BR>"
|
||||
else
|
||||
. += "<pre>Requested medical record not found.</pre><BR>"
|
||||
if(medicalActive2 in data_core.medical)
|
||||
if(medicalActive2 in GLOB.data_core.medical)
|
||||
. += "<BR>\n<CENTER><B>Medical Data</B></CENTER><BR>\nBlood Type: <A href='?src=\ref[src];field=blood_type'>[medicalActive2.fields["blood_type"]]</A><BR>\nDNA: <A href='?src=\ref[src];field=b_dna'>[medicalActive2.fields["b_dna"]]</A><BR>\n<BR>\nMinor Disabilities: <A href='?src=\ref[src];field=mi_dis'>[medicalActive2.fields["mi_dis"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=mi_dis_d'>[medicalActive2.fields["mi_dis_d"]]</A><BR>\n<BR>\nMajor Disabilities: <A href='?src=\ref[src];field=ma_dis'>[medicalActive2.fields["ma_dis"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=ma_dis_d'>[medicalActive2.fields["ma_dis_d"]]</A><BR>\n<BR>\nAllergies: <A href='?src=\ref[src];field=alg'>[medicalActive2.fields["alg"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=alg_d'>[medicalActive2.fields["alg_d"]]</A><BR>\n<BR>\nCurrent Diseases: <A href='?src=\ref[src];field=cdi'>[medicalActive2.fields["cdi"]]</A> (per disease info placed in log/comment section)<BR>\nDetails: <A href='?src=\ref[src];field=cdi_d'>[medicalActive2.fields["cdi_d"]]</A><BR>\n<BR>\nImportant Notes:<BR>\n\t<A href='?src=\ref[src];field=notes'>[medicalActive2.fields["notes"]]</A><BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>"
|
||||
else
|
||||
. += "<pre>Requested medical record not found.</pre><BR>"
|
||||
@@ -446,16 +447,16 @@
|
||||
switch(subscreen)
|
||||
if(0)
|
||||
. += "<h3>Security Records</h3><HR>"
|
||||
if(data_core.general)
|
||||
for(var/datum/data/record/R in sortRecord(data_core.general))
|
||||
if(GLOB.data_core.general)
|
||||
for(var/datum/data/record/R in sortRecord(GLOB.data_core.general))
|
||||
. += "<A href='?src=\ref[src];sec_rec=[R.fields["id"]];software=securityrecord;sub=1'>[R.fields["id"]]: [R.fields["name"]]<BR>"
|
||||
if(1)
|
||||
. += "<h3>Security Record</h3>"
|
||||
if(securityActive1 in data_core.general)
|
||||
if(securityActive1 in GLOB.data_core.general)
|
||||
. += "Name: <A href='?src=\ref[src];field=name'>[securityActive1.fields["name"]]</A> ID: <A href='?src=\ref[src];field=id'>[securityActive1.fields["id"]]</A><BR>\nSex: <A href='?src=\ref[src];field=sex'>[securityActive1.fields["sex"]]</A><BR>\nAge: <A href='?src=\ref[src];field=age'>[securityActive1.fields["age"]]</A><BR>\nRank: <A href='?src=\ref[src];field=rank'>[securityActive1.fields["rank"]]</A><BR>\nFingerprint: <A href='?src=\ref[src];field=fingerprint'>[securityActive1.fields["fingerprint"]]</A><BR>\nPhysical Status: [securityActive1.fields["p_stat"]]<BR>\nMental Status: [securityActive1.fields["m_stat"]]<BR>"
|
||||
else
|
||||
. += "<pre>Requested security record not found,</pre><BR>"
|
||||
if(securityActive2 in data_core.security)
|
||||
if(securityActive2 in GLOB.data_core.security)
|
||||
. += "<BR>\nSecurity Data<BR>\nCriminal Status: [securityActive2.fields["criminal"]]<BR>\n<BR>\nMinor Crimes: <A href='?src=\ref[src];field=mi_crim'>[securityActive2.fields["mi_crim"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=mi_crim_d'>[securityActive2.fields["mi_crim_d"]]</A><BR>\n<BR>\nMajor Crimes: <A href='?src=\ref[src];field=ma_crim'>[securityActive2.fields["ma_crim"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=ma_crim_d'>[securityActive2.fields["ma_crim_d"]]</A><BR>\n<BR>\nImportant Notes:<BR>\n\t<A href='?src=\ref[src];field=notes'>[securityActive2.fields["notes"]]</A><BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>"
|
||||
else
|
||||
. += "<pre>Requested security record not found,</pre><BR>"
|
||||
@@ -464,11 +465,10 @@
|
||||
|
||||
// Universal Translator
|
||||
/mob/living/silicon/pai/proc/softwareTranslator()
|
||||
var/translator_on = HAS_SECONDARY_FLAG(src, OMNITONGUE)
|
||||
. = {"<h3>Universal Translator</h3><br>
|
||||
When enabled, this device will automatically convert all spoken and written language into a format that any known recipient can understand.<br><br>
|
||||
The device is currently [ ((languages_spoken == ALL) && (languages_understood == ALL)) ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled.</font><br>
|
||||
<a href='byond://?src=\ref[src];software=translator;sub=0;toggle=1'>Toggle Device</a><br>
|
||||
"}
|
||||
When enabled, this device will permamently be able to speak and understand all known forms of communication.<br><br>
|
||||
The device is currently [translator_on ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled.</font><br>[translator_on ? "" : "<a href='byond://?src=\ref[src];software=translator;sub=0;toggle=1'>Activate Translation Module</a><br>"]"}
|
||||
return .
|
||||
|
||||
// Security HUD
|
||||
@@ -599,7 +599,7 @@
|
||||
// Door Jack - supporting proc
|
||||
/mob/living/silicon/pai/proc/hackloop()
|
||||
var/turf/T = get_turf(src.loc)
|
||||
for(var/mob/living/silicon/ai/AI in player_list)
|
||||
for(var/mob/living/silicon/ai/AI in GLOB.player_list)
|
||||
if(T.loc)
|
||||
to_chat(AI, "<font color = red><b>Network Alert: Brute-force encryption crack in progress in [T.loc].</b></font>")
|
||||
else
|
||||
|
||||
@@ -36,9 +36,11 @@
|
||||
if(is_servant_of_ratvar(src) && user.Adjacent(src) && !stat) //To counter pseudo-stealth by using headlamps
|
||||
msg += "<span class='warning'>Its eyes are glowing a blazing yellow!</span>\n"
|
||||
|
||||
switch(src.stat)
|
||||
switch(stat)
|
||||
if(CONSCIOUS)
|
||||
if(!src.client)
|
||||
if(shell)
|
||||
msg += "It appears to be an [deployed ? "active" : "empty"] AI shell.\n"
|
||||
else if(!client)
|
||||
msg += "It appears to be in stand-by mode.\n" //afk
|
||||
if(UNCONSCIOUS)
|
||||
msg += "<span class='warning'>It doesn't seem to be responding.</span>\n"
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
|
||||
to_chat(who, "<b>Obey these laws:</b>")
|
||||
laws.show_laws(who)
|
||||
if (is_special_character(src) && connected_ai)
|
||||
if (shell) //AI shell
|
||||
to_chat(who, "<b>Remember, you are an AI remotely controlling your shell, other AIs can be ignored.</b>")
|
||||
else if (is_special_character(src) && connected_ai)
|
||||
to_chat(who, "<b>Remember, [connected_ai.name] is technically your master, but your objective comes first.</b>")
|
||||
else if (connected_ai)
|
||||
to_chat(who, "<b>Remember, [connected_ai.name] is your master, other AIs can be ignored.</b>")
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
update_cell_hud_icon()
|
||||
|
||||
if(syndicate)
|
||||
if(ticker.mode.name == "traitor")
|
||||
for(var/datum/mind/tra in ticker.mode.traitors)
|
||||
if(SSticker.mode.name == "traitor")
|
||||
for(var/datum/mind/tra in SSticker.mode.traitors)
|
||||
if(tra.current)
|
||||
var/I = image('icons/mob/mob.dmi', loc = tra.current, icon_state = "traitor") //no traitor sprite in that dmi!
|
||||
src.client.images += I
|
||||
@@ -48,7 +48,7 @@
|
||||
if(mind)
|
||||
if(!mind.special_role)
|
||||
mind.special_role = "traitor"
|
||||
ticker.mode.traitors += mind
|
||||
SSticker.mode.traitors += mind
|
||||
|
||||
|
||||
/mob/living/silicon/robot/update_health_hud()
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
regenerate_icons()
|
||||
show_laws(0)
|
||||
if(mind)
|
||||
ticker.mode.remove_revolutionary(mind)
|
||||
ticker.mode.remove_gangster(mind,1,remove_bosses=1)
|
||||
SSticker.mode.remove_revolutionary(mind)
|
||||
SSticker.mode.remove_gangster(mind,1,remove_bosses=1)
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
var/obj/item/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of..
|
||||
var/obj/item/device/mmi/mmi = null
|
||||
|
||||
var/shell = FALSE
|
||||
var/deployed = FALSE
|
||||
var/mob/living/silicon/ai/mainframe = null
|
||||
var/datum/action/innate/undeployment/undeployment_action = new
|
||||
|
||||
//Hud stuff
|
||||
|
||||
@@ -47,7 +51,7 @@
|
||||
|
||||
var/ident = 0
|
||||
var/locked = 1
|
||||
var/list/req_access = list(access_robotics)
|
||||
var/list/req_access = list(GLOB.access_robotics)
|
||||
|
||||
var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list())
|
||||
|
||||
@@ -73,7 +77,7 @@
|
||||
|
||||
var/sight_mode = 0
|
||||
var/updating = 0 //portable camera camerachunk update
|
||||
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD)
|
||||
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_TRACK_HUD)
|
||||
|
||||
var/list/upgrades = list()
|
||||
|
||||
@@ -129,8 +133,12 @@
|
||||
update_icons()
|
||||
..()
|
||||
|
||||
//If this body is meant to be a borg controlled by the AI player
|
||||
if(shell)
|
||||
make_shell()
|
||||
|
||||
//MMI stuff. Held togheter by magic. ~Miauw
|
||||
if(!mmi || !mmi.brainmob)
|
||||
else if(!mmi || !mmi.brainmob)
|
||||
mmi = new (src)
|
||||
mmi.brain = new /obj/item/organ/brain(mmi)
|
||||
mmi.brain.name = "[real_name]'s brain"
|
||||
@@ -159,8 +167,8 @@
|
||||
if(mmi.brainmob)
|
||||
if(mmi.brainmob.stat == DEAD)
|
||||
mmi.brainmob.stat = CONSCIOUS
|
||||
dead_mob_list -= mmi.brainmob
|
||||
living_mob_list += mmi.brainmob
|
||||
GLOB.dead_mob_list -= mmi.brainmob
|
||||
GLOB.living_mob_list += mmi.brainmob
|
||||
mind.transfer_to(mmi.brainmob)
|
||||
mmi.update_icon()
|
||||
else
|
||||
@@ -170,6 +178,8 @@
|
||||
mmi = null
|
||||
if(connected_ai)
|
||||
connected_ai.connected_robots -= src
|
||||
if(shell)
|
||||
GLOB.available_ai_shells -= src
|
||||
qdel(wires)
|
||||
qdel(module)
|
||||
qdel(eye_lights)
|
||||
@@ -204,6 +214,8 @@
|
||||
|
||||
|
||||
/mob/living/silicon/robot/proc/updatename()
|
||||
if(shell)
|
||||
return
|
||||
var/changed_name = ""
|
||||
if(custom_name)
|
||||
changed_name = custom_name
|
||||
@@ -424,7 +436,9 @@
|
||||
update_icons()
|
||||
|
||||
else if(istype(W, /obj/item/weapon/screwdriver) && opened && cell) // radio
|
||||
if(radio)
|
||||
if(shell)
|
||||
to_chat(user, "You cannot seem to open the radio compartment") //Prevent AI radio key theft
|
||||
else if(radio)
|
||||
radio.attackby(W,user)//Push it to the radio to let it handle everything
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Unable to locate a radio!</span>")
|
||||
@@ -453,6 +467,9 @@
|
||||
if(!cell)
|
||||
to_chat(user, "<span class='warning'>You need to install a power cell to do that!</span>")
|
||||
return
|
||||
if(shell) //AI shells always have the laws of the AI
|
||||
to_chat(user, "<span class='warning'>[src] is controlled remotely! You cannot upload new laws this way!</span>")
|
||||
return
|
||||
if(emagged || (connected_ai && lawupdate)) //Can't be sure which, metagamers
|
||||
emote("buzz-[user.name]")
|
||||
return
|
||||
@@ -594,7 +611,7 @@
|
||||
|
||||
/mob/living/silicon/robot/proc/do_camera_update(oldLoc)
|
||||
if(oldLoc != src.loc)
|
||||
cameranet.updatePortableCamera(src.camera)
|
||||
GLOB.cameranet.updatePortableCamera(src.camera)
|
||||
updating = 0
|
||||
|
||||
/mob/living/silicon/robot/Move(a, b, flag)
|
||||
@@ -606,36 +623,6 @@
|
||||
updating = 1
|
||||
addtimer(CALLBACK(src, .proc/do_camera_update, oldLoc), BORG_CAMERA_BUFFER)
|
||||
if(module)
|
||||
if(istype(module, /obj/item/weapon/robot_module/janitor))
|
||||
var/turf/tile = loc
|
||||
if(isturf(tile))
|
||||
tile.clean_blood()
|
||||
for(var/A in tile)
|
||||
if(is_cleanable(A))
|
||||
qdel(A)
|
||||
else if(istype(A, /obj/item))
|
||||
var/obj/item/cleaned_item = A
|
||||
cleaned_item.clean_blood()
|
||||
else if(ishuman(A))
|
||||
var/mob/living/carbon/human/cleaned_human = A
|
||||
if(cleaned_human.lying)
|
||||
if(cleaned_human.head)
|
||||
cleaned_human.head.clean_blood()
|
||||
cleaned_human.update_inv_head()
|
||||
if(cleaned_human.wear_suit)
|
||||
cleaned_human.wear_suit.clean_blood()
|
||||
cleaned_human.update_inv_wear_suit()
|
||||
else if(cleaned_human.w_uniform)
|
||||
cleaned_human.w_uniform.clean_blood()
|
||||
cleaned_human.update_inv_w_uniform()
|
||||
if(cleaned_human.shoes)
|
||||
cleaned_human.shoes.clean_blood()
|
||||
cleaned_human.update_inv_shoes()
|
||||
cleaned_human.clean_blood()
|
||||
cleaned_human.wash_cream()
|
||||
to_chat(cleaned_human, "<span class='danger'>[src] cleans your face!</span>")
|
||||
return
|
||||
|
||||
if(istype(module, /obj/item/weapon/robot_module/miner))
|
||||
if(istype(loc, /turf/open/floor/plating/asteroid))
|
||||
for(var/obj/item/I in held_items)
|
||||
@@ -806,7 +793,7 @@
|
||||
icon_state = "syndie_bloodhound"
|
||||
faction = list("syndicate")
|
||||
bubble_icon = "syndibot"
|
||||
req_access = list(access_syndicate)
|
||||
req_access = list(GLOB.access_syndicate)
|
||||
lawupdate = FALSE
|
||||
scrambledcodes = TRUE // These are rogue borgs.
|
||||
ionpulse = TRUE
|
||||
@@ -829,6 +816,9 @@
|
||||
if(playstyle_string)
|
||||
to_chat(src, playstyle_string)
|
||||
|
||||
/mob/living/silicon/robot/syndicate/ResetModule()
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/syndicate/medical
|
||||
icon_state = "syndi-medi"
|
||||
playstyle_string = "<span class='userdanger'>You are a Syndicate medical cyborg!</span><br>\
|
||||
@@ -843,12 +833,14 @@
|
||||
if(!connected_ai)
|
||||
return
|
||||
switch(notifytype)
|
||||
if(1) //New Cyborg
|
||||
if(NEW_BORG) //New Cyborg
|
||||
to_chat(connected_ai, "<br><br><span class='notice'>NOTICE - New cyborg connection detected: <a href='?src=\ref[connected_ai];track=[html_encode(name)]'>[name]</a></span><br>")
|
||||
if(2) //New Module
|
||||
if(NEW_MODULE) //New Module
|
||||
to_chat(connected_ai, "<br><br><span class='notice'>NOTICE - Cyborg module change detected: [name] has loaded the [designation] module.</span><br>")
|
||||
if(3) //New Name
|
||||
if(RENAME) //New Name
|
||||
to_chat(connected_ai, "<br><br><span class='notice'>NOTICE - Cyborg reclassification detected: [oldname] is now designated as [newname].</span><br>")
|
||||
if(AI_SHELL) //New Shell
|
||||
to_chat(connected_ai, "<br><br><span class='notice'>NOTICE - New cyborg shell detected: <a href='?src=\ref[connected_ai];track=[html_encode(name)]'>[name]</a></span><br>")
|
||||
|
||||
/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close = 0)
|
||||
if(stat || lockcharge || low_power_mode)
|
||||
@@ -889,12 +881,12 @@
|
||||
|
||||
if(sight_mode & BORGMESON)
|
||||
sight |= SEE_TURFS
|
||||
see_invisible = min(see_invisible, SEE_INVISIBLE_MINIMUM)
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
|
||||
see_in_dark = 1
|
||||
|
||||
if(sight_mode & BORGMATERIAL)
|
||||
sight |= SEE_OBJS
|
||||
see_invisible = min(see_invisible, SEE_INVISIBLE_MINIMUM)
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
see_in_dark = 1
|
||||
|
||||
if(sight_mode & BORGXRAY)
|
||||
@@ -909,6 +901,7 @@
|
||||
|
||||
if(see_override)
|
||||
see_invisible = see_override
|
||||
sync_lighting_plane_alpha()
|
||||
|
||||
/mob/living/silicon/robot/update_stat()
|
||||
if(status_flags & GODMODE)
|
||||
@@ -931,6 +924,7 @@
|
||||
update_headlamp()
|
||||
diag_hud_set_status()
|
||||
diag_hud_set_health()
|
||||
diag_hud_set_aishell()
|
||||
update_health_hud()
|
||||
|
||||
/mob/living/silicon/robot/revive(full_heal = 0, admin_revive = 0)
|
||||
@@ -940,13 +934,13 @@
|
||||
update_headlamp()
|
||||
if(admin_revive)
|
||||
locked = 1
|
||||
notify_ai(1)
|
||||
notify_ai(NEW_BORG)
|
||||
. = 1
|
||||
|
||||
/mob/living/silicon/robot/fully_replace_character_name(oldname, newname)
|
||||
..()
|
||||
if(oldname != real_name)
|
||||
notify_ai(3, oldname, newname)
|
||||
notify_ai(RENAME, oldname, newname)
|
||||
if(camera)
|
||||
camera.c_tag = real_name
|
||||
custom_name = newname
|
||||
@@ -967,6 +961,7 @@
|
||||
|
||||
speed = 0
|
||||
ionpulse = FALSE
|
||||
revert_shell()
|
||||
|
||||
return 1
|
||||
|
||||
@@ -985,6 +980,11 @@
|
||||
else
|
||||
status_flags &= ~CANPUSH
|
||||
|
||||
if(module.clean_on_move)
|
||||
flags |= CLEAN_ON_MOVE
|
||||
else
|
||||
flags &= ~CLEAN_ON_MOVE
|
||||
|
||||
hat_offset = module.hat_offset
|
||||
|
||||
magpulse = module.magpulsing
|
||||
@@ -998,6 +998,97 @@
|
||||
new_hat.forceMove(src)
|
||||
update_icons()
|
||||
|
||||
/mob/living/silicon/robot/proc/make_shell(var/obj/item/borg/upgrade/ai/board)
|
||||
if(!board)
|
||||
upgrades |= new /obj/item/borg/upgrade/ai(src)
|
||||
shell = TRUE
|
||||
braintype = "AI Shell"
|
||||
name = "[designation] AI Shell [rand(100,999)]"
|
||||
real_name = name
|
||||
GLOB.available_ai_shells |= src
|
||||
if(camera)
|
||||
camera.c_tag = real_name //update the camera name too
|
||||
diag_hud_set_aishell()
|
||||
notify_ai(AI_SHELL)
|
||||
|
||||
/mob/living/silicon/robot/proc/revert_shell()
|
||||
if(!shell)
|
||||
return
|
||||
undeploy()
|
||||
for(var/obj/item/borg/upgrade/ai/boris in src)
|
||||
//A player forced reset of a borg would drop the module before this is called, so this is for catching edge cases
|
||||
qdel(boris)
|
||||
shell = FALSE
|
||||
GLOB.available_ai_shells -= src
|
||||
name = "Unformatted Cyborg [rand(100,999)]"
|
||||
real_name = name
|
||||
if(camera)
|
||||
camera.c_tag = real_name
|
||||
diag_hud_set_aishell()
|
||||
|
||||
/mob/living/silicon/robot/proc/deploy_init(var/mob/living/silicon/ai/AI)
|
||||
real_name = "[AI.real_name] shell [rand(100, 999)] - [designation]" //Randomizing the name so it shows up seperately in the shells list
|
||||
name = real_name
|
||||
if(camera)
|
||||
camera.c_tag = real_name //update the camera name too
|
||||
mainframe = AI
|
||||
deployed = TRUE
|
||||
connected_ai = mainframe
|
||||
mainframe.connected_robots |= src
|
||||
lawupdate = TRUE
|
||||
lawsync()
|
||||
if(radio && AI.radio) //AI keeps all channels, including Syndie if it is a Traitor
|
||||
if(AI.radio.syndie)
|
||||
radio.make_syndie()
|
||||
radio.subspace_transmission = TRUE
|
||||
radio.channels = AI.radio.channels
|
||||
for(var/chan in radio.channels)
|
||||
radio.secure_radio_connections[chan] = add_radio(radio, GLOB.radiochannels[chan])
|
||||
|
||||
diag_hud_set_aishell()
|
||||
undeployment_action.Grant(src)
|
||||
|
||||
/datum/action/innate/undeployment
|
||||
name = "Disconnect from shell"
|
||||
desc = "Stop controlling your shell and resume normal core operations."
|
||||
button_icon_state = "ai_core"
|
||||
|
||||
/datum/action/innate/undeployment/Trigger()
|
||||
if(!..())
|
||||
return FALSE
|
||||
var/mob/living/silicon/robot/R = owner
|
||||
|
||||
R.undeploy()
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/silicon/robot/proc/undeploy()
|
||||
|
||||
if(!deployed || !mind || !mainframe)
|
||||
return
|
||||
mainframe.redeploy_action.Grant(mainframe)
|
||||
mainframe.redeploy_action.last_used_shell = src
|
||||
mind.transfer_to(mainframe)
|
||||
deployed = FALSE
|
||||
mainframe.deployed_shell = null
|
||||
undeployment_action.Remove(src)
|
||||
if(radio) //Return radio to normal
|
||||
radio.recalculateChannels()
|
||||
if(camera)
|
||||
camera.c_tag = real_name //update the camera name too
|
||||
diag_hud_set_aishell()
|
||||
mainframe.diag_hud_set_deployed()
|
||||
mainframe.show_laws() //Always remind the AI when switching
|
||||
mainframe = null
|
||||
|
||||
/mob/living/silicon/robot/attack_ai(mob/user)
|
||||
if(shell && (!connected_ai || connected_ai == user))
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
AI.deploy_to_shell(src)
|
||||
|
||||
/mob/living/silicon/robot/shell
|
||||
shell = TRUE
|
||||
|
||||
/mob/living/silicon/robot/MouseDrop_T(mob/living/M, mob/living/user)
|
||||
. = ..()
|
||||
if(!(M in buckled_mobs) && isliving(M))
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
if (M.a_intent == INTENT_DISARM)
|
||||
if(!(lying))
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
if(get_active_held_item())
|
||||
var/obj/item/I = get_active_held_item()
|
||||
if(I)
|
||||
uneq_active()
|
||||
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has disabled [src]'s active module!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
add_logs(M, src, "disarmed")
|
||||
add_logs(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
|
||||
else
|
||||
Stun(2)
|
||||
step(src,get_dir(M,src))
|
||||
@@ -92,6 +93,8 @@
|
||||
if(locked)
|
||||
to_chat(user, "<span class='notice'>You emag the cover lock.</span>")
|
||||
locked = 0
|
||||
if(shell) //A warning to Traitors who may not know that emagging AI shells does not slave them.
|
||||
to_chat(user, "<span class='boldwarning'>[src] seems to be controlled remotely! Emagging the interface may not work as expected.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The cover is already unlocked!</span>")
|
||||
return
|
||||
@@ -125,6 +128,12 @@
|
||||
log_game("[key_name(user)] attempted to emag cyborg [key_name(src)], but they were slaved to traitor AI [connected_ai].")
|
||||
return
|
||||
|
||||
if(shell) //AI shells cannot be emagged, so we try to make it look like a standard reset. Smart players may see through this, however.
|
||||
to_chat(user, "<span class='danger'>[src] is remotely controlled! Your emag attempt has triggered a system reset instead!</span>")
|
||||
log_game("[key_name(user)] attempted to emag an AI shell belonging to [key_name(src) ? key_name(src) : connected_ai]. The shell has been reset as a result.")
|
||||
ResetModule()
|
||||
return
|
||||
|
||||
SetEmagged(1)
|
||||
SetStunned(3) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown
|
||||
lawupdate = 0
|
||||
@@ -132,7 +141,7 @@
|
||||
message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.")
|
||||
log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.")
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
lawchanges.Add("[time] <B>:</B> [user.name]([user.key]) emagged [name]([key])")
|
||||
GLOB.lawchanges.Add("[time] <B>:</B> [user.name]([user.key]) emagged [name]([key])")
|
||||
to_chat(src, "<span class='danger'>ALERT: Foreign software detected.</span>")
|
||||
sleep(5)
|
||||
to_chat(src, "<span class='danger'>Initiating diagnostics...</span>")
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
var/can_be_pushed = TRUE
|
||||
var/magpulsing = FALSE
|
||||
var/clean_on_move = FALSE
|
||||
|
||||
var/did_feedback = FALSE
|
||||
var/feedback_key
|
||||
@@ -217,7 +218,7 @@
|
||||
R.SetLockdown(0)
|
||||
R.anchored = FALSE
|
||||
R.notransform = FALSE
|
||||
R.notify_ai(2)
|
||||
R.notify_ai(NEW_MODULE)
|
||||
if(R.hud_used)
|
||||
R.hud_used.update_robot_modules_display()
|
||||
if(feedback_key && !did_feedback)
|
||||
@@ -228,8 +229,17 @@
|
||||
basic_modules = list(
|
||||
/obj/item/device/assembly/flash/cyborg,
|
||||
/obj/item/weapon/reagent_containers/borghypo/epi,
|
||||
/obj/item/device/healthanalyzer,
|
||||
/obj/item/weapon/weldingtool/largetank/cyborg,
|
||||
/obj/item/weapon/wrench/cyborg,
|
||||
/obj/item/weapon/crowbar/cyborg,
|
||||
/obj/item/stack/sheet/metal/cyborg,
|
||||
/obj/item/stack/rods/cyborg,
|
||||
/obj/item/stack/tile/plasteel/cyborg,
|
||||
/obj/item/weapon/extinguisher,
|
||||
/obj/item/weapon/pickaxe,
|
||||
/obj/item/device/t_scanner/adv_mining_scanner,
|
||||
/obj/item/weapon/restraints/handcuffs/cable/zipties/cyborg,
|
||||
/obj/item/weapon/soap/nanotrasen,
|
||||
/obj/item/borg/cyborghug)
|
||||
emag_modules = list(/obj/item/weapon/melee/energy/sword/cyborg)
|
||||
@@ -382,6 +392,7 @@
|
||||
moduleselect_icon = "janitor"
|
||||
feedback_key = "cyborg_janitor"
|
||||
hat_offset = -5
|
||||
clean_on_move = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/spray/cyborg_drying
|
||||
name = "drying agent spray"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
desig = trim_left(S.designation + " " + S.job)
|
||||
var/message_a = say_quote(message, get_spans())
|
||||
var/rendered = "<i><span class='game say'>Robotic Talk, <span class='name'>[name]</span> <span class='message'>[message_a]</span></span></i>"
|
||||
for(var/mob/M in player_list)
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.binarycheck())
|
||||
if(isAI(M))
|
||||
var/renderedAI = "<i><span class='game say'>Robotic Talk, <a href='?src=\ref[M];track=[html_encode(name)]'><span class='name'>[name] ([desig])</span></a> <span class='message'>[message_a]</span></span></i>"
|
||||
@@ -33,19 +33,19 @@
|
||||
/mob/living/silicon/lingcheck()
|
||||
return 0 //Borged or AI'd lings can't speak on the ling channel.
|
||||
|
||||
/mob/living/silicon/radio(message, message_mode, list/spans)
|
||||
/mob/living/silicon/radio(message, message_mode, list/spans, language)
|
||||
. = ..()
|
||||
if(. != 0)
|
||||
return .
|
||||
|
||||
if(message_mode == "robot")
|
||||
if (radio)
|
||||
radio.talk_into(src, message, , spans)
|
||||
radio.talk_into(src, message, , spans, language)
|
||||
return REDUCE_RANGE
|
||||
|
||||
else if(message_mode in radiochannels)
|
||||
else if(message_mode in GLOB.radiochannels)
|
||||
if(radio)
|
||||
radio.talk_into(src, message, message_mode, spans)
|
||||
radio.talk_into(src, message, message_mode, spans, language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
return 0
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
/mob/living/silicon
|
||||
gender = NEUTER
|
||||
voice_name = "synthesized voice"
|
||||
languages_spoken = ROBOT | HUMAN
|
||||
languages_understood = ROBOT | HUMAN
|
||||
has_unlimited_silicon_privilege = 1
|
||||
verb_say = "states"
|
||||
verb_ask = "queries"
|
||||
verb_exclaim = "declares"
|
||||
verb_yell = "alarms"
|
||||
initial_languages = list(/datum/language/common, /datum/language/machine)
|
||||
see_in_dark = 8
|
||||
bubble_icon = "machine"
|
||||
weather_immunities = list("ash")
|
||||
@@ -21,8 +20,7 @@
|
||||
var/designation = ""
|
||||
var/radiomod = "" //Radio character used before state laws/arrivals announce to allow department transmissions, default, or none at all.
|
||||
var/obj/item/device/camera/siliconcam/aicamera = null //photography
|
||||
//hud_possible = list(DIAG_STAT_HUD, DIAG_HUD, ANTAG_HUD)
|
||||
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD)
|
||||
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_TRACK_HUD)
|
||||
|
||||
var/obj/item/device/radio/borg/radio = null //AIs dont use this but this is at the silicon level to advoid copypasta in say()
|
||||
|
||||
@@ -41,8 +39,8 @@
|
||||
|
||||
/mob/living/silicon/Initialize()
|
||||
..()
|
||||
silicon_mobs += src
|
||||
var/datum/atom_hud/data/diagnostic/diag_hud = huds[DATA_HUD_DIAGNOSTIC]
|
||||
GLOB.silicon_mobs += src
|
||||
var/datum/atom_hud/data/diagnostic/diag_hud = GLOB.huds[DATA_HUD_DIAGNOSTIC]
|
||||
diag_hud.add_to_hud(src)
|
||||
diag_hud_set_status()
|
||||
diag_hud_set_health()
|
||||
@@ -56,7 +54,7 @@
|
||||
/mob/living/silicon/Destroy()
|
||||
radio = null
|
||||
aicamera = null
|
||||
silicon_mobs -= src
|
||||
GLOB.silicon_mobs -= src
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/contents_explosion(severity, target)
|
||||
@@ -307,8 +305,8 @@
|
||||
else if(Autochan == "None") //Prevents use of the radio for automatic annoucements.
|
||||
radiomod = ""
|
||||
else //For department channels, if any, given by the internal radio.
|
||||
for(var/key in department_radio_keys)
|
||||
if(department_radio_keys[key] == Autochan)
|
||||
for(var/key in GLOB.department_radio_keys)
|
||||
if(GLOB.department_radio_keys[key] == Autochan)
|
||||
radiomod = key
|
||||
break
|
||||
|
||||
@@ -327,23 +325,23 @@
|
||||
return -10
|
||||
|
||||
/mob/living/silicon/proc/remove_med_sec_hud()
|
||||
var/datum/atom_hud/secsensor = huds[sec_hud]
|
||||
var/datum/atom_hud/medsensor = huds[med_hud]
|
||||
var/datum/atom_hud/diagsensor = huds[d_hud]
|
||||
var/datum/atom_hud/secsensor = GLOB.huds[sec_hud]
|
||||
var/datum/atom_hud/medsensor = GLOB.huds[med_hud]
|
||||
var/datum/atom_hud/diagsensor = GLOB.huds[d_hud]
|
||||
secsensor.remove_hud_from(src)
|
||||
medsensor.remove_hud_from(src)
|
||||
diagsensor.remove_hud_from(src)
|
||||
|
||||
/mob/living/silicon/proc/add_sec_hud()
|
||||
var/datum/atom_hud/secsensor = huds[sec_hud]
|
||||
var/datum/atom_hud/secsensor = GLOB.huds[sec_hud]
|
||||
secsensor.add_hud_to(src)
|
||||
|
||||
/mob/living/silicon/proc/add_med_hud()
|
||||
var/datum/atom_hud/medsensor = huds[med_hud]
|
||||
var/datum/atom_hud/medsensor = GLOB.huds[med_hud]
|
||||
medsensor.add_hud_to(src)
|
||||
|
||||
/mob/living/silicon/proc/add_diag_hud()
|
||||
var/datum/atom_hud/diagsensor = huds[d_hud]
|
||||
var/datum/atom_hud/diagsensor = GLOB.huds[d_hud]
|
||||
diagsensor.add_hud_to(src)
|
||||
|
||||
/mob/living/silicon/proc/sensor_mode()
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
"<span class='userdanger'>[M] took a swipe at [src]!</span>")
|
||||
|
||||
/mob/living/silicon/attack_animal(mob/living/simple_animal/M)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
if(prob(damage))
|
||||
for(var/mob/living/N in buckled_mobs)
|
||||
@@ -44,7 +45,6 @@
|
||||
adjustCloneLoss(damage)
|
||||
if(STAMINA)
|
||||
adjustStaminaLoss(damage)
|
||||
updatehealth()
|
||||
|
||||
/mob/living/silicon/attack_paw(mob/living/user)
|
||||
return attack_hand(user)
|
||||
|
||||
@@ -10,10 +10,7 @@
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
|
||||
if("grab")
|
||||
if(grab_state >= GRAB_AGGRESSIVE && isliving(pulling))
|
||||
vore_attack(M, pulling)
|
||||
else
|
||||
grabbedby(M)
|
||||
grabbedby(M)
|
||||
|
||||
if("harm", "disarm")
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
@@ -63,25 +60,25 @@
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
if(..() && stat != DEAD) //successful larva bite
|
||||
. = ..()
|
||||
if(. && stat != DEAD) //successful larva bite
|
||||
var/damage = rand(5, 10)
|
||||
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
|
||||
attack_threshold_check(damage)
|
||||
return 1
|
||||
. = attack_threshold_check(damage)
|
||||
if(.)
|
||||
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
|
||||
|
||||
/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
attack_threshold_check(damage, M.melee_damage_type)
|
||||
return 1
|
||||
return attack_threshold_check(damage, M.melee_damage_type)
|
||||
|
||||
/mob/living/simple_animal/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
var/damage = rand(15, 25)
|
||||
if(M.is_adult)
|
||||
damage = rand(20, 35)
|
||||
attack_threshold_check(damage)
|
||||
return 1
|
||||
return attack_threshold_check(damage)
|
||||
|
||||
/mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE, armorcheck = "melee")
|
||||
var/temp_damage = damage
|
||||
@@ -92,8 +89,10 @@
|
||||
|
||||
if(temp_damage >= 0 && temp_damage <= force_threshold)
|
||||
visible_message("<span class='warning'>[src] looks unharmed.</span>")
|
||||
return FALSE
|
||||
else
|
||||
apply_damage(damage, damagetype, null, getarmor(null, armorcheck))
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/bullet_act(obj/item/projectile/Proj)
|
||||
if(!Proj)
|
||||
@@ -136,4 +135,4 @@
|
||||
visual_effect_icon = ATTACK_EFFECT_PUNCH
|
||||
else
|
||||
visual_effect_icon = ATTACK_EFFECT_SMASH
|
||||
..()
|
||||
..()
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
verb_ask = "queries"
|
||||
verb_exclaim = "declares"
|
||||
verb_yell = "alarms"
|
||||
initial_languages = list(/datum/language/common, /datum/language/machine)
|
||||
bubble_icon = "machine"
|
||||
|
||||
faction = list("neutral", "silicon" , "turret")
|
||||
@@ -118,7 +119,7 @@
|
||||
..()
|
||||
access_card = new /obj/item/weapon/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.
|
||||
access_card.access += access_robotics
|
||||
access_card.access += GLOB.access_robotics
|
||||
set_custom_texts()
|
||||
Radio = new/obj/item/device/radio(src)
|
||||
if(radio_key)
|
||||
@@ -131,7 +132,7 @@
|
||||
|
||||
//Adds bot to the diagnostic HUD system
|
||||
prepare_huds()
|
||||
var/datum/atom_hud/data/diagnostic/diag_hud = huds[DATA_HUD_DIAGNOSTIC]
|
||||
var/datum/atom_hud/data/diagnostic/diag_hud = GLOB.huds[DATA_HUD_DIAGNOSTIC]
|
||||
diag_hud.add_to_hud(src)
|
||||
diag_hud_set_bothealth()
|
||||
diag_hud_set_botstat()
|
||||
@@ -140,6 +141,9 @@
|
||||
//Gives a HUD view to player bots that use a HUD.
|
||||
activate_data_hud()
|
||||
|
||||
grant_language(/datum/language/common)
|
||||
grant_language(/datum/language/machine)
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/update_canmove()
|
||||
. = ..()
|
||||
@@ -323,30 +327,29 @@
|
||||
if((!on) || (!message))
|
||||
return
|
||||
if(channel && Radio.channels[channel])// Use radio if we have channel key
|
||||
Radio.talk_into(src, message, channel, get_spans())
|
||||
Radio.talk_into(src, message, channel, get_spans(), get_default_language())
|
||||
else
|
||||
say(message)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/get_spans()
|
||||
return ..() | SPAN_ROBOT
|
||||
|
||||
/mob/living/simple_animal/bot/radio(message, message_mode, list/spans)
|
||||
/mob/living/simple_animal/bot/radio(message, message_mode, list/spans, language)
|
||||
. = ..()
|
||||
if(. != 0)
|
||||
return .
|
||||
|
||||
switch(message_mode)
|
||||
if(MODE_HEADSET)
|
||||
Radio.talk_into(src, message, , spans)
|
||||
Radio.talk_into(src, message, , spans, language)
|
||||
return REDUCE_RANGE
|
||||
|
||||
if(MODE_DEPARTMENT)
|
||||
Radio.talk_into(src, message, message_mode, spans)
|
||||
Radio.talk_into(src, message, message_mode, spans, language)
|
||||
return REDUCE_RANGE
|
||||
|
||||
if(message_mode in radiochannels)
|
||||
Radio.talk_into(src, message, message_mode, spans)
|
||||
if(message_mode in GLOB.radiochannels)
|
||||
Radio.talk_into(src, message, message_mode, spans, language)
|
||||
return REDUCE_RANGE
|
||||
return 0
|
||||
|
||||
@@ -607,7 +610,7 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
|
||||
/mob/living/simple_animal/bot/proc/get_next_patrol_target()
|
||||
// search the beacon list for the next target in the list.
|
||||
for(var/obj/machinery/navbeacon/NB in navbeacons["[z]"])
|
||||
for(var/obj/machinery/navbeacon/NB in GLOB.navbeacons["[z]"])
|
||||
if(NB.location == next_destination) //Does the Beacon location text match the destination?
|
||||
destination = new_destination //We now know the name of where we want to go.
|
||||
patrol_target = NB.loc //Get its location and set it as the target.
|
||||
@@ -615,7 +618,7 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/bot/proc/find_nearest_beacon()
|
||||
for(var/obj/machinery/navbeacon/NB in navbeacons["[z]"])
|
||||
for(var/obj/machinery/navbeacon/NB in GLOB.navbeacons["[z]"])
|
||||
var/dist = get_dist(src, NB)
|
||||
if(nearest_beacon) //Loop though the beacon net to find the true closest beacon.
|
||||
//Ignore the beacon if were are located on it.
|
||||
@@ -922,5 +925,5 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
//If a bot has its own HUD (for player bots), provide it.
|
||||
if(!data_hud_type)
|
||||
return
|
||||
var/datum/atom_hud/datahud = huds[data_hud_type]
|
||||
var/datum/atom_hud/datahud = GLOB.huds[data_hud_type]
|
||||
datahud.add_hud_to(src)
|
||||
|
||||
@@ -265,7 +265,7 @@
|
||||
..()
|
||||
|
||||
/obj/machinery/bot_core/cleanbot
|
||||
req_one_access = list(access_janitor, access_robotics)
|
||||
req_one_access = list(GLOB.access_janitor, GLOB.access_robotics)
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/cleanbot/get_controls(mob/user)
|
||||
|
||||
@@ -419,8 +419,7 @@
|
||||
return
|
||||
build_step++
|
||||
to_chat(user, "<span class='notice'>You complete the Securitron! Beep boop.</span>")
|
||||
var/mob/living/simple_animal/bot/secbot/S = new /mob/living/simple_animal/bot/secbot
|
||||
S.loc = get_turf(src)
|
||||
var/mob/living/simple_animal/bot/secbot/S = new /mob/living/simple_animal/bot/secbot(get_turf(src))
|
||||
S.name = created_name
|
||||
S.baton_type = I.type
|
||||
qdel(I)
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
shot_delay = 6//Longer shot delay because JESUS CHRIST
|
||||
check_records = 0//Don't actively target people set to arrest
|
||||
arrest_type = 1//Don't even try to cuff
|
||||
bot_core.req_access = list(access_maint_tunnels, access_theatre)
|
||||
bot_core.req_access = list(GLOB.access_maint_tunnels, GLOB.access_theatre)
|
||||
arrest_type = 1
|
||||
if((lasercolor == "b") && (name == "\improper ED-209 Security Robot"))//Picks a name if there isn't already a custome one
|
||||
name = pick("BLUE BALLER","SANIC","BLUE KILLDEATH MURDERBOT")
|
||||
@@ -67,7 +67,7 @@
|
||||
name = pick("RED RAMPAGE","RED ROVER","RED KILLDEATH MURDERBOT")
|
||||
|
||||
//SECHUD
|
||||
var/datum/atom_hud/secsensor = huds[DATA_HUD_SECURITY_ADVANCED]
|
||||
var/datum/atom_hud/secsensor = GLOB.huds[DATA_HUD_SECURITY_ADVANCED]
|
||||
secsensor.add_hud_to(src)
|
||||
|
||||
/mob/living/simple_animal/bot/ed209/turn_on()
|
||||
|
||||
@@ -387,7 +387,7 @@
|
||||
..()
|
||||
|
||||
/obj/machinery/bot_core/floorbot
|
||||
req_one_access = list(access_construction, access_robotics)
|
||||
req_one_access = list(GLOB.access_construction, GLOB.access_robotics)
|
||||
|
||||
/mob/living/simple_animal/bot/floorbot/UnarmedAttack(atom/A)
|
||||
if(isturf(A))
|
||||
|
||||
@@ -338,7 +338,7 @@
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/proc/assess_patient(mob/living/carbon/C)
|
||||
//Time to see if they need medical help!
|
||||
if(C.stat == 2)
|
||||
if(C.stat == DEAD || (C.status_flags & FAKEDEATH))
|
||||
return 0 //welp too late for them!
|
||||
|
||||
if(C.suiciding)
|
||||
@@ -404,7 +404,7 @@
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
if(C.stat == 2)
|
||||
if(C.stat == DEAD || (C.status_flags & FAKEDEATH))
|
||||
var/list/messagevoice = list("No! Stay with me!" = 'sound/voice/mno.ogg',"Live, damnit! LIVE!" = 'sound/voice/mlive.ogg',"I...I've never lost a patient before. Not today, I mean." = 'sound/voice/mlost.ogg')
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
@@ -496,7 +496,7 @@
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/proc/check_overdose(mob/living/carbon/patient,reagent_id,injection_amount)
|
||||
var/datum/reagent/R = chemical_reagents_list[reagent_id]
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[reagent_id]
|
||||
if(!R.overdose_threshold) //Some chems do not have an OD threshold
|
||||
return 0
|
||||
var/current_volume = patient.reagents.get_reagent_amount(reagent_id)
|
||||
@@ -545,4 +545,4 @@
|
||||
declare_cooldown = 0
|
||||
|
||||
/obj/machinery/bot_core/medbot
|
||||
req_one_access =list(access_medical, access_robotics)
|
||||
req_one_access =list(GLOB.access_medical, GLOB.access_robotics)
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
// Navigates via floor navbeacons
|
||||
// Remote Controlled from QM's PDA
|
||||
|
||||
var/global/mulebot_count = 0
|
||||
|
||||
#define SIGH 0
|
||||
#define ANNOYED 1
|
||||
#define DELIGHT 2
|
||||
@@ -58,10 +56,10 @@ var/global/mulebot_count = 0
|
||||
cell.charge = 2000
|
||||
cell.maxcharge = 2000
|
||||
|
||||
spawn(10) // must wait for map loading to finish
|
||||
mulebot_count += 1
|
||||
if(!suffix)
|
||||
set_suffix("#[mulebot_count]")
|
||||
var/static/mulebot_count = 0
|
||||
mulebot_count += 1
|
||||
if(!suffix)
|
||||
set_suffix("#[mulebot_count]")
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/Destroy()
|
||||
unload(0)
|
||||
@@ -165,7 +163,7 @@ var/global/mulebot_count = 0
|
||||
ui_interact(user)
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "mulebot", name, 600, 375, master_ui, state)
|
||||
@@ -231,7 +229,7 @@ var/global/mulebot_count = 0
|
||||
if(mode == BOT_IDLE || mode == BOT_DELIVER)
|
||||
start_home()
|
||||
if("destination")
|
||||
var/new_dest = input(user, "Enter Destination:", name, destination) as null|anything in deliverybeacontags
|
||||
var/new_dest = input(user, "Enter Destination:", name, destination) as null|anything in GLOB.deliverybeacontags
|
||||
if(new_dest)
|
||||
set_destination(new_dest)
|
||||
if("setid")
|
||||
@@ -239,7 +237,7 @@ var/global/mulebot_count = 0
|
||||
if(new_id)
|
||||
set_suffix(new_id)
|
||||
if("sethome")
|
||||
var/new_home = input(user, "Enter Home:", name, home_destination) as null|anything in deliverybeacontags
|
||||
var/new_home = input(user, "Enter Home:", name, home_destination) as null|anything in GLOB.deliverybeacontags
|
||||
if(new_home)
|
||||
home_destination = new_home
|
||||
if("unload")
|
||||
@@ -686,7 +684,7 @@ var/global/mulebot_count = 0
|
||||
if(!on || wires.is_cut(WIRE_BEACON))
|
||||
return
|
||||
|
||||
for(var/obj/machinery/navbeacon/NB in deliverybeacons)
|
||||
for(var/obj/machinery/navbeacon/NB in GLOB.deliverybeacons)
|
||||
if(NB.location == new_destination) // if the beacon location matches the set destination
|
||||
// the we will navigate there
|
||||
destination = new_destination
|
||||
@@ -754,4 +752,4 @@ var/global/mulebot_count = 0
|
||||
#undef DELIGHT
|
||||
|
||||
/obj/machinery/bot_core/mulebot
|
||||
req_access = list(access_cargo)
|
||||
req_access = list(GLOB.access_cargo)
|
||||
|
||||
@@ -27,18 +27,28 @@
|
||||
var/target_lastloc //Loc of target when arrested.
|
||||
var/last_found //There's a delay
|
||||
var/declare_arrests = 1 //When making an arrest, should it notify everyone on the security channel?
|
||||
var/idcheck = 1 //If true, arrest people with no IDs
|
||||
var/weaponscheck = 1 //If true, arrest people for weapons if they lack access
|
||||
var/idcheck = 0 //If true, arrest people with no IDs
|
||||
var/weaponscheck = 0 //If true, arrest people for weapons if they lack access
|
||||
var/check_records = 1 //Does it check security records?
|
||||
var/arrest_type = 0 //If true, don't handcuff
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/beepsky
|
||||
name = "Officer Beep O'sky"
|
||||
desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey."
|
||||
idcheck = 1
|
||||
weaponscheck = 1
|
||||
idcheck = 0
|
||||
weaponscheck = 0
|
||||
auto_patrol = 1
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/beepsky/jr
|
||||
name = "Officer Pipsqueak"
|
||||
desc = "It's Officer Beep O'sky's smaller, just-as aggressive cousin, Pipsqueak."
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/beepsky/jr/Initialize()
|
||||
..()
|
||||
resize = 0.8
|
||||
update_transform()
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/beepsky/explode()
|
||||
var/turf/Tsec = get_turf(src)
|
||||
new /obj/item/weapon/stock_parts/cell/potato(Tsec)
|
||||
@@ -61,7 +71,7 @@
|
||||
prev_access = access_card.access
|
||||
|
||||
//SECHUD
|
||||
var/datum/atom_hud/secsensor = huds[DATA_HUD_SECURITY_ADVANCED]
|
||||
var/datum/atom_hud/secsensor = GLOB.huds[DATA_HUD_SECURITY_ADVANCED]
|
||||
secsensor.add_hud_to(src)
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/turn_on()
|
||||
@@ -410,4 +420,4 @@ Auto Patrol: []"},
|
||||
..()
|
||||
|
||||
/obj/machinery/bot_core/secbot
|
||||
req_access = list(access_security)
|
||||
req_access = list(GLOB.access_security)
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
else
|
||||
to_chat(M, "<span class='cult'>You cannot repair your own dents, as you have none!</span>")
|
||||
else if(src != M)
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/Process_Spacemove(movement_dir = 0)
|
||||
return 1
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
back = /obj/item/weapon/storage/backpack
|
||||
has_id = 1
|
||||
id_job = "Operative"
|
||||
id_access_list = list(access_syndicate)
|
||||
id_access_list = list(GLOB.access_syndicate)
|
||||
|
||||
/obj/effect/mob_spawn/human/corpse/syndicatecommando
|
||||
name = "Syndicate Commando"
|
||||
@@ -34,7 +34,7 @@
|
||||
pocket1 = /obj/item/weapon/tank/internals/emergency_oxygen
|
||||
has_id = 1
|
||||
id_job = "Operative"
|
||||
id_access_list = list(access_syndicate)
|
||||
id_access_list = list(GLOB.access_syndicate)
|
||||
|
||||
/obj/effect/mob_spawn/human/corpse/syndicatestormtrooper
|
||||
name = "Syndicate Stormtrooper"
|
||||
@@ -47,7 +47,7 @@
|
||||
back = /obj/item/weapon/tank/jetpack/oxygen/harness
|
||||
has_id = 1
|
||||
id_job = "Operative"
|
||||
id_access_list = list(access_syndicate)
|
||||
id_access_list = list(GLOB.access_syndicate)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
verb_ask = "flutters inquisitively"
|
||||
verb_exclaim = "flutters intensely"
|
||||
verb_yell = "flutters intensely"
|
||||
devourable = 1
|
||||
|
||||
/mob/living/simple_animal/butterfly/Initialize()
|
||||
..()
|
||||
|
||||
@@ -94,9 +94,9 @@
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/pet/cat/Runtime/Life()
|
||||
if(!cats_deployed && ticker.current_state >= GAME_STATE_SETTING_UP)
|
||||
if(!cats_deployed && SSticker.current_state >= GAME_STATE_SETTING_UP)
|
||||
Deploy_The_Cats()
|
||||
if(!stat && ticker.current_state == GAME_STATE_FINISHED && !memory_saved)
|
||||
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
|
||||
Write_Memory()
|
||||
..()
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
del_on_death = 1
|
||||
|
||||
/mob/living/simple_animal/cockroach/death(gibbed)
|
||||
if(ticker.cinematic) //If the nuke is going off, then cockroaches are invincible. Keeps the nuke from killing them, cause cockroaches are immune to nukes.
|
||||
if(SSticker.cinematic) //If the nuke is going off, then cockroaches are invincible. Keeps the nuke from killing them, cause cockroaches are immune to nukes.
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
var/obj/item/inventory_head
|
||||
var/obj/item/inventory_mask
|
||||
gold_core_spawnable = 2
|
||||
devourable = 1
|
||||
|
||||
/mob/living/simple_animal/crab/Life()
|
||||
..()
|
||||
|
||||
@@ -70,20 +70,25 @@
|
||||
onclose(user, "mob[real_name]")
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/attackby(obj/item/O, mob/user, params)
|
||||
if(inventory_head && inventory_back)
|
||||
//helmet and armor = 100% protection
|
||||
if( istype(inventory_head,/obj/item/clothing/head/helmet) && istype(inventory_back,/obj/item/clothing/suit/armor) )
|
||||
if( O.force )
|
||||
to_chat(user, "<span class='warning'>[src] is wearing too much armor! You can't cause [p_them()] any damage.</span>")
|
||||
visible_message("<span class='danger'>[user] hits [src] with [O], however [src] is too armored.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src] is wearing too much armor! You can't reach [p_their()] skin.<span>")
|
||||
visible_message("[user] gently taps [src] with [O].")
|
||||
if(health>0 && prob(15))
|
||||
emote("me", 1, "looks at [user] with [pick("an amused","an annoyed","a confused","a resentful", "a happy", "an excited")] expression.")
|
||||
return
|
||||
/mob/living/simple_animal/pet/dog/corgi/getarmor(def_zone, type)
|
||||
var/armorval = 0
|
||||
|
||||
if(def_zone)
|
||||
if(def_zone == "head")
|
||||
if(inventory_head)
|
||||
armorval = inventory_head.armor[type]
|
||||
else
|
||||
if(inventory_back)
|
||||
armorval = inventory_back.armor[type]
|
||||
return armorval
|
||||
else
|
||||
if(inventory_head)
|
||||
armorval += inventory_head.armor[type]
|
||||
if(inventory_back)
|
||||
armorval += inventory_back.armor[type]
|
||||
return armorval*0.5
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/attackby(obj/item/O, mob/user, params)
|
||||
if (istype(O, /obj/item/weapon/razor))
|
||||
if (shaved)
|
||||
to_chat(user, "<span class='warning'>You can't shave this corgi, it's already been shaved!</span>")
|
||||
@@ -304,7 +309,7 @@
|
||||
turns_per_move = 20
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
|
||||
if(ticker.current_state == GAME_STATE_FINISHED && !memory_saved)
|
||||
if(SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
|
||||
Write_Memory(0)
|
||||
..()
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
voice_name = "synthesized chirp"
|
||||
speak_emote = list("chirps")
|
||||
bubble_icon = "machine"
|
||||
languages_spoken = DRONE
|
||||
languages_understood = DRONE|HUMAN
|
||||
initial_languages = list(/datum/language/common, /datum/language/machine, /datum/language/drone)
|
||||
only_speaks_language = /datum/language/drone
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
has_unlimited_silicon_privilege = 1
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
|
||||
@@ -51,6 +51,7 @@
|
||||
var/staticChoice = "static"
|
||||
var/list/staticChoices = list("static", "blank", "letter", "animal")
|
||||
var/picked = FALSE //Have we picked our visual appearence (+ colour if applicable)
|
||||
var/colour = "grey" //Stored drone color, so we can go back when unhacked.
|
||||
var/list/drone_overlays[DRONE_TOTAL_LAYERS]
|
||||
var/laws = \
|
||||
"1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone.\n"+\
|
||||
@@ -67,6 +68,15 @@
|
||||
var/visualAppearence = MAINTDRONE //What we appear as
|
||||
var/hacked = 0 //If we have laws to destroy the station
|
||||
var/can_be_held = TRUE //if assholes can pick us up
|
||||
var/flavortext = \
|
||||
"\n<big><span class='warning'>DO NOT INTERFERE WITH THE ROUND AS A DRONE OR YOU WILL BE DRONE BANNED</span></big>\n"+\
|
||||
"<span class='notify'>Drones are a ghost role that are allowed to fix the station and build things. Interfering with the round as a drone is against the rules.</span>\n"+\
|
||||
"<span class='notify'>Actions that constitute interference include, but are not limited to:</span>\n"+\
|
||||
"<span class='notify'> - Interacting with round critical objects (IDs, weapons, contraband, powersinks, bombs, etc.)</span>\n"+\
|
||||
"<span class='notify'> - Interacting with living beings (communication, attacking, healing, etc.)</span>\n"+\
|
||||
"<span class='notify'> - Interacting with non-living beings (dragging bodies, looting bodies, etc.)</span>\n"+\
|
||||
"<span class='warning'>These rules are at admin discretion and will be heavily enforced.</span>\n"+\
|
||||
"<span class='warning'><u>If you do not have the regular drone laws, follow your laws to the best of your ability.</u></span>"
|
||||
|
||||
/mob/living/simple_animal/drone/Initialize()
|
||||
. = ..()
|
||||
@@ -92,7 +102,7 @@
|
||||
else
|
||||
verbs -= /mob/living/simple_animal/drone/verb/toggle_statics
|
||||
|
||||
var/datum/atom_hud/data/diagnostic/diag_hud = huds[DATA_HUD_DIAGNOSTIC]
|
||||
var/datum/atom_hud/data/diagnostic/diag_hud = GLOB.huds[DATA_HUD_DIAGNOSTIC]
|
||||
diag_hud.add_to_hud(src)
|
||||
|
||||
|
||||
@@ -121,6 +131,9 @@
|
||||
..()
|
||||
check_laws()
|
||||
|
||||
if(flavortext)
|
||||
to_chat(src, "[flavortext]")
|
||||
|
||||
updateSeeStaticMobs()
|
||||
|
||||
if(!picked)
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
notify_ghosts("A drone shell has been created in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE)
|
||||
poi_list |= src
|
||||
GLOB.poi_list |= src
|
||||
|
||||
/obj/item/drone_shell/Destroy()
|
||||
poi_list -= src
|
||||
GLOB.poi_list -= src
|
||||
. = ..()
|
||||
|
||||
/obj/item/drone_shell/attack_ghost(mob/user)
|
||||
@@ -36,7 +36,7 @@
|
||||
if(user.client.player_age < DRONE_MINIMUM_AGE)
|
||||
to_chat(user, "<span class='danger'>You're too new to play as a drone! Please try again in [DRONE_MINIMUM_AGE - user.client.player_age] days.</span>")
|
||||
return
|
||||
if(!ticker.mode)
|
||||
if(!SSticker.mode)
|
||||
to_chat(user, "Can't become a drone before the game has started.")
|
||||
return
|
||||
var/be_drone = alert("Become a drone? (Warning, You can no longer be cloned!)",,"Yes","No")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user