diff --git a/code/modules/mob/living/carbon/human/ai/action_datums/item_pickup.dm b/code/modules/mob/living/carbon/human/ai/action_datums/item_pickup.dm index 0350514143..b187d3b543 100644 --- a/code/modules/mob/living/carbon/human/ai/action_datums/item_pickup.dm +++ b/code/modules/mob/living/carbon/human/ai/action_datums/item_pickup.dm @@ -21,7 +21,10 @@ if(get_dist(to_pickup, brain.tied_human) > 1) return ONGOING_ACTION_UNFINISHED - if(!brain.primary_weapon && isgun(to_pickup)) + if(brain.primary_weapon) + brain.primary_weapon.unwield(brain.tied_human) + + else if(isgun(to_pickup)) brain.tied_human.put_in_hands(to_pickup, TRUE) var/obj/item/weapon/gun/primary = to_pickup // We do the three below lines to make it so that the AI can immediately pick up a gun and open fire. This ensures that we don't need to account for this possibility when firing. diff --git a/code/modules/mob/living/carbon/human/ai/brain/ai_brain.dm b/code/modules/mob/living/carbon/human/ai/brain/ai_brain.dm index 5d7af3da8b..e2d2f80cd4 100644 --- a/code/modules/mob/living/carbon/human/ai/brain/ai_brain.dm +++ b/code/modules/mob/living/carbon/human/ai/brain/ai_brain.dm @@ -21,6 +21,9 @@ GLOBAL_LIST_EMPTY(human_ai_brains) /// How far the AI will chuck a nade if they can't find an enemy to throw it back at var/nade_direction_throw = 4 + /// How long we will ignore max fire distance after shot from afar + var/return_fire_duration = 5 SECONDS + /// List of current action datums var/list/ongoing_actions = list() @@ -92,6 +95,10 @@ GLOBAL_LIST_EMPTY(human_ai_brains) item_search(things_around) //bullet_detect(things_around) + if(!currently_busy && should_reload_primary()) + currently_busy = TRUE + reload_primary() + if(primary_weapon && current_target) if(!has_ongoing_action(AI_ACTION_APPROACH) && !has_ongoing_action(AI_ACTION_RETREAT)) var/target_futile = current_target.is_mob_incapacitated() @@ -113,10 +120,6 @@ GLOBAL_LIST_EMPTY(human_ai_brains) currently_busy = TRUE start_healing() - if(!currently_busy && should_reload_primary()) - currently_busy = TRUE - reload_primary() - if(!currently_busy && !current_target && primary_weapon) current_target = get_target(view_distance) RegisterSignal(current_target, COMSIG_PARENT_QDELETING, PROC_REF(on_target_delete)) @@ -289,6 +292,7 @@ GLOBAL_LIST_EMPTY(human_ai_brains) /datum/human_ai_brain/proc/exit_combat() if(in_combat) say_exit_combat_line() + holster_primary() in_combat = FALSE /datum/human_ai_brain/proc/can_process_order() @@ -302,11 +306,17 @@ GLOBAL_LIST_EMPTY(human_ai_brains) /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) + if(primary_weapon?.ammo.max_range <= get_dist(tied_human, firer)) + COOLDOWN_START(src, return_fire, return_fire_duration) + if(!faction_check(firer)) + if(current_target != firer) + end_gun_fire() current_target = firer /datum/human_ai_brain/proc/on_neutral_faction_betray(faction) diff --git a/code/modules/mob/living/carbon/human/ai/brain/ai_brain_health.dm b/code/modules/mob/living/carbon/human/ai/brain/ai_brain_health.dm index 32f5381b57..bddf6a5041 100644 --- a/code/modules/mob/living/carbon/human/ai/brain/ai_brain_health.dm +++ b/code/modules/mob/living/carbon/human/ai/brain/ai_brain_health.dm @@ -78,6 +78,7 @@ if(!brute_heal) goto bleed + end_gun_fire() holster_primary() equip_item_from_equipment_map(HUMAN_AI_HEALTHITEMS, brute_heal) sleep(short_action_delay) diff --git a/code/modules/mob/living/carbon/human/ai/brain/ai_brain_targeting.dm b/code/modules/mob/living/carbon/human/ai/brain/ai_brain_targeting.dm index b91cd20420..9219b8a511 100644 --- a/code/modules/mob/living/carbon/human/ai/brain/ai_brain_targeting.dm +++ b/code/modules/mob/living/carbon/human/ai/brain/ai_brain_targeting.dm @@ -16,6 +16,8 @@ /// List of overwatched turfs var/list/turf/open/overwatch_turfs = list() + COOLDOWN_DECLARE(return_fire) + /datum/human_ai_brain/proc/get_target(range) var/list/viable_targets = list() var/atom/movable/closest_target @@ -144,13 +146,13 @@ tied_human.face_atom(current_target) - if(get_dist(tied_human, current_target) > gun_data.maximum_range) + if(get_dist(tied_human, current_target) > gun_data.maximum_range && COOLDOWN_FINISHED(src, return_fire)) currently_busy = FALSE return primary_weapon.set_target(current_target) gun_data.before_fire(primary_weapon, tied_human, src) - if((!primary_weapon?.current_mag.current_rounds && !primary_weapon.in_chamber) || !friendly_check()) + if((!primary_weapon?.current_mag?.current_rounds && !primary_weapon?.in_chamber) || !friendly_check()) end_gun_fire() return @@ -203,7 +205,7 @@ end_gun_fire() return - if(primary_weapon.current_mag?.current_rounds <= 1 && !primary_weapon.in_chamber) // bullet removal comes after comsig is triggered + if(primary_weapon.current_mag?.current_rounds <= 0 && !primary_weapon.in_chamber) // bullet removal comes after comsig is triggered end_gun_fire() if(gun_data?.disposable) var/obj/item/gun = primary_weapon @@ -211,14 +213,21 @@ tied_human.drop_held_item(gun) return - if(get_dist(tied_human, current_target) > gun_data.maximum_range) - end_gun_fire() - if(grenading_allowed) + if(!(current_target in viewers(view_distance, tied_human))) + if(COOLDOWN_FINISHED(src, return_fire)) + end_gun_fire() + if(grenading_allowed && length(equipment_map[HUMAN_AI_GRENADES])) throw_grenade_cover() - else if(overwatch_allowed) + return + if(overwatch_allowed) establish_overwatch() - else if(!in_cover) - ADD_ONGOING_ACTION(src, AI_ACTION_APPROACH_CAREFUL, current_target, 0) + return + + if(get_dist(tied_human, current_target) > gun_data.maximum_range) + if(COOLDOWN_FINISHED(src, return_fire)) + end_gun_fire() + if(!in_cover) // Doing this independently from viewers() check so we don't chase enemy if it's hid just around the corner. Might move it back + ADD_ONGOING_ACTION(src, AI_ACTION_APPROACH_CAREFUL, target_floor, 0) return if(istype(primary_weapon, /obj/item/weapon/gun/shotgun/pump)) diff --git a/code/modules/mob/living/carbon/human/ai/firearm_appraisal.dm b/code/modules/mob/living/carbon/human/ai/firearm_appraisal.dm index c027d7fd77..da22edd568 100644 --- a/code/modules/mob/living/carbon/human/ai/firearm_appraisal.dm +++ b/code/modules/mob/living/carbon/human/ai/firearm_appraisal.dm @@ -57,12 +57,11 @@ GLOBAL_LIST_INIT_TYPED(firearm_appraisals, /datum/firearm_appraisal, build_firea /obj/item/weapon/gun/shotgun, ) -/datum/firearm_appraisal/shotgun/before_fire(obj/item/weapon/gun/shotgun/pump/firearm, mob/living/carbon/user, datum/human_ai_brain/AI) +/datum/firearm_appraisal/shotgun/before_fire(obj/item/weapon/gun/shotgun/firearm, mob/living/carbon/user, datum/human_ai_brain/AI) . = ..() if(firearm.in_chamber) return firearm.unique_action(user) - firearm.recent_pump = world.time /datum/firearm_appraisal/boltaction gun_types = list( @@ -97,7 +96,7 @@ GLOBAL_LIST_INIT_TYPED(firearm_appraisals, /datum/firearm_appraisal, build_firea minimum_range = 5 optimal_range = 6 gun_types = list( - /obj/item/weapon/gun/launcher/rocket/anti_tank, + /obj/item/weapon/gun/launcher/rocket/anti_tank/disposable, ) disposable = TRUE @@ -105,4 +104,4 @@ GLOBAL_LIST_INIT_TYPED(firearm_appraisals, /datum/firearm_appraisal, build_firea gun_types = list( /obj/item/weapon/gun/launcher/rocket ) - disposable = TRUE + disposable = FALSE diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index aaa8a03f5f..76472dd9b3 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -253,6 +253,7 @@ bullets/shells. ~N max_rounds = 5 // For shotguns, though this will be determined by the handful type when generated. flags_atom = FPRINT|CONDUCT flags_magazine = AMMUNITION_HANDFUL + flags_human_ai = null attack_speed = 3 // should make reloading less painful /obj/item/ammo_magazine/handful/Initialize(mapload, spawn_empty) diff --git a/code/modules/projectiles/magazines/lever_action.dm b/code/modules/projectiles/magazines/lever_action.dm index ac1d57dbd4..a32a49d926 100644 --- a/code/modules/projectiles/magazines/lever_action.dm +++ b/code/modules/projectiles/magazines/lever_action.dm @@ -92,6 +92,7 @@ Handfuls of lever_action rounds. For spawning directly on mobs in roundstart, ER gun_type = /obj/item/weapon/gun/lever_action handful_state = "lever_action_bullet" transfer_handful_amount = 9 + flags_human_ai = AMMUNITION_ITEM /obj/item/ammo_magazine/handful/lever_action/training name = "handful of blanks (45-70)" diff --git a/code/modules/projectiles/magazines/shotguns.dm b/code/modules/projectiles/magazines/shotguns.dm index 9fe9f0f440..f47a472bd3 100644 --- a/code/modules/projectiles/magazines/shotguns.dm +++ b/code/modules/projectiles/magazines/shotguns.dm @@ -189,6 +189,7 @@ GLOBAL_LIST_INIT(shotgun_handfuls_12g, list( gun_type = /obj/item/weapon/gun/shotgun handful_state = "slug_shell" transfer_handful_amount = 5 + flags_human_ai = AMMUNITION_ITEM /obj/item/ammo_magazine/handful/shotgun/slug @@ -321,6 +322,7 @@ GLOBAL_LIST_INIT(shotgun_handfuls_12g, list( max_rounds = 8 current_rounds = 8 gun_type = /obj/item/weapon/gun/shotgun/double/cane + flags_human_ai = AMMUNITION_ITEM /obj/item/ammo_magazine/handful/revolver/marksman name = "handful of marksman revolver bullets (.44)"