Ports maneuvers (and the leap maneuver) from Bay. (#15063)

This commit is contained in:
Matt Atlas
2022-11-12 23:08:41 +01:00
committed by GitHub
parent 7f0c342c5b
commit 56515acc8b
15 changed files with 369 additions and 2 deletions
@@ -90,6 +90,8 @@
sync_organ_dna()
make_blood()
available_maneuvers = species.maneuvers.Copy()
pixel_x = species.icon_x_offset
pixel_y = species.icon_y_offset
@@ -0,0 +1,48 @@
/mob/living/carbon/human/get_acrobatics_multiplier(var/decl/maneuver/attempting_maneuver)
. = ..()
// Broken limb checks
for (var/_limb in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT))
var/obj/item/organ/external/limb = get_organ(_limb)
if (limb.status & ORGAN_BROKEN)
. -= limb.status & ORGAN_SPLINTED ? 0.25 : 0.5
/mob/living/carbon/human/get_jump_distance()
return species.standing_jump_range
/mob/living/carbon/human/can_do_maneuver(var/decl/maneuver/maneuver, var/silent = FALSE)
. = ..()
if(.)
if(nutrition <= 20)
if(!silent)
to_chat(src, SPAN_WARNING("You are too hungry to jump around."))
return FALSE
if(hydration <= 20)
if(!silent)
to_chat(src, SPAN_WARNING("You are too thirsty to jump around."))
return FALSE
/mob/living/carbon/human/post_maneuver()
..()
var/broken_limb_fail_chance = 0
var/list/broken_limbs = list()
for (var/_limb in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT))
var/obj/item/organ/external/limb = get_organ(_limb)
if (limb.status & ORGAN_BROKEN)
broken_limbs += limb
broken_limb_fail_chance += limb.status & ORGAN_SPLINTED ? 25 : 50
if (broken_limb_fail_chance)
var/obj/item/organ/external/limb = pick(broken_limbs)
if (prob(broken_limb_fail_chance))
visible_message(
SPAN_WARNING("\The [src]'s [limb.name] buckles beneath them as they land!"),
SPAN_DANGER("Your [limb.name] buckles beneath you as you land!")
)
apply_effect(1, WEAKEN)
limb.add_pain(30)
limb.take_damage(5)
else
to_chat(src, SPAN_DANGER("You feel a sharp pain through your [limb.name] as you land!"))
apply_effect(1, STUN)
limb.add_pain(15)
@@ -74,6 +74,9 @@
/datum/unarmed_attack/bite
)
var/list/unarmed_attacks = null // For empty hand harm-intent attack
var/standing_jump_range = 2
var/list/maneuvers = list(/decl/maneuver/leap)
var/pain_mod = 1 // Pain multiplier
var/brute_mod = 1 // Physical damage multiplier.
var/burn_mod = 1 // Burn damage multiplier.
@@ -110,7 +110,6 @@
/datum/unarmed_attack/bite/strong)
inherent_verbs = list(
/mob/living/carbon/human/proc/leap,
/mob/living/carbon/human/proc/self_diagnostics
)
@@ -161,6 +160,10 @@
flags = IS_IPC | ACCEPTS_COOLER
appearance_flags = HAS_EYE_COLOR | HAS_UNDERWEAR | HAS_SOCKS
maneuvers = list(
/decl/maneuver/leap/industrial
)
heat_level_1 = 800
heat_level_2 = 1600
heat_level_3 = 3200
@@ -423,6 +426,7 @@
sprint_speed_factor = 0.6
sprint_cost_factor = 2
move_charge_factor = 2
standing_jump_range = 3
grab_mod = 1.1 // Smooth, fast
resist_mod = 4 // Not super strong, but still rather strong
@@ -451,6 +455,9 @@
/mob/living/carbon/human/proc/self_diagnostics,
/mob/living/carbon/human/proc/check_tag
)
maneuvers = list(
/decl/maneuver/leap/zenghu
)
/datum/species/machine/zenghu/get_light_color(mob/living/carbon/human/H)
@@ -17,6 +17,9 @@
/datum/unarmed_attack/palm,
/datum/unarmed_attack/bite/sharp
)
maneuvers = list(
/decl/maneuver/leap/tajara
)
darksight = 8
slowdown = -1
@@ -43,6 +46,7 @@
stamina_recovery = 4
sprint_speed_factor = 0.65
sprint_cost_factor = 0.75
standing_jump_range = 3
bp_base_systolic = 140 // Default 120
bp_base_disatolic = 90 // Default 80
low_pulse = 50 // Default 40
@@ -13,11 +13,16 @@
slowdown = -0.8 //As opposed to -1 for Base tajara
sprint_speed_factor = 0.55 // As opposed to 0.65
standing_jump_range = 2
stamina = 100 // As opposed to 90
brute_mod = 1.1 // Less Brute Damage
ethanol_resistance = 1 // Default value
climb_coeff = 1.1
maneuvers = list(
/decl/maneuver/leap
)
resist_mod = 1.5 // ZHAN POWERRRRRR
cold_level_1 = 160 //RaceDefault 200 Default 260
@@ -52,10 +57,15 @@
slowdown = -1.2 //As opposed to -1 for Base tajara
sprint_speed_factor = 0.75 // As opposed to 0.65
standing_jump_range = 3
stamina = 80 // As opposed to 90
brute_mod = 1.3 // More Brute Damage
ethanol_resistance = 0.6 // Species Default 0.8
maneuvers = list(
/decl/maneuver/leap/tajara/msai
)
cold_level_1 = 220 //RaceDefault 200 Default 260
cold_level_2 = 160 //RaceDefault 140 Default 200
cold_level_3 = 100 //RaceDefault 80 Default 120
@@ -12,6 +12,7 @@
burn_mod = 1.2
oxy_mod = 1
radiation_mod = 0.5
standing_jump_range = 3
grab_mod = 1.25
resist_mod = 1.75
@@ -217,6 +218,9 @@
slowdown = 2
unarmed_types = list(/datum/unarmed_attack/claws/vaurca_bulwark)
maneuvers = list(
/decl/maneuver/leap/bulwark
)
natural_armor = list(
melee = ARMOR_MELEE_SMALL
@@ -0,0 +1,65 @@
/mob/living
var/decl/maneuver/prepared_maneuver
var/list/available_maneuvers = list()
/mob/living/begin_falling(var/lastloc, var/below)
if(throwing)
return
if(!can_fall(lastloc) && prepared_maneuver && prepared_maneuver.can_be_used_by(src, silent = TRUE))
var/turf/check = get_turf(lastloc)
for(var/i = 1 to Ceiling((get_jump_distance() * get_acrobatics_multiplier()) * prepared_maneuver.reflexive_modifier))
var/turf/next_check = get_step(check, dir)
if(!next_check || next_check.density)
break
check = next_check
if(!can_fall(check))
break
if(check && check != loc)
addtimer(CALLBACK(src, /mob/living/proc/reflexive_maneuver_callback, lastloc, check), 0)
return
. = ..()
/mob/living/proc/reflexive_maneuver_callback(var/turf/origin, var/turf/check)
if(prepared_maneuver)
if(origin)
forceMove(get_turf(origin))
prepared_maneuver.perform(src, check, get_acrobatics_multiplier(prepared_maneuver), reflexively = TRUE)
/mob/living/verb/prepare_maneuver()
set name = "Prepare To Maneuver"
set desc = "Select a maneuver to perform."
set category = "IC"
if(!length(available_maneuvers))
to_chat(src, SPAN_WARNING("You are unable to perform any maneuvers."))
return
var/list/maneuvers = list()
for(var/maneuver in available_maneuvers)
maneuvers += decls_repository.get_decl(maneuver)
var/next_maneuver = input(src, "Select a maneuver.") as null|anything in maneuvers
if(next_maneuver)
prepared_maneuver = next_maneuver
to_chat(src, SPAN_NOTICE("You prepare to [prepared_maneuver.name]."))
else
prepared_maneuver = null
to_chat(src, SPAN_NOTICE("You are no longer preparing to perform a maneuver."))
/mob/living/proc/perform_maneuver(var/maneuver, var/atom/target)
var/decl/maneuver/performing_maneuver = ispath(maneuver) ? decls_repository.get_decl(maneuver) : maneuver
if(istype(performing_maneuver))
. = performing_maneuver.perform(src, target, get_acrobatics_multiplier(performing_maneuver))
/mob/living/proc/get_acrobatics_multiplier(var/decl/maneuver/attempting_maneuver)
return 1
/mob/living/proc/can_do_maneuver(var/decl/maneuver/maneuver, var/silent = FALSE)
. = ((istype(maneuver) ? maneuver.type : maneuver) in available_maneuvers)
/mob/living/proc/get_jump_distance()
return 0
/mob/living/proc/post_maneuver()
return
@@ -0,0 +1,56 @@
/decl/maneuver
var/name = "unnamed"
var/delay = 2 SECONDS
var/cooldown = 5 SECONDS
var/stamina_cost = 10
var/reflexive_modifier = 1
var/charge_cost = 0 //Charge cost for robot species.
/decl/maneuver/proc/can_be_used_by(var/mob/living/user, var/atom/target, var/silent = FALSE)
if(!istype(user) || !user.can_do_maneuver(src, silent))
return FALSE
if(user.buckled_to)
if(!silent)
to_chat(user, SPAN_WARNING("You are buckled down and cannot maneuver!"))
return FALSE
if(!has_gravity(user))
if(!silent)
to_chat(user, SPAN_WARNING("You cannot maneuver in zero gravity!"))
return FALSE
if(user.incapacitated(INCAPACITATION_DISABLED) || user.lying || !isturf(user.loc))
if(!silent)
to_chat(user, SPAN_WARNING("You are not in position for maneuvering."))
return FALSE
if(world.time < user.last_special)
if(!silent)
to_chat(user, SPAN_WARNING("You cannot maneuver again for another [Floor((user.last_special - world.time)*0.1)] second\s."))
return FALSE
if(!isipc(user))
if(user.stamina < stamina_cost)
if(!silent)
to_chat(user, SPAN_WARNING("You are too exhausted to maneuver right now."))
return FALSE
if (target && user.z != target.z)
if (!silent)
to_chat(user, SPAN_WARNING("You cannot maneuver to a different z-level!"))
return FALSE
return TRUE
/decl/maneuver/proc/show_initial_message(var/mob/user, var/atom/target)
return
/decl/maneuver/proc/perform(var/mob/living/user, var/atom/target, var/strength, var/reflexively = FALSE)
if(can_be_used_by(user, target))
if(!reflexively)
show_initial_message(user, target)
user.face_atom(target)
. = (!delay || reflexively || (do_after(user, delay, target) && can_be_used_by(user, target)))
if(cooldown)
user.last_special = world.time + cooldown
if(stamina_cost)
user.stamina -= stamina_cost
if(isipc(user))
var/mob/living/carbon/human/H = user
var/obj/item/cell/C = H.internal_organs_by_name[BP_CELL]
if(C)
C.use(charge_cost)
@@ -0,0 +1,112 @@
/decl/maneuver/leap
name = "leap"
stamina_cost = 10
charge_cost = 500
reflexive_modifier = 1.5
/decl/maneuver/leap/perform(var/mob/living/user, var/atom/target, var/strength, var/reflexively = FALSE)
. = ..()
if(.)
var/old_pass_flags = user.pass_flags
user.pass_flags |= PASSTABLE
user.visible_message(SPAN_DANGER("\The [user] takes a flying leap!"))
strength = max(2, strength * user.get_jump_distance())
if(reflexively)
strength *= reflexive_modifier
animate(user, pixel_z = 16, time = 3, easing = SINE_EASING | EASE_IN)
animate(pixel_z = 0, time = 3, easing = SINE_EASING | EASE_OUT)
user.throw_at(get_turf(target), strength, 1, user, FALSE)
end_leap(user, target, old_pass_flags)
/decl/maneuver/leap/proc/end_leap(var/mob/living/user, var/atom/target, var/pass_flag)
user.pass_flags = pass_flag
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.species.mob_size >= 10)
var/turf/T = get_turf(target)
var/damage_mod = 1
var/from_above = FALSE
if(H.can_fall(GET_BELOW(T)))
from_above = TRUE
if(isopenspace(T))
while(isopenspace(T))
T = GET_BELOW(T)
damage_mod += 1
if(isturf(T))
T.visible_message(SPAN_DANGER("[H] lands on \the [T] with a quake!"))
playsound(get_turf(T), 'sound/effects/bangtaper.ogg')
for(var/mob/living/L in range(2, T))
shake_camera(L, 2, 4)
for(var/mob/living/rebecca in T)
if(rebecca.lying || from_above)
rebecca.apply_damage(40 * damage_mod, BRUTE, pick(BP_ALL_LIMBS), used_weapon = "landing", armor_pen = 30) //so true choomfie
T.visible_message(SPAN_DANGER("<font size=4>[H] lands on [rebecca]!</font>"))
to_chat(H, SPAN_DANGER("<font size=4>You land on [rebecca]!</font>")) //since the mob won't be on the turf yet
user.post_maneuver()
/decl/maneuver/leap/show_initial_message(var/mob/living/user, var/atom/target)
user.visible_message(SPAN_WARNING("\The [user] crouches, preparing for a leap!"))
/decl/maneuver/leap/can_be_used_by(var/mob/living/user, var/atom/target, var/silent = FALSE)
. = ..()
if(.)
var/can_leap_distance = user.get_jump_distance() * user.get_acrobatics_multiplier()
if (can_leap_distance <= 0)
if (!silent)
to_chat(user, SPAN_WARNING("You can't leap in your current state."))
return FALSE
if (!istype(target))
if (!silent)
to_chat(user, SPAN_WARNING("That is not a valid leap target."))
return FALSE
if (get_dist(user, target) > can_leap_distance)
if (!silent)
to_chat(user, SPAN_WARNING("You can't leap that far."))
return FALSE
return TRUE
/decl/maneuver/leap/spider
stamina_cost = 0
/decl/maneuver/leap/spider/show_initial_message(var/mob/living/user, var/atom/target)
user.visible_message(SPAN_WARNING("\The [user] reels back and prepares to launch itself at \the [target]!"))
/decl/maneuver/leap/grab/end_leap(mob/living/user, atom/target, pass_flag)
. = ..()
if(ishuman(user) && !user.lying && ismob(target) && user.Adjacent(target))
var/mob/living/carbon/human/H = user
var/use_hand = "left"
if(H.l_hand)
if(H.r_hand)
to_chat(H, SPAN_DANGER("You need to have one hand free to grab someone."))
return
else
use_hand = "right"
var/obj/item/grab/G = new(H, target)
if(use_hand == "left")
H.l_hand = G
else
H.r_hand = G
G.state = GRAB_PASSIVE
G.icon_state = "grabbed1"
G.synch()
/decl/maneuver/leap/industrial
cooldown = 8 SECONDS
/decl/maneuver/leap/zenghu
cooldown = 4 SECONDS
charge_cost = 1500
/decl/maneuver/leap/bulwark
cooldown = 10 SECONDS //bigger than industrials = more cooldown
/decl/maneuver/leap/tajara
cooldown = 4 SECONDS
delay = 2 SECONDS
stamina_cost = 25
/decl/maneuver/leap/tajara/msai
delay = 1 SECOND
cooldown = 4 SECONDS