Skip to content

Commit

Permalink
Merge pull request #6 from Zonespace27/human-ai
Browse files Browse the repository at this point in the history
Human ai
  • Loading branch information
xDanilcusx authored Sep 8, 2024
2 parents 92944b9 + c7d4807 commit 7dfe97f
Show file tree
Hide file tree
Showing 49 changed files with 2,823 additions and 45 deletions.
3 changes: 3 additions & 0 deletions code/__DEFINES/dcs/signals/atom/mob/living/signals_human.dm
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
//from /mob/living/carbon/human/equip_to_slot()
#define COMSIG_HUMAN_EQUIPPED_ITEM "human_equipped_item"

//from /mob/living/carbon/human/u_equip()
#define COMSIG_HUMAN_UNEQUIPPED_ITEM "human_unequipped_item"

/// From /mob/proc/equip_to_slot_if_possible()
#define COMSIG_HUMAN_ATTEMPTING_EQUIP "human_attempting_equip"
#define COMPONENT_HUMAN_CANCEL_ATTEMPT_EQUIP (1<<0)
Expand Down
2 changes: 2 additions & 0 deletions code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,5 @@

/// Cancels all running cloaking effects on target
#define COMSIG_MOB_EFFECT_CLOAK_CANCEL "mob_effect_cloak_cancel"

#define COMSIG_MOB_DROP_ITEM "mob_drop_item"
4 changes: 4 additions & 0 deletions code/__DEFINES/equipment.dm
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@
#define FORCEDROP_CONDITIONAL (1<<14)
/// Overrides smartgunner not being able to wear backpacks
#define SMARTGUNNER_BACKPACK_OVERRIDE (1<<15)
/// This item is classified as a healing item for the sake of human AI
#define HEALING_ITEM (1<<16)
/// This item is classified as ammunition for the sake of human AI
#define AMMUNITION_ITEM (1<<17)
//==========================================================================================


Expand Down
13 changes: 13 additions & 0 deletions code/__DEFINES/human_ai.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#define HUMAN_AI_HEALTHITEMS "health"
#define HUMAN_AI_AMMUNITION "ammo"

/// Action is completed, delete this and move onto the next ongoing action
#define ONGOING_ACTION_COMPLETED "completed"
/// Action isn't finished, move onto the next ongoing action
#define ONGOING_ACTION_UNFINISHED "unfinished"
/// Action isn't finished, block any further actions from the AI this tick
#define ONGOING_ACTION_UNFINISHED_BLOCK "unfinished_block"

#define ADD_ONGOING_ACTION(brain, path, arguments...) brain:_add_ongoing_action(path, ##arguments)

#define HUMAN_AI_MAX_PATHFINDING_RANGE 45
3 changes: 2 additions & 1 deletion code/__DEFINES/subsystems.dm
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@
#define SS_PRIORITY_SOUND 250
#define SS_PRIORITY_TICKER 200
#define SS_PRIORITY_XENO_AI 185
#define SS_PRIORITY_HUMAN_AI 182
#define SS_PRIORITY_NIGHTMARE 180
#define SS_PRIORITY_QUADTREE 160
#define SS_PRIORITY_CHAT 155
Expand All @@ -171,7 +172,7 @@
#define SS_PRIORITY_MOB 150
#define SS_PRIORITY_XENO 149
#define SS_PRIORITY_HUMAN 148
#define SS_PRIORITY_XENO_PATHFINDING 130
#define SS_PRIORITY_PATHFINDING 130
#define SS_PRIORITY_STAMINA 126
#define SS_PRIORITY_COMPONENT 125
#define SS_PRIORITY_NANOUI 120
Expand Down
2 changes: 1 addition & 1 deletion code/__DEFINES/xeno_ai.dm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#define XENO_CALCULATING_PATH(X) (X in SSxeno_pathfinding.hash_path)
#define CALCULATING_PATH(X) (X in SSpathfinding.hash_path)

#define DIRECTION_CHANGE_PENALTY 2
#define NO_WEED_PENALTY 2
Expand Down
31 changes: 29 additions & 2 deletions code/__HELPERS/unsorted.dm
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
#define format_frequency(f) "[round(f / 10)].[f % 10]"

#define reverse_direction(direction) ( \
( dir & (NORTH|SOUTH) ? ~dir & (NORTH|SOUTH) : 0 ) | \
( dir & (EAST|WEST) ? ~dir & (EAST|WEST) : 0 ) \
( direction & (NORTH|SOUTH) ? ~direction & (NORTH|SOUTH) : 0 ) | \
( direction & (EAST|WEST) ? ~direction & (EAST|WEST) : 0 ) \
)

// The sane, counter-clockwise angle to turn to get from /direction/ A to /direction/ B
Expand Down Expand Up @@ -2149,3 +2149,30 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars,list(

if(NORTHWEST)
return list(NORTHWEST, NORTH, WEST)

/// Makes a given dir cardinal. If the dir is non-cardinal, it will return both cardinal directions that make up the direction. Else, it will be a single-entry list returned.
/proc/make_dir_cardinal(direction)
switch(direction)
if(NORTH)
return list(NORTH)

if(EAST)
return list(EAST)

if(SOUTH)
return list(SOUTH)

if(WEST)
return list(WEST)

if(NORTHEAST)
return list(NORTH, EAST)

if(SOUTHEAST)
return list(EAST, SOUTH)

if(SOUTHWEST)
return list(SOUTH, WEST)

if(NORTHWEST)
return list(NORTH, WEST)
2 changes: 1 addition & 1 deletion code/_compile_options.dm
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@

//#define UNIT_TESTS //If this is uncommented, we do a single run though of the game setup and tear down process with unit tests in between

// #define TESTING
#define TESTING
// #define REFERENCE_TRACKING
// #define GC_FAILURE_HARD_LOOKUP
6 changes: 3 additions & 3 deletions code/_globalvars/global_lists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ GLOBAL_REFERENCE_LIST_INDEXED(xeno_datum_list, /datum/caste_datum, caste_type)

//Chem Stuff
var/global/list/chemical_reactions_filtered_list //List of all /datum/chemical_reaction datums filtered by reaction components. Used during chemical reactions
var/global/list/chemical_reactions_list //List of all /datum/chemical_reaction datums indexed by reaction id. Used to search for the result instead of the components.
var/global/list/chemical_reagents_list //List of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff
var/global/list/chemical_properties_list //List of all /datum/chem_property datums indexed by property name
var/global/list/datum/chemical_reaction/chemical_reactions_list //List of all /datum/chemical_reaction datums indexed by reaction id. Used to search for the result instead of the components.
var/global/list/datum/reagent/chemical_reagents_list //List of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff
var/global/list/datum/chem_property/chemical_properties_list //List of all /datum/chem_property datums indexed by property name
//List of all id's from classed /datum/reagent datums indexed by class or tier. Used by chemistry generator and chem spawners.
var/global/list/list/chemical_gen_classes_list = list("C" = list(),"C1" = list(),"C2" = list(),"C3" = list(),"C4" = list(),"C5" = list(),"C6" = list(),"T1" = list(),"T2" = list(),"T3" = list(),"T4" = list(),"tau" = list())
//properties generated in chemicals, helps to make sure the same property doesn't show up 10 times
Expand Down
72 changes: 72 additions & 0 deletions code/controllers/subsystem/human_ai.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@

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()

var/ai_kill = FALSE

/// List of current squads
var/list/datum/human_ai_squad/squads = list()

/// Dict of "id" : squad
var/list/squad_id_dict = list()

/// The current highest ID of any squad
var/highest_squad_id = 0

/// List of all existing orders
var/list/datum/ongoing_action/existing_orders = list()

/datum/controller/subsystem/human_ai/stat_entry(msg)
msg = "P:[length(GLOB.human_ai_brains)]"
return ..()

/datum/admins/proc/toggle_human_ai()
set name = "Toggle Human AI"
set category = "Debug.HumanAI"

if(!check_rights(R_DEBUG))
return

SShuman_ai.ai_kill = !SShuman_ai.ai_kill
message_admins("[key_name_admin(usr)] [SShuman_ai.ai_kill? "killed" : "revived"] all human AI.")

/datum/controller/subsystem/human_ai/fire(resumed = FALSE)
if(ai_kill)
return

if(!resumed)
src.current_run = GLOB.human_ai_brains.Copy()
// Cache for sanic speed (lists are references anyways)
var/list/current_run = src.current_run
while(length(current_run))
var/datum/human_ai_brain/brain = current_run[length(current_run)]
current_run.len--
if(!QDELETED(brain) && !brain.tied_human?.client)
brain.process(wait * 0.1)

if(MC_TICK_CHECK)
return

/datum/controller/subsystem/human_ai/proc/create_new_squad()
highest_squad_id++
var/datum/human_ai_squad/new_squad = new
squads += new_squad
squad_id_dict["[highest_squad_id]"] = new_squad

/datum/controller/subsystem/human_ai/proc/get_squad(squad_id)
RETURN_TYPE(/datum/human_ai_squad)

if(!squad_id || !(squad_id in squad_id_dict))
return null
return squad_id_dict[squad_id]

/datum/controller/subsystem/human_ai/proc/create_new_order(datum/ongoing_action/path, ...)
if(!path::order)
stack_trace("Action of [path] was attempted to be created as an order.")
existing_orders += new path(args)

51 changes: 24 additions & 27 deletions code/controllers/subsystem/pathfinding.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
SUBSYSTEM_DEF(xeno_pathfinding)
name = "Xeno Pathfinding"
priority = SS_PRIORITY_XENO_PATHFINDING
SUBSYSTEM_DEF(pathfinding)
name = "Pathfinding"
priority = SS_PRIORITY_PATHFINDING
flags = SS_NO_INIT|SS_TICKER|SS_BACKGROUND
wait = 1
/// A list of mobs scheduled to process
Expand All @@ -11,11 +11,11 @@ SUBSYSTEM_DEF(xeno_pathfinding)
var/list/hash_path = list()
var/current_position = 1

/datum/controller/subsystem/xeno_pathfinding/stat_entry(msg)
/datum/controller/subsystem/pathfinding/stat_entry(msg)
msg = "P:[length(paths_to_calculate)]"
return ..()

/datum/controller/subsystem/xeno_pathfinding/fire(resumed = FALSE)
/datum/controller/subsystem/pathfinding/fire(resumed = FALSE)
if(!resumed)
current_processing = paths_to_calculate.Copy()

Expand All @@ -29,8 +29,6 @@ SUBSYSTEM_DEF(xeno_pathfinding)

var/turf/target = current_run.finish

var/mob/living/carbon/xenomorph/X = current_run.travelling_xeno

var/list/visited_nodes = current_run.visited_nodes
var/list/distances = current_run.distances
var/list/f_distances = current_run.f_distances
Expand All @@ -46,7 +44,7 @@ SUBSYSTEM_DEF(xeno_pathfinding)
var/turf/neighbor = get_step(current_run.current_node, direction)
var/distance_between = distances[current_run.current_node] * DISTANCE_PENALTY
if(isnull(distances[neighbor]))
if(get_dist(neighbor, X) > current_run.path_range)
if(get_dist(neighbor, current_run.agent) > current_run.path_range)
continue
distances[neighbor] = INFINITY
f_distances[neighbor] = INFINITY
Expand All @@ -61,12 +59,11 @@ SUBSYSTEM_DEF(xeno_pathfinding)
var/atom/A = i
distance_between += A.object_weight

var/list/L = LinkBlocked(X, current_run.current_node, neighbor, current_run.ignore, TRUE)
L += check_special_blockers(X, neighbor)
var/list/L = LinkBlocked(current_run.agent, current_run.current_node, neighbor, current_run.ignore, TRUE)
L += check_special_blockers(current_run.agent, neighbor)
if(length(L))
for(var/i in L)
var/atom/A = i
distance_between += A.xeno_ai_obstacle(X, direction, target)
for(var/atom/A as anything in L)
distance_between += A.xeno_ai_obstacle(current_run.agent, direction, target)

if(distance_between < distances[neighbor])
distances[neighbor] = distance_between
Expand Down Expand Up @@ -126,7 +123,7 @@ SUBSYSTEM_DEF(xeno_pathfinding)
current_run.to_return.Invoke(path)
QDEL_NULL(current_run)

/datum/controller/subsystem/xeno_pathfinding/proc/check_special_blockers(mob/living/carbon/xenomorph/xeno, turf/checking_turf)
/datum/controller/subsystem/pathfinding/proc/check_special_blockers(mob/agent, turf/checking_turf)
var/list/pass_back = list()

for(var/spec_blocker in XENO_AI_SPECIAL_BLOCKERS)
Expand All @@ -137,23 +134,23 @@ SUBSYSTEM_DEF(xeno_pathfinding)

return pass_back

/datum/controller/subsystem/xeno_pathfinding/proc/stop_calculating_path(mob/living/carbon/xenomorph/X)
var/datum/xeno_pathinfo/data = hash_path[X]
/datum/controller/subsystem/pathfinding/proc/stop_calculating_path(mob/agent)
var/datum/xeno_pathinfo/data = hash_path[agent]
qdel(data)

/datum/controller/subsystem/xeno_pathfinding/proc/calculate_path(atom/start, atom/finish, path_range, mob/living/carbon/xenomorph/travelling_xeno, datum/callback/CB, list/ignore)
/datum/controller/subsystem/pathfinding/proc/calculate_path(atom/start, atom/finish, path_range, mob/agent, datum/callback/CB, list/ignore)
if(!get_turf(start) || !get_turf(finish))
return

var/datum/xeno_pathinfo/data = hash_path[travelling_xeno]
SSxeno_pathfinding.current_processing -= data
var/datum/xeno_pathinfo/data = hash_path[agent]
SSpathfinding.current_processing -= data


if(!data)
data = new()
data.RegisterSignal(travelling_xeno, COMSIG_PARENT_QDELETING, TYPE_PROC_REF(/datum/xeno_pathinfo, qdel_wrapper))
data.RegisterSignal(agent, COMSIG_PARENT_QDELETING, TYPE_PROC_REF(/datum/xeno_pathinfo, qdel_wrapper))

hash_path[travelling_xeno] = data
hash_path[agent] = data
paths_to_calculate += data

data.current_node = get_turf(start)
Expand All @@ -162,7 +159,7 @@ SUBSYSTEM_DEF(xeno_pathfinding)
var/turf/target = get_turf(finish)

data.finish = target
data.travelling_xeno = travelling_xeno
data.agent = agent
data.to_return = CB
data.path_range = path_range
data.ignore = ignore
Expand All @@ -175,7 +172,7 @@ SUBSYSTEM_DEF(xeno_pathfinding)
/datum/xeno_pathinfo
var/turf/start
var/turf/finish
var/mob/living/carbon/xenomorph/travelling_xeno
var/mob/agent
var/datum/callback/to_return
var/path_range

Expand All @@ -198,17 +195,17 @@ SUBSYSTEM_DEF(xeno_pathfinding)
prev = list()

/datum/xeno_pathinfo/Destroy(force)
SSxeno_pathfinding.hash_path -= travelling_xeno
SSxeno_pathfinding.paths_to_calculate -= src
SSxeno_pathfinding.current_processing -= src
SSpathfinding.hash_path -= agent
SSpathfinding.paths_to_calculate -= src
SSpathfinding.current_processing -= src

#ifdef TESTING
addtimer(CALLBACK(src, PROC_REF(clear_colors), distances), 5 SECONDS)
#endif

start = null
finish = null
travelling_xeno = null
agent = null
to_return = null
visited_nodes = null
distances = null
Expand Down
6 changes: 6 additions & 0 deletions code/game/objects/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1087,3 +1087,9 @@ cases. Override_icon_state should be a list.*/
///Called by /mob/living/carbon/swap_hand() when hands are swapped
/obj/item/proc/hands_swapped(mob/living/carbon/swapper_of_hands)
return

/obj/item/proc/ai_use(mob/living/carbon/human/user)
return

/obj/item/proc/ai_can_use(mob/living/carbon/human/user)
return FALSE
Loading

0 comments on commit 7dfe97f

Please sign in to comment.