Skip to content

Commit

Permalink
[MIRROR] Legion Mob Abilities (#636)
Browse files Browse the repository at this point in the history
* Legion Mob Abilities (#81082)

## About The Pull Request

Converts legions hardcoded abilities to the cooldown action / mob
abilities system.

I also took the liberty of converting the hacky 360 second cooldowns in
a lot of the mob actions into simply disabling other abilities while the
ability is active, this will make it easier to have bosses without
everything on a shared cooldown and also not allow abilities to be used
simultaneously.

## Why It's Good For The Game

Paving the way for basic megafauna.

## Changelog

:cl:
refactor: Legions abilities have been changed into actions that can be
added to any mob.
/:cl:

---------

Co-authored-by: Changelogs <[email protected]>

* Legion Mob Abilities

---------

Co-authored-by: Whoneedspacee <[email protected]>
Co-authored-by: Changelogs <[email protected]>
  • Loading branch information
3 people authored and FFMirrorBot committed Jan 27, 2024
1 parent b1a7972 commit 504a4be
Show file tree
Hide file tree
Showing 14 changed files with 246 additions and 187 deletions.
4 changes: 4 additions & 0 deletions code/datums/actions/action.dm
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
var/overlay_icon = 'icons/mob/actions/backgrounds.dmi'
/// This is the icon state for any FOREGROUND overlay icons on the button (such as borders)
var/overlay_icon_state
/// Toggles whether this action is usable or not
var/action_disabled = FALSE

/datum/action/New(Target)
link_to(Target)
Expand Down Expand Up @@ -162,6 +164,8 @@
/datum/action/proc/IsAvailable(feedback = FALSE)
if(!owner)
return FALSE
if(action_disabled)
return FALSE
if((check_flags & AB_CHECK_HANDS_BLOCKED) && HAS_TRAIT(owner, TRAIT_HANDS_BLOCKED))
if (feedback)
owner.balloon_alert(owner, "hands blocked!")
Expand Down
25 changes: 25 additions & 0 deletions code/datums/actions/cooldown_action.dm
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,31 @@
else
shared_ability.StartCooldownSelf(cooldown_time)

/// Resets the cooldown of this ability
/datum/action/cooldown/proc/ResetCooldown()
next_use_time = world.time
build_all_button_icons(UPDATE_BUTTON_STATUS)

/// Re-enables this cooldown action
/datum/action/cooldown/proc/enable()
action_disabled = FALSE
build_all_button_icons(UPDATE_BUTTON_STATUS)

/// Disables this cooldown action
/datum/action/cooldown/proc/disable()
action_disabled = TRUE
build_all_button_icons(UPDATE_BUTTON_STATUS)

/// Re-enables all cooldown actions
/datum/action/cooldown/proc/enable_cooldown_actions()
for(var/datum/action/cooldown/cd_action in owner.actions)
cd_action.enable()

/// Disables all cooldown actions
/datum/action/cooldown/proc/disable_cooldown_actions()
for(var/datum/action/cooldown/cd_action in owner.actions)
cd_action.disable()

/datum/action/cooldown/Trigger(trigger_flags, atom/target)
. = ..()
if(!.)
Expand Down
2 changes: 2 additions & 0 deletions code/datums/actions/mobs/blood_warp.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
var/remove_inner_pools = TRUE

/datum/action/cooldown/mob_cooldown/blood_warp/Activate(atom/target_atom)
disable_cooldown_actions()
blood_warp(target_atom)
StartCooldown()
enable_cooldown_actions()
return TRUE

/datum/action/cooldown/mob_cooldown/blood_warp/proc/blood_warp(atom/target)
Expand Down
3 changes: 2 additions & 1 deletion code/datums/actions/mobs/charge.dm
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@
var/list/charging = list()

/datum/action/cooldown/mob_cooldown/charge/Activate(atom/target_atom)
StartCooldown(360 SECONDS, 360 SECONDS)
disable_cooldown_actions()
charge_sequence(owner, target_atom, charge_delay, charge_past)
StartCooldown()
enable_cooldown_actions()
return TRUE

/datum/action/cooldown/mob_cooldown/charge/proc/charge_sequence(atom/movable/charger, atom/target_atom, delay, past)
Expand Down
42 changes: 42 additions & 0 deletions code/datums/actions/mobs/chase_target.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/datum/action/cooldown/mob_cooldown/chase_target
name = "Chase Target"
button_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "sniper_zoom"
desc = "Gain a burst of speed to chase down a target."
cooldown_time = 6 SECONDS
/// Affects volume of the charge tell depending on the size of the mob charging
var/size = 1

/datum/action/cooldown/mob_cooldown/chase_target/Activate(atom/target_atom)
disable_cooldown_actions()
charge(target_atom)
StartCooldown()
enable_cooldown_actions()
return TRUE

/// Causes the mob to gain speed and charge at a target
/datum/action/cooldown/mob_cooldown/chase_target/proc/charge(atom/target)
var/mob/living/living_mob = target
if(istype(living_mob) && living_mob.stat == DEAD)
return
owner.visible_message(span_boldwarning("[owner] charges!"))
owner.SpinAnimation(speed = 20, loops = 3, parallel = FALSE)
if(ishostile(owner))
var/mob/living/simple_animal/hostile/hostile_mob = owner
hostile_mob.retreat_distance = 0
hostile_mob.minimum_distance = 0
hostile_mob.set_varspeed(0)
addtimer(CALLBACK(src, PROC_REF(reset_charge)), 6 SECONDS)
addtimer(CALLBACK(src, PROC_REF(throw_thyself)), 2 SECONDS)

/// This is the proc that actually does the throwing. Charge only adds a timer for this.
/datum/action/cooldown/mob_cooldown/chase_target/proc/throw_thyself()
playsound(owner, 'sound/weapons/sonic_jackhammer.ogg', 50, TRUE)
owner.throw_at(target, 7, 1.1, owner, FALSE, FALSE, CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(playsound), owner, 'sound/effects/meteorimpact.ogg', 50 * size, TRUE, 2), INFINITY)

/// Resets the charge buffs.
/datum/action/cooldown/mob_cooldown/chase_target/proc/reset_charge()
var/mob/living/simple_animal/hostile/hostile_mob = owner
hostile_mob.retreat_distance = 5
hostile_mob.minimum_distance = 5
hostile_mob.set_varspeed(2)
19 changes: 19 additions & 0 deletions code/datums/actions/mobs/create_legion_skull.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/datum/action/cooldown/mob_cooldown/create_legion_skull
name = "Create Legion Skull"
button_icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi'
button_icon_state = "legion_head"
desc = "Create a legion skull to chase down a targeted enemy"
cooldown_time = 2 SECONDS

/datum/action/cooldown/mob_cooldown/create_legion_skull/Activate(atom/target_atom)
disable_cooldown_actions()
create(target_atom)
StartCooldown()
enable_cooldown_actions()
return TRUE

/// Creates a new skull assigned to the owner of this action
/datum/action/cooldown/mob_cooldown/create_legion_skull/proc/create(atom/target)
var/mob/living/basic/legion_brood/minion = new(owner.loc)
minion.assign_creator(owner)
minion.ai_controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] = target
116 changes: 116 additions & 0 deletions code/datums/actions/mobs/create_legion_turrets.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/datum/action/cooldown/mob_cooldown/create_legion_turrets
name = "Create Sentinels"
button_icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi'
button_icon_state = "legion_turret"
desc = "Create legion sentinels that fire at any enemies."
cooldown_time = 2 SECONDS
/// Minimum number of turrets that can be spawned
var/minimum_turrets = 2
/// Maximum number of turrets that can be spawned
var/maximum_turrets = 2

/datum/action/cooldown/mob_cooldown/create_legion_turrets/Activate(atom/target_atom)
disable_cooldown_actions()
create(target_atom)
StartCooldown()
enable_cooldown_actions()
return TRUE

/// Creates new legion turrets around the owner between the minimum and maximum
/datum/action/cooldown/mob_cooldown/create_legion_turrets/proc/create(atom/target)
playsound(owner, 'sound/magic/RATTLEMEBONES.ogg', 100, TRUE)
var/list/possible_locations = list()
for(var/turf/checked_turf in oview(owner, 4)) //Only place the turrets on open turfs
if(checked_turf.is_blocked_turf())
continue
possible_locations += checked_turf
for(var/i in 1 to min(rand(minimum_turrets, maximum_turrets), length(possible_locations))) //Makes sure aren't spawning in nullspace.
var/chosen = pick_n_take(possible_locations)
new /obj/structure/legionturret(chosen)

/// A basic turret that shoots at nearby mobs. Intended to be used for the legion megafauna.
/obj/structure/legionturret
name = "\improper Legion sentinel"
desc = "The eye pierces your soul."
icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi'
icon_state = "legion_turret"
light_power = 0.5
light_range = 2
max_integrity = 80
luminosity = 6
anchored = TRUE
density = TRUE
layer = ABOVE_OBJ_LAYER
armor_type = /datum/armor/structure_legionturret
//Compared with the targeted mobs. If they have the faction, turret won't shoot.
faction = list(FACTION_MINING)
///What kind of projectile the actual damaging part should be.
var/projectile_type = /obj/projectile/beam/legion
///Time until the tracer gets shot
var/initial_firing_time = 1.8 SECONDS
///How long it takes between shooting the tracer and the projectile.
var/shot_delay = 0.8 SECONDS

/datum/armor/structure_legionturret
laser = 100

/obj/structure/legionturret/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(set_up_shot)), initial_firing_time)
ADD_TRAIT(src, TRAIT_NO_FLOATING_ANIM, INNATE_TRAIT)

/// Handles an extremely basic AI
/obj/structure/legionturret/proc/set_up_shot()
for(var/mob/living/possible_target in oview(9, src))
if(possible_target.stat == DEAD || possible_target.stat == UNCONSCIOUS)
continue
if(faction_check(faction, possible_target.faction))
continue
fire(possible_target)
return
fire(get_edge_target_turf(src, pick(GLOB.cardinals)))

/// Called when attacking a target. Shoots a projectile at the turf underneath the target.
/obj/structure/legionturret/proc/fire(atom/target)
var/turf/target_turf = get_turf(target)
var/turf/our_turf = get_turf(src)
if(!target_turf || !our_turf)
return
//Now we generate the tracer.
var/angle = get_angle(our_turf, target_turf)
var/datum/point/vector/V = new(our_turf.x, our_turf.y, our_turf.z, 0, 0, angle)
generate_tracer_between_points(V, V.return_vector_after_increments(6), /obj/effect/projectile/tracer/legion/tracer, 0, shot_delay, 0, 0, 0, null)
playsound(src, 'sound/machines/airlockopen.ogg', 100, TRUE)
addtimer(CALLBACK(src, PROC_REF(fire_beam), angle), shot_delay)

/// Called shot_delay after the turret shot the tracer. Shoots a projectile into the same direction.
/obj/structure/legionturret/proc/fire_beam(angle)
var/obj/projectile/ouchie = new projectile_type(loc)
ouchie.firer = src
ouchie.fire(angle)
playsound(src, 'sound/effects/bin_close.ogg', 100, TRUE)
QDEL_IN(src, 0.5 SECONDS)

/// Used for the legion turret.
/obj/projectile/beam/legion
name = "blood pulse"
hitsound = 'sound/magic/magic_missile.ogg'
damage = 19
range = 6
light_color = COLOR_SOFT_RED
impact_effect_type = /obj/effect/temp_visual/kinetic_blast
tracer_type = /obj/effect/projectile/tracer/legion
muzzle_type = /obj/effect/projectile/tracer/legion
impact_type = /obj/effect/projectile/tracer/legion
hitscan = TRUE
projectile_piercing = ALL

/// Used for the legion turret tracer.
/obj/effect/projectile/tracer/legion/tracer
icon = 'icons/effects/beam.dmi'
icon_state = "blood_light"

/// Used for the legion turret beam.
/obj/effect/projectile/tracer/legion
icon = 'icons/effects/beam.dmi'
icon_state = "blood"
3 changes: 2 additions & 1 deletion code/datums/actions/mobs/dash.dm
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
var/pick_range = 5

/datum/action/cooldown/mob_cooldown/dash/Activate(atom/target_atom)
StartCooldown(360 SECONDS, 360 SECONDS)
disable_cooldown_actions()
dash_to(target_atom)
StartCooldown()
enable_cooldown_actions()
return TRUE

/datum/action/cooldown/mob_cooldown/dash/proc/dash_to(atom/dash_target)
Expand Down
3 changes: 2 additions & 1 deletion code/datums/actions/mobs/lava_swoop.dm
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
M.remove_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_NOFIRE), REF(src))

/datum/action/cooldown/mob_cooldown/lava_swoop/Activate(atom/target_atom)
StartCooldown(360 SECONDS, 360 SECONDS)
disable_cooldown_actions()
attack_sequence(target_atom)
StartCooldown()
enable_cooldown_actions()
return TRUE

/datum/action/cooldown/mob_cooldown/lava_swoop/proc/attack_sequence(atom/target)
Expand Down
3 changes: 2 additions & 1 deletion code/datums/actions/mobs/meteors.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
cooldown_time = 3 SECONDS

/datum/action/cooldown/mob_cooldown/meteors/Activate(atom/target_atom)
StartCooldown(360 SECONDS, 360 SECONDS)
disable_cooldown_actions()
create_meteors(target_atom)
StartCooldown()
enable_cooldown_actions()
return TRUE

/datum/action/cooldown/mob_cooldown/meteors/proc/create_meteors(atom/target)
Expand Down
3 changes: 2 additions & 1 deletion code/datums/actions/mobs/projectileattack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
var/projectile_speed_multiplier = 1

/datum/action/cooldown/mob_cooldown/projectile_attack/Activate(atom/target_atom)
StartCooldown(360 SECONDS, 360 SECONDS)
disable_cooldown_actions()
attack_sequence(owner, target_atom)
StartCooldown()
enable_cooldown_actions()
return TRUE

/datum/action/cooldown/mob_cooldown/projectile_attack/proc/attack_sequence(mob/living/firer, atom/target)
Expand Down
3 changes: 2 additions & 1 deletion code/datums/actions/mobs/transform_weapon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
var/max_cooldown_time = 10 SECONDS

/datum/action/cooldown/mob_cooldown/transform_weapon/Activate(atom/target_atom)
StartCooldown(360 SECONDS, 360 SECONDS)
disable_cooldown_actions()
do_transform(target_atom)
StartCooldown(rand(cooldown_time, max_cooldown_time), 0)
enable_cooldown_actions()
return TRUE

/datum/action/cooldown/mob_cooldown/transform_weapon/proc/do_transform(atom/target)
Expand Down
Loading

0 comments on commit 504a4be

Please sign in to comment.