mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-10 01:49:19 +00:00
Merge pull request #15742 from timothyteakettle/vtuber-ai
lets AIs control status displays (vtuber mode)
This commit is contained in:
@@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#define MODE_ALIEN "alientalk"
|
#define MODE_ALIEN "alientalk"
|
||||||
#define MODE_HOLOPAD "holopad"
|
#define MODE_HOLOPAD "holopad"
|
||||||
|
#define MODE_STATUSDISPLAY "statusdisplay"
|
||||||
|
|
||||||
#define MODE_CHANGELING "changeling"
|
#define MODE_CHANGELING "changeling"
|
||||||
#define MODE_KEY_CHANGELING "g"
|
#define MODE_KEY_CHANGELING "g"
|
||||||
|
|||||||
@@ -120,6 +120,17 @@
|
|||||||
return FALSE
|
return FALSE
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
|
/datum/saymode/statusdisplay
|
||||||
|
key = "q"
|
||||||
|
mode = MODE_STATUSDISPLAY
|
||||||
|
|
||||||
|
/datum/saymode/statusdisplay/handle_message(mob/living/user, message, datum/language/language)
|
||||||
|
if(isAI(user))
|
||||||
|
var/mob/living/silicon/ai/AI = user
|
||||||
|
AI.statusdisplay_talk(message, language)
|
||||||
|
return FALSE
|
||||||
|
return TRUE
|
||||||
|
|
||||||
/datum/saymode/monkey
|
/datum/saymode/monkey
|
||||||
key = "k"
|
key = "k"
|
||||||
mode = MODE_MONKEY
|
mode = MODE_MONKEY
|
||||||
|
|||||||
@@ -29,10 +29,12 @@
|
|||||||
|
|
||||||
var/obj/effect/overlay/status_display_text/message1_overlay
|
var/obj/effect/overlay/status_display_text/message1_overlay
|
||||||
var/obj/effect/overlay/status_display_text/message2_overlay
|
var/obj/effect/overlay/status_display_text/message2_overlay
|
||||||
|
var/mutable_appearance/ai_vtuber_overlay
|
||||||
var/current_picture = ""
|
var/current_picture = ""
|
||||||
var/current_mode = SD_BLANK
|
var/current_mode = SD_BLANK
|
||||||
var/message1 = ""
|
var/message1 = ""
|
||||||
var/message2 = ""
|
var/message2 = ""
|
||||||
|
var/mob/living/silicon/ai/master
|
||||||
|
|
||||||
/obj/item/wallframe/status_display
|
/obj/item/wallframe/status_display
|
||||||
name = "status display frame"
|
name = "status display frame"
|
||||||
@@ -122,6 +124,10 @@
|
|||||||
if(overlay && message == overlay.message)
|
if(overlay && message == overlay.message)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
// if an AI is controlling, we don't update the overlay
|
||||||
|
if(master)
|
||||||
|
return
|
||||||
|
|
||||||
if(overlay)
|
if(overlay)
|
||||||
qdel(overlay)
|
qdel(overlay)
|
||||||
|
|
||||||
@@ -147,6 +153,10 @@
|
|||||||
remove_messages()
|
remove_messages()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if(master)
|
||||||
|
remove_messages()
|
||||||
|
return
|
||||||
|
|
||||||
switch(current_mode)
|
switch(current_mode)
|
||||||
if(SD_BLANK)
|
if(SD_BLANK)
|
||||||
remove_messages()
|
remove_messages()
|
||||||
@@ -493,6 +503,42 @@
|
|||||||
user.emote(initial(emote.key))
|
user.emote(initial(emote.key))
|
||||||
break
|
break
|
||||||
|
|
||||||
|
// ai vtuber moment
|
||||||
|
/obj/machinery/status_display/AICtrlClick(mob/living/silicon/ai/user)
|
||||||
|
if(!isAI(user) || master || (user.current && !istype(user.current, /obj/machinery/status_display))) // don't let two AIs control the same one, don't let AI control two things at once
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!user.client.prefs.custom_holoform_icon)
|
||||||
|
to_chat(user, span_notice("You have no custom holoform set!"))
|
||||||
|
return
|
||||||
|
|
||||||
|
// move AI to the location, set master, update overlays (removes messages)
|
||||||
|
user.current = src
|
||||||
|
user.eyeobj.setLoc(get_turf(src))
|
||||||
|
icon_state = initial(icon_state)
|
||||||
|
user.controlled_display = src
|
||||||
|
master = user
|
||||||
|
update_overlays()
|
||||||
|
update_appearance()
|
||||||
|
|
||||||
|
// we set the avatar here
|
||||||
|
var/icon/I = icon(user.client.prefs.custom_holoform_icon)
|
||||||
|
I.Crop(1,16,32,32)
|
||||||
|
ai_vtuber_overlay = mutable_appearance(I)
|
||||||
|
ai_vtuber_overlay.blend_mode = BLEND_ADD
|
||||||
|
ai_vtuber_overlay.pixel_y = 8
|
||||||
|
update_overlays()
|
||||||
|
add_overlay(ai_vtuber_overlay)
|
||||||
|
|
||||||
|
// tell the user how to speak
|
||||||
|
to_chat(user, span_notice("Use :q to relay messages through the status display."))
|
||||||
|
|
||||||
|
// modified version of how holopads 'hear' and relay to AIs
|
||||||
|
/obj/machinery/status_display/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list())
|
||||||
|
. = ..()
|
||||||
|
if(master && !radio_freq && master.controlled_display == src)
|
||||||
|
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
|
||||||
|
|
||||||
/obj/machinery/status_display/ai/process()
|
/obj/machinery/status_display/ai/process()
|
||||||
if(stat & NOPOWER)
|
if(stat & NOPOWER)
|
||||||
update_appearance()
|
update_appearance()
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
var/mob/living/simple_animal/bot/Bot
|
var/mob/living/simple_animal/bot/Bot
|
||||||
var/tracking = FALSE //this is 1 if the AI is currently tracking somebody, but the track has not yet been completed.
|
var/tracking = FALSE //this is 1 if the AI is currently tracking somebody, but the track has not yet been completed.
|
||||||
var/datum/effect_system/spark_spread/spark_system//So they can initialize sparks whenever/N
|
var/datum/effect_system/spark_spread/spark_system//So they can initialize sparks whenever/N
|
||||||
|
var/obj/machinery/status_display/controlled_display
|
||||||
|
|
||||||
//MALFUNCTION
|
//MALFUNCTION
|
||||||
var/datum/module_picker/malf_picker
|
var/datum/module_picker/malf_picker
|
||||||
@@ -1043,3 +1044,14 @@
|
|||||||
|
|
||||||
/mob/living/silicon/ai/zMove(dir, feedback = FALSE)
|
/mob/living/silicon/ai/zMove(dir, feedback = FALSE)
|
||||||
. = eyeobj.zMove(dir, feedback)
|
. = eyeobj.zMove(dir, feedback)
|
||||||
|
|
||||||
|
/mob/living/silicon/ai/proc/stop_controlling_display()
|
||||||
|
if(!controlled_display)
|
||||||
|
return
|
||||||
|
controlled_display.master = null
|
||||||
|
controlled_display.cut_overlay(controlled_display.ai_vtuber_overlay)
|
||||||
|
controlled_display.ai_vtuber_overlay = null
|
||||||
|
if(current == controlled_display)
|
||||||
|
current = null
|
||||||
|
controlled_display.update_appearance()
|
||||||
|
controlled_display = null
|
||||||
|
|||||||
@@ -92,6 +92,8 @@
|
|||||||
ai.light_cameras()
|
ai.light_cameras()
|
||||||
if(ai.master_multicam)
|
if(ai.master_multicam)
|
||||||
ai.master_multicam.refresh_view()
|
ai.master_multicam.refresh_view()
|
||||||
|
if(ai.controlled_display)
|
||||||
|
ai.stop_controlling_display()
|
||||||
|
|
||||||
//it uses setLoc not forceMove, talks to the sillycone and not the camera mob
|
//it uses setLoc not forceMove, talks to the sillycone and not the camera mob
|
||||||
/mob/camera/aiEye/zMove(dir, feedback = FALSE)
|
/mob/camera/aiEye/zMove(dir, feedback = FALSE)
|
||||||
@@ -168,6 +170,9 @@
|
|||||||
if(!user.tracking)
|
if(!user.tracking)
|
||||||
user.cameraFollow = null
|
user.cameraFollow = null
|
||||||
|
|
||||||
|
if(user.controlled_display)
|
||||||
|
user.stop_controlling_display()
|
||||||
|
|
||||||
// Return to the Core.
|
// Return to the Core.
|
||||||
/mob/living/silicon/ai/proc/view_core()
|
/mob/living/silicon/ai/proc/view_core()
|
||||||
if(istype(current,/obj/machinery/holopad))
|
if(istype(current,/obj/machinery/holopad))
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
//For holopads only. Usable by AI.
|
//For holopads only. Usable by AI.
|
||||||
/mob/living/silicon/ai/proc/holopad_talk(message, language)
|
/mob/living/silicon/ai/proc/holopad_talk(message, language)
|
||||||
|
message_admins("HOLOPAD TALK")
|
||||||
|
|
||||||
message = trim(message)
|
message = trim(message)
|
||||||
|
|
||||||
@@ -56,6 +56,30 @@
|
|||||||
to_chat(src, "No holopad connected.")
|
to_chat(src, "No holopad connected.")
|
||||||
|
|
||||||
|
|
||||||
|
//For status displays only. Usable by AI.
|
||||||
|
/mob/living/silicon/ai/proc/statusdisplay_talk(message, language)
|
||||||
|
message_admins("STATUSDISPLAY TALK")
|
||||||
|
message = trim(message)
|
||||||
|
|
||||||
|
if (!message)
|
||||||
|
return
|
||||||
|
|
||||||
|
var/obj/machinery/status_display/T = controlled_display
|
||||||
|
if(T)
|
||||||
|
var/turf/padturf = get_turf(T)
|
||||||
|
var/padloc
|
||||||
|
if(padturf)
|
||||||
|
padloc = AREACOORD(padturf)
|
||||||
|
else
|
||||||
|
padloc = "(UNKNOWN)"
|
||||||
|
src.log_talk(message, LOG_SAY, tag="STATUS DISPLAY in [padloc]")
|
||||||
|
send_speech(message, 7, T, "robot", message_language = language)
|
||||||
|
to_chat(src, "<i><span class='game say'>Status Display message transmitted, <span class='name'>[real_name]</span> <span class='message robot'>\"[message]\"</span></span></i>")
|
||||||
|
else
|
||||||
|
to_chat(src, "No status display connected.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Make sure that the code compiles with AI_VOX undefined
|
// Make sure that the code compiles with AI_VOX undefined
|
||||||
#ifdef AI_VOX
|
#ifdef AI_VOX
|
||||||
#define VOX_DELAY 600
|
#define VOX_DELAY 600
|
||||||
|
|||||||
Reference in New Issue
Block a user