mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-24 13:38:41 +01:00
[MIRROR] General pAI code improvements [MDB IGNORE] (#10683)
* General pAI code improvements * Feex Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>
This commit is contained in:
co-authored by
John Willard
GoldenAlpharex
parent
d7f0071902
commit
32bc9a96b6
@@ -39,6 +39,7 @@
|
||||
//Silicon
|
||||
#define JOB_AI "AI"
|
||||
#define JOB_CYBORG "Cyborg"
|
||||
#define JOB_PERSONAL_AI "Personal AI"
|
||||
//Security
|
||||
#define JOB_WARDEN "Warden"
|
||||
#define JOB_DETECTIVE "Detective"
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
/// Total percent required to hack a door.
|
||||
#define HACK_COMPLETE 100
|
||||
@@ -44,7 +44,7 @@ GLOBAL_LIST_INIT(poll_ignore_desc, list(
|
||||
POLL_IGNORE_CONTRACTOR_SUPPORT = "Contractor Support Unit",
|
||||
POLL_IGNORE_ACADEMY_WIZARD = "Academy Wizard Defender",
|
||||
POLL_IGNORE_CORTICAL_BORER = "Cortical Borer",
|
||||
POLL_IGNORE_PAI = "Personal AI"
|
||||
POLL_IGNORE_PAI = JOB_PERSONAL_AI,
|
||||
))
|
||||
//Skyrat Edit Stop: Cortical Borer
|
||||
GLOBAL_LIST_INIT(poll_ignore, init_poll_ignore())
|
||||
|
||||
@@ -144,8 +144,8 @@
|
||||
|
||||
return SECONDARY_ATTACK_CALL_NORMAL
|
||||
|
||||
/obj/attackby(obj/item/I, mob/living/user, params)
|
||||
return ..() || ((obj_flags & CAN_BE_HIT) && I.attack_atom(src, user, params))
|
||||
/obj/attackby(obj/item/attacking_item, mob/user, params)
|
||||
return ..() || ((obj_flags & CAN_BE_HIT) && attacking_item.attack_atom(src, user, params))
|
||||
|
||||
/mob/living/attackby(obj/item/attacking_item, mob/living/user, params)
|
||||
if(..())
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
custom_premium_price = PAYCHECK_HARD * 1.25
|
||||
///don't spam alert messages.
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF | INDESTRUCTIBLE
|
||||
|
||||
/// Spam alert prevention
|
||||
var/alert_cooldown
|
||||
/// If the pAIcard is slotted in a PDA
|
||||
var/slotted = FALSE
|
||||
@@ -17,7 +19,6 @@
|
||||
var/mob/living/silicon/pai/pai
|
||||
///what emotion icon we have. handled in /mob/living/silicon/pai/Topic()
|
||||
var/emotion_icon = "off"
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF | INDESTRUCTIBLE
|
||||
|
||||
/obj/item/paicard/suicide_act(mob/living/user)
|
||||
user.visible_message(span_suicide("[user] is staring sadly at [src]! [user.p_they()] can't keep living without real human intimacy!"))
|
||||
@@ -102,16 +103,16 @@
|
||||
break
|
||||
if(isnull(candidate))
|
||||
return FALSE
|
||||
if(src.pai)
|
||||
if(pai)
|
||||
return FALSE
|
||||
if(SSpai.check_ready(candidate) != candidate)
|
||||
return FALSE
|
||||
/// The newly downloaded pAI personality
|
||||
var/mob/living/silicon/pai/pai = new(src)
|
||||
pai.name = candidate.name || pick(GLOB.ninja_names)
|
||||
pai.real_name = pai.name
|
||||
pai.key = candidate.key
|
||||
src.setPersonality(pai)
|
||||
var/mob/living/silicon/pai/new_pai = new(src)
|
||||
new_pai.name = candidate.name || pick(GLOB.ninja_names)
|
||||
new_pai.real_name = new_pai.name
|
||||
new_pai.key = candidate.key
|
||||
setPersonality(new_pai)
|
||||
SSpai.candidates -= candidate
|
||||
if("fix_speech")
|
||||
to_chat(pai, span_notice("Your owner has corrected your speech modulation!"))
|
||||
@@ -159,13 +160,15 @@
|
||||
to_chat(pai, span_notice("Your owner has [transmit_holder ? "enabled" : "disabled"] your [transmitting ? "outgoing" : "incoming"] radio transmissions!"))
|
||||
if("wipe_pai")
|
||||
var/confirm = tgui_alert(usr, "Are you certain you wish to delete the current personality? This action cannot be undone.", "Personality Wipe", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
if(pai)
|
||||
to_chat(pai, span_warning("You feel yourself slipping away from reality."))
|
||||
to_chat(pai, span_danger("Byte by byte you lose your sense of self."))
|
||||
to_chat(pai, span_userdanger("Your mental faculties leave you."))
|
||||
to_chat(pai, span_rose("oblivion... "))
|
||||
qdel(pai)
|
||||
if(confirm != "Yes")
|
||||
return
|
||||
if(!pai)
|
||||
return
|
||||
to_chat(pai, span_warning("You feel yourself slipping away from reality."))
|
||||
to_chat(pai, span_danger("Byte by byte you lose your sense of self."))
|
||||
to_chat(pai, span_userdanger("Your mental faculties leave you."))
|
||||
to_chat(pai, span_rose("oblivion... "))
|
||||
qdel(pai)
|
||||
return
|
||||
|
||||
// WIRE_SIGNAL = 1
|
||||
|
||||
@@ -439,16 +439,13 @@
|
||||
else
|
||||
. += span_notice("It cannot be modified or attached.")
|
||||
|
||||
/obj/item/radio/attackby(obj/item/W, mob/user, params)
|
||||
/obj/item/radio/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
add_fingerprint(user)
|
||||
if(W.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
unscrewed = !unscrewed
|
||||
if(unscrewed)
|
||||
to_chat(user, span_notice("The radio can now be attached and modified!"))
|
||||
else
|
||||
to_chat(user, span_notice("The radio can no longer be modified or attached!"))
|
||||
unscrewed = !unscrewed
|
||||
if(unscrewed)
|
||||
to_chat(user, span_notice("The radio can now be attached and modified!"))
|
||||
else
|
||||
return ..()
|
||||
to_chat(user, span_notice("The radio can no longer be modified or attached!"))
|
||||
|
||||
/obj/item/radio/emp_act(severity)
|
||||
. = ..()
|
||||
@@ -508,36 +505,36 @@
|
||||
. = ..()
|
||||
set_frequency(FREQ_SYNDICATE)
|
||||
|
||||
/obj/item/radio/borg/attackby(obj/item/W, mob/user, params)
|
||||
/obj/item/radio/borg/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
if(!keyslot)
|
||||
to_chat(user, span_warning("This radio doesn't have any encryption keys!"))
|
||||
return
|
||||
|
||||
if(W.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
if(keyslot)
|
||||
for(var/ch_name in channels)
|
||||
SSradio.remove_object(src, GLOB.radiochannels[ch_name])
|
||||
secure_radio_connections[ch_name] = null
|
||||
for(var/ch_name in channels)
|
||||
SSradio.remove_object(src, GLOB.radiochannels[ch_name])
|
||||
secure_radio_connections[ch_name] = null
|
||||
|
||||
if(keyslot)
|
||||
var/turf/user_turf = get_turf(user)
|
||||
if(user_turf)
|
||||
keyslot.forceMove(user_turf)
|
||||
keyslot = null
|
||||
|
||||
if(keyslot)
|
||||
var/turf/T = get_turf(user)
|
||||
if(T)
|
||||
keyslot.forceMove(T)
|
||||
keyslot = null
|
||||
recalculateChannels()
|
||||
to_chat(user, span_notice("You pop out the encryption key in the radio."))
|
||||
return ..()
|
||||
|
||||
recalculateChannels()
|
||||
to_chat(user, span_notice("You pop out the encryption key in the radio."))
|
||||
/obj/item/radio/borg/attackby(obj/item/attacking_item, mob/user, params)
|
||||
|
||||
else
|
||||
to_chat(user, span_warning("This radio doesn't have any encryption keys!"))
|
||||
|
||||
else if(istype(W, /obj/item/encryptionkey/))
|
||||
if(istype(attacking_item, /obj/item/encryptionkey))
|
||||
if(keyslot)
|
||||
to_chat(user, span_warning("The radio can't hold another key!"))
|
||||
return
|
||||
|
||||
if(!keyslot)
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
if(!user.transferItemToLoc(attacking_item, src))
|
||||
return
|
||||
keyslot = W
|
||||
keyslot = attacking_item
|
||||
|
||||
recalculateChannels()
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
item_flags = NOBLUDGEON
|
||||
var/obj/machinery/machine //what machine we're currently hacking.
|
||||
|
||||
/obj/item/pai_cable/machine/Destroy()
|
||||
/obj/item/pai_cable/Destroy()
|
||||
machine = null
|
||||
return ..()
|
||||
|
||||
|
||||
+1
-1
@@ -225,7 +225,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/virtualspeaker)
|
||||
var/mob/living/silicon/robot/B = M
|
||||
job = "[B.designation] Cyborg"
|
||||
else if(istype(M, /mob/living/silicon/pai)) // Personal AI (pAI)
|
||||
job = "Personal AI"
|
||||
job = JOB_PERSONAL_AI
|
||||
else if(isobj(M)) // Cold, emotionless machines
|
||||
job = "Machine"
|
||||
else // Unidentifiable mob
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/mob/living/silicon/pai/Login()
|
||||
. = ..()
|
||||
if(!. || !client)
|
||||
return FALSE
|
||||
|
||||
client.perspective = EYE_PERSPECTIVE
|
||||
if(holoform)
|
||||
client.eye = src
|
||||
else
|
||||
client.eye = card
|
||||
@@ -1,6 +1,9 @@
|
||||
/mob/living/silicon/pai
|
||||
name = "pAI"
|
||||
icon = 'icons/mob/pai.dmi'
|
||||
held_lh = 'icons/mob/pai_item_lh.dmi'
|
||||
held_rh = 'icons/mob/pai_item_rh.dmi'
|
||||
head_icon = 'icons/mob/pai_item_head.dmi'
|
||||
icon_state = "repairbot"
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
density = FALSE
|
||||
@@ -16,74 +19,78 @@
|
||||
pull_force = 0
|
||||
move_resist = 0
|
||||
worn_slot_flags = ITEM_SLOT_HEAD
|
||||
held_lh = 'icons/mob/pai_item_lh.dmi'
|
||||
held_rh = 'icons/mob/pai_item_rh.dmi'
|
||||
head_icon = 'icons/mob/pai_item_head.dmi'
|
||||
radio = /obj/item/radio/headset/silicon/pai
|
||||
can_buckle_to = FALSE
|
||||
mobility_flags = MOBILITY_FLAGS_REST_CAPABLE_DEFAULT
|
||||
var/network = "ss13"
|
||||
var/obj/machinery/camera/current = null
|
||||
|
||||
/// The card we inhabit
|
||||
var/obj/item/paicard/card
|
||||
|
||||
/// Used as currency to purchase different abilities
|
||||
var/ram = 100
|
||||
/// Installed software on the pAI
|
||||
var/list/software = list()
|
||||
/// current user's DNA
|
||||
var/userDNA
|
||||
/// The card we inhabit
|
||||
var/obj/item/paicard/card
|
||||
/// Are we hacking a door?
|
||||
var/hacking = FALSE
|
||||
/// The progress for hacking
|
||||
var/datum/progressbar/hackbar
|
||||
/// The strength of the internal flashlight
|
||||
var/brightness_power = 5
|
||||
/// Changes the display to syndi if true
|
||||
var/emagged = FALSE
|
||||
|
||||
var/speakStatement = "states"
|
||||
var/speakExclamation = "declares"
|
||||
var/speakDoubleExclamation = "alarms"
|
||||
var/speakQuery = "queries"
|
||||
/// The cable we produce when hacking a door
|
||||
var/obj/item/pai_cable/hacking_cable
|
||||
/// Name of the one who commands us
|
||||
var/master
|
||||
/// DNA string for owner verification
|
||||
var/master_dna
|
||||
/// Whether we are currently holoformed
|
||||
var/holoform = FALSE
|
||||
/// Whether the pAI can enter holoform or not
|
||||
var/canholo = TRUE
|
||||
/// Whether this pAI can transmit radio messages
|
||||
var/can_transmit = TRUE
|
||||
/// Whether this pAI can recieve radio messages
|
||||
var/can_receive = TRUE
|
||||
|
||||
// Various software-specific vars
|
||||
|
||||
// Various software-specific vars
|
||||
|
||||
/// Toggles whether the Security HUD is active or not
|
||||
var/secHUD = FALSE
|
||||
/// Toggles whether the Medical HUD is active or not
|
||||
var/medHUD = FALSE
|
||||
/// Toggles whether the pAI can hold encryption keys or not
|
||||
var/encryptmod = FALSE
|
||||
/// Toggles whether universal translator has been activated. Cannot be reversed
|
||||
var/languages_granted = FALSE
|
||||
/// The airlock being hacked
|
||||
var/obj/machinery/door/hackdoor
|
||||
/// Possible values: 0 - 100, >= 100 means the hack is complete and will be reset upon next check
|
||||
var/hackprogress = 0
|
||||
|
||||
// Software
|
||||
/// Atmospheric analyzer
|
||||
var/obj/item/analyzer/atmos_analyzer
|
||||
/// AI's signaler
|
||||
var/obj/item/assembly/signaler/internal/signaler
|
||||
/// Synthesizer
|
||||
/// pAI Synthesizer
|
||||
var/obj/item/instrument/piano_synth/internal_instrument
|
||||
/// pAI Newscaster
|
||||
var/obj/machinery/newscaster
|
||||
/// pAI healthanalyzer
|
||||
var/obj/item/healthanalyzer/hostscan
|
||||
/// Internal pAI GPS, enabled if pAI downloads GPS software, and then uses it.
|
||||
var/obj/item/gps/pai/internal_gps = null
|
||||
var/obj/item/gps/pai/internal_gps
|
||||
/// The cable we produce when hacking a door
|
||||
var/obj/item/pai_cable/hacking_cable
|
||||
|
||||
var/encryptmod = FALSE
|
||||
var/holoform = FALSE
|
||||
var/canholo = TRUE
|
||||
var/can_transmit = TRUE
|
||||
var/can_receive = TRUE
|
||||
/// The current chasis that will appear when in holoform
|
||||
var/chassis = "repairbot"
|
||||
var/list/possible_chassis = list("cat" = TRUE, "mouse" = TRUE, "monkey" = TRUE, "corgi" = FALSE, "fox" = FALSE, "repairbot" = TRUE, "rabbit" = TRUE, "bat" = FALSE, "butterfly" = FALSE, "hawk" = FALSE, "lizard" = FALSE, "duffel" = TRUE) //assoc value is whether it can be picked up.
|
||||
/// List of all possible chasises. TRUE means the pAI can be picked up in this chasis.
|
||||
var/list/possible_chassis = list(
|
||||
"cat" = TRUE,
|
||||
"mouse" = TRUE,
|
||||
"monkey" = TRUE,
|
||||
"corgi" = FALSE,
|
||||
"fox" = FALSE,
|
||||
"repairbot" = TRUE,
|
||||
"rabbit" = TRUE,
|
||||
"bat" = FALSE,
|
||||
"butterfly" = FALSE,
|
||||
"hawk" = FALSE,
|
||||
"lizard" = FALSE,
|
||||
"duffel" = TRUE,
|
||||
)
|
||||
|
||||
var/emitterhealth = 20
|
||||
var/emittermaxhealth = 20
|
||||
@@ -92,62 +99,68 @@
|
||||
var/emitteroverloadcd = 100
|
||||
var/emittersemicd = FALSE
|
||||
|
||||
var/overload_ventcrawl = 0
|
||||
var/overload_bulletblock = 0 //Why is this a good idea?
|
||||
var/overload_maxhealth = 0
|
||||
var/silent = FALSE
|
||||
var/brightness_power = 5
|
||||
/// Bool that determines if the pAI can refresh medical/security records.
|
||||
var/refresh_spam = FALSE
|
||||
/// Cached list for medical records to send as static data
|
||||
var/list/medical_records = list()
|
||||
/// Cached list for security records to send as static data
|
||||
var/list/security_records = list()
|
||||
|
||||
var/list/available_software = list(
|
||||
"crew manifest" = 5,
|
||||
"digital messenger" = 5,
|
||||
"atmosphere sensor" = 5,
|
||||
"photography module" = 5,
|
||||
"camera zoom" = 10,
|
||||
"printer module" = 10,
|
||||
"remote signaler" = 10,
|
||||
"medical records" = 10,
|
||||
"security records" = 10,
|
||||
"host scan" = 10,
|
||||
"medical HUD" = 20,
|
||||
"security HUD" = 20,
|
||||
"loudness booster" = 20,
|
||||
"newscaster" = 20,
|
||||
"door jack" = 25,
|
||||
"encryption keys" = 25,
|
||||
"internal gps" = 35,
|
||||
"universal translator" = 35,
|
||||
)
|
||||
|
||||
/mob/living/silicon/pai/add_sensors() //pAIs have to buy their HUDs
|
||||
return
|
||||
|
||||
/mob/living/silicon/pai/handle_atom_del(atom/A)
|
||||
if(A == hacking_cable)
|
||||
/mob/living/silicon/pai/handle_atom_del(atom/deleting_atom)
|
||||
if(deleting_atom == hacking_cable)
|
||||
hacking_cable = null
|
||||
if(!QDELETED(card))
|
||||
card.update_appearance()
|
||||
if(A == atmos_analyzer)
|
||||
if(deleting_atom == atmos_analyzer)
|
||||
atmos_analyzer = null
|
||||
if(A == internal_instrument)
|
||||
if(deleting_atom == internal_instrument)
|
||||
internal_instrument = null
|
||||
if(A == newscaster)
|
||||
if(deleting_atom == newscaster)
|
||||
newscaster = null
|
||||
if(A == signaler)
|
||||
if(deleting_atom == signaler)
|
||||
signaler = null
|
||||
if(A == hostscan)
|
||||
if(deleting_atom == hostscan)
|
||||
hostscan = null
|
||||
if(A == internal_gps)
|
||||
if(deleting_atom == internal_gps)
|
||||
internal_gps = null
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/pai/Destroy()
|
||||
QDEL_NULL(atmos_analyzer)
|
||||
QDEL_NULL(internal_instrument)
|
||||
QDEL_NULL(hacking_cable)
|
||||
QDEL_NULL(newscaster)
|
||||
QDEL_NULL(signaler)
|
||||
QDEL_NULL(hostscan)
|
||||
QDEL_NULL(internal_gps)
|
||||
if(!QDELETED(card) && loc != card)
|
||||
card.forceMove(drop_location())
|
||||
card.pai = null //these are otherwise handled by paicard/handle_atom_del()
|
||||
card.emotion_icon = initial(card.emotion_icon)
|
||||
card.update_appearance()
|
||||
GLOB.pai_list -= src
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/pai/Initialize(mapload)
|
||||
var/obj/item/paicard/P = loc
|
||||
var/obj/item/paicard/pai_card = loc
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
GLOB.pai_list += src
|
||||
make_laws()
|
||||
if(!istype(P)) //when manually spawning a pai, we create a card to put it into.
|
||||
var/newcardloc = P
|
||||
P = new /obj/item/paicard(newcardloc)
|
||||
P.setPersonality(src)
|
||||
forceMove(P)
|
||||
card = P
|
||||
job = "Personal AI"
|
||||
if(!istype(pai_card)) //when manually spawning a pai, we create a card to put it into.
|
||||
var/newcardloc = pai_card
|
||||
pai_card = new /obj/item/paicard(newcardloc)
|
||||
pai_card.setPersonality(src)
|
||||
forceMove(pai_card)
|
||||
card = pai_card
|
||||
job = JOB_PERSONAL_AI
|
||||
atmos_analyzer = new /obj/item/analyzer(src)
|
||||
signaler = new /obj/item/assembly/signaler/internal(src)
|
||||
hostscan = new /obj/item/healthanalyzer(src)
|
||||
@@ -167,57 +180,37 @@
|
||||
ADD_TRAIT(src, TRAIT_IMMOBILIZED, PAI_FOLDED)
|
||||
ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, PAI_FOLDED)
|
||||
|
||||
/mob/living/silicon/pai/Destroy()
|
||||
QDEL_NULL(atmos_analyzer)
|
||||
QDEL_NULL(internal_instrument)
|
||||
QDEL_NULL(hacking_cable)
|
||||
QDEL_NULL(newscaster)
|
||||
QDEL_NULL(signaler)
|
||||
QDEL_NULL(hostscan)
|
||||
QDEL_NULL(internal_gps)
|
||||
if(!QDELETED(card) && loc != card)
|
||||
card.forceMove(drop_location())
|
||||
card.pai = null //these are otherwise handled by paicard/handle_atom_del()
|
||||
card.emotion_icon = initial(card.emotion_icon)
|
||||
card.update_appearance()
|
||||
GLOB.pai_list -= src
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/pai/proc/pdaconfig()
|
||||
//PDA
|
||||
aiPDA = new/obj/item/pda/ai(src)
|
||||
aiPDA = new /obj/item/pda/ai(src)
|
||||
aiPDA.owner = real_name
|
||||
aiPDA.ownjob = "pAI Messenger"
|
||||
aiPDA.name = real_name + " (" + aiPDA.ownjob + ")"
|
||||
|
||||
/mob/living/silicon/pai/proc/process_hack(delta_time, times_fired)
|
||||
if(hacking_cable?.machine && istype(hacking_cable.machine, /obj/machinery/door) && hacking_cable.machine == hackdoor && get_dist(src, hackdoor) <= 1)
|
||||
hackprogress = clamp(hackprogress + (2 * delta_time), 0, HACK_COMPLETE)
|
||||
hackbar.update(hackprogress)
|
||||
else
|
||||
to_chat(src, span_notice("Door Jack: Connection to airlock has been lost. Hack aborted."))
|
||||
hackprogress = 0
|
||||
hacking = FALSE
|
||||
hackdoor = null
|
||||
hackbar.end_progress()
|
||||
QDEL_NULL(hackbar)
|
||||
QDEL_NULL(hacking_cable)
|
||||
if(!QDELETED(card))
|
||||
card.update_appearance()
|
||||
return
|
||||
if(hackprogress >= HACK_COMPLETE)
|
||||
hackprogress = 0
|
||||
hacking = FALSE
|
||||
hackbar.end_progress()
|
||||
var/obj/machinery/door/door = hacking_cable.machine
|
||||
door.open()
|
||||
QDEL_NULL(hackbar)
|
||||
QDEL_NULL(hacking_cable)
|
||||
aiPDA.name = "[real_name] ([aiPDA.ownjob])"
|
||||
|
||||
/mob/living/silicon/pai/make_laws()
|
||||
laws = new /datum/ai_laws/pai()
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/pai/Login()
|
||||
. = ..()
|
||||
if(!. || !client)
|
||||
return FALSE
|
||||
|
||||
client.perspective = EYE_PERSPECTIVE
|
||||
if(holoform)
|
||||
client.eye = src
|
||||
else
|
||||
client.eye = card
|
||||
|
||||
/mob/living/silicon/pai/get_status_tab_items()
|
||||
. += ..()
|
||||
if(!stat)
|
||||
. += text("Emitter Integrity: [emitterhealth * (100/emittermaxhealth)]")
|
||||
. += text("Emitter Integrity: [emitterhealth * (100 / emittermaxhealth)]")
|
||||
else
|
||||
. += text("Systems nonfunctional")
|
||||
|
||||
@@ -236,65 +229,6 @@
|
||||
if(delold)
|
||||
qdel(src)
|
||||
|
||||
/datum/action/innate/pai
|
||||
name = "PAI Action"
|
||||
icon_icon = 'icons/mob/actions/actions_silicon.dmi'
|
||||
var/mob/living/silicon/pai/P
|
||||
|
||||
/datum/action/innate/pai/Trigger()
|
||||
if(!ispAI(owner))
|
||||
return 0
|
||||
P = owner
|
||||
|
||||
/datum/action/innate/pai/software
|
||||
name = "Software Interface"
|
||||
button_icon_state = "pai"
|
||||
background_icon_state = "bg_tech"
|
||||
|
||||
/datum/action/innate/pai/software/Trigger()
|
||||
..()
|
||||
P.ui_act()
|
||||
|
||||
/datum/action/innate/pai/shell
|
||||
name = "Toggle Holoform"
|
||||
button_icon_state = "pai_holoform"
|
||||
background_icon_state = "bg_tech"
|
||||
|
||||
/datum/action/innate/pai/shell/Trigger()
|
||||
..()
|
||||
if(P.holoform)
|
||||
P.fold_in(0)
|
||||
else
|
||||
P.fold_out()
|
||||
|
||||
/datum/action/innate/pai/chassis
|
||||
name = "Holochassis Appearance Composite"
|
||||
button_icon_state = "pai_chassis"
|
||||
background_icon_state = "bg_tech"
|
||||
|
||||
/datum/action/innate/pai/chassis/Trigger()
|
||||
..()
|
||||
P.choose_chassis()
|
||||
|
||||
/datum/action/innate/pai/rest
|
||||
name = "Rest"
|
||||
button_icon_state = "pai_rest"
|
||||
background_icon_state = "bg_tech"
|
||||
|
||||
/datum/action/innate/pai/rest/Trigger()
|
||||
..()
|
||||
P.toggle_resting()
|
||||
|
||||
/datum/action/innate/pai/light
|
||||
name = "Toggle Integrated Lights"
|
||||
icon_icon = 'icons/mob/actions/actions_spells.dmi'
|
||||
button_icon_state = "emp"
|
||||
background_icon_state = "bg_tech"
|
||||
|
||||
/datum/action/innate/pai/light/Trigger()
|
||||
..()
|
||||
P.toggle_integrated_light()
|
||||
|
||||
/mob/living/silicon/pai/Process_Spacemove(movement_dir = 0)
|
||||
. = ..()
|
||||
if(!.)
|
||||
@@ -307,21 +241,6 @@
|
||||
. = ..()
|
||||
. += "A personal AI in holochassis mode. Its master ID string seems to be [master]."
|
||||
|
||||
/mob/living/silicon/pai/Life(delta_time = SSMOBS_DT, times_fired)
|
||||
. = ..()
|
||||
if(QDELETED(src) || stat == DEAD)
|
||||
return
|
||||
if(hacking_cable)
|
||||
if(get_dist(src, hacking_cable) > 1)
|
||||
var/turf/T = get_turf(src)
|
||||
T.visible_message(span_warning("[hacking_cable] rapidly retracts back into its spool."), span_hear("You hear a click and the sound of wire spooling rapidly."))
|
||||
QDEL_NULL(hacking_cable)
|
||||
if(!QDELETED(card))
|
||||
card.update_appearance()
|
||||
else if(hacking)
|
||||
process_hack(delta_time, times_fired)
|
||||
silent = max(silent - (0.5 * delta_time), 0)
|
||||
|
||||
/mob/living/silicon/pai/updatehealth()
|
||||
if(status_flags & GODMODE)
|
||||
return
|
||||
@@ -337,8 +256,11 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/paicard/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
return pai.radio.screwdriver_act(user, tool)
|
||||
|
||||
/obj/item/paicard/attackby(obj/item/used, mob/user, params)
|
||||
if(pai && (istype(used, /obj/item/encryptionkey) || used.tool_behaviour == TOOL_SCREWDRIVER))
|
||||
if(pai && istype(used, /obj/item/encryptionkey))
|
||||
if(!pai.encryptmod)
|
||||
to_chat(user, span_alert("Encryption Key ports not configured."))
|
||||
return
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/datum/action/innate/pai
|
||||
name = "PAI Action"
|
||||
icon_icon = 'icons/mob/actions/actions_silicon.dmi'
|
||||
var/mob/living/silicon/pai/pai_owner
|
||||
|
||||
/datum/action/innate/pai/Trigger()
|
||||
if(!ispAI(owner))
|
||||
return FALSE
|
||||
pai_owner = owner
|
||||
|
||||
/datum/action/innate/pai/software
|
||||
name = "Software Interface"
|
||||
button_icon_state = "pai"
|
||||
background_icon_state = "bg_tech"
|
||||
|
||||
/datum/action/innate/pai/software/Trigger()
|
||||
..()
|
||||
pai_owner.ui_act()
|
||||
|
||||
/datum/action/innate/pai/shell
|
||||
name = "Toggle Holoform"
|
||||
button_icon_state = "pai_holoform"
|
||||
background_icon_state = "bg_tech"
|
||||
|
||||
/datum/action/innate/pai/shell/Trigger()
|
||||
..()
|
||||
if(pai_owner.holoform)
|
||||
pai_owner.fold_in(0)
|
||||
else
|
||||
pai_owner.fold_out()
|
||||
|
||||
/datum/action/innate/pai/chassis
|
||||
name = "Holochassis Appearance Composite"
|
||||
button_icon_state = "pai_chassis"
|
||||
background_icon_state = "bg_tech"
|
||||
|
||||
/datum/action/innate/pai/chassis/Trigger()
|
||||
..()
|
||||
pai_owner.choose_chassis()
|
||||
|
||||
/datum/action/innate/pai/rest
|
||||
name = "Rest"
|
||||
button_icon_state = "pai_rest"
|
||||
background_icon_state = "bg_tech"
|
||||
|
||||
/datum/action/innate/pai/rest/Trigger()
|
||||
..()
|
||||
pai_owner.toggle_resting()
|
||||
|
||||
/datum/action/innate/pai/light
|
||||
name = "Toggle Integrated Lights"
|
||||
icon_icon = 'icons/mob/actions/actions_spells.dmi'
|
||||
button_icon_state = "emp"
|
||||
background_icon_state = "bg_tech"
|
||||
|
||||
/datum/action/innate/pai/light/Trigger()
|
||||
..()
|
||||
pai_owner.toggle_integrated_light()
|
||||
@@ -6,9 +6,8 @@
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
take_holo_damage(50/severity)
|
||||
Paralyze(400/severity)
|
||||
silent = max(20/severity, silent)
|
||||
take_holo_damage(50 / severity)
|
||||
Stun(400 / severity)
|
||||
if(holoform)
|
||||
fold_in(force = TRUE)
|
||||
//Need more effects that aren't instadeath or permanent law corruption.
|
||||
@@ -41,19 +40,20 @@
|
||||
Paralyze(200)
|
||||
|
||||
/mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user, list/modifiers)
|
||||
if(user.combat_mode)
|
||||
user.do_attack_animation(src)
|
||||
if (user.name == master)
|
||||
visible_message(span_notice("Responding to its master's touch, [src] disengages its holochassis emitter, rapidly losing coherence."))
|
||||
if(do_after(user, 1 SECONDS, TRUE, src))
|
||||
fold_in()
|
||||
if(user.put_in_hands(card))
|
||||
user.visible_message(span_notice("[user] promptly scoops up [user.p_their()] pAI's card."))
|
||||
else
|
||||
visible_message(span_danger("[user] stomps on [src]!."))
|
||||
take_holo_damage(2)
|
||||
else
|
||||
if(!user.combat_mode)
|
||||
visible_message(span_notice("[user] gently pats [src] on the head, eliciting an off-putting buzzing from its holographic field."))
|
||||
return
|
||||
user.do_attack_animation(src)
|
||||
if(user.name != master)
|
||||
visible_message(span_danger("[user] stomps on [src]!."))
|
||||
take_holo_damage(2)
|
||||
return
|
||||
visible_message(span_notice("Responding to its master's touch, [src] disengages its holochassis emitter, rapidly losing coherence."))
|
||||
if(!do_after(user, 1 SECONDS, TRUE, src))
|
||||
return
|
||||
fold_in()
|
||||
if(user.put_in_hands(card))
|
||||
user.visible_message(span_notice("[user] promptly scoops up [user.p_their()] pAI's card."))
|
||||
|
||||
/mob/living/silicon/pai/bullet_act(obj/projectile/Proj)
|
||||
if(Proj.stun)
|
||||
@@ -61,14 +61,15 @@
|
||||
src.visible_message(span_warning("The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!"))
|
||||
. = ..(Proj)
|
||||
|
||||
/mob/living/silicon/pai/IgniteMob(mob/living/silicon/pai/P)
|
||||
return FALSE //No we're not flammable
|
||||
/mob/living/silicon/pai/IgniteMob()
|
||||
fire_stacks = 0
|
||||
. = ..()
|
||||
|
||||
/mob/living/silicon/pai/proc/take_holo_damage(amount)
|
||||
emitterhealth = clamp((emitterhealth - amount), -50, emittermaxhealth)
|
||||
if(emitterhealth < 0)
|
||||
fold_in(force = TRUE)
|
||||
if (amount > 0)
|
||||
if(amount > 0)
|
||||
to_chat(src, span_userdanger("The impact degrades your holochassis!"))
|
||||
return amount
|
||||
|
||||
|
||||
@@ -1,8 +1,2 @@
|
||||
/mob/living/silicon/pai/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
|
||||
if(silent)
|
||||
to_chat(src, span_warning("Communication circuits remain uninitialized."))
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/silicon/pai/binarycheck()
|
||||
return radio?.translate_binary
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
name
|
||||
key
|
||||
description
|
||||
role
|
||||
comments
|
||||
ready = 0
|
||||
*/
|
||||
/**
|
||||
* name
|
||||
* key
|
||||
* description
|
||||
* role
|
||||
* comments
|
||||
* ready = TRUE
|
||||
*/
|
||||
|
||||
/datum/pai_candidate/proc/savefile_path(mob/user)
|
||||
return "data/player_saves/[user.ckey[1]]/[user.ckey]/pai.sav"
|
||||
@@ -24,17 +24,17 @@
|
||||
|
||||
// loads the savefile corresponding to the mob's ckey
|
||||
// if silent=true, report incompatible savefiles
|
||||
// returns 1 if loaded (or file was incompatible)
|
||||
// returns 0 if savefile did not exist
|
||||
// returns TRUE if loaded (or file was incompatible)
|
||||
// returns FALSE if savefile did not exist
|
||||
|
||||
/datum/pai_candidate/proc/savefile_load(mob/user, silent = TRUE)
|
||||
if (is_guest_key(user.key))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/path = savefile_path(user)
|
||||
|
||||
if (!fexists(path))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/savefile/F = new /savefile(path)
|
||||
|
||||
@@ -48,9 +48,9 @@
|
||||
fdel(path)
|
||||
if (!silent)
|
||||
tgui_alert(user, "Your savefile was incompatible with this version and was deleted.")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
F["name"] >> src.name
|
||||
F["description"] >> src.description
|
||||
F["comments"] >> src.comments
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
@@ -1,35 +1,3 @@
|
||||
/mob/living/silicon/pai/var/list/available_software = list(
|
||||
//Nightvision
|
||||
//T-Ray
|
||||
//radiation eyes
|
||||
//chem goggs
|
||||
//mesons
|
||||
"crew manifest" = 5,
|
||||
"digital messenger" = 5,
|
||||
"atmosphere sensor" = 5,
|
||||
"photography module" = 5,
|
||||
"camera zoom" = 10,
|
||||
"printer module" = 10,
|
||||
"remote signaler" = 10,
|
||||
"medical records" = 10,
|
||||
"security records" = 10,
|
||||
"host scan" = 10,
|
||||
"medical HUD" = 20,
|
||||
"security HUD" = 20,
|
||||
"loudness booster" = 20,
|
||||
"newscaster" = 20,
|
||||
"door jack" = 25,
|
||||
"encryption keys" = 25,
|
||||
"internal gps" = 35,
|
||||
"universal translator" = 35
|
||||
)
|
||||
/// Bool that determines if the pAI can refresh medical/security records.
|
||||
/mob/living/silicon/pai/var/refresh_spam = FALSE
|
||||
/// Cached list for medical records to send as static data
|
||||
/mob/living/silicon/pai/var/list/medical_records = list()
|
||||
/// Cached list for security records to send as static data
|
||||
/mob/living/silicon/pai/var/list/security_records = list()
|
||||
|
||||
// Opens TGUI interface
|
||||
/mob/living/silicon/pai/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
@@ -124,10 +92,8 @@
|
||||
if("door_jack")
|
||||
if(params["jack"] == "jack")
|
||||
if(hacking_cable?.machine)
|
||||
hackdoor = hacking_cable.machine
|
||||
hackloop()
|
||||
hack_door()
|
||||
if(params["jack"] == "cancel")
|
||||
hackdoor = null
|
||||
QDEL_NULL(hacking_cable)
|
||||
if(params["jack"] == "cable")
|
||||
extendcable()
|
||||
@@ -213,20 +179,20 @@
|
||||
return
|
||||
to_chat(pai, span_notice("Requesting a DNA sample."))
|
||||
var/confirm = tgui_alert(master, "[pai] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "Checking DNA", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
master.visible_message(span_notice("[master] presses [master.p_their()] thumb against [pai]."),\
|
||||
span_notice("You press your thumb against [pai]."),\
|
||||
span_notice("[pai] makes a sharp clicking sound as it extracts DNA material from [master]."))
|
||||
if(!master.has_dna())
|
||||
to_chat(pai, "<b>No DNA detected.</b>")
|
||||
return
|
||||
to_chat(pai, "<font color = red><h3>[master]'s UE string : [master.dna.unique_enzymes]</h3></font>")
|
||||
if(master.dna.unique_enzymes == pai.master_dna)
|
||||
to_chat(pai, "<b>DNA is a match to stored Master DNA.</b>")
|
||||
else
|
||||
to_chat(pai, "<b>DNA does not match stored Master DNA.</b>")
|
||||
else
|
||||
if(confirm != "Yes")
|
||||
to_chat(pai, span_warning("[master] does not seem like [master.p_theyre()] going to provide a DNA sample willingly."))
|
||||
return
|
||||
master.visible_message(span_notice("[master] presses [master.p_their()] thumb against [pai]."),\
|
||||
span_notice("You press your thumb against [pai]."),\
|
||||
span_notice("[pai] makes a sharp clicking sound as it extracts DNA material from [master]."))
|
||||
if(!master.has_dna())
|
||||
to_chat(pai, "<b>No DNA detected.</b>")
|
||||
return
|
||||
to_chat(pai, "<font color = red><h3>[master]'s UE string : [master.dna.unique_enzymes]</h3></font>")
|
||||
if(master.dna.unique_enzymes == pai.master_dna)
|
||||
to_chat(pai, span_bold("DNA is a match to stored Master DNA."))
|
||||
else
|
||||
to_chat(pai, span_bold("DNA does not match stored Master DNA."))
|
||||
|
||||
/**
|
||||
* Host scan supporting proc
|
||||
@@ -253,35 +219,46 @@
|
||||
/mob/living/silicon/pai/proc/extendcable()
|
||||
QDEL_NULL(hacking_cable) //clear any old cables
|
||||
hacking_cable = new
|
||||
var/transfered_to_mob
|
||||
if(isliving(card.loc))
|
||||
var/mob/living/hacker = card.loc
|
||||
if(hacker.put_in_hands(hacking_cable))
|
||||
transfered_to_mob = TRUE
|
||||
hacker.visible_message(span_warning("A port on [src] opens to reveal \a [hacking_cable], which you quickly grab hold of."), span_hear("You hear the soft click of something light and manage to catch hold of [hacking_cable]."))
|
||||
if(!transfered_to_mob)
|
||||
hacking_cable.forceMove(drop_location())
|
||||
hacking_cable.visible_message(span_warning("A port on [src] opens to reveal \a [hacking_cable], which promptly falls to the floor."), span_hear("You hear the soft click of something light and hard falling to the ground."))
|
||||
if(!isliving(card.loc))
|
||||
return
|
||||
var/mob/living/hacker = card.loc
|
||||
if(hacker.put_in_hands(hacking_cable))
|
||||
hacker.visible_message(span_warning("A port on [src] opens to reveal \a [hacking_cable], which you quickly grab hold of."), span_hear("You hear the soft click of something light and manage to catch hold of [hacking_cable]."))
|
||||
return
|
||||
hacking_cable.forceMove(drop_location())
|
||||
hacking_cable.visible_message(span_warning("A port on [src] opens to reveal \a [hacking_cable], which promptly falls to the floor."), span_hear("You hear the soft click of something light and hard falling to the ground."))
|
||||
|
||||
/**
|
||||
* Door jacking supporting proc
|
||||
*
|
||||
* This begins the hacking process on a door.
|
||||
* Mostly, this gives UI feedback, while the "hack"
|
||||
* is handled inside pai.dm itself.
|
||||
* This will, after alerting any AIs on station, begin to hack open a door.
|
||||
* After a 10 second timer, the door will crack open, provided they don't move out of the way.
|
||||
*/
|
||||
/mob/living/silicon/pai/proc/hackloop()
|
||||
|
||||
/mob/living/silicon/pai/proc/hack_door()
|
||||
var/turf/turf = get_turf(src)
|
||||
playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, TRUE)
|
||||
to_chat(usr, span_boldnotice("You begin overriding the airlock security protocols."))
|
||||
for(var/mob/living/silicon/ai/AI in GLOB.player_list)
|
||||
for(var/mob/living/silicon/ai/all_ais in GLOB.player_list)
|
||||
if(!all_ais.stat)
|
||||
continue
|
||||
if(turf.loc)
|
||||
to_chat(AI, "<font color = red><b>Network Alert: Brute-force security override in progress in [turf.loc].</b></font>")
|
||||
to_chat(all_ais, span_boldannounce("Network Alert: Brute-force security override in progress in [turf.loc]."))
|
||||
else
|
||||
to_chat(AI, "<font color = red><b>Network Alert: Brute-force security override in progress. Unable to pinpoint location.</b></font>")
|
||||
if(!hackbar)
|
||||
hackbar = new(src, HACK_COMPLETE, hacking_cable.machine)
|
||||
hacking = TRUE
|
||||
to_chat(all_ais, span_boldannounce("Network Alert: Brute-force security override in progress. Unable to pinpoint location."))
|
||||
//Now begin hacking
|
||||
if(!do_after(src, 10 SECONDS, hacking_cable.machine, timed_action_flags = NONE, progress = TRUE))
|
||||
to_chat(src, span_notice("Door Jack: Connection to airlock has been lost. Hack aborted."))
|
||||
hacking_cable.visible_message(
|
||||
span_warning("[hacking_cable] rapidly retracts back into its spool."),\
|
||||
span_hear("You hear a click and the sound of wire spooling rapidly."))
|
||||
QDEL_NULL(hacking_cable)
|
||||
if(!QDELETED(card))
|
||||
card.update_appearance()
|
||||
return
|
||||
var/obj/machinery/door/door = hacking_cable.machine
|
||||
door.open()
|
||||
QDEL_NULL(hacking_cable)
|
||||
|
||||
/**
|
||||
* Proc that switches whether a pAI can refresh
|
||||
|
||||
@@ -82,7 +82,7 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real
|
||||
if(shell)
|
||||
to_chat(user, span_warning("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
|
||||
radio.screwdriver_act(user, W)//Push it to the radio to let it handle everything
|
||||
else
|
||||
to_chat(user, span_warning("Unable to locate a radio!"))
|
||||
update_icons()
|
||||
@@ -159,7 +159,7 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real
|
||||
MOD.install(laws, user) //Proc includes a success mesage so we don't need another one
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/encryptionkey/) && opened)
|
||||
if(istype(W, /obj/item/encryptionkey) && opened)
|
||||
if(radio)//sanityyyyyy
|
||||
radio.attackby(W,user)//GTFO, you have your own procs
|
||||
else
|
||||
|
||||
+2
-1
@@ -111,7 +111,6 @@
|
||||
#include "code\__DEFINES\networks.dm"
|
||||
#include "code\__DEFINES\nitrile.dm"
|
||||
#include "code\__DEFINES\obj_flags.dm"
|
||||
#include "code\__DEFINES\pai.dm"
|
||||
#include "code\__DEFINES\pinpointers.dm"
|
||||
#include "code\__DEFINES\pipe_construction.dm"
|
||||
#include "code\__DEFINES\plumbing.dm"
|
||||
@@ -3149,7 +3148,9 @@
|
||||
#include "code\modules\mob\living\silicon\ai\freelook\chunk.dm"
|
||||
#include "code\modules\mob\living\silicon\ai\freelook\eye.dm"
|
||||
#include "code\modules\mob\living\silicon\pai\death.dm"
|
||||
#include "code\modules\mob\living\silicon\pai\login.dm"
|
||||
#include "code\modules\mob\living\silicon\pai\pai.dm"
|
||||
#include "code\modules\mob\living\silicon\pai\pai_actions.dm"
|
||||
#include "code\modules\mob\living\silicon\pai\pai_defense.dm"
|
||||
#include "code\modules\mob\living\silicon\pai\pai_say.dm"
|
||||
#include "code\modules\mob\living\silicon\pai\pai_shell.dm"
|
||||
|
||||
Reference in New Issue
Block a user