mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 16:47:13 +01:00
[MIRROR] Sapient bots can play voice lines [MDB IGNORE] (#22768)
* Sapient bots can play voice lines (#76920) ## About The Pull Request Part of the "throwing stuff at the wall and seeing what happens" series of changes. We were discussing player bots and there was some small support for "what if bots couldn't talk except to other bots and primarily communicated via emoting and playing their prerecorded lines". I coded this but I'll be honest, my heart wasn't in it, especially because we have _already_ released sapient bots who can talk so I'd have to justify taking it away in a better way than "I want to see what would happen", so I'm not doing that (feel free to revert the last commit in this PR if you want to carry that cross yourself). But I'm keeping the button that plays the prerecorded voice messages. No these lists _aren't_ alphabetised, that's because I wanted to vaguely order them in order of "this is something the bot regularly says" to "this is something the bot rarely says (because it is rude or mean)". This priority is possibly the inverse of how players will want to use the button, but perhaps they should try being politer. Additionally this PR ensures that if you put a pAI in a bot then it will be able to speak any languages the pAI could. ## Why It's Good For The Game Saying "I should have been a plastic surgeon" is iconic medbot behaviour and players should be able to do it. We don't currently have bot TTS voices which directly sound like the bots themselves to apply, and it might be mildly concerning if we did because I believe at least one of the voices is the IRL voice of a community member with some filters added? ## Changelog 🆑 add: Player-controlled bots can now play the prerecorded lines associated with that bot. add: Placing a pAI into a bot temporarily teaches that bot all the langauges the pAI could speak. /🆑 * Sapient bots can play voice lines --------- Co-authored-by: Jacquerel <hnevard@gmail.com>
This commit is contained in:
committed by
nevimer
co-authored by
Jacquerel
parent
f46a300a93
commit
b2b8e872b8
@@ -31,6 +31,7 @@
|
||||
#define LANGUAGE_MALF "malf"
|
||||
#define LANGUAGE_PIRATE "pirate"
|
||||
#define LANGUAGE_MASTER "master"
|
||||
#define LANGUAGE_PAI "pai"
|
||||
#define LANGUAGE_SOFTWARE "software"
|
||||
#define LANGUAGE_STONER "stoner"
|
||||
#define LANGUAGE_VOICECHANGE "voicechange"
|
||||
|
||||
@@ -234,3 +234,75 @@ DEFINE_BITFIELD(janitor_mode_flags, list(
|
||||
#define NAVBEACON_PATROL_NEXT "next_patrol"
|
||||
#define NAVBEACON_DELIVERY_MODE "delivery"
|
||||
#define NAVBEACON_DELIVERY_DIRECTION "dir"
|
||||
|
||||
// Defines for lines that bots can speak which also have corresponding voice lines
|
||||
|
||||
#define ED209_VOICED_DOWN_WEAPONS "Please put down your weapon. You have 20 seconds to comply."
|
||||
|
||||
#define HONKBOT_VOICED_HONK_HAPPY "Honk!"
|
||||
#define HONKBOT_VOICED_HONK_SAD "Honk..."
|
||||
|
||||
#define BEEPSKY_VOICED_CRIMINAL_DETECTED "Criminal detected!"
|
||||
#define BEEPSKY_VOICED_FREEZE "Freeze, scumbag!"
|
||||
#define BEEPSKY_VOICED_JUSTICE "Prepare for justice!"
|
||||
#define BEEPSKY_VOICED_YOUR_MOVE "Your move, creep."
|
||||
#define BEEPSKY_VOICED_I_AM_THE_LAW "I am the law!"
|
||||
#define BEEPSKY_VOICED_SECURE_DAY "Have a secure day."
|
||||
|
||||
#define FIREBOT_VOICED_FIRE_DETECTED "Fire detected!"
|
||||
#define FIREBOT_VOICED_STOP_DROP "Stop, drop and roll!"
|
||||
#define FIREBOT_VOICED_EXTINGUISHING "Extinguishing!"
|
||||
#define FIREBOT_VOICED_NO_FIRES "No fires detected."
|
||||
#define FIREBOT_VOICED_ONLY_YOU "Only you can prevent station fires."
|
||||
#define FIREBOT_VOICED_TEMPERATURE_NOMINAL "Temperature nominal."
|
||||
#define FIREBOT_VOICED_KEEP_COOL "Keep it cool."
|
||||
|
||||
#define HYGIENEBOT_VOICED_UNHYGIENIC "Unhygienic client found. Please stand still so I can clean you."
|
||||
#define HYGIENEBOT_VOICED_ENJOY_DAY "Enjoy your clean and tidy day!"
|
||||
#define HYGIENEBOT_VOICED_THREAT_AIRLOCK "Either you stop running or I will fucking drag you out of an airlock."
|
||||
#define HYGIENEBOT_VOICED_FOUL_SMELL "Get back here you foul smelling fucker."
|
||||
#define HYGIENEBOT_VOICED_TROGLODYTE "I just want to fucking clean you you troglodyte."
|
||||
#define HYGIENEBOT_VOICED_GREEN_CLOUD "If you don't come back here I'll put a green cloud around you cunt."
|
||||
#define HYGIENEBOT_VOICED_ARSEHOLE "Just fucking let me clean you you arsehole!"
|
||||
#define HYGIENEBOT_VOICED_THREAT_ARTERIES "STOP RUNNING OR I WILL CUT YOUR ARTERIES!"
|
||||
#define HYGIENEBOT_VOICED_STOP_RUNNING "STOP. RUNNING."
|
||||
#define HYGIENEBOT_VOICED_FUCKING_FINALLY "Fucking finally."
|
||||
#define HYGIENEBOT_VOICED_THANK_GOD "Thank god, you finally stopped."
|
||||
#define HYGIENEBOT_VOICED_DEGENERATE "Well about fucking time you degenerate."
|
||||
|
||||
#define MEDIBOT_VOICED_HOLD_ON "Hey! Hold on, I'm coming."
|
||||
#define MEDIBOT_VOICED_WANT_TO_HELP "Wait! I want to help!"
|
||||
#define MEDIBOT_VOICED_YOU_ARE_INJURED "You appear to be injured!"
|
||||
#define MEDIBOT_VOICED_ALL_PATCHED_UP "All patched up!"
|
||||
#define MEDIBOT_VOICED_APPLE_A_DAY "An apple a day keeps me away."
|
||||
#define MEDIBOT_VOICED_FEEL_BETTER "Feel better soon!"
|
||||
#define MEDIBOT_VOICED_STAY_WITH_ME "No! Stay with me!"
|
||||
#define MEDIBOT_VOICED_LIVE "Live, damnit! LIVE!"
|
||||
#define MEDIBOT_VOICED_NEVER_LOST "I...I've never lost a patient before. Not today, I mean."
|
||||
#define MEDIBOT_VOICED_DELICIOUS "Delicious!"
|
||||
#define MEDIBOT_VOICED_PLASTIC_SURGEON "I knew it, I should've been a plastic surgeon."
|
||||
#define MEDIBOT_VOICED_MASK_ON "Radar, put a mask on!"
|
||||
#define MEDIBOT_VOICED_ALWAYS_A_CATCH "There's always a catch, and I'm the best there is."
|
||||
#define MEDIBOT_VOICED_LIKE_FLIES "What kind of medbay is this? Everyone's dropping like flies."
|
||||
#define MEDIBOT_VOICED_SUFFER "Why are we still here? Just to suffer?"
|
||||
#define MEDIBOT_VOICED_FUCK_YOU "Fuck you."
|
||||
#define MEDIBOT_VOICED_NOT_A_GAME "Turn off your computer. This is not a game."
|
||||
#define MEDIBOT_VOICED_IM_DIFFERENT "I'm different!"
|
||||
#define MEDIBOT_VOICED_FOURTH_WALL "Close Dreamseeker.exe now. Or else."
|
||||
#define MEDIBOT_VOICED_SHINDEMASHOU "Shindemashou."
|
||||
#define MEDIBOT_VOICED_WAIT "Hey, wait..."
|
||||
#define MEDIBOT_VOICED_DONT "Please don't..."
|
||||
#define MEDIBOT_VOICED_TRUSTED_YOU "I trusted you..."
|
||||
#define MEDIBOT_VOICED_NO_SAD "Nooo..."
|
||||
#define MEDIBOT_VOICED_OH_FUCK "Oh fuck-"
|
||||
#define MEDIBOT_VOICED_FORGIVE "I forgive you."
|
||||
#define MEDIBOT_VOICED_THANKS "Thank you!"
|
||||
#define MEDIBOT_VOICED_GOOD_PERSON "You are a good person."
|
||||
#define MEDIBOT_VOICED_BEHAVIOUR_REPORTED "Your behavior has been reported, have a nice day."
|
||||
#define MEDIBOT_VOICED_ASSISTANCE "I require assistance."
|
||||
#define MEDIBOT_VOICED_PUT_BACK "Please put me back."
|
||||
#define MEDIBOT_VOICED_IM_SCARED "Please, I am scared!"
|
||||
#define MEDIBOT_VOICED_NEED_HELP "I don't like this, I need help!"
|
||||
#define MEDIBOT_VOICED_THIS_HURTS "This hurts, my pain is real!"
|
||||
#define MEDIBOT_VOICED_THE_END "Is this the end?"
|
||||
#define MEDIBOT_VOICED_NOOO "Nooo!"
|
||||
|
||||
@@ -1544,7 +1544,7 @@
|
||||
var/area/atom_area = get_area(src)
|
||||
|
||||
if(!atom_turf) // some machines spawn in nullspace
|
||||
return
|
||||
return FALSE
|
||||
|
||||
if(!is_station_level(atom_turf.z) && !istype(atom_area, /area/shuttle/escape))
|
||||
// Why snowflake check for escape shuttle? Well, a lot of shuttles spawn with machines
|
||||
|
||||
@@ -112,6 +112,10 @@
|
||||
COOLDOWN_DECLARE(offer_ghosts_cooldown)
|
||||
/// Message to display upon possession
|
||||
var/possessed_message = "You're a generic bot. How did one of these even get made?"
|
||||
/// List of strings to sound effects corresponding to automated messages the bot can play
|
||||
var/list/automated_announcements
|
||||
/// Action we use to say voice lines out loud, also we just pass anything we try to say through here just in case it plays a voice line
|
||||
var/datum/action/cooldown/bot_announcement/pa_system
|
||||
|
||||
/mob/living/simple_animal/bot/proc/get_mode()
|
||||
if(client) //Player bots do not have modes, thus the override. Also an easy way for PDA users/AI to know when a bot is a player.
|
||||
@@ -195,10 +199,14 @@
|
||||
if(mapload && is_station_level(z) && bot_mode_flags & BOT_MODE_CAN_BE_SAPIENT && bot_mode_flags & BOT_MODE_ROUNDSTART_POSSESSION)
|
||||
enable_possession(mapload = mapload)
|
||||
|
||||
pa_system = new(src, automated_announcements = automated_announcements)
|
||||
pa_system.Grant(src)
|
||||
|
||||
/mob/living/simple_animal/bot/Destroy()
|
||||
if(paicard)
|
||||
ejectpai()
|
||||
GLOB.bots_list -= src
|
||||
QDEL_NULL(pa_system)
|
||||
QDEL_NULL(personality_download)
|
||||
QDEL_NULL(internal_radio)
|
||||
QDEL_NULL(access_card)
|
||||
@@ -526,13 +534,14 @@
|
||||
if(was_on)
|
||||
turn_on()
|
||||
|
||||
/mob/living/simple_animal/bot/proc/speak(message,channel) //Pass a message to have the bot say() it. Pass a frequency to say it on the radio.
|
||||
if((!(bot_mode_flags & BOT_MODE_ON)) || (!message))
|
||||
/**
|
||||
* Pass a message to have the bot say() it, passing through our announcement action to potentially also play a sound.
|
||||
* Optionally pass a frequency to say it on the radio.
|
||||
*/
|
||||
/mob/living/simple_animal/bot/proc/speak(message, channel)
|
||||
if(!message)
|
||||
return
|
||||
if(channel && internal_radio.channels[channel])// Use radio if we have channel key
|
||||
internal_radio.talk_into(src, message, channel)
|
||||
else
|
||||
say(message)
|
||||
pa_system.announce(message, channel)
|
||||
|
||||
/mob/living/simple_animal/bot/radio(message, list/message_mods = list(), list/spans, language)
|
||||
. = ..()
|
||||
@@ -1069,6 +1078,8 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
disable_possession()
|
||||
if(paicard.pai.holoform)
|
||||
paicard.pai.fold_in()
|
||||
copy_languages(paicard.pai, source_override = LANGUAGE_PAI)
|
||||
set_active_language(paicard.pai.get_selected_language())
|
||||
user.visible_message(span_notice("[user] inserts [card] into [src]!"), span_notice("You insert [card] into [src]."))
|
||||
paicard.pai.mind.transfer_to(src)
|
||||
to_chat(src, span_notice("You sense your form change as you are uploaded into [src]."))
|
||||
@@ -1104,6 +1115,8 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
paicard = null
|
||||
name = initial(src.name)
|
||||
faction = initial(faction)
|
||||
remove_all_languages(source = LANGUAGE_PAI)
|
||||
get_selected_language()
|
||||
|
||||
/// Ejects the pAI remotely.
|
||||
/mob/living/simple_animal/bot/proc/ejectpairemote(mob/user)
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/// Say something and play a corresponding sound effect
|
||||
/datum/action/cooldown/bot_announcement
|
||||
name = "Make automated announcement"
|
||||
desc = "Play a prerecorded message for the benefit of those around you."
|
||||
background_icon_state = "bg_tech_blue"
|
||||
overlay_icon_state = "bg_tech_blue_border"
|
||||
button_icon = 'icons/mob/actions/actions_AI.dmi'
|
||||
button_icon_state = "intercom"
|
||||
cooldown_time = 10 SECONDS
|
||||
melee_cooldown_time = 0 SECONDS
|
||||
/// List of strings to sound effects corresponding to automated messages we can play
|
||||
var/list/automated_announcements
|
||||
|
||||
/datum/action/cooldown/bot_announcement/New(Target, original, list/automated_announcements)
|
||||
src.automated_announcements = automated_announcements
|
||||
return ..()
|
||||
|
||||
/datum/action/cooldown/bot_announcement/IsAvailable(feedback)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return
|
||||
if (!isbot(owner))
|
||||
if (feedback)
|
||||
owner.balloon_alert(owner, "no announcement system!")
|
||||
return FALSE
|
||||
if (!length(automated_announcements))
|
||||
if (feedback)
|
||||
owner.balloon_alert(owner, "no valid announcements!")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/cooldown/bot_announcement/Activate(trigger_flags, atom/target)
|
||||
var/picked
|
||||
if (length(automated_announcements) > 1)
|
||||
picked = tgui_input_list(owner, message = "Choose announcement to make.", title = "Select announcement", items = automated_announcements)
|
||||
else
|
||||
picked = pick(automated_announcements)
|
||||
if (isnull(picked))
|
||||
return
|
||||
announce(picked)
|
||||
return ..()
|
||||
|
||||
/// Speak the provided line on the provided radio channel
|
||||
/datum/action/cooldown/bot_announcement/proc/announce(line, channel)
|
||||
var/mob/living/simple_animal/bot/bot_owner = owner
|
||||
if (!(bot_owner.bot_mode_flags & BOT_MODE_ON))
|
||||
return
|
||||
|
||||
if (channel && bot_owner.internal_radio.channels[channel])
|
||||
bot_owner.internal_radio.talk_into(bot_owner, message = line, channel = channel)
|
||||
else
|
||||
bot_owner.say(line)
|
||||
|
||||
if (length(automated_announcements) && !isnull(automated_announcements[line]))
|
||||
playsound(bot_owner, automated_announcements[line], vol = 50, vary = FALSE)
|
||||
@@ -12,6 +12,8 @@
|
||||
bot_type = ADVANCED_SEC_BOT
|
||||
hackables = "combat inhibitors"
|
||||
|
||||
automated_announcements = list(ED209_VOICED_DOWN_WEAPONS = 'sound/voice/ed209_20sec.ogg')
|
||||
|
||||
var/lastfired = 0
|
||||
var/shot_delay = 15
|
||||
var/shoot_sound = 'sound/weapons/laser.ogg'
|
||||
@@ -54,6 +56,10 @@
|
||||
shoot_at(all_targets)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/ed209/threat_react(threatlevel)
|
||||
speak("Level [threatlevel] infraction alert!")
|
||||
playsound(src, pick('sound/voice/ed209_20sec.ogg', 'sound/voice/edplaceholder.ogg'), 50, FALSE)
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/ed209/proc/set_weapon() //used to update the projectile type and firing sound
|
||||
shoot_sound = 'sound/weapons/laser.ogg'
|
||||
if(bot_cover_flags & BOT_COVER_EMAGGED)
|
||||
|
||||
@@ -22,6 +22,16 @@
|
||||
path_image_color = "#FFA500"
|
||||
possessed_message = "You are a firebot! Protect the station from fires to the best of your ability!"
|
||||
|
||||
automated_announcements = list(
|
||||
FIREBOT_VOICED_FIRE_DETECTED = 'sound/voice/firebot/detected.ogg',
|
||||
FIREBOT_VOICED_STOP_DROP = 'sound/voice/firebot/stopdropnroll.ogg',
|
||||
FIREBOT_VOICED_EXTINGUISHING = 'sound/voice/firebot/extinguishing.ogg',
|
||||
FIREBOT_VOICED_NO_FIRES = 'sound/voice/firebot/nofires.ogg',
|
||||
FIREBOT_VOICED_ONLY_YOU = 'sound/voice/firebot/onlyyou.ogg',
|
||||
FIREBOT_VOICED_TEMPERATURE_NOMINAL = 'sound/voice/firebot/tempnominal.ogg',
|
||||
FIREBOT_VOICED_KEEP_COOL = 'sound/voice/firebot/keepitcool.ogg',
|
||||
)
|
||||
|
||||
var/atom/target_fire
|
||||
var/atom/old_target_fire
|
||||
|
||||
@@ -175,13 +185,13 @@
|
||||
return
|
||||
|
||||
if(prob(1) && target_fire == null)
|
||||
var/list/messagevoice = list("No fires detected." = 'sound/voice/firebot/nofires.ogg',
|
||||
"Only you can prevent station fires." = 'sound/voice/firebot/onlyyou.ogg',
|
||||
"Temperature nominal." = 'sound/voice/firebot/tempnominal.ogg',
|
||||
"Keep it cool." = 'sound/voice/firebot/keepitcool.ogg')
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 50)
|
||||
var/static/list/idle_line = list(
|
||||
FIREBOT_VOICED_NO_FIRES,
|
||||
FIREBOT_VOICED_ONLY_YOU,
|
||||
FIREBOT_VOICED_TEMPERATURE_NOMINAL,
|
||||
FIREBOT_VOICED_KEEP_COOL,
|
||||
)
|
||||
speak(pick(idle_line))
|
||||
|
||||
// Couldn't reach the target, reset and try again ignoring the old one
|
||||
if(frustration > 8)
|
||||
@@ -207,11 +217,9 @@
|
||||
if(target_fire && (get_dist(src, target_fire) <= (bot_cover_flags & BOT_COVER_EMAGGED ? 1 : 2))) // Make the bot spray water from afar when not emagged
|
||||
if((speech_cooldown + SPEECH_INTERVAL) < world.time)
|
||||
if(ishuman(target_fire))
|
||||
speak("Stop, drop and roll!")
|
||||
playsound(src, 'sound/voice/firebot/stopdropnroll.ogg', 50, FALSE)
|
||||
speak(FIREBOT_VOICED_STOP_DROP)
|
||||
else
|
||||
speak("Extinguishing!")
|
||||
playsound(src, 'sound/voice/firebot/extinguishing.ogg', 50, FALSE)
|
||||
speak(FIREBOT_VOICED_EXTINGUISHING)
|
||||
speech_cooldown = world.time
|
||||
|
||||
flick("firebot1_use", src)
|
||||
@@ -260,8 +268,7 @@
|
||||
return null
|
||||
|
||||
if((detected_cooldown + DETECTED_VOICE_INTERVAL) < world.time)
|
||||
speak("Fire detected!")
|
||||
playsound(src, 'sound/voice/firebot/detected.ogg', 50, FALSE)
|
||||
speak(FIREBOT_VOICED_FIRE_DETECTED)
|
||||
detected_cooldown = world.time
|
||||
return scan_target
|
||||
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
security_mode_flags = SECBOT_CHECK_WEAPONS | SECBOT_HANDCUFF_TARGET
|
||||
possessed_message = "You are a honkbot! Make sure the crew are having a great time!"
|
||||
|
||||
automated_announcements = list(
|
||||
HONKBOT_VOICED_HONK_HAPPY = 'sound/items/bikehorn.ogg',
|
||||
HONKBOT_VOICED_HONK_SAD = 'sound/misc/sadtrombone.ogg',
|
||||
)
|
||||
|
||||
///Keeping track of how much we honk to prevent spamming it
|
||||
var/limiting_spam = FALSE
|
||||
///Sound played when HONKing someone
|
||||
@@ -44,11 +49,13 @@
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/honkbot/knockOver(mob/living/carbon/tripped_target)
|
||||
. = ..()
|
||||
INVOKE_ASYNC(src, TYPE_PROC_REF(/mob/living/simple_animal/bot, speak), "Honk!")
|
||||
playsound(loc, 'sound/misc/sadtrombone.ogg', 50, TRUE, -1)
|
||||
INVOKE_ASYNC(src, TYPE_PROC_REF(/mob/living/simple_animal/bot, speak), HONKBOT_VOICED_HONK_SAD)
|
||||
icon_state = "[initial(icon_state)]-c"
|
||||
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_appearance)), 0.2 SECONDS)
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/honkbot/threat_react(threatlevel)
|
||||
speak(HONKBOT_VOICED_HONK_HAPPY)
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/honkbot/bot_reset()
|
||||
..()
|
||||
limiting_spam = FALSE
|
||||
|
||||
@@ -20,6 +20,21 @@
|
||||
hackables = "cleaning service protocols"
|
||||
path_image_color = "#993299"
|
||||
|
||||
automated_announcements = list(
|
||||
HYGIENEBOT_VOICED_UNHYGIENIC = 'sound/voice/hygienebot/unhygienicclient.ogg',
|
||||
HYGIENEBOT_VOICED_ENJOY_DAY = 'sound/voice/hygienebot/cleanandtidy.ogg',
|
||||
HYGIENEBOT_VOICED_THREAT_AIRLOCK = 'sound/voice/hygienebot/dragyouout.ogg',
|
||||
HYGIENEBOT_VOICED_FOUL_SMELL = 'sound/voice/hygienebot/foulsmelling.ogg',
|
||||
HYGIENEBOT_VOICED_TROGLODYTE = 'sound/voice/hygienebot/troglodyte.ogg',
|
||||
HYGIENEBOT_VOICED_GREEN_CLOUD = 'sound/voice/hygienebot/greencloud.ogg',
|
||||
HYGIENEBOT_VOICED_ARSEHOLE = 'sound/voice/hygienebot/letmeclean.ogg',
|
||||
HYGIENEBOT_VOICED_THREAT_ARTERIES = 'sound/voice/hygienebot/cutarteries.ogg',
|
||||
HYGIENEBOT_VOICED_STOP_RUNNING = 'sound/voice/hygienebot/stoprunning.ogg',
|
||||
HYGIENEBOT_VOICED_FUCKING_FINALLY = 'sound/voice/hygienebot/finally.ogg',
|
||||
HYGIENEBOT_VOICED_THANK_GOD = 'sound/voice/hygienebot/thankgod.ogg',
|
||||
HYGIENEBOT_VOICED_DEGENERATE = 'sound/voice/hygienebot/degenerate.ogg',
|
||||
)
|
||||
|
||||
///The human target the bot is trying to wash.
|
||||
var/mob/living/carbon/human/target
|
||||
///The mob's current speed, which varies based on how long the bot chases it's target.
|
||||
@@ -127,14 +142,12 @@
|
||||
if(target.loc == loc && isturf(target.loc)) //LADIES AND GENTLEMAN WE GOTEM PREPARE TO DUMP
|
||||
start_washing()
|
||||
if(mad)
|
||||
var/static/list/messagevoice = list(
|
||||
"Fucking finally." = 'sound/voice/hygienebot/finally.ogg',
|
||||
"Thank god, you finally stopped." = 'sound/voice/hygienebot/thankgod.ogg',
|
||||
"Well about fucking time you degenerate." = 'sound/voice/hygienebot/degenerate.ogg',
|
||||
var/static/list/relief = list(
|
||||
HYGIENEBOT_VOICED_FUCKING_FINALLY,
|
||||
HYGIENEBOT_VOICED_THANK_GOD,
|
||||
HYGIENEBOT_VOICED_DEGENERATE,
|
||||
)
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(loc, messagevoice[message], 50)
|
||||
speak(pick(relief))
|
||||
playsound(loc, 'sound/effects/hygienebot_angry.ogg', 60, 1) //i think it should still make robot noises too
|
||||
mad = FALSE
|
||||
mode = BOT_SHOWERSTANCE
|
||||
@@ -146,18 +159,16 @@
|
||||
return
|
||||
SSmove_manager.move_to(src, target, 0, currentspeed)
|
||||
if(mad && prob(min(frustration * 2, 60)))
|
||||
var/static/list/messagevoice = list(
|
||||
"Either you stop running or I will fucking drag you out of an airlock." = 'sound/voice/hygienebot/dragyouout.ogg',
|
||||
"Get back here you foul smelling fucker." = 'sound/voice/hygienebot/foulsmelling.ogg',
|
||||
"I just want to fucking clean you you troglodyte." = 'sound/voice/hygienebot/troglodyte.ogg',
|
||||
"If you don't come back here I'll put a green cloud around you cunt." = 'sound/voice/hygienebot/greencloud.ogg',
|
||||
"Just fucking let me clean you you arsehole!" = 'sound/voice/hygienebot/letmeclean.ogg',
|
||||
"STOP RUNNING OR I WILL CUT YOUR ARTERIES!" = 'sound/voice/hygienebot/cutarteries.ogg',
|
||||
"STOP. RUNNING." = 'sound/voice/hygienebot/stoprunning.ogg',
|
||||
var/static/list/threats = list(
|
||||
HYGIENEBOT_VOICED_THREAT_AIRLOCK,
|
||||
HYGIENEBOT_VOICED_FOUL_SMELL,
|
||||
HYGIENEBOT_VOICED_TROGLODYTE,
|
||||
HYGIENEBOT_VOICED_GREEN_CLOUD,
|
||||
HYGIENEBOT_VOICED_ARSEHOLE,
|
||||
HYGIENEBOT_VOICED_THREAT_ARTERIES,
|
||||
HYGIENEBOT_VOICED_STOP_RUNNING,
|
||||
)
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(loc, messagevoice[message], 50)
|
||||
speak(pick(threats))
|
||||
playsound(loc, 'sound/effects/hygienebot_angry.ogg', 60, 1)
|
||||
if((get_dist(src, target)) >= olddist)
|
||||
frustration++
|
||||
@@ -168,8 +179,7 @@
|
||||
|
||||
if(BOT_SHOWERSTANCE)
|
||||
if(check_purity(target))
|
||||
speak("Enjoy your clean and tidy day!")
|
||||
playsound(loc, 'sound/voice/hygienebot/cleanandtidy.ogg', 50)
|
||||
speak(HYGIENEBOT_VOICED_ENJOY_DAY)
|
||||
playsound(loc, 'sound/effects/hygienebot_happy.ogg', 60, 1)
|
||||
back_to_idle()
|
||||
return
|
||||
@@ -208,8 +218,7 @@
|
||||
if(!check_purity(H)) //Theyre impure
|
||||
target = H
|
||||
oldtarget_name = H.name
|
||||
speak("Unhygienic client found. Please stand still so I can clean you.")
|
||||
playsound(loc, 'sound/voice/hygienebot/unhygienicclient.ogg', 50)
|
||||
speak(HYGIENEBOT_VOICED_UNHYGIENIC)
|
||||
playsound(loc, 'sound/effects/hygienebot_happy.ogg', 60, 1)
|
||||
visible_message("<b>[src]</b> points at [H.name]!")
|
||||
mode = BOT_HUNT
|
||||
|
||||
@@ -35,6 +35,45 @@
|
||||
path_image_color = "#DDDDFF"
|
||||
possessed_message = "You are a medbot! Ensure good health among the crew to the best of your ability!"
|
||||
|
||||
automated_announcements = list(
|
||||
MEDIBOT_VOICED_HOLD_ON = 'sound/voice/medbot/coming.ogg',
|
||||
MEDIBOT_VOICED_WANT_TO_HELP = 'sound/voice/medbot/help.ogg',
|
||||
MEDIBOT_VOICED_YOU_ARE_INJURED = 'sound/voice/medbot/injured.ogg',
|
||||
MEDIBOT_VOICED_ALL_PATCHED_UP = 'sound/voice/medbot/patchedup.ogg',
|
||||
MEDIBOT_VOICED_APPLE_A_DAY = 'sound/voice/medbot/apple.ogg',
|
||||
MEDIBOT_VOICED_FEEL_BETTER = 'sound/voice/medbot/feelbetter.ogg',
|
||||
MEDIBOT_VOICED_STAY_WITH_ME = 'sound/voice/medbot/no.ogg',
|
||||
MEDIBOT_VOICED_LIVE = 'sound/voice/medbot/live.ogg',
|
||||
MEDIBOT_VOICED_NEVER_LOST = 'sound/voice/medbot/lost.ogg',
|
||||
MEDIBOT_VOICED_DELICIOUS = 'sound/voice/medbot/delicious.ogg',
|
||||
MEDIBOT_VOICED_PLASTIC_SURGEON = 'sound/voice/medbot/surgeon.ogg',
|
||||
MEDIBOT_VOICED_MASK_ON = 'sound/voice/medbot/radar.ogg',
|
||||
MEDIBOT_VOICED_ALWAYS_A_CATCH = 'sound/voice/medbot/catch.ogg',
|
||||
MEDIBOT_VOICED_LIKE_FLIES = 'sound/voice/medbot/flies.ogg',
|
||||
MEDIBOT_VOICED_SUFFER = 'sound/voice/medbot/why.ogg',
|
||||
MEDIBOT_VOICED_FUCK_YOU = 'sound/voice/medbot/fuck_you.ogg',
|
||||
MEDIBOT_VOICED_NOT_A_GAME = 'sound/voice/medbot/turn_off.ogg',
|
||||
MEDIBOT_VOICED_IM_DIFFERENT = 'sound/voice/medbot/im_different.ogg',
|
||||
MEDIBOT_VOICED_FOURTH_WALL = 'sound/voice/medbot/close.ogg',
|
||||
MEDIBOT_VOICED_SHINDEMASHOU = 'sound/voice/medbot/shindemashou.ogg',
|
||||
MEDIBOT_VOICED_WAIT = 'sound/voice/medbot/hey_wait.ogg',
|
||||
MEDIBOT_VOICED_DONT = 'sound/voice/medbot/please_dont.ogg',
|
||||
MEDIBOT_VOICED_TRUSTED_YOU = 'sound/voice/medbot/i_trusted_you.ogg',
|
||||
MEDIBOT_VOICED_NO_SAD = 'sound/voice/medbot/nooo.ogg',
|
||||
MEDIBOT_VOICED_OH_FUCK = 'sound/voice/medbot/oh_fuck.ogg',
|
||||
MEDIBOT_VOICED_FORGIVE = 'sound/voice/medbot/forgive.ogg',
|
||||
MEDIBOT_VOICED_THANKS = 'sound/voice/medbot/thank_you.ogg',
|
||||
MEDIBOT_VOICED_GOOD_PERSON = 'sound/voice/medbot/youre_good.ogg',
|
||||
MEDIBOT_VOICED_BEHAVIOUR_REPORTED = 'sound/voice/medbot/reported.ogg',
|
||||
MEDIBOT_VOICED_ASSISTANCE = 'sound/voice/medbot/i_require_asst.ogg',
|
||||
MEDIBOT_VOICED_PUT_BACK = 'sound/voice/medbot/please_put_me_back.ogg',
|
||||
MEDIBOT_VOICED_IM_SCARED = 'sound/voice/medbot/please_im_scared.ogg',
|
||||
MEDIBOT_VOICED_NEED_HELP = 'sound/voice/medbot/dont_like.ogg',
|
||||
MEDIBOT_VOICED_THIS_HURTS = 'sound/voice/medbot/pain_is_real.ogg',
|
||||
MEDIBOT_VOICED_THE_END = 'sound/voice/medbot/is_this_the_end.ogg',
|
||||
MEDIBOT_VOICED_NOOO = 'sound/voice/medbot/nooo.ogg',
|
||||
)
|
||||
|
||||
/// drop determining variable
|
||||
var/healthanalyzer = /obj/item/healthanalyzer
|
||||
/// drop determining variable
|
||||
@@ -251,7 +290,11 @@
|
||||
last_found = world.time
|
||||
if(COOLDOWN_FINISHED(src, last_newpatient_speak))
|
||||
COOLDOWN_START(src, last_newpatient_speak, MEDBOT_NEW_PATIENTSPEAK_DELAY)
|
||||
var/list/messagevoice = list("Hey, [H.name]! Hold on, I'm coming." = 'sound/voice/medbot/coming.ogg',"Wait [H.name]! I want to help!" = 'sound/voice/medbot/help.ogg',"[H.name], you appear to be injured!" = 'sound/voice/medbot/injured.ogg')
|
||||
var/list/messagevoice = list(
|
||||
"Hey, [H.name]! Hold on, I'm coming." = 'sound/voice/medbot/coming.ogg',
|
||||
"Wait [H.name]! I want to help!" = 'sound/voice/medbot/help.ogg',
|
||||
"[H.name], you appear to be injured!" = 'sound/voice/medbot/injured.ogg',
|
||||
)
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 50, FALSE)
|
||||
@@ -267,16 +310,14 @@
|
||||
return
|
||||
|
||||
COOLDOWN_START(src, last_tipping_action_voice, MEDBOT_FREAKOUT_DELAY) // message for tipping happens when we start interacting, message for righting comes after finishing
|
||||
var/static/list/messagevoice = list(
|
||||
"Hey, wait..." = 'sound/voice/medbot/hey_wait.ogg',
|
||||
"Please don't..." = 'sound/voice/medbot/please_dont.ogg',
|
||||
"I trusted you..." = 'sound/voice/medbot/i_trusted_you.ogg',
|
||||
"Nooo..." = 'sound/voice/medbot/nooo.ogg',
|
||||
"Oh fuck-" = 'sound/voice/medbot/oh_fuck.ogg',
|
||||
)
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 70, FALSE)
|
||||
var/static/list/worried_line = list(
|
||||
MEDIBOT_VOICED_WAIT,
|
||||
MEDIBOT_VOICED_DONT,
|
||||
MEDIBOT_VOICED_TRUSTED_YOU,
|
||||
MEDIBOT_VOICED_NO_SAD,
|
||||
MEDIBOT_VOICED_OH_FUCK,
|
||||
)
|
||||
speak(pick(worried_line))
|
||||
|
||||
/*
|
||||
* Proc used in a callback for after this medibot is tipped by the tippable component.
|
||||
@@ -297,18 +338,16 @@
|
||||
var/list/messagevoice
|
||||
if(user)
|
||||
if(user.name == tipper_name)
|
||||
messagevoice = list("I forgive you." = 'sound/voice/medbot/forgive.ogg')
|
||||
messagevoice = list(MEDIBOT_VOICED_FORGIVE)
|
||||
else
|
||||
messagevoice = list("Thank you!" = 'sound/voice/medbot/thank_you.ogg', "You are a good person." = 'sound/voice/medbot/youre_good.ogg')
|
||||
messagevoice = list(MEDIBOT_VOICED_THANKS, MEDIBOT_VOICED_GOOD_PERSON)
|
||||
else
|
||||
messagevoice = list("Fuck you." = 'sound/voice/medbot/fuck_you.ogg', "Your behavior has been reported, have a nice day." = 'sound/voice/medbot/reported.ogg')
|
||||
messagevoice = list(MEDIBOT_VOICED_FUCK_YOU, MEDIBOT_VOICED_BEHAVIOUR_REPORTED)
|
||||
tipper_name = null
|
||||
|
||||
if(COOLDOWN_FINISHED(src, last_tipping_action_voice))
|
||||
COOLDOWN_START(src, last_tipping_action_voice, MEDBOT_FREAKOUT_DELAY)
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 70)
|
||||
speak(pick(messagevoice))
|
||||
tipped_status = MEDBOT_PANIC_NONE
|
||||
mode = BOT_IDLE
|
||||
|
||||
@@ -319,15 +358,15 @@
|
||||
|
||||
switch(tipped_status)
|
||||
if(MEDBOT_PANIC_LOW)
|
||||
messagevoice = list("I require assistance." = 'sound/voice/medbot/i_require_asst.ogg')
|
||||
messagevoice = list(MEDIBOT_VOICED_ASSISTANCE)
|
||||
if(MEDBOT_PANIC_MED)
|
||||
messagevoice = list("Please put me back." = 'sound/voice/medbot/please_put_me_back.ogg')
|
||||
messagevoice = list(MEDIBOT_VOICED_PUT_BACK)
|
||||
if(MEDBOT_PANIC_HIGH)
|
||||
messagevoice = list("Please, I am scared!" = 'sound/voice/medbot/please_im_scared.ogg')
|
||||
messagevoice = list(MEDIBOT_VOICED_IM_SCARED)
|
||||
if(MEDBOT_PANIC_FUCK)
|
||||
messagevoice = list("I don't like this, I need help!" = 'sound/voice/medbot/dont_like.ogg', "This hurts, my pain is real!" = 'sound/voice/medbot/pain_is_real.ogg')
|
||||
messagevoice = list(MEDIBOT_VOICED_NEED_HELP, MEDIBOT_VOICED_THIS_HURTS)
|
||||
if(MEDBOT_PANIC_ENDING)
|
||||
messagevoice = list("Is this the end?" = 'sound/voice/medbot/is_this_the_end.ogg', "Nooo!" = 'sound/voice/medbot/nooo.ogg')
|
||||
messagevoice = list(MEDIBOT_VOICED_THE_END, MEDIBOT_VOICED_NOOO)
|
||||
if(MEDBOT_PANIC_END)
|
||||
speak("PSYCH ALERT: Crewmember [tipper_name] recorded displaying antisocial tendencies torturing bots in [get_area(src)]. Please schedule psych evaluation.", radio_channel)
|
||||
|
||||
@@ -335,9 +374,7 @@
|
||||
do_jitter_animation(tipped_status * 0.1)
|
||||
|
||||
if(messagevoice)
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 70)
|
||||
speak(pick(messagevoice))
|
||||
else if(prob(tipped_status * 0.2))
|
||||
playsound(src, 'sound/machines/warning-buzzer.ogg', 30, extrarange=-2)
|
||||
|
||||
@@ -366,26 +403,24 @@
|
||||
if(QDELETED(patient))
|
||||
if(medical_mode_flags & MEDBOT_SPEAK_MODE && prob(1))
|
||||
if(bot_cover_flags & BOT_COVER_EMAGGED && prob(30))
|
||||
var/list/i_need_scissors = list(
|
||||
'sound/voice/medbot/fuck_you.ogg',
|
||||
'sound/voice/medbot/turn_off.ogg',
|
||||
'sound/voice/medbot/im_different.ogg',
|
||||
'sound/voice/medbot/close.ogg',
|
||||
'sound/voice/medbot/shindemashou.ogg',
|
||||
var/static/list/i_need_scissors = list(
|
||||
MEDIBOT_VOICED_FUCK_YOU,
|
||||
MEDIBOT_VOICED_NOT_A_GAME,
|
||||
MEDIBOT_VOICED_IM_DIFFERENT,
|
||||
MEDIBOT_VOICED_FOURTH_WALL,
|
||||
MEDIBOT_VOICED_SHINDEMASHOU,
|
||||
)
|
||||
playsound(src, pick(i_need_scissors), 70)
|
||||
speak(pick(i_need_scissors))
|
||||
else
|
||||
var/static/list/messagevoice = list(
|
||||
"Delicious!" = 'sound/voice/medbot/delicious.ogg',
|
||||
"I knew it, I should've been a plastic surgeon." = 'sound/voice/medbot/surgeon.ogg',
|
||||
"Radar, put a mask on!" = 'sound/voice/medbot/radar.ogg',
|
||||
"There's always a catch, and I'm the best there is." = 'sound/voice/medbot/catch.ogg',
|
||||
"What kind of medbay is this? Everyone's dropping like flies." = 'sound/voice/medbot/flies.ogg',
|
||||
"Why are we still here? Just to suffer?" = 'sound/voice/medbot/why.ogg',
|
||||
var/static/list/idle_lines = list(
|
||||
MEDIBOT_VOICED_DELICIOUS,
|
||||
MEDIBOT_VOICED_PLASTIC_SURGEON,
|
||||
MEDIBOT_VOICED_MASK_ON,
|
||||
MEDIBOT_VOICED_ALWAYS_A_CATCH,
|
||||
MEDIBOT_VOICED_LIKE_FLIES,
|
||||
MEDIBOT_VOICED_SUFFER,
|
||||
)
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 50)
|
||||
speak(pick(idle_lines))
|
||||
var/scan_range = (medical_mode_flags & MEDBOT_STATIONARY_MODE ? 1 : DEFAULT_SCAN_RANGE) //If in stationary mode, scan range is limited to adjacent patients.
|
||||
patient = scan(list(/mob/living/carbon/human), oldpatient, scan_range)
|
||||
oldpatient = patient
|
||||
@@ -515,10 +550,12 @@
|
||||
return
|
||||
|
||||
if(C.stat == DEAD || (HAS_TRAIT(C, TRAIT_FAKEDEATH)))
|
||||
var/list/messagevoice = list("No! Stay with me!" = 'sound/voice/medbot/no.ogg',"Live, damnit! LIVE!" = 'sound/voice/medbot/live.ogg',"I...I've never lost a patient before. Not today, I mean." = 'sound/voice/medbot/lost.ogg')
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 50)
|
||||
var/static/list/grief_lines = list(
|
||||
MEDIBOT_VOICED_STAY_WITH_ME,
|
||||
MEDIBOT_VOICED_LIVE,
|
||||
MEDIBOT_VOICED_NEVER_LOST,
|
||||
)
|
||||
speak(pick(grief_lines))
|
||||
oldpatient = patient
|
||||
soft_reset()
|
||||
return
|
||||
@@ -552,10 +589,12 @@
|
||||
if(C.maxHealth - C.get_organic_health() < heal_threshold)
|
||||
to_chat(src, span_notice("[C] is healthy! Your programming prevents you from tending the wounds of anyone without at least [heal_threshold] damage of any one type ([heal_threshold + 5] for oxygen damage.)"))
|
||||
|
||||
var/list/messagevoice = list("All patched up!" = 'sound/voice/medbot/patchedup.ogg',"An apple a day keeps me away." = 'sound/voice/medbot/apple.ogg',"Feel better soon!" = 'sound/voice/medbot/feelbetter.ogg')
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 50)
|
||||
var/static/list/success_lines = list(
|
||||
MEDIBOT_VOICED_ALL_PATCHED_UP,
|
||||
MEDIBOT_VOICED_APPLE_A_DAY,
|
||||
MEDIBOT_VOICED_FEEL_BETTER,
|
||||
)
|
||||
speak(pick(success_lines))
|
||||
bot_reset()
|
||||
tending = FALSE
|
||||
else if(patient)
|
||||
|
||||
@@ -21,6 +21,15 @@
|
||||
path_image_color = "#FF0000"
|
||||
possessed_message = "You are a securitron! Guard the station to the best of your ability!"
|
||||
|
||||
automated_announcements = list(
|
||||
BEEPSKY_VOICED_CRIMINAL_DETECTED = 'sound/voice/beepsky/criminal.ogg',
|
||||
BEEPSKY_VOICED_FREEZE = 'sound/voice/beepsky/freeze.ogg',
|
||||
BEEPSKY_VOICED_JUSTICE = 'sound/voice/beepsky/justice.ogg',
|
||||
BEEPSKY_VOICED_YOUR_MOVE = 'sound/voice/beepsky/creep.ogg',
|
||||
BEEPSKY_VOICED_I_AM_THE_LAW = 'sound/voice/beepsky/iamthelaw.ogg',
|
||||
BEEPSKY_VOICED_SECURE_DAY = 'sound/voice/beepsky/secureday.ogg',
|
||||
)
|
||||
|
||||
///The type of baton this Secbot will use
|
||||
var/baton_type = /obj/item/melee/baton/security
|
||||
///The type of cuffs we use on criminals after making arrests
|
||||
@@ -453,22 +462,17 @@
|
||||
if(threatlevel >= 4)
|
||||
target = nearby_carbons
|
||||
oldtarget_name = nearby_carbons.name
|
||||
switch(bot_type)
|
||||
if(ADVANCED_SEC_BOT)
|
||||
speak("Level [threatlevel] infraction alert!")
|
||||
playsound(src, pick('sound/voice/ed209_20sec.ogg', 'sound/voice/edplaceholder.ogg'), 50, FALSE)
|
||||
if(HONK_BOT)
|
||||
speak("Honk!")
|
||||
playsound(src, pick('sound/items/bikehorn.ogg'), 50, FALSE)
|
||||
else
|
||||
speak("Level [threatlevel] infraction alert!")
|
||||
playsound(src, pick('sound/voice/beepsky/criminal.ogg', 'sound/voice/beepsky/justice.ogg', 'sound/voice/beepsky/freeze.ogg'), 50, FALSE)
|
||||
|
||||
threat_react(threatlevel)
|
||||
visible_message("<b>[src]</b> points at [nearby_carbons.name]!")
|
||||
mode = BOT_HUNT
|
||||
INVOKE_ASYNC(src, PROC_REF(handle_automated_action))
|
||||
break
|
||||
|
||||
/// React to detecting criminal scum by making some kind of noise
|
||||
/mob/living/simple_animal/bot/secbot/proc/threat_react(threatlevel)
|
||||
speak("Level [threatlevel] infraction alert!")
|
||||
playsound(src, pick('sound/voice/beepsky/criminal.ogg', 'sound/voice/beepsky/justice.ogg', 'sound/voice/beepsky/freeze.ogg'), 50, FALSE)
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/check_for_weapons(obj/item/slot_item)
|
||||
if(slot_item && (slot_item.item_flags & NEEDS_PERMIT))
|
||||
return TRUE
|
||||
|
||||
@@ -4392,6 +4392,7 @@
|
||||
#include "code\modules\mob\living\simple_animal\shade.dm"
|
||||
#include "code\modules\mob\living\simple_animal\simple_animal.dm"
|
||||
#include "code\modules\mob\living\simple_animal\bot\bot.dm"
|
||||
#include "code\modules\mob\living\simple_animal\bot\bot_announcement.dm"
|
||||
#include "code\modules\mob\living\simple_animal\bot\cleanbot.dm"
|
||||
#include "code\modules\mob\living\simple_animal\bot\construction.dm"
|
||||
#include "code\modules\mob\living\simple_animal\bot\ed209bot.dm"
|
||||
|
||||
Reference in New Issue
Block a user