Refactored new AI components (#31421)

This commit is contained in:
DamianX
2021-11-28 05:53:50 +01:00
committed by GitHub
parent 64e891d318
commit 31f528a797
6 changed files with 69 additions and 56 deletions

View File

@@ -1,11 +1,9 @@
#define EVENT_HANDLER_OBJREF_INDEX 1
#define EVENT_HANDLER_PROCNAME_INDEX 2
// WARNING
// Event handlers (i.e.: procs that are registered with `proc/register_event` MUST NOT sleep()).
// Declare children of this type path to use as identifiers for the events.
/event
// TODO: Document here the arguments that need to be passed to the procs invoked by each event
// Called by human/proc/apply_radiation()
// Arguments:
// mob/carbon/living/human/user: The human.
@@ -238,6 +236,25 @@
// mob/source: the mob performing the emote
/event/emote
// Called by mob/living/Hear
// Arguments:
// datum/speech/speech: the speech datum being heard
/event/hear
// Called by area/Entered
// Arguments:
// atom/movable/enterer: the movable entering the area
/event/area_entered
// Called by area/Exited
// Arguments:
// atom/movable/exiter: the movable exiting the area
/event/area_exited
// Note: the following are used by datum/component/ai subtypes to give instructions to each other.
// AI components are expected to INVOKE_EVENT these to send commands to other components
// on the same datum without having to hold references to them.
// They may need to be reworked, and they are currently undocumented.
/event/comp_ai_friend_attacked
/event/comp_ai_cmd_get_best_target
@@ -260,11 +277,8 @@
/event/comp_ai_cmd_set_state
/event/comp_ai_cmd_get_state
/event/comp_ai_cmd_hear
/event/comp_ai_cmd_say
/event/comp_ai_cmd_specific_say
/event/comp_ai_cmd_area_enter
/event/comp_ai_cmd_area_exit
/datum
/// Associative list of type path -> list(),
@@ -283,6 +297,9 @@
*/
#define INVOKE_EVENT(target, event_type, arguments...) (target.registered_events?[event_type] && target.invoke_event(event_type, list(##arguments)))
#define EVENT_HANDLER_OBJREF_INDEX 1
#define EVENT_HANDLER_PROCNAME_INDEX 2
/datum/proc/invoke_event(event/event_type, list/arguments)
SHOULD_NOT_OVERRIDE(TRUE)
var/list/event_handlers = registered_events[event_type]

View File

@@ -446,10 +446,9 @@ var/area/space_area
thing.area_entered(src)
for(var/mob/mob_in_obj in Obj.contents)
CallHook("MobAreaChange", list("mob" = mob_in_obj, "new" = src, "old" = oldArea))
INVOKE_EVENT(src, /event/comp_ai_cmd_area_enter, "enterer" = Obj)
INVOKE_EVENT(src, /event/area_entered, "enterer" = Obj)
var/mob/M = Obj
if(istype(M))
CallHook("MobAreaChange", list("mob" = M, "new" = src, "old" = oldArea)) // /vg/ - EVENTS!
@@ -457,7 +456,7 @@ var/area/space_area
narrator.Crossed(M)
/area/Exited(atom/movable/Obj)
INVOKE_EVENT(src, /event/comp_ai_cmd_area_exit, "exiter" = Obj)
INVOKE_EVENT(src, /event/area_exited, "exiter" = Obj)
..()
/area/proc/subjectDied(target)

View File

@@ -7,20 +7,20 @@
/datum/component/ai/area_territorial/proc/SetArea(var/area/new_area)
if(territory)
territory.unregister_event(/event/comp_ai_cmd_area_enter, src, .proc/area_enter)
territory.unregister_event(/event/comp_ai_cmd_area_exit, src, .proc/area_exit)
territory.unregister_event(/event/area_entered, src, .proc/area_enter)
territory.unregister_event(/event/area_exited, src, .proc/area_exit)
territory = new_area
territory.register_event(/event/comp_ai_cmd_area_enter, src, .proc/area_enter)
territory.register_event(/event/comp_ai_cmd_area_exit, src, .proc/area_exit)
territory.register_event(/event/area_entered, src, .proc/area_enter)
territory.register_event(/event/area_exited, src, .proc/area_exit)
/datum/component/ai/area_territorial/proc/area_enter(var/obj/enterer)
/datum/component/ai/area_territorial/proc/area_enter(atom/movable/enterer)
if(isliving(enterer)) // No ghosts
INVOKE_EVENT(parent, enter_signal, enter_args)
/datum/component/ai/area_territorial/proc/area_exit(var/obj/exiter)
/datum/component/ai/area_territorial/proc/area_exit(atom/movable/exiter)
if(isliving(exiter)) // No ghosts
INVOKE_EVENT(parent, exit_signal, exit_args)
/datum/component/ai/area_territorial/say
enter_signal = /event/comp_ai_cmd_specific_say
exit_signal = /event/comp_ai_cmd_specific_say
exit_signal = /event/comp_ai_cmd_specific_say

View File

@@ -25,11 +25,9 @@
var/speech_prob = 30
var/next_speech
var/speech_delay
var/datum/component/ai/target_finder/finder = null
/datum/component/ai/conversation/auto/initialize()
if(..())
finder = parent.get_component(/datum/component/ai/target_finder/simple_view)
active_components += src
return TRUE
@@ -38,15 +36,13 @@
..()
/datum/component/ai/conversation/auto/process()
if(finder && next_speech < world.time && prob(speech_prob))
var/listener
for(var/mob/living/M in finder.cmd_find_targets())
if(next_speech < world.time && prob(speech_prob))
var/list/targets = INVOKE_EVENT(parent, /event/comp_ai_cmd_find_targets)
for(var/mob/living/M in targets)
if(M == src)
continue
if(M.isDead()) //No speaking to the dead
continue
listener = TRUE
next_speech = world.time + speech_delay
cmd_say()
break
if(listener)
next_speech = world.time+speech_delay
cmd_say()

View File

@@ -1,43 +1,44 @@
/datum/component/ai/hearing
var/hear_signal
var/list/required_messages = list()
var/list/hear_args
var/response_delay = 10
var/hear_signal
var/list/required_messages = list()
var/list/hear_args
var/response_delay = 10
/datum/component/ai/hearing/initialize()
parent.register_event(/event/comp_ai_cmd_hear, src, .proc/on_hear)
return TRUE
parent.register_event(/event/hear, src, .proc/on_hear)
return TRUE
/datum/component/ai/hearing/Destroy()
parent.unregister_event(/event/comp_ai_cmd_hear, src, .proc/on_hear)
..()
parent.unregister_event(/event/hear, src, .proc/on_hear)
..()
/datum/component/ai/hearing/proc/on_hear(var/datum/speech/speech)
var/filtered_message = speech.message
filtered_message = replacetext(filtered_message , "?" , "") //Ignores punctuation.
filtered_message = replacetext(filtered_message , "!" , "") //Ignores punctuation.
filtered_message = replacetext(filtered_message , "." , "") //Ignores punctuation.
filtered_message = replacetext(filtered_message , "," , "") //Ignores punctuation.
if(speech.speaker != parent)
if(!required_messages.len)
sleep(response_delay)
INVOKE_EVENT(parent, hear_signal, hear_args)
else
for(var/message in required_messages)
if(findtext(filtered_message,message))
sleep(response_delay)
INVOKE_EVENT(parent, hear_signal, hear_args)
return
/datum/component/ai/hearing/proc/on_hear(datum/speech/speech)
set waitfor = FALSE
var/filtered_message = speech.message
filtered_message = replacetext(filtered_message , "?" , "") //Ignores punctuation.
filtered_message = replacetext(filtered_message , "!" , "") //Ignores punctuation.
filtered_message = replacetext(filtered_message , "." , "") //Ignores punctuation.
filtered_message = replacetext(filtered_message , "," , "") //Ignores punctuation.
if(speech.speaker != parent)
if(!required_messages.len)
sleep(response_delay)
INVOKE_EVENT(parent, hear_signal, hear_args)
else
for(var/message in required_messages)
if(findtext(filtered_message,message))
sleep(response_delay)
INVOKE_EVENT(parent, hear_signal, hear_args)
return
/datum/component/ai/hearing/say
hear_signal = /event/comp_ai_cmd_say
hear_signal = /event/comp_ai_cmd_say
/datum/component/ai/hearing/say_response
hear_signal = /event/comp_ai_cmd_specific_say
hear_signal = /event/comp_ai_cmd_specific_say
/datum/component/ai/hearing/say_response/time
required_messages = list("what time is it","whats the time","do you have the time")
required_messages = list("what time is it","whats the time","do you have the time")
/datum/component/ai/hearing/say_response/time/on_hear(var/datum/speech/speech)
hear_args = list("The current time is [worldtime2text()].")
..()
hear_args = list("The current time is [worldtime2text()].")
..()

View File

@@ -244,7 +244,7 @@ var/list/headset_modes = list(
if(V.spread & SPREAD_MEMETIC)
infect_disease2(V, notes="(Memed, from [L])")
INVOKE_EVENT(src, /event/comp_ai_cmd_hear, "speech" = speech)
INVOKE_EVENT(src, /event/hear, "speech" = speech)
if(!client)
return
say_testing(src, "[src] ([src.type]) has heard a message (lang=[speech.language ? speech.language.name : "null"])")