diff --git a/code/__DEFINES/xeno_ai.dm b/code/__DEFINES/xeno_ai.dm index f67cb3f6dd..defe61de11 100644 --- a/code/__DEFINES/xeno_ai.dm +++ b/code/__DEFINES/xeno_ai.dm @@ -122,3 +122,5 @@ PROBABILITY CALCULATIONS ARE HERE #define XENO_SPAWN_T2 (1<<1) #define XENO_SPAWN_T3 (1<<2) +/// Special blockers for pathfinding or obstacle handling +#define XENO_AI_SPECIAL_BLOCKERS list(/obj/flamer_fire, /obj/vehicle/multitile) diff --git a/code/controllers/subsystem/pathfinding.dm b/code/controllers/subsystem/pathfinding.dm index 552da1fb8a..b87c65d42c 100644 --- a/code/controllers/subsystem/pathfinding.dm +++ b/code/controllers/subsystem/pathfinding.dm @@ -11,9 +11,6 @@ SUBSYSTEM_DEF(xeno_pathfinding) var/list/hash_path = list() var/current_position = 1 - /// Any special blockers we want to account for that do not normally block movement - var/list/special_blockers = list(/obj/flamer_fire) - /datum/controller/subsystem/xeno_pathfinding/stat_entry(msg) msg = "P:[length(paths_to_calculate)]" return ..() @@ -133,7 +130,7 @@ SUBSYSTEM_DEF(xeno_pathfinding) var/list/pass_back = list() for(var/atom/checked_atom as anything in checking_turf) - for(var/special_block in special_blockers) + for(var/special_block in XENO_AI_SPECIAL_BLOCKERS) if(istype(checked_atom, special_block)) pass_back += checked_atom diff --git a/code/game/area/almayer.dm b/code/game/area/almayer.dm index 32db45fc7c..21ff397665 100644 --- a/code/game/area/almayer.dm +++ b/code/game/area/almayer.dm @@ -63,7 +63,6 @@ fake_zlevel = 1 // upperdeck soundscape_playlist = SCAPE_PL_CIC soundscape_interval = 50 - flags_area = AREA_NOTUNNEL /area/almayer/command/cichallway name = "\improper Secure Command Hallway" @@ -76,10 +75,6 @@ fake_zlevel = 1 // upperdeck soundscape_playlist = SCAPE_PL_ARES soundscape_interval = 120 - flags_area = AREA_NOTUNNEL|AREA_UNWEEDABLE - can_build_special = FALSE - is_resin_allowed = FALSE - resin_construction_allowed = FALSE /area/almayer/command/securestorage name = "\improper Secure Storage" @@ -95,13 +90,11 @@ name = "\improper Telecommunications" icon_state = "tcomms" fake_zlevel = 1 // upperdeck - flags_area = AREA_NOTUNNEL /area/almayer/command/self_destruct name = "\improper Self-Destruct Core Room" icon_state = "selfdestruct" fake_zlevel = 1 // upperdeck - flags_area = AREA_NOTUNNEL /area/almayer/command/corporateliason name = "\improper Corporate Liaison Office" @@ -732,19 +725,16 @@ /area/almayer/ert_port name = "\improper ERT Docking Port" icon_state = "lifeboat" - flags_area = AREA_NOTUNNEL /area/space/almayer/lifeboat_dock name = "\improper Lifeboat Docking Port" icon_state = "lifeboat" fake_zlevel = 1 // upperdeck - flags_area = AREA_NOTUNNEL /area/almayer/evacuation icon = 'icons/turf/areas.dmi' icon_state = "shuttle2" requires_power = 0 - flags_area = AREA_NOTUNNEL //Placeholder. /area/almayer/evacuation/pod1 diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index c81da5556e..a1d8b6d919 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -40,7 +40,7 @@ var/gas_type = GAS_TYPE_AIR var/temperature = T20C var/pressure = ONE_ATMOSPHERE - var/can_build_special = FALSE + var/can_build_special = TRUE var/is_resin_allowed = TRUE // can xenos weed, place resin holes or dig tunnels at said areas var/is_landing_zone = FALSE // primarily used to prevent mortars from hitting this location var/resin_construction_allowed = TRUE // Allow construction of resin walls, and other special diff --git a/code/game/machinery/vending/cm_vending.dm b/code/game/machinery/vending/cm_vending.dm index d4dfb9b823..18b62b9d77 100644 --- a/code/game/machinery/vending/cm_vending.dm +++ b/code/game/machinery/vending/cm_vending.dm @@ -763,10 +763,9 @@ GLOBAL_LIST_EMPTY(vending_products) /obj/structure/machinery/cm_vending/gear/Initialize() . = ..() - if(length(list(z) & SSmapping.levels_by_trait(ZTRAIT_GROUND))) + if(z in SSmapping.levels_by_trait(ZTRAIT_GROUND)) malfunction() - /obj/structure/machinery/cm_vending/gear/ui_static_data(mob/user) . = ..(user) .["vendor_type"] = "gear" @@ -786,7 +785,7 @@ GLOBAL_LIST_EMPTY(vending_products) /obj/structure/machinery/cm_vending/clothing/Initialize() . = ..() - if(length(list(z) & SSmapping.levels_by_trait(ZTRAIT_GROUND))) + if(z in SSmapping.levels_by_trait(ZTRAIT_GROUND)) malfunction() /obj/structure/machinery/cm_vending/clothing/ui_static_data(mob/user) diff --git a/code/game/machinery/vending/vendor_types/requisitions.dm b/code/game/machinery/vending/vendor_types/requisitions.dm index b824e2bb6e..a0be9e2793 100644 --- a/code/game/machinery/vending/vendor_types/requisitions.dm +++ b/code/game/machinery/vending/vendor_types/requisitions.dm @@ -12,7 +12,7 @@ /obj/structure/machinery/cm_vending/sorted/cargo_guns/Initialize() . = ..() - if(length(list(z) & SSmapping.levels_by_trait(ZTRAIT_GROUND))) + if(z in SSmapping.levels_by_trait(ZTRAIT_GROUND)) malfunction() /obj/structure/machinery/cm_vending/sorted/cargo_guns/vend_fail() @@ -216,7 +216,7 @@ /obj/structure/machinery/cm_vending/sorted/cargo_ammo/Initialize() . = ..() - if(length(list(z) & SSmapping.levels_by_trait(ZTRAIT_GROUND))) + if(z in SSmapping.levels_by_trait(ZTRAIT_GROUND)) malfunction() /obj/structure/machinery/cm_vending/sorted/cargo_ammo/vend_fail() @@ -343,7 +343,7 @@ /obj/structure/machinery/cm_vending/sorted/attachments/Initialize() . = ..() - if(length(list(z) & SSmapping.levels_by_trait(ZTRAIT_GROUND))) + if(z in SSmapping.levels_by_trait(ZTRAIT_GROUND)) malfunction() /obj/structure/machinery/cm_vending/sorted/attachments/vend_fail() diff --git a/code/modules/admin/tabs/event_tab.dm b/code/modules/admin/tabs/event_tab.dm index 80aacdc14b..f689d11cef 100644 --- a/code/modules/admin/tabs/event_tab.dm +++ b/code/modules/admin/tabs/event_tab.dm @@ -238,7 +238,7 @@ if(prompt == "Current Location") override_spawn_loc = get_turf(usr) - chosen_ert.activate(quiet_launch = launch_broadcast, announce_incoming = announce_receipt, override_spawn_loc = override_spawn_loc) + chosen_ert.activate(quiet_launch = !launch_broadcast, announce_incoming = announce_receipt, override_spawn_loc = override_spawn_loc) message_admins("[key_name_admin(usr)] admin-called a [choice == "Randomize" ? "randomized ":""]distress beacon: [chosen_ert.name]") diff --git a/code/modules/admin/topic/topic_events.dm b/code/modules/admin/topic/topic_events.dm index c38f715d93..6609e1a3b4 100644 --- a/code/modules/admin/topic/topic_events.dm +++ b/code/modules/admin/topic/topic_events.dm @@ -218,7 +218,7 @@ else announce_receipt = FALSE - em_call.activate(launch_broadcast, announce_receipt) + em_call.activate(!launch_broadcast, announce_receipt) message_admins("[key_name_admin(usr)] created [humans_to_spawn] humans as [job_name] at [get_area(initial_spot)]") diff --git a/code/modules/mob/living/carbon/xenomorph/ai/movement/base_define.dm b/code/modules/mob/living/carbon/xenomorph/ai/movement/base_define.dm index e85952a435..bb90128dc3 100644 --- a/code/modules/mob/living/carbon/xenomorph/ai/movement/base_define.dm +++ b/code/modules/mob/living/carbon/xenomorph/ai/movement/base_define.dm @@ -65,7 +65,6 @@ if(T == get_turf(X.current_target)) break - if(!X.move_to_next_turf(T)) X.current_target = null return TRUE diff --git a/code/modules/mob/living/carbon/xenomorph/ai/movement/linger.dm b/code/modules/mob/living/carbon/xenomorph/ai/movement/linger.dm index e22b9756be..bbaebfda6e 100644 --- a/code/modules/mob/living/carbon/xenomorph/ai/movement/linger.dm +++ b/code/modules/mob/living/carbon/xenomorph/ai/movement/linger.dm @@ -17,7 +17,13 @@ if(moving_xeno.throwing) return - if(moving_xeno.current_target.is_mob_incapacitated()) + // Always charge forward if sentries/APCs, no real reason to dodge and weave + var/incapacitated_check = TRUE + if(istype(moving_xeno.current_target, /mob)) + var/mob/current_target_mob = moving_xeno.current_target + incapacitated_check = current_target_mob.is_mob_incapacitated() + + if(incapacitated_check) return ..() check_for_travelling_turf_change(moving_xeno) diff --git a/code/modules/mob/living/carbon/xenomorph/ai/xeno_ai.dm b/code/modules/mob/living/carbon/xenomorph/ai/xeno_ai.dm index 732a463ade..8ffe258ca7 100644 --- a/code/modules/mob/living/carbon/xenomorph/ai/xeno_ai.dm +++ b/code/modules/mob/living/carbon/xenomorph/ai/xeno_ai.dm @@ -1,7 +1,7 @@ /mob/living/carbon/xenomorph // AI stuff var/flags_ai = XENO_AI_NO_DESPAWN - var/mob/current_target + var/atom/movable/current_target var/next_path_generation = 0 var/list/current_path @@ -64,7 +64,12 @@ GLOBAL_LIST_INIT(ai_target_limbs, list( current_path = null return TRUE - if(QDELETED(current_target) || current_target.stat != CONSCIOUS || get_dist(current_target, src) > ai_range) + var/stat_check = FALSE + if(istype(current_target, /mob)) + var/mob/current_target_mob = current_target + stat_check = (current_target_mob != CONSCIOUS) + + if(QDELETED(current_target) || stat_check || get_dist(current_target, src) > ai_range) current_target = get_target(ai_range) if(QDELETED(src)) return TRUE @@ -96,8 +101,19 @@ GLOBAL_LIST_INIT(ai_target_limbs, list( if(XA.process_ai(src, delta_time) == PROCESS_KILL) unregister_ai_action(XA) - if(get_dist(src, current_target) <= 1 && DT_PROB(XENO_SLASH, delta_time)) + if(!current_target || !DT_PROB(XENO_SLASH, delta_time)) + return + + var/list/turf/turfs_to_dist_check = list(get_turf(current_target)) + + if(length(current_target.locs) > 1) + turfs_to_dist_check = get_multitile_turfs_to_check() + + for(var/turf/checked_turf as anything in turfs_to_dist_check) + if(get_dist(src, checked_turf) > 1) + continue INVOKE_ASYNC(src, PROC_REF(do_click), current_target, "", list()) + return /** Controls movement when idle. Called by process_ai */ /mob/living/carbon/xenomorph/proc/ai_move_idle(delta_time) @@ -172,9 +188,9 @@ GLOBAL_LIST_INIT(ai_target_limbs, list( if(!can_move_and_apply_move_delay()) return TRUE - var/turf/next_turf = current_path[current_path.len] var/list/L = LinkBlocked(src, loc, next_turf, list(src, current_target), TRUE) + L += SSxeno_pathfinding.check_special_blockers(src, next_turf) for(var/a in L) var/atom/A = a if(A.xeno_ai_obstacle(src, get_dir(loc, next_turf)) == INFINITY) @@ -197,9 +213,14 @@ GLOBAL_LIST_INIT(ai_target_limbs, list( var/smallest_distance = INFINITY for(var/mob/living/carbon/human/alive_human as anything in GLOB.alive_human_list) if(alive_human.species.flags & IS_SYNTHETIC) - return pick(viable_humans) + continue + if(z != alive_human.z) continue + + if(FACTION_XENOMORPH in alive_human.faction_group) + continue + var/distance = get_dist(src, alive_human) if(distance < ai_range && alive_human.stat == CONSCIOUS) @@ -262,60 +283,36 @@ GLOBAL_LIST_INIT(ai_target_limbs, list( SHOULD_CALL_PARENT(TRUE) SSxeno_ai.remove_ai(src) -GLOBAL_LIST_EMPTY_TYPED(xeno_ai_spawns, /obj/effect/landmark/xeno_ai) -/obj/effect/landmark/xeno_ai - name = "Xeno AI Spawn" - var/list/spawned_xenos - var/remaining_spawns = 5 - - var/spawn_radius = 5 - var/list/spawnable_turfs - -/obj/effect/landmark/xeno_ai/Initialize(mapload, ...) - . = ..() - spawned_xenos = list() - - GLOB.xeno_ai_spawns += src - spawnable_turfs = list() - for(var/i in RANGE_TURFS(spawn_radius, src)) - var/turf/T = i - if(T == get_turf(src)) - spawnable_turfs += T - continue - - if(T.density) - continue - - var/failed = FALSE - for(var/a in T) - var/atom/A = a - if(A.density) - failed = TRUE - break - - if(failed) - continue - - for(var/t in getline(T, src)) - var/turf/line = t - if(line.density) - failed = TRUE - break - - if(failed) - continue - - spawnable_turfs += T - -/obj/effect/landmark/xeno_ai/proc/reduce_remaining_spawns(mob/living/carbon/xenomorph/X) - SIGNAL_HANDLER - remaining_spawns-- - -/obj/effect/landmark/xeno_ai/proc/handle_xeno_delete(mob/living/carbon/xenomorph/X) - SIGNAL_HANDLER - spawned_xenos -= X - -/obj/effect/landmark/xeno_ai/Destroy() - spawnable_turfs = null - GLOB.xeno_ai_spawns -= src - return ..() +/mob/living/carbon/xenomorph/proc/get_multitile_turfs_to_check() + var/angle = get_angle(current_target, src) + var/turf/base_turf = current_target.locs[1] + + switch(angle) + if(315 to 360, 0 to 45) //northerly + var/max_y_value = base_turf.y + (round(current_target.bound_height / 32) - 1) + var/list/turf/max_y_turfs = list() + for(var/turf/cycled_turf as anything in current_target.locs) + if(cycled_turf.y == max_y_value) + max_y_turfs += cycled_turf + return max_y_turfs + if(45 to 135) //easterly + var/max_x_value = base_turf.x + (round(current_target.bound_width / 32) - 1) + var/list/turf/max_x_turfs = list() + for(var/turf/cycled_turf as anything in current_target.locs) + if(cycled_turf.x == max_x_value) + max_x_turfs += cycled_turf + return max_x_turfs + if(135 to 225) //southerly + var/min_y_value = base_turf.y + var/list/turf/min_y_turfs = list() + for(var/turf/cycled_turf as anything in current_target.locs) + if(cycled_turf.y == min_y_value) + min_y_turfs += cycled_turf + return min_y_turfs + if(225 to 315) //westerly + var/min_x_value = base_turf.x + var/list/turf/min_x_turfs = list() + for(var/turf/cycled_turf as anything in current_target.locs) + if(cycled_turf.x == min_x_value) + min_x_turfs += cycled_turf + return min_x_turfs diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm b/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm index a3b5158121..d95989693d 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm @@ -114,7 +114,12 @@ if(get_dist(current_target, src) > 1) return - if(!current_target.is_mob_incapacitated()) + if(!istype(current_target, /mob)) + return + + var/mob/current_target_mob = current_target + + if(!current_target_mob.is_mob_incapacitated()) return if(isxeno(current_target.pulledby)) diff --git a/code/modules/vehicles/apc/apc.dm b/code/modules/vehicles/apc/apc.dm index 55e2cf2d11..f7f5f32105 100644 --- a/code/modules/vehicles/apc/apc.dm +++ b/code/modules/vehicles/apc/apc.dm @@ -61,8 +61,6 @@ GLOBAL_LIST_EMPTY(command_apc_list) vehicle_flags = VEHICLE_CLASS_LIGHT - mob_size_required_to_hit = MOB_SIZE_XENO - dmg_multipliers = list( "all" = 1, "acid" = 1.6, diff --git a/code/modules/vehicles/van/van.dm b/code/modules/vehicles/van/van.dm index 5969b73957..c017eae28d 100644 --- a/code/modules/vehicles/van/van.dm +++ b/code/modules/vehicles/van/van.dm @@ -57,8 +57,6 @@ door_locked = FALSE - mob_size_required_to_hit = MOB_SIZE_XENO - var/overdrive_next = 0 var/overdrive_cooldown = 15 SECONDS var/overdrive_duration = 3 SECONDS diff --git a/maps/derelict_almayer.json b/maps/derelict_almayer.json index 6f27befaee..0d0fc08da4 100644 --- a/maps/derelict_almayer.json +++ b/maps/derelict_almayer.json @@ -7,5 +7,12 @@ "announce_text": "An automated distress signal has been received from the \"USS Almayer\". A response team from the ###SHIPNAME### will be dispatched shortly to investigate.", "traits": [{ "Ground": true }], "nightmare_path": "maps/Nightmare/maps/derelict_almayer/", - "camouflage": "classic" + "camouflage": "classic", + "gamemodes": [ + "Distress Signal", + "Hunter Games", + "Hive Wars", + "Faction Clash", + "Infection" + ] }