Skip to content

Commit

Permalink
Makes hunter mirages more convincing, motion detectors now ignore xen…
Browse files Browse the repository at this point in the history
…os in stealth, adds some ap to hunter's stealth attacks. (#13)

* motion sensors

* Update xeno_illusion.dm

* Update mobs.dm

* Update sentries.dm

* Update ai.dm

* Update mobs.dm

* Update abilities_hunter.dm
  • Loading branch information
Helg2 authored Jul 14, 2024
1 parent cb15e36 commit 5c0fc3f
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 57 deletions.
13 changes: 11 additions & 2 deletions code/__HELPERS/ai.dm
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@
continue
. += nearby_mech

///Returns a list of mobs/illusion via get_dist and same z level method, very cheap compared to range()
/proc/cheap_get_illusions_near(atom/movable/source, distance)
. = list()
for(var/mob/illusion/nearby_illusion AS in GLOB.mob_illusions_list)
if(source.z != nearby_illusion.z)
continue
if(get_dist(source, nearby_illusion) > distance)
continue
. += nearby_illusion

///Returns the nearest target that has the right target flag
/proc/get_nearest_target(atom/source, distance, target_flags, attacker_faction, attacker_hive)
if(!source)
Expand All @@ -62,8 +72,7 @@
var/shorter_distance = distance + 1
if(target_flags & TARGET_HUMAN)
for(var/mob/living/nearby_human AS in cheap_get_humans_near(source, distance))
//if(nearby_human.stat == DEAD || nearby_human.faction == attacker_faction || nearby_human.alpha <= SCOUT_CLOAK_RUN_ALPHA) //ORIGINAL
if(nearby_human.stat == DEAD || nearby_human.faction == attacker_faction || nearby_human.alpha <= SCOUT_CLOAK_RUN_ALPHA || isnestedhost(nearby_human)) //RUTGMC EDIT, no nest breaking minions
if(nearby_human.stat == DEAD || nearby_human.faction == attacker_faction || nearby_human.alpha <= SCOUT_CLOAK_RUN_ALPHA || isnestedhost(nearby_human))
continue
if(get_dist(source, nearby_human) < shorter_distance)
nearest_target = nearby_human
Expand Down
8 changes: 4 additions & 4 deletions code/_globalvars/lists/mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,13 @@ GLOBAL_LIST_INIT(forbid_excepts, list(
/mob/living/carbon/xenomorph/shrike,
/mob/living/carbon/xenomorph/larva,
/mob/living/carbon/xenomorph/drone,
))
))

GLOBAL_LIST_EMPTY_TYPED(hellhound_list, /mob/living/carbon/xenomorph/hellhound)
GLOBAL_LIST_EMPTY_TYPED(yautja_mob_list, /mob/living/carbon/human/species/yautja)

GLOBAL_LIST_EMPTY_TYPED(mob_illusions_list, /mob/illusion)

GLOBAL_LIST_INIT(xeno_types_tier_one, list(/mob/living/carbon/xenomorph/runner, /mob/living/carbon/xenomorph/drone, /mob/living/carbon/xenomorph/sentinel, /mob/living/carbon/xenomorph/defender))
GLOBAL_LIST_INIT(xeno_types_tier_two, list(/mob/living/carbon/xenomorph/hunter, /mob/living/carbon/xenomorph/panther, /mob/living/carbon/xenomorph/warrior, /mob/living/carbon/xenomorph/spitter, /mob/living/carbon/xenomorph/hivelord, /mob/living/carbon/xenomorph/carrier, /mob/living/carbon/xenomorph/bull))
GLOBAL_LIST_INIT(xeno_types_tier_three, list(/mob/living/carbon/xenomorph/gorger, /mob/living/carbon/xenomorph/ravager, /mob/living/carbon/xenomorph/praetorian, /mob/living/carbon/xenomorph/boiler, /mob/living/carbon/xenomorph/defiler, /mob/living/carbon/xenomorph/crusher, /mob/living/carbon/xenomorph/shrike, /mob/living/carbon/xenomorph/behemoth, /mob/living/carbon/xenomorph/chimera))
Expand Down Expand Up @@ -149,7 +151,7 @@ GLOBAL_LIST_INIT(hive_ui_static_data, init_hive_status_lists()) // init by make_

GLOB.hive_ui_caste_index[type_path] = length(.) //Starts from 0.

var/icon/xeno_minimap = icon('icons/UI_icons/map_blips.dmi', initial(caste.minimap_icon)) ///RUTGMC edit, icon redirect to module
var/icon/xeno_minimap = icon('icons/UI_icons/map_blips.dmi', initial(caste.minimap_icon))
var/tier = initial(caste.tier)
if(tier == XENO_TIER_MINION)
continue
Expand All @@ -167,8 +169,6 @@ GLOBAL_LIST_INIT(hive_ui_static_data, init_hive_status_lists()) // init by make_
"evolution_max" = initial(caste.evolution_threshold)
))



/proc/update_config_movespeed_type_lookup(update_mobs = TRUE)
var/list/mob_types = list()
var/list/entry_value = CONFIG_GET(keyed_list/multiplicative_movespeed)
Expand Down
18 changes: 6 additions & 12 deletions code/game/objects/items/motion_detector.dm
Original file line number Diff line number Diff line change
Expand Up @@ -130,24 +130,18 @@
clean_operator()
return
hostile_detected = FALSE
for (var/mob/living/carbon/human/nearby_human AS in cheap_get_humans_near(operator, range))
for(var/mob/living/carbon/human/nearby_human AS in cheap_get_humans_near(operator, range))
if(nearby_human == operator)
continue
/* RU TGMC EDIT
if(nearby_human.last_move_time + move_sensitivity < world.time)
continue
RU TGMC EDIT */
//RU TGMC EDIT
if(HAS_TRAIT(nearby_human, TRAIT_LIGHT_STEP))
continue
//RUTGMC EDIT ADDITION END
prepare_blip(nearby_human, nearby_human.wear_id?.iff_signal & operator.wear_id.iff_signal ? MOTION_DETECTOR_FRIENDLY : MOTION_DETECTOR_HOSTILE)
for (var/mob/living/carbon/xenomorph/nearby_xeno AS in cheap_get_xenos_near(operator, range))
/* RU TGMC EDIT
if(nearby_xeno.last_move_time + move_sensitivity < world.time )
for(var/mob/living/carbon/xenomorph/nearby_xeno AS in cheap_get_xenos_near(operator, range))
if(HAS_TRAIT(nearby_xeno, TRAIT_TURRET_HIDDEN))
continue
RU TGMC EDIT */
prepare_blip(nearby_xeno, MOTION_DETECTOR_HOSTILE)
for(var/mob/illusion/nearby_illusion AS in cheap_get_illusions_near(operator, range))
prepare_blip(nearby_illusion, MOTION_DETECTOR_HOSTILE)
if(hostile_detected)
playsound(loc, 'sound/items/tick.ogg', 100, 0, 7, 2)
addtimer(CALLBACK(src, PROC_REF(clean_blips)), 1 SECONDS)
Expand All @@ -164,7 +158,7 @@
/obj/item/attachable/motiondetector/proc/prepare_blip(mob/target, status)
if(!operator.client)
return
if(!target) // RUTGMC ADDITION
if(!target)
return
if(status == MOTION_DETECTOR_HOSTILE)
hostile_detected = TRUE
Expand Down
23 changes: 18 additions & 5 deletions code/modules/ai/ai_behaviors/xeno/xeno_illusion.dm
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,22 @@
return

/datum/ai_behavior/xeno/illusion/attack_target(datum/soure, atom/attacked)
if(world.time < mob_parent.next_move)
return
if(!attacked)
attacked = atom_to_walk_to
if(get_dist(attacked, mob_parent) > 1)
return
var/mob/illusion/illusion_parent = mob_parent
var/mob/living/carbon/xenomorph/original_xeno = illusion_parent.original_mob
mob_parent.changeNext_move(original_xeno.xeno_caste.attack_delay)
illusion_parent.changeNext_move(original_xeno.xeno_caste.attack_delay + rand(0, 5))
illusion_parent.face_atom(attacked)
if(ismob(attacked))
mob_parent.do_attack_animation(attacked, ATTACK_EFFECT_REDSLASH)
playsound(mob_parent.loc, "alien_claw_flesh", 25, 1)
illusion_parent.do_attack_animation(attacked, ATTACK_EFFECT_REDSLASH)
playsound(illusion_parent.loc, "alien_claw_flesh", 25, 1)
return
mob_parent.do_attack_animation(attacked, ATTACK_EFFECT_CLAW)
illusion_parent.do_attack_animation(attacked, ATTACK_EFFECT_CLAW)
playsound(illusion_parent.loc, "alien_claw_metal", 25, 1)

/mob/illusion
density = FALSE
Expand All @@ -48,14 +54,21 @@
return INITIALIZE_HINT_QDEL
src.original_mob = original_mob
appearance = original_mob.appearance
setDir(original_mob.dir)
desc = original_mob.desc
name = original_mob.name
RegisterSignals(original_mob, list(COMSIG_QDELETING, COMSIG_MOB_DEATH), PROC_REF(destroy_illusion))
GLOB.mob_illusions_list += src
QDEL_IN(src, life_time)

/mob/illusion/Destroy()
. = ..()
GLOB.mob_illusions_list -= src

///Delete this illusion when the original xeno is ded
/mob/illusion/proc/destroy_illusion()
SIGNAL_HANDLER
GLOB.mob_illusions_list -= src
qdel(src)

/// Remove the filter effect added when it was hit
Expand All @@ -73,5 +86,5 @@
. = ..()
if(.)
return INITIALIZE_HINT_QDEL
add_movespeed_modifier(MOVESPEED_ID_XENO_CASTE_SPEED, TRUE, 0, NONE, TRUE, original_mob.xeno_caste.speed * 1.3)
add_movespeed_modifier(MOVESPEED_ID_XENO_CASTE_SPEED, TRUE, 0, NONE, FALSE, original_mob.xeno_caste.speed * pick(0.9, 1, 1.1, 1.2, 1.3)) // rand doesn't work here because it's decimals
AddComponent(/datum/component/ai_controller, /datum/ai_behavior/xeno/illusion, escorted_atom)
13 changes: 8 additions & 5 deletions code/modules/clothing/modular_armor/attachments/modules.dm
Original file line number Diff line number Diff line change
Expand Up @@ -491,15 +491,15 @@
/obj/item/armor_module/module/welding/on_attach(obj/item/attaching_to, mob/user)
. = ..()
parent.AddComponent(/datum/component/clothing_tint, TINT_5, active)
if(active) // RUTGMC ADDITION START
parent.eye_protection += eye_protection_mod // reset to the users base eye // RUTGMC ADDITION END
if(active)
parent.eye_protection += eye_protection_mod // reset to the users base eye

/obj/item/armor_module/module/welding/on_detach(obj/item/detaching_from, mob/user)
parent.GetComponent(/datum/component/clothing_tint)
var/datum/component/clothing_tint/tints = parent?.GetComponent(/datum/component/clothing_tint)
tints.RemoveComponent()
if(active) // RUTGMC ADDITION START
parent.eye_protection -= eye_protection_mod // reset to the users base eye // RUTGMC ADDITION END
if(active)
parent.eye_protection -= eye_protection_mod // reset to the users base eye
return ..()

/obj/item/armor_module/module/welding/activate(mob/living/user)
Expand Down Expand Up @@ -763,7 +763,6 @@
flags_attach_features = ATTACH_REMOVABLE|ATTACH_ACTIVATION|ATTACH_APPLY_ON_MOB
slot = ATTACHMENT_SLOT_HEAD_MODULE
prefered_slot = SLOT_HEAD

/// Who's using this item
var/mob/living/carbon/human/operator
///The range of this motion detector
Expand Down Expand Up @@ -824,9 +823,13 @@
hostile_detected = TRUE
prepare_blip(nearby_human, nearby_human.wear_id?.iff_signal & operator.wear_id?.iff_signal ? MOTION_DETECTOR_FRIENDLY : MOTION_DETECTOR_HOSTILE)
for(var/mob/living/carbon/xenomorph/nearby_xeno AS in cheap_get_xenos_near(operator, range))
if(HAS_TRAIT(nearby_xeno, TRAIT_TURRET_HIDDEN))
continue
if(!hostile_detected)
hostile_detected = TRUE
prepare_blip(nearby_xeno, MOTION_DETECTOR_HOSTILE)
for(var/mob/illusion/nearby_illusion AS in cheap_get_illusions_near(operator, range))
prepare_blip(nearby_illusion, MOTION_DETECTOR_HOSTILE)
if(hostile_detected)
playsound(loc, 'sound/items/tick.ogg', 100, 0, 1)
addtimer(CALLBACK(src, PROC_REF(clean_blips)), scan_time / 2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
var/can_sneak_attack = FALSE
var/stealth_alpha_multiplier = 1

/datum/action/ability/xeno_action/stealth/remove_action(mob/living/L)
/datum/action/ability/xeno_action/stealth/remove_action()
if(stealth)
cancel_stealth()
return ..()
Expand Down Expand Up @@ -51,16 +51,15 @@

RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(handle_stealth))
RegisterSignal(owner, COMSIG_XENOMORPH_POUNCE_END, PROC_REF(sneak_attack_pounce))
RegisterSignal(owner, COMSIG_XENO_LIVING_THROW_HIT, PROC_REF(mob_hit))
RegisterSignal(owner, COMSIG_XENOMORPH_ATTACK_LIVING, PROC_REF(sneak_attack_slash))
RegisterSignal(owner, COMSIG_XENOMORPH_DISARM_HUMAN, PROC_REF(sneak_attack_slash))
RegisterSignal(owner, COMSIG_XENOMORPH_LEAP_BUMP, PROC_REF(mob_hit))
RegisterSignals(owner, list(COMSIG_XENOMORPH_ATTACK_LIVING, COMSIG_XENOMORPH_DISARM_HUMAN), PROC_REF(sneak_attack_slash))
RegisterSignal(owner, COMSIG_XENOMORPH_ZONE_SELECT, PROC_REF(sneak_attack_zone))
RegisterSignal(owner, COMSIG_XENOMORPH_PLASMA_REGEN, PROC_REF(plasma_regen))

// TODO: attack_alien() overrides are a mess and need a lot of work to make them require parentcalling
RegisterSignals(owner, list(
COMSIG_XENOMORPH_GRAB,
COMSIG_XENOMORPH_THROW_HIT,
COMSIG_XENOMORPH_LEAP_BUMP,
COMSIG_LIVING_IGNITED,
COMSIG_LIVING_ADD_VENTCRAWL), PROC_REF(cancel_stealth))

Expand Down Expand Up @@ -163,14 +162,18 @@
cancel_stealth()

/// Callback for when a mob gets hit as part of a pounce
/datum/action/ability/xeno_action/stealth/proc/mob_hit(datum/source, mob/living/M)
/datum/action/ability/xeno_action/stealth/proc/mob_hit(datum/source, mob/living/living_target)
SIGNAL_HANDLER
if(M.stat || isxeno(M))
if(living_target.stat || isxeno(living_target))
return
if(!can_sneak_attack)
return
if(can_sneak_attack)
M.adjust_stagger(3 SECONDS)
M.add_slowdown(1)
to_chat(owner, span_xenodanger("Pouncing from the shadows, we stagger our victim."))
living_target.adjust_stagger(3 SECONDS)
living_target.add_slowdown(1)

var/mob/living/carbon/xenomorph/xeno = owner
living_target.attack_alien_harm(xeno, xeno.xeno_caste.melee_damage * xeno.xeno_melee_damage_modifier)
to_chat(owner, span_xenodanger("Pouncing from the shadows, we stagger our victim."))

/datum/action/ability/xeno_action/stealth/proc/sneak_attack_slash(datum/source, mob/living/target, damage, list/damage_mod, list/armor_mod)
SIGNAL_HANDLER
Expand All @@ -185,7 +188,7 @@
target.adjust_stagger(2 SECONDS)
target.add_slowdown(1)
target.ParalyzeNoChain(1 SECONDS)
target.apply_damage(damage, BRUTE, xeno.zone_selected, MELEE) // additional damage
target.apply_damage(damage, BRUTE, xeno.zone_selected, MELEE, , penetration = 15) // additional damage

cancel_stealth()

Expand Down Expand Up @@ -270,11 +273,12 @@
return

var/mob/living/carbon/xenomorph/xeno = owner
damage = xeno.xeno_caste.melee_damage * xeno.xeno_melee_damage_modifier

owner.visible_message(span_danger("\The [owner] strikes [target] with deadly precision!"), \
span_danger("We strike [target] with deadly precision!"))
target.ParalyzeNoChain(1 SECONDS)
target.apply_damage(20, BRUTE, xeno.zone_selected) // additional damage
target.apply_damage(damage, BRUTE, xeno.zone_selected, MELEE, penetration = 25) // additional damage

cancel_stealth()

Expand Down Expand Up @@ -316,8 +320,7 @@
if(owner.layer != MOB_LAYER)
owner.layer = MOB_LAYER
var/datum/action/ability/xeno_action/xenohide/hide_action = owner.actions_by_path[/datum/action/ability/xeno_action/xenohide]
//hide_action?.button?.cut_overlay(mutable_appearance('icons/Xeno/actions.dmi', "selected_purple_frame", ACTION_LAYER_ACTION_ICON_STATE, FLOAT_PLANE)) // Removes Hide action icon border // ORIGINAL
hide_action?.button?.cut_overlay(mutable_appearance('icons/Xeno/actions.dmi', "selected_purple_frame", ACTION_LAYER_ACTION_ICON_STATE, FLOAT_PLANE)) // RUTGMC EDIT
hide_action?.button?.cut_overlay(mutable_appearance('icons/Xeno/actions.dmi', "selected_purple_frame", ACTION_LAYER_ACTION_ICON_STATE, FLOAT_PLANE)) // Removes Hide action icon border
if(owner.buckled)
owner.buckled.unbuckle_mob(owner)
RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(movement_fx))
Expand Down Expand Up @@ -354,7 +357,7 @@
if(!human_target.check_shields(COMBAT_TOUCH_ATTACK, 30, "melee"))
xeno_owner.Paralyze(XENO_POUNCE_SHIELD_STUN_DURATION)
xeno_owner.set_throwing(FALSE)
playsound(xeno_owner, 'sound/machines/bonk.ogg', 50, FALSE) // RUTGMC ADDITION
playsound(xeno_owner, 'sound/machines/bonk.ogg', 50, FALSE)
return
trigger_pounce_effect(living_target)
pounce_complete()
Expand All @@ -373,7 +376,7 @@
UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_XENO_OBJ_THROW_HIT, COMSIG_XENOMORPH_LEAP_BUMP, COMSIG_MOVABLE_POST_THROW))
SEND_SIGNAL(owner, COMSIG_XENOMORPH_POUNCE_END)
var/mob/living/carbon/xenomorph/xeno_owner = owner
xeno_owner.set_throwing(FALSE) // RUTGMC ADDITION, for whatever modular fuckery, without this pounce doesn't stop
xeno_owner.set_throwing(FALSE)
xeno_owner.xeno_flags &= ~XENO_LEAPING

/datum/action/ability/activable/xeno/pounce/proc/reset_pass_flags()
Expand Down
15 changes: 3 additions & 12 deletions code/modules/projectiles/sentries.dm
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
/obj/machinery/deployable/mounted/sentry

resistance_flags = UNACIDABLE|XENO_DAMAGEABLE
use_power = 0
req_one_access = list(ACCESS_MARINE_ENGINEERING, ACCESS_MARINE_ENGPREP, ACCESS_MARINE_LEADER)
hud_possible = list(MACHINE_HEALTH_HUD, MACHINE_AMMO_HUD)

///Spark system for making sparks
var/datum/effect_system/spark_spread/spark_system
///Camera for viewing with cam consoles
Expand All @@ -13,18 +11,14 @@
var/range = 7
///Damage required to knock the sentry over and disable it
var/knockdown_threshold = 150

///List of targets that can be shot at
var/list/atom/potential_targets = list()

///Time of last alert
var/last_alert = 0
///Time of last damage alert
var/last_damage_alert = 0

///Radio so that the sentry can scream for help
var/obj/item/radio/radio

///Iff signal of the sentry. If the /gun has a set IFF then this will be the same as that. If not the sentry will get its IFF signal from the deployer
var/iff_signal = NONE
///List of terrains/structures/machines that the sentry ignores for targetting. (If a window is inside the list, the sentry will shot at targets even if the window breaks los) For accuracy, this is on a specific typepath base and not istype().
Expand Down Expand Up @@ -311,10 +305,7 @@
return
if(prob(10))
spark_system.start()
//RUTGMC EDIT CHANGE BEGIN
//if(damage_amount >= knockdown_threshold) // ORIGINAL
if(damage_amount >= knockdown_threshold && damage_type != STAMINA) //Knockdown is certain if we deal this much in one hit; no more RNG nonsense, the fucking thing is bolted.
//RUTGMC EDIT END
knock_down()

. = ..()
Expand All @@ -331,7 +322,7 @@
if(!internal_item)
return
var/obj/item/weapon/gun/gun = get_internal_item()
if(!gun) // RUTGMC ADDITION
if(!gun)
return
if(!alert_code || !CHECK_BITFIELD(gun.turret_flags, TURRET_ALERTS) || !CHECK_BITFIELD(gun.turret_flags, TURRET_ON))
return
Expand Down Expand Up @@ -361,7 +352,6 @@
playsound(loc, 'sound/machines/warning-buzzer.ogg', 50, FALSE)
radio.talk_into(src, "[notice]", FREQ_COMMON)


/obj/machinery/deployable/mounted/sentry/process()
update_icon()
if(!scan())
Expand All @@ -388,6 +378,8 @@
if(nearby_xeno.stat == DEAD || HAS_TRAIT(nearby_xeno, TRAIT_TURRET_HIDDEN) || CHECK_BITFIELD(nearby_xeno.status_flags, INCORPOREAL) || CHECK_BITFIELD(nearby_xeno.xeno_iff_check(), iff_signal)) //So wraiths wont be shot at when in phase shift
continue
potential_targets += nearby_xeno
for(var/mob/illusion/nearby_illusion AS in cheap_get_illusions_near(src, range))
potential_targets += nearby_illusion
for(var/obj/vehicle/sealed/mecha/nearby_mech AS in cheap_get_mechs_near(src, range))
if(!length(nearby_mech.occupants))
continue
Expand Down Expand Up @@ -536,7 +528,6 @@
if(internal_gun)
. += image('icons/Marine/sentry.dmi', src, internal_gun.placed_overlay_iconstate, dir = dir)


//Throwable turret
/obj/machinery/deployable/mounted/sentry/cope
density = FALSE
Expand Down

0 comments on commit 5c0fc3f

Please sign in to comment.