Skip to content

Commit

Permalink
Merge pull request cmss13-devs#7 from Zonespace27/human-ai
Browse files Browse the repository at this point in the history
Human ai
  • Loading branch information
xDanilcusx committed Sep 12, 2024
2 parents 4ef8055 + b8b6829 commit 14dc359
Show file tree
Hide file tree
Showing 10 changed files with 252 additions and 38 deletions.
9 changes: 8 additions & 1 deletion code/controllers/subsystem/human_ai.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
SUBSYSTEM_DEF(human_ai)
name = "Human AI"
priority = SS_PRIORITY_HUMAN_AI
flags = SS_NO_INIT
wait = 0.2 SECONDS
/// A list of mobs scheduled to process
var/list/mob/living/carbon/human/ai/current_run = list()
Expand All @@ -21,6 +20,14 @@ SUBSYSTEM_DEF(human_ai)
/// List of all existing orders
var/list/datum/ongoing_action/existing_orders = list()

var/list/human_ai_factions = list()

/datum/controller/subsystem/human_ai/Initialize()
for(var/faction_path in subtypesof(/datum/human_ai_faction))
var/datum/human_ai_faction/faction_obj = new faction_path
human_ai_factions[faction_obj.faction] = faction_obj
return SS_INIT_SUCCESS

/datum/controller/subsystem/human_ai/stat_entry(msg)
msg = "P:[length(GLOB.human_ai_brains)]"
return ..()
Expand Down
4 changes: 2 additions & 2 deletions code/modules/mob/living/carbon/human/ai/ai_management_menu.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/datum/human_ai_management_menu/New()

/datum/human_ai_management_menu/proc/ui_interact(mob/user, datum/tgui/ui)
/datum/human_ai_management_menu/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "HumanAIManager")
Expand Down Expand Up @@ -122,7 +122,7 @@
return

if(human_ai_menu)
human_ai_menu.ui_interact(mob)
human_ai_menu.tgui_interact(mob)
return

human_ai_menu = new /datum/human_ai_management_menu(src)
Expand Down
56 changes: 48 additions & 8 deletions code/modules/mob/living/carbon/human/ai/brain/ai_brain.dm
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ GLOBAL_LIST_EMPTY(human_ai_brains)
var/combat_decay_time = 30 SECONDS
var/squad_covering = FALSE

var/list/friendly_factions = list()
var/list/neutral_factions = list()
var/previous_faction

/datum/human_ai_brain/New(mob/living/carbon/human/tied_human)
. = ..()
src.tied_human = tied_human
Expand All @@ -43,6 +47,7 @@ GLOBAL_LIST_EMPTY(human_ai_brains)
RegisterSignal(tied_human, COMSIG_MOB_PICKUP_ITEM, PROC_REF(on_item_pickup))
RegisterSignal(tied_human, COMSIG_MOB_DROP_ITEM, PROC_REF(on_item_drop))
RegisterSignal(tied_human, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
RegisterSignal(tied_human, COMSIG_HUMAN_BULLET_ACT, PROC_REF(on_shot))
if(!length(all_medical_items))
all_medical_items = brute_heal_items + burn_heal_items + tox_heal_items + oxy_heal_items + bleed_heal_items + bonebreak_heal_items + painkiller_items
GLOB.human_ai_brains += src
Expand Down Expand Up @@ -85,6 +90,13 @@ GLOBAL_LIST_EMPTY(human_ai_brains)
item_search(things_around)
//bullet_detect(things_around)

if(!currently_busy && primary_weapon && current_target && !currently_firing && COOLDOWN_FINISHED(src, fire_overload_cooldown) && primary_weapon.has_ammunition())
currently_busy = TRUE
if(get_dist(tied_human, current_target) > gun_data.maximum_range)
if(!has_ongoing_action(/datum/ongoing_action/approach_target) && !in_cover)
ADD_ONGOING_ACTION(src, /datum/ongoing_action/approach_target, current_target, gun_data.maximum_range)
attack_target()

if(!currently_busy && healing_start_check())
currently_busy = TRUE
start_healing()
Expand All @@ -97,13 +109,6 @@ GLOBAL_LIST_EMPTY(human_ai_brains)
current_target = get_target(view_distance)
RegisterSignal(current_target, COMSIG_PARENT_QDELETING, PROC_REF(on_target_delete))

if(!currently_busy && primary_weapon && current_target && !currently_firing && COOLDOWN_FINISHED(src, fire_overload_cooldown) && primary_weapon.has_ammunition())
currently_busy = TRUE
if(get_dist(tied_human, current_target) > gun_data.maximum_range)
if(!has_ongoing_action(/datum/ongoing_action/approach_target) && !in_cover)
ADD_ONGOING_ACTION(src, /datum/ongoing_action/approach_target, current_target, gun_data.maximum_range)
attack_target()

/datum/human_ai_brain/proc/on_human_delete(datum/source, force)
SIGNAL_HANDLER
tied_human = null
Expand Down Expand Up @@ -215,8 +220,21 @@ GLOBAL_LIST_EMPTY(human_ai_brains)
if(!in_cover && !faction_check(firer)) // If it's our own bullets, we don't need to be alarmed
locate_cover(bullet, bullet.dir)

/// Returns TRUE if the target is friendly/neutral to us
/datum/human_ai_brain/proc/faction_check(mob/target)
return target?.faction == tied_human.faction
if(!target)
return FALSE

if(target.faction == tied_human.faction)
return TRUE

if(target.faction in friendly_factions)
return TRUE

if(target.faction in neutral_factions)
return TRUE

return FALSE

/datum/human_ai_brain/proc/setup_detection_radius()
if(length(detection_turfs))
Expand Down Expand Up @@ -251,10 +269,14 @@ GLOBAL_LIST_EMPTY(human_ai_brains)
/datum/human_ai_brain/proc/enter_combat()
SIGNAL_HANDLER

if(!in_combat)
say_in_combat_line()
in_combat = TRUE
addtimer(CALLBACK(src, PROC_REF(exit_combat)), combat_decay_time, TIMER_UNIQUE | TIMER_OVERRIDE)

/datum/human_ai_brain/proc/exit_combat()
if(in_combat)
say_exit_combat_line()
in_combat = FALSE

/datum/human_ai_brain/proc/can_process_order()
Expand All @@ -265,3 +287,21 @@ GLOBAL_LIST_EMPTY(human_ai_brains)
return FALSE

return TRUE

/datum/human_ai_brain/proc/on_shot(datum/source, damage_result, ammo_flags, obj/projectile/bullet)
SIGNAL_HANDLER
var/mob/firer = bullet.firer
if(firer?.faction in neutral_factions)
on_neutral_faction_betray(firer.faction)


/datum/human_ai_brain/proc/on_neutral_faction_betray(faction)
if(!tied_human.faction)
return

var/datum/human_ai_faction/our_faction = SShuman_ai.human_ai_factions[tied_human.faction]
if(!our_faction)
return

our_faction.neutral_factions -= faction
our_faction.reapply_faction_data()
Original file line number Diff line number Diff line change
@@ -1,2 +1,54 @@
/datum/human_ai_brain
var/list/in_combat_lines = list()
var/list/in_combat_lines = list(
"Taking fire!",
"Getting shot at!",
"Engaging hostiles!",
"Contact!",
"Contact contact!",
"We've got hostiles!",
"Take 'em down!",
"Hostile spotted, engaging!",
"Enemy hostiles here!",
"Being fired upon!",
"Blast 'em!"
)

var/list/exit_combat_lines = list(
"No more contacts.",
"Don't see 'em.",
"Going back to regular duties.",
"Nothin' left.",
"Can't find 'em.",
"No hostiles, returning to duties.",
)

var/list/squad_member_death_lines = list(
"Fuck! Man down!",
"We lost one!",
"Man down!",
"We're taking losses here!",
"Goddamn it.",
"Fuck!",
"Shit, our squad's down a man!",
"Squad integrity's failing!"
)

var/in_combat_line_chance = 40
var/exit_combat_line_chance = 40
var/squad_member_death_line_chance = 20


/datum/human_ai_brain/proc/say_in_combat_line(chance = in_combat_line_chance)
if(!prob(chance))
return
tied_human.say(pick(in_combat_lines))

/datum/human_ai_brain/proc/say_exit_combat_line(chance = exit_combat_line_chance)
if(!prob(chance))
return
tied_human.say(pick(exit_combat_lines))

/datum/human_ai_brain/proc/on_squad_member_death(mob/living/carbon/human/dead_member)
if(!prob(squad_member_death_line_chance))
return
tied_human.say(pick(squad_member_death_lines))
106 changes: 97 additions & 9 deletions code/modules/mob/living/carbon/human/ai/brain/ai_brain_factions.dm
Original file line number Diff line number Diff line change
@@ -1,14 +1,102 @@
GLOBAL_LIST_INIT(human_ai_factions, assemble_human_ai_factions())

/proc/assemble_human_ai_factions()
. = list()
for(var/datum/human_ai_faction/faction as anything in subtypesof(/datum/human_ai_faction))
faction = new
.[faction.faction] = faction

/datum/human_ai_faction
var/faction = FACTION_NEUTRAL
var/shoot_to_kill = TRUE

var/list/in_combat_lines = list()
var/list/exit_combat_lines = list()
var/list/squad_member_death_lines = list()

var/list/friendly_factions = list()
var/list/neutral_factions = list()

/datum/human_ai_faction/proc/apply_faction_data(datum/human_ai_brain/brain)
return
if(length(in_combat_lines))
brain.in_combat_lines = in_combat_lines

if(length(exit_combat_lines))
brain.exit_combat_lines = exit_combat_lines

if(length(squad_member_death_lines))
brain.squad_member_death_lines = squad_member_death_lines

brain.shoot_to_kill = shoot_to_kill
brain.friendly_factions = friendly_factions
brain.neutral_factions = neutral_factions

/datum/human_ai_faction/proc/reapply_faction_data()
for(var/datum/human_ai_brain/brain in GLOB.human_ai_brains)
if(brain.tied_human?.faction == faction)
apply_faction_data(brain)

/datum/human_ai_faction/clf
faction = FACTION_CLF
friendly_factions = list(
FACTION_COLONIST,
)


/datum/human_ai_faction/uscm
faction = FACTION_USCM
friendly_factions = list(
FACTION_COLONIST,
FACTION_TWE,
FACTION_WY,
)
neutral_factions = list(
FACTION_FREELANCER,
FACTION_CONTRACTOR,
FACTION_UPP,
FACTION_MERCENARY,
)

/datum/human_ai_faction/upp
faction = FACTION_UPP
friendly_factions = list(
FACTION_COLONIST,
)
neutral_factions = list(
FACTION_FREELANCER,
FACTION_CONTRACTOR,
FACTION_USCM,
FACTION_MERCENARY,
FACTION_TWE,
)

/datum/human_ai_faction/wy
faction = FACTION_WY
friendly_factions = list(
FACTION_COLONIST,
FACTION_TWE,
FACTION_MARINE,
)
neutral_factions = list(
FACTION_FREELANCER,
FACTION_CONTRACTOR,
FACTION_USCM,
FACTION_MERCENARY,
)

/datum/human_ai_faction/wy_deathsquad
faction = FACTION_WY_DEATHSQUAD
friendly_factions = list(
FACTION_WY,
)
in_combat_lines = list(
"Visual confirmed, engaging.",
"Engaging hostile.",
"Eliminating hostile.",
"Engaging.",
"Contact.",
"Viscon, proceeding."
)
exit_combat_lines = list(
"Hostilities ceased.",
"Ceasing engagement."
)
squad_member_death_lines = list(
"Allied unit disabled.",
"Friendly unit decomissioned.",
"Allied unit decomissioned.",
"Friendly unit disabled."
)

Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@

/// Currently doesn't support recursive storage
/datum/human_ai_brain/proc/appraise_inventory(belt = TRUE, back = TRUE, pocket_l = TRUE, pocket_r = TRUE)
if(previous_faction != tied_human.faction)
previous_faction = tied_human.faction
var/datum/human_ai_faction/our_faction = SShuman_ai.human_ai_factions[tied_human.faction]
if(!our_faction)
return
our_faction.apply_faction_data(src)

tried_reload = FALSE // We don't really need to do this in a smart way
if(belt)
if(!istype(tied_human.belt, /obj/item/storage/belt))
Expand Down
30 changes: 28 additions & 2 deletions code/modules/mob/living/carbon/human/ai/brain/ai_brain_squad.dm
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,18 @@
ai_in_squad += adding

adding.set_ongoing_order(assigned_order)
RegisterSignal(adding.tied_human, COMSIG_MOB_DEATH, PROC_REF(on_squad_member_death))
RegisterSignal(adding, COMSIG_PARENT_QDELETING, PROC_REF(on_squad_member_delete))

/datum/human_ai_squad/proc/remove_from_squad(datum/human_ai_brain/removing)
if(removing == squad_leader)
squad_leader = null
set_squad_leader(null)
removing.ongoing_order = null
removing.squad_id = null
removing.is_squad_leader = FALSE
ai_in_squad -= removing
UnregisterSignal(removing?.tied_human, COMSIG_MOB_DEATH)
UnregisterSignal(removing, COMSIG_PARENT_QDELETING)

/datum/human_ai_squad/proc/set_order(datum/ongoing_action/order)
assigned_order = order
Expand All @@ -43,7 +47,29 @@
if(squad_leader)
squad_leader.is_squad_leader = FALSE
squad_leader = new_leader
new_leader.is_squad_leader = TRUE
if(squad_leader)
new_leader.is_squad_leader = TRUE

/datum/human_ai_squad/proc/on_squad_member_death(mob/living/carbon/human/dead_mob)
SIGNAL_HANDLER

if(istype(dead_mob, /mob/living/carbon/human/ai))
var/mob/living/carbon/human/ai/dead_squddie = dead_mob
if(squad_leader == dead_squddie.ai_brain)
set_squad_leader(null)

for(var/datum/human_ai_brain/squaddie as anything in ai_in_squad)
if(squaddie.tied_human.is_mob_incapacitated())
continue

squaddie.on_squad_member_death(dead_mob)

/datum/human_ai_squad/proc/on_squad_member_delete(datum/human_ai_brain/deleting)
SIGNAL_HANDLER

remove_from_squad(deleting)



/datum/human_ai_brain
/// Numeric ID of the squad this AI is in, if any
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/// Ref to the last turf that the AI shot at
var/turf/open/target_floor
/// If TRUE, the AI is allowed to establish overwatches
var/overwatch_allowed = TRUE
var/overwatch_allowed = FALSE
/// List of overwatched turfs
var/list/turf/open/overwatch_turfs = list()

Expand Down Expand Up @@ -119,7 +119,7 @@
if(!shoot_to_kill && target.stat == UNCONSCIOUS)
return FALSE

if(target.faction == tied_human.faction)
if(faction_check(target))
return FALSE

if(HAS_TRAIT(target, TRAIT_CLOAKED) && get_dist(tied_human, target) > cloak_visible_range)
Expand Down
Loading

0 comments on commit 14dc359

Please sign in to comment.