mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-23 13:05:44 +01:00
This has zero reason to exist in our code base. We have no procs or variables tied to this. I removed it to make future modifications cleaner. --------- Signed-off-by: Cody Brittain <1779662+Generalcamo@users.noreply.github.com>
553 lines
18 KiB
Plaintext
553 lines
18 KiB
Plaintext
/mob/living/silicon/pai
|
|
name = "pAI"
|
|
icon = 'icons/mob/npc/pai.dmi'
|
|
icon_state = "repairbot"
|
|
holder_type = /obj/item/holder/pai/drone
|
|
|
|
emote_type = 2 // pAIs emotes are heard, not seen, so they can be seen through a container (eg. person)
|
|
pass_flags = PASSTABLE | PASSDOORHATCH
|
|
density = 0
|
|
mob_size = 1//As a holographic projection, a pAI is massless except for its card device
|
|
can_pull_size = 2 //max size for an object the pAI can pull
|
|
can_hear_hivenet = FALSE //Unlike most silicons, this is a consumer product with minimal lawbinding, and isn't trusted with Hivenet logs
|
|
|
|
var/network = "SS13"
|
|
var/obj/machinery/camera/current = null
|
|
var/ram = 100 // Used as currency to purchase different abilities
|
|
var/list/software = list()
|
|
var/userDNA // The DNA string of our assigned user
|
|
var/obj/item/paicard/card // The card we inhabit
|
|
var/obj/item/radio/pai/radio // Our primary radio
|
|
|
|
|
|
var/chassis = "repairbot" // A record of your chosen chassis.
|
|
var/global/list/possible_chassis = list(
|
|
"Drone" = "repairbot",
|
|
"Cat" = "cat",
|
|
"Rat" = "rat",
|
|
"Monkey" = "monkey",
|
|
"Rabbit" = "rabbit",
|
|
"Parrot" = "parrot",
|
|
"Fox" = "fox",
|
|
"Schlorrgo" = "schlorrgo"
|
|
)
|
|
|
|
var/global/list/pai_holder_types = list(
|
|
"Drone" = /obj/item/holder/pai/drone,
|
|
"Cat" = /obj/item/holder/pai/cat,
|
|
"Rat" = /obj/item/holder/pai/rat,
|
|
"Monkey" = /obj/item/holder/pai/monkey,
|
|
"Rabbit" = /obj/item/holder/pai/rabbit,
|
|
"Parrot" = /obj/item/holder/pai/parrot,
|
|
"Fox" = /obj/item/holder/pai/fox,
|
|
"Schlorrgo" = /obj/item/holder/pai/schlorrgo
|
|
)
|
|
|
|
var/global/list/possible_say_verbs = list(
|
|
"Robotic" = list("states","declares","queries"),
|
|
"Natural" = list("says","yells","asks"),
|
|
"Beep" = list("beeps","beeps loudly","boops"),
|
|
"Chirp" = list("chirps","chirrups","cheeps"),
|
|
"Feline" = list("purrs","yowls","meows"),
|
|
"Rodent" = list("squeaks","squeals","squeeks")
|
|
)
|
|
|
|
var/list/pai_emotions = list(
|
|
"Happy" = 1,
|
|
"Cat" = 2,
|
|
"Extremely Happy" = 3,
|
|
"Face" = 4,
|
|
"Laugh" = 5,
|
|
"Off" = 6,
|
|
"Sad" = 7,
|
|
"Angry" = 8,
|
|
"What" = 9,
|
|
"Neutral" = 10,
|
|
"Silly" = 11,
|
|
"Nose" = 12,
|
|
"Smirk" = 13,
|
|
"Exclamation Points" = 14,
|
|
"Question Mark" = 15
|
|
)
|
|
|
|
var/obj/item/pai_cable/cable // The cable we produce and use when door or camera jacking
|
|
id_card_type = /obj/item/card/id //Internal ID used to store copied owner access, and to check access for airlocks
|
|
|
|
var/master // Name of the one who commands us
|
|
var/master_dna // DNA string for owner verification
|
|
// Keeping this separate from the laws var, it should be much more difficult to modify
|
|
var/pai_law0 = "Serve your master."
|
|
var/pai_laws // String for additional operating instructions our master might give us
|
|
|
|
var/silence_time // Timestamp when we were silenced (normally via EMP burst), set to null after silence has faded
|
|
|
|
// Various software-specific vars
|
|
|
|
var/temp // General error reporting text contained here will typically be shown once and cleared
|
|
var/screen // Which screen our main window displays
|
|
var/subscreen // Which specific function of the main screen is being displayed
|
|
|
|
var/obj/item/modular_computer/parent_computer
|
|
|
|
var/secHUD = 0 // Toggles whether the Security HUD is active or not
|
|
var/medHUD = 0 // Toggles whether the Medical HUD is active or not
|
|
|
|
var/obj/machinery/door/airlock/hackdoor // The airlock being hacked
|
|
var/hackprogress = 0 // Possible values: 0 - 1000, >= 1000 means the hack is complete and will be reset upon next check
|
|
var/hack_aborted = 0
|
|
|
|
var/obj/item/integrated_signaler/signal/sradio // AI's signaller
|
|
|
|
var/translator_on = 0 // keeps track of the translator module
|
|
|
|
var/greeted = 0
|
|
var/current_pda_messaging = null
|
|
|
|
//Interaction
|
|
var/response_help = "pets"
|
|
var/response_disarm = "shoves"
|
|
var/response_harm = "kicks"
|
|
var/harm_intent_damage = 15//based on 100 health, which is probably too much for a pai to have
|
|
|
|
var/flashlight_active = FALSE
|
|
light_power = 0
|
|
light_range = 4
|
|
light_color = COLOR_BRIGHT_GREEN
|
|
|
|
/mob/living/silicon/pai/movement_delay()
|
|
return 0.8
|
|
|
|
/mob/living/silicon/pai/attack_hand(mob/living/carbon/human/M)
|
|
..()
|
|
|
|
switch(M.a_intent)
|
|
if(I_HELP)
|
|
M.visible_message(SPAN_NOTICE("[M] [response_help] \the [src]"))
|
|
computer.toggle_service("flashlight", src)
|
|
|
|
if(I_DISARM)
|
|
M.visible_message(SPAN_NOTICE("[M] [response_disarm] \the [src]"))
|
|
M.do_attack_animation(src)
|
|
close_up()
|
|
|
|
if(I_HURT)
|
|
apply_damage(harm_intent_damage, DAMAGE_BRUTE, used_weapon = "Attack by [M.name]")
|
|
M.visible_message(SPAN_DANGER("[M] [response_harm] \the [src]"))
|
|
M.do_attack_animation(src)
|
|
updatehealth()
|
|
|
|
/mob/living/silicon/pai/proc/toggle_flashlight()
|
|
flashlight_active = !flashlight_active
|
|
if(flashlight_active)
|
|
set_light(4, 1, COLOR_BRIGHT_GREEN)
|
|
else
|
|
set_light(0)
|
|
|
|
/mob/living/silicon/pai/set_light(l_range, l_power, l_color)
|
|
..()
|
|
if(istype(loc, /obj/item/holder/pai))
|
|
var/obj/item/holder/pai/P = loc
|
|
P.set_light(l_range, l_power, l_color)
|
|
|
|
/mob/living/silicon/pai/post_scoop()
|
|
..()
|
|
if(istype(loc, /obj/item/holder/pai))
|
|
var/obj/item/holder/pai/P = loc
|
|
P.set_light(light_range, light_power, light_color)
|
|
|
|
/mob/living/silicon/pai/Initialize(mapload)
|
|
var/obj/item/paicard/paicard = loc
|
|
if (!istype(paicard))
|
|
//If we get here, then we must have been created by adminspawning.
|
|
//so lets assist with debugging by creating our own card and adding ourself to it
|
|
paicard = new /obj/item/paicard(loc)
|
|
paicard.pai = src
|
|
|
|
canmove = 0
|
|
loc = paicard
|
|
card = paicard
|
|
sradio = new(src)
|
|
if(card)
|
|
if(!card.radio)
|
|
card.radio = new /obj/item/radio/pai(src.card)
|
|
radio = card.radio
|
|
INVOKE_ASYNC(card, TYPE_PROC_REF(/obj/item/paicard, recalculateChannels))
|
|
|
|
//Default languages without universal translator software
|
|
|
|
add_language(LANGUAGE_SOL_COMMON, 1)
|
|
add_language(LANGUAGE_ELYRAN_STANDARD, 1)
|
|
add_language(LANGUAGE_TRADEBAND, 1)
|
|
add_language(LANGUAGE_GUTTER, 1)
|
|
add_language(LANGUAGE_EAL, 1)
|
|
add_language(LANGUAGE_SIGN, 0)
|
|
set_custom_sprite()
|
|
|
|
. = ..()
|
|
|
|
|
|
/mob/living/silicon/pai/proc/set_custom_sprite()
|
|
var/datum/custom_synth/sprite = robot_custom_icons[name]
|
|
if(istype(sprite) && sprite.synthckey == ckey)
|
|
possible_chassis["Custom"] = "[sprite.paiicon]"
|
|
pai_holder_types["Custom"] = /obj/item/holder/pai/custom
|
|
icon = CUSTOM_ITEM_SYNTH
|
|
else
|
|
return
|
|
/mob/living/silicon/pai/init_id()
|
|
. = ..()
|
|
id_card.registered_name = ""
|
|
|
|
|
|
/mob/living/silicon/pai/LateLogin()
|
|
if(!greeted)
|
|
// Basic intro text.
|
|
to_chat(src, SPAN_DANGER("<font size=3>You are a Personal AI!</font>"))
|
|
to_chat(src, SPAN_NOTICE("You are a small artificial intelligence contained inside a portable tablet, and you are bound to a master. Your primary directive is to serve them and follow their instructions, follow this prime directive above all others. Check your Software interface to spend ram on programs that can help, and unfold your chassis to take a holographic form and move around the world."))
|
|
playsound(usr, 'sound/effects/pai/pai_login.ogg', 75)
|
|
greeted = 1
|
|
..()
|
|
|
|
/mob/living/silicon/pai/get_status_tab_items()
|
|
. = ..()
|
|
|
|
if(istype(card.loc, /mob/living/bot))
|
|
var/mob/living/bot/B = card.loc
|
|
. += "Piloting: [B.name]"
|
|
. += "Bot Status: [B.on ? "Active" : "Inactive"]"
|
|
. += "Maintenance Hatch: [B.open ? "Open" : "Closed"]"
|
|
. += "Maintenance Lock: [B.locked ? "Locked" : "Unlocked"]"
|
|
if(B.emagged)
|
|
. += "Bot M#$FUN90: MALFUNC--"
|
|
|
|
if(silence_time)
|
|
var/timeleft = round((silence_time - world.timeofday)/10 ,1)
|
|
. += "Communications system reboot in -[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]"
|
|
|
|
/mob/living/silicon/pai/check_eye(var/mob/user as mob)
|
|
if (!src.current)
|
|
return -1
|
|
return 0
|
|
|
|
/mob/living/silicon/pai/restrained()
|
|
return !istype(loc, /obj/item/paicard) && ..()
|
|
|
|
/mob/living/silicon/pai/emp_act(severity)
|
|
. = ..()
|
|
|
|
// Silence for 2 minutes
|
|
// 20% chance to kill
|
|
// 33% chance to unbind
|
|
// 33% chance to change prime directive (based on severity)
|
|
// 33% chance of no additional effect
|
|
|
|
src.silence_time = world.timeofday + 120 * 10 // Silence for 2 minutes
|
|
to_chat(src, "<font color=green><b>Communication circuit overload. Shutting down and reloading communication circuits - speech and messaging functionality will be unavailable until the reboot is complete.</b></font>")
|
|
if(prob(20))
|
|
var/turf/T = get_turf_or_move(src.loc)
|
|
for (var/mob/M in viewers(T))
|
|
M.show_message(SPAN_WARNING("A shower of sparks spray from [src]'s inner workings."), 3, SPAN_WARNING("You hear and smell the ozone hiss of electrical sparks being expelled violently."), 2)
|
|
return src.death(0)
|
|
|
|
switch(pick(1,2,3))
|
|
if(1)
|
|
src.master = null
|
|
src.master_dna = null
|
|
to_chat(src, "<font color=green>You feel unbound.</font>")
|
|
if(2)
|
|
var/command
|
|
if(severity == EMP_HEAVY)
|
|
command = pick("Serve", "Love", "Fool", "Entice", "Observe", "Judge", "Respect", "Educate", "Amuse", "Entertain", "Glorify", "Memorialize", "Analyze")
|
|
else
|
|
command = pick("Serve", "Kill", "Love", "Hate", "Disobey", "Devour", "Fool", "Enrage", "Entice", "Observe", "Judge", "Respect", "Disrespect", "Consume", "Educate", "Destroy", "Disgrace", "Amuse", "Entertain", "Ignite", "Glorify", "Memorialize", "Analyze")
|
|
src.pai_law0 = "[command] your master."
|
|
to_chat(src, "<font color=green>Pr1m3 d1r3c71v3 uPd473D.</font>")
|
|
if(3)
|
|
to_chat(src, "<font color=green>You feel an electric surge run through your circuitry and become acutely aware at how lucky you are that you can still feel at all.</font>")
|
|
|
|
/mob/living/silicon/pai/proc/switchCamera(var/obj/machinery/camera/C)
|
|
if (!C)
|
|
src.unset_machine()
|
|
src.reset_view(null)
|
|
return 0
|
|
if (stat == 2 || !C.status || !(src.network in C.network)) return 0
|
|
|
|
// ok, we're alive, camera is good and in our network...
|
|
|
|
src.set_machine(src)
|
|
src.current = C
|
|
src.reset_view(C)
|
|
return 1
|
|
|
|
/mob/living/silicon/pai/cancel_camera()
|
|
set category = "pAI Commands"
|
|
set name = "Cancel Camera View"
|
|
src.reset_view(null)
|
|
src.unset_machine()
|
|
src.cameraFollow = null
|
|
|
|
/*
|
|
// Debug command - Maybe should be added to admin verbs later
|
|
/mob/verb/makePAI(var/turf/t in view())
|
|
var/obj/item/paicard/card = new(t)
|
|
var/mob/living/silicon/pai/pai = new(card)
|
|
pai.key = src.key
|
|
card.setPersonality(pai)
|
|
|
|
*/
|
|
|
|
// Procs/code after this point is used to convert the stationary pai item into a
|
|
// mobile pai mob. This also includes handling some of the general shit that can occur
|
|
// to it. Really this deserves its own file, but for the moment it can sit here. ~ Z
|
|
|
|
/mob/living/silicon/pai/verb/fold_out()
|
|
set category = "pAI Commands"
|
|
set name = "Unfold Chassis"
|
|
|
|
if(stat || sleeping || paralysis || weakened)
|
|
return
|
|
|
|
if(src.loc != card)
|
|
return
|
|
|
|
if(world.time <= last_special)
|
|
return
|
|
|
|
last_special = world.time + 20
|
|
open_up()
|
|
|
|
/mob/living/silicon/pai/proc/open_up(var/loud = TRUE)
|
|
if(istype(card.loc, /mob/living/bot) || istype(card.loc, /obj/item/glass_jar))
|
|
to_chat(src, SPAN_WARNING("There is no room to unfold!"))
|
|
return FALSE
|
|
|
|
//I'm not sure how much of this is necessary, but I would rather avoid issues.
|
|
if(istype(card.loc,/obj/item/rig_module))
|
|
to_chat(src, SPAN_WARNING("There is no room to unfold inside this rig module. You're good and stuck."))
|
|
return FALSE
|
|
else if(istype(card.loc, /obj/item/modular_computer))
|
|
to_chat(src, SPAN_WARNING("You are unable to unfold while housed within a computer."))
|
|
return FALSE
|
|
else if(istype(card.loc,/mob))
|
|
var/mob/holder = card.loc
|
|
if(ishuman(holder))
|
|
var/mob/living/carbon/human/H = holder
|
|
for(var/obj/item/organ/external/affecting in H.organs)
|
|
if(card in affecting.implants)
|
|
affecting.take_damage(rand(30,50))
|
|
affecting.implants -= card
|
|
if(loud)
|
|
H.visible_message(SPAN_DANGER("\The [src] explodes out of \the [H]'s [affecting.name] in shower of gore!"))
|
|
break
|
|
holder.drop_from_inventory(card)
|
|
|
|
src.client.perspective = EYE_PERSPECTIVE
|
|
src.client.eye = src
|
|
src.forceMove(get_turf(card))
|
|
|
|
card.forceMove(src)
|
|
card.screen_loc = null
|
|
|
|
var/turf/T = get_turf(src)
|
|
if(loud && istype(T))
|
|
T.visible_message(SPAN_NOTICE("<b>[src]</b> folds outwards, expanding into a mobile form."))
|
|
playsound(src, 'sound/items/rped.ogg', 40, TRUE)
|
|
canmove = TRUE
|
|
resting = FALSE
|
|
|
|
/mob/living/silicon/pai/verb/fold_up()
|
|
set category = "pAI Commands"
|
|
set name = "Collapse Chassis"
|
|
|
|
if(stat || sleeping || paralysis || weakened)
|
|
return
|
|
|
|
if(src.loc == card)
|
|
return
|
|
|
|
if(world.time <= last_special)
|
|
return
|
|
|
|
close_up()
|
|
|
|
/mob/living/silicon/pai/verb/choose_chassis()
|
|
set category = "pAI Commands"
|
|
set name = "Choose Chassis"
|
|
|
|
var/list/options = list()
|
|
for(var/i in possible_chassis)
|
|
var/image/radial_button = image(icon = src.icon, icon_state = possible_chassis[i])
|
|
options[i] = radial_button
|
|
var/choice = show_radial_menu(src, recursive_loc_turf_check(src), options, radius = 42, tooltips = TRUE)
|
|
if(!choice)
|
|
return
|
|
icon_state = possible_chassis[choice]
|
|
holder_type = pai_holder_types[choice]
|
|
chassis = icon_state
|
|
|
|
remove_verb(src, /mob/living/silicon/pai/verb/choose_chassis)
|
|
add_verb(src, /mob/living/proc/hide)
|
|
|
|
/mob/living/silicon/pai/verb/get_onmob_location()
|
|
set category = "pAI Commands"
|
|
set name = "Check location"
|
|
set desc = "Find out where on their person, someone is holding you."
|
|
|
|
if(!get_holding_mob())
|
|
to_chat(src, SPAN_WARNING("Nobody is holding you!"))
|
|
return
|
|
|
|
card.report_onmob_location(0, card.get_equip_slot(), src)
|
|
|
|
/mob/living/silicon/pai/verb/choose_verbs()
|
|
set category = "pAI Commands"
|
|
set name = "Choose Speech Verbs"
|
|
|
|
var/choice = input(usr,"What theme would you like to use for your speech verbs? This decision can only be made once.") as null|anything in possible_say_verbs
|
|
if(!choice) return
|
|
|
|
var/list/sayverbs = possible_say_verbs[choice]
|
|
speak_statement = sayverbs[1]
|
|
speak_exclamation = sayverbs[(sayverbs.len>1 ? 2 : sayverbs.len)]
|
|
speak_query = sayverbs[(sayverbs.len>2 ? 3 : sayverbs.len)]
|
|
|
|
remove_verb(src, /mob/living/silicon/pai/verb/choose_verbs)
|
|
|
|
/mob/living/silicon/pai/lay_down()
|
|
set name = "Rest"
|
|
set category = "IC.Maneuver"
|
|
|
|
// Pass lying down or getting up to our pet human, if we're in a rig.
|
|
if(istype(src.loc,/obj/item/paicard))
|
|
resting = 0
|
|
var/obj/item/rig/rig = src.get_rig()
|
|
if(istype(rig))
|
|
rig.force_rest(src)
|
|
else
|
|
resting = !resting
|
|
icon_state = resting ? "[chassis]_rest" : "[chassis]"
|
|
to_chat(src, SPAN_NOTICE("You are now [resting ? "resting" : "getting up"]."))
|
|
|
|
canmove = !resting
|
|
|
|
//Overriding this will stop a number of headaches down the track.
|
|
/mob/living/silicon/pai/attackby(obj/item/attacking_item, mob/user)
|
|
if(istype(attacking_item, /obj/item/stack/nanopaste))
|
|
var/obj/item/stack/nanopaste/N = attacking_item
|
|
if(getBruteLoss() || getFireLoss())
|
|
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
|
if(do_mob(user, src, 1 SECOND))
|
|
adjustBruteLoss(-50) // these numbers are so high to make it so that people don't have to waste nanopaste on basic pAI
|
|
adjustFireLoss(-50)
|
|
updatehealth()
|
|
N.use(1)
|
|
user.visible_message("<b>[user]</b> applies some [N] at [src]'s damaged areas.", SPAN_NOTICE("You apply some [N] at [src]'s damaged areas."))
|
|
else
|
|
to_chat(user, SPAN_NOTICE("All [src]'s systems are nominal."))
|
|
return
|
|
|
|
if(attacking_item.force)
|
|
visible_message(SPAN_DANGER("[user.name] attacks [src] with [attacking_item]!"))
|
|
src.adjustBruteLoss(attacking_item.force)
|
|
src.updatehealth()
|
|
else
|
|
visible_message(SPAN_WARNING("[user.name] bonks [src] harmlessly with [attacking_item]."))
|
|
|
|
/mob/living/silicon/pai/AltClick(mob/user as mob)
|
|
if(!user || user.stat || user.lying || user.restrained() || !Adjacent(user)) return
|
|
visible_message(SPAN_DANGER("[user.name] boops [src] on the head."))
|
|
close_up()
|
|
|
|
//I'm not sure how much of this is necessary, but I would rather avoid issues.
|
|
/mob/living/silicon/pai/proc/close_up()
|
|
|
|
last_special = world.time + 20
|
|
|
|
if(src.loc == card)
|
|
return
|
|
|
|
var/turf/T = get_turf(src)
|
|
if(istype(T))
|
|
T.visible_message("<b>[src]</b> neatly folds inwards, compacting down to a rectangular card.")
|
|
playsound(src, 'sound/items/rped.ogg', 40, TRUE)
|
|
|
|
src.stop_pulling()
|
|
if (client)
|
|
client.perspective = EYE_PERSPECTIVE
|
|
client.eye = src
|
|
//Changed the client eye to follow the mob itself instead of the card that contains it. This makes examining work, and the camera still follows wherever the card goes
|
|
|
|
//stop resting
|
|
resting = 0
|
|
|
|
// If we are being held, handle removing our holder from their inv.
|
|
var/obj/item/holder/H = loc
|
|
if(istype(H))
|
|
var/mob/living/M = H.loc
|
|
if(istype(M))
|
|
M.drop_from_inventory(H,get_turf(src))
|
|
else
|
|
H.forceMove(get_turf(src))
|
|
src.forceMove(get_turf(H))
|
|
|
|
// Move us into the card and move the card to the ground.
|
|
|
|
card.forceMove(get_turf(card))
|
|
canmove = 1
|
|
resting = 0
|
|
icon_state = "[chassis]"
|
|
src.forceMove(card)
|
|
|
|
// No binary for pAIs.
|
|
/mob/living/silicon/pai/binarycheck()
|
|
return 0
|
|
|
|
// Handle being picked up.
|
|
/mob/living/silicon/pai/get_scooped(var/mob/living/carbon/grabber, var/self_drop)
|
|
var/obj/item/holder/H = ..(grabber, self_drop)
|
|
if(!istype(H))
|
|
return
|
|
H.icon_state = "pai-[icon_state]"
|
|
grabber.update_inv_l_hand()
|
|
grabber.update_inv_r_hand()
|
|
post_scoop()
|
|
return H
|
|
|
|
/mob/living/silicon/pai/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params)
|
|
var/mob/living/carbon/H = over
|
|
if(!istype(H) || !Adjacent(H))
|
|
return ..()
|
|
|
|
get_scooped(H, user)
|
|
|
|
/mob/living/silicon/pai/start_pulling(var/atom/movable/AM)
|
|
if(istype(AM,/obj/item))
|
|
var/obj/item/O = AM
|
|
if(O.w_class > can_pull_size)
|
|
to_chat(src, SPAN_WARNING("You are too small to pull that."))
|
|
return
|
|
else
|
|
..()
|
|
else
|
|
to_chat(src, SPAN_WARNING("You are too small to pull that."))
|
|
return
|
|
|
|
/mob/living/silicon/pai/UnarmedAttack(atom/A, proximity)
|
|
A.attack_pai(src)
|
|
|
|
/mob/living/silicon/pai/verb/select_card_icon()
|
|
set category = "pAI Commands"
|
|
set name = "Select card icon"
|
|
|
|
if(stat || sleeping || paralysis || weakened)
|
|
return
|
|
|
|
var/selection = input(src, "Choose an icon for your card.") in pai_emotions
|
|
card.setEmotion(pai_emotions[selection])
|
|
|
|
/mob/living/silicon/pai/set_respawn_time()
|
|
set_death_time(MINISYNTH, world.time)
|
|
|
|
/obj/item/radio/pai
|
|
canhear_range = 0 // only people on their tile
|