Files
Bubberstation/code/modules/mob/living/basic/lavaland/goliath/goliath.dm
T
Ben10OmintrixandGitHub 01620b9c46 fixes goliaths being untamable (#88779)
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may
not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull
request process. -->

## About The Pull Request

<!-- Describe The Pull Request. Please be sure every change is
documented or this can delay review and even discourage maintainers from
merging your PR! --> you can now tame goliaths again!

## Why It's Good For The Game

<!-- Argue for the merits of your changes and how they benefit the game,
especially if they are controversial and/or far reaching. If you can't
actually explain WHY what you are doing will improve the game, then it
probably isn't good for the game in the first place. --> closes #88761

## Changelog

<!-- If your PR modifies aspects of the game that can be concretely
observed by players or admins you should add a changelog. If your change
does NOT meet this description, remove this section. Be sure to properly
mark your PRs to prevent unnecessary GBP loss. You can read up on GBP
and its effects on PRs in the tgstation guides for contributors. Please
note that maintainers freely reserve the right to remove and add tags
should they deem it appropriate. You can attempt to finagle the system
all you want, but it's best to shoot for clear communication right off
the bat. -->

🆑
fix: goliaths can now be tamed
/🆑

<!-- Both 🆑's are required for the changelog to work! You can put
your name to the right of the first 🆑 if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->
2025-01-06 18:17:03 -08:00

231 lines
9.1 KiB
Plaintext

/// Slow moving mob which attempts to immobilise its target
/mob/living/basic/mining/goliath
name = "goliath"
desc = "A hulking, armor-plated beast with long tendrils arching from its back."
icon = 'icons/mob/simple/lavaland/lavaland_monsters_wide.dmi'
icon_state = "goliath"
icon_living = "goliath"
icon_dead = "goliath_dead"
pixel_x = -12
base_pixel_x = -12
gender = MALE // Female ones are the bipedal elites
speed = 30
basic_mob_flags = IMMUNE_TO_FISTS
maxHealth = 300
health = 300
friendly_verb_continuous = "wails at"
friendly_verb_simple = "wail at"
speak_emote = list("bellows")
obj_damage = 100
melee_damage_lower = 25
melee_damage_upper = 25
attack_sound = 'sound/items/weapons/punch1.ogg'
attack_verb_continuous = "pulverizes"
attack_verb_simple = "pulverize"
throw_blocked_message = "does nothing to the tough hide of"
move_force = MOVE_FORCE_VERY_STRONG
move_resist = MOVE_FORCE_VERY_STRONG
pull_force = MOVE_FORCE_VERY_STRONG
ai_controller = /datum/ai_controller/basic_controller/goliath
crusher_loot = /obj/item/crusher_trophy/goliath_tentacle
butcher_results = list(/obj/item/food/meat/slab/goliath = 2, /obj/item/stack/sheet/bone = 2)
guaranteed_butcher_results = list(/obj/item/stack/sheet/animalhide/goliath_hide = 1)
/// Icon state to use when tentacles are available
var/tentacle_warning_state = "goliath_preattack"
/// Can this kind of goliath be tamed?
var/tameable = TRUE
/// Has this particular goliath been tamed?
var/tamed = FALSE
/// Can someone ride us around like a horse?
var/saddled = FALSE
/// Slight cooldown to prevent double-dipping if we use both abilities at once
COOLDOWN_DECLARE(ability_animation_cooldown)
/// Our base tentacles ability
var/datum/action/cooldown/mob_cooldown/goliath_tentacles/tentacles
/// Our melee tentacles ability
var/datum/action/cooldown/mob_cooldown/tentacle_burst/melee_tentacles
/// Our long-ranged tentacles ability
var/datum/action/cooldown/mob_cooldown/tentacle_grasp/tentacle_line
/// Things we want to eat off the floor (or a plate, we're not picky)
var/static/list/goliath_foods = list(/obj/item/food/grown/ash_flora, /obj/item/food/bait/worm)
/mob/living/basic/mining/goliath/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_TENTACLE_IMMUNE, INNATE_TRAIT)
AddElement(/datum/element/ai_retaliate)
AddElement(/datum/element/footstep, FOOTSTEP_MOB_HEAVY)
AddElement(/datum/element/basic_eating, heal_amt = 10, food_types = goliath_foods)
AddElement(\
/datum/element/change_force_on_death,\
move_force = MOVE_FORCE_DEFAULT,\
move_resist = MOVE_RESIST_DEFAULT,\
pull_force = PULL_FORCE_DEFAULT,\
)
AddComponent(/datum/component/ai_target_timer)
AddComponent(/datum/component/basic_mob_attack_telegraph)
AddComponentFrom(INNATE_TRAIT, /datum/component/shovel_hands)
if (tameable)
AddComponent(/datum/component/tameable, tame_chance = 10, bonus_tame_chance = 5)
tentacles = new (src)
tentacles.Grant(src)
melee_tentacles = new(src)
melee_tentacles.Grant(src)
AddComponent(/datum/component/revenge_ability, melee_tentacles, targeting = GET_TARGETING_STRATEGY(ai_controller.blackboard[BB_TARGETING_STRATEGY]), max_range = 1, target_self = TRUE)
tentacle_line = new (src)
tentacle_line.Grant(src)
AddComponent(/datum/component/revenge_ability, tentacle_line, targeting = GET_TARGETING_STRATEGY(ai_controller.blackboard[BB_TARGETING_STRATEGY]), min_range = 2, max_range = 9)
tentacles_ready()
RegisterSignal(src, COMSIG_MOB_ABILITY_FINISHED, PROC_REF(used_ability))
ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(goliath_foods))
ai_controller.set_blackboard_key(BB_GOLIATH_TENTACLES, tentacles)
/mob/living/basic/mining/goliath/examine(mob/user)
. = ..()
if (saddled)
. += span_info("Someone appears to have attached a saddle to this one.")
// Goliaths can summon tentacles more frequently as they take damage, scary.
/mob/living/basic/mining/goliath/apply_damage(damage, damagetype, def_zone, blocked, forced, spread_damage, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item)
. = ..()
if (. <= 0)
return
if (tentacles.cooldown_time > 1 SECONDS)
tentacles.cooldown_time -= 1 SECONDS
/mob/living/basic/mining/goliath/attackby(obj/item/attacking_item, mob/living/user, params)
if (!istype(attacking_item, /obj/item/goliath_saddle))
return ..()
if (!tameable)
balloon_alert(user, "doesn't fit!")
return
if (saddled)
balloon_alert(user, "already saddled!")
return
if (!tamed)
balloon_alert(user, "too rowdy!")
return
balloon_alert(user, "affixing saddle...")
if (!do_after(user, delay = 5.5 SECONDS, target = src))
return
balloon_alert(user, "ready to ride")
qdel(attacking_item)
make_rideable()
/mob/living/basic/mining/goliath/proc/make_rideable()
saddled = TRUE
add_overlay("goliath_saddled")
AddElement(/datum/element/ridable, /datum/component/riding/creature/goliath)
/// When we use an ability, activate some kind of visual tell
/mob/living/basic/mining/goliath/proc/used_ability(mob/living/source, datum/action/cooldown/ability)
SIGNAL_HANDLER
if (stat == DEAD || ability.IsAvailable())
return // We died or the action failed for some reason like being out of range
if (istype(ability, /datum/action/cooldown/mob_cooldown/goliath_tentacles))
if (ability.cooldown_time <= 2 SECONDS)
return
icon_state = icon_living
addtimer(CALLBACK(src, PROC_REF(tentacles_ready)), ability.cooldown_time - 2 SECONDS, TIMER_DELETE_ME)
return
if (!COOLDOWN_FINISHED(src, ability_animation_cooldown))
return
COOLDOWN_START(src, ability_animation_cooldown, 2 SECONDS)
playsound(src, 'sound/effects/magic/demon_attack1.ogg', vol = 50, vary = TRUE)
Shake(1, 0, 1.5 SECONDS)
/// Called slightly before tentacles ability comes off cooldown, as a warning
/mob/living/basic/mining/goliath/proc/tentacles_ready()
if (stat == DEAD)
return
icon_state = tentacle_warning_state
/// Get ready for mounting
/mob/living/basic/mining/goliath/tamed(mob/living/tamer, atom/food)
tamed = TRUE
// Copy entire faction rather than just placing user into faction, to avoid tentacle peril on station
/mob/living/basic/mining/goliath/befriend(mob/living/new_friend)
. = ..()
faction = new_friend.faction.Copy()
/mob/living/basic/mining/goliath/RangedAttack(atom/atom_target, modifiers)
tentacles?.Trigger(target = atom_target)
/mob/living/basic/mining/goliath/ranged_secondary_attack(atom/atom_target, modifiers)
tentacle_line?.Trigger(target = atom_target)
/// Version of the goliath that already starts saddled and doesn't require a lasso to be ridden.
/mob/living/basic/mining/goliath/deathmatch
saddled = TRUE
buckle_lying = 0
/mob/living/basic/mining/goliath/deathmatch/Initialize(mapload)
. = ..()
make_rideable()
/mob/living/basic/mining/goliath/deathmatch/make_rideable()
add_overlay("goliath_saddled")
AddElement(/datum/element/ridable, /datum/component/riding/creature/goliath/deathmatch)
/// Legacy Goliath mob with different sprites, largely the same behaviour
/mob/living/basic/mining/goliath/ancient
name = "ancient goliath"
desc = "A massive beast that uses long tentacles to ensnare its prey, threatening them is not advised under any conditions."
icon = 'icons/mob/simple/lavaland/lavaland_monsters_wide.dmi'
icon_state = "ancient_goliath"
icon_living = "ancient_goliath"
icon_dead = "ancient_goliath_dead"
tentacle_warning_state = "ancient_goliath_preattack"
tameable = FALSE
/// Rare Goliath variant which occasionally replaces the normal mining mob, releases shitloads of tentacles
/mob/living/basic/mining/goliath/ancient/immortal
name = "immortal goliath"
desc = "Goliaths are biologically immortal, and rare specimens have survived for centuries. \
This one is clearly ancient, and its tentacles constantly churn the earth around it."
maxHealth = 400
health = 400
crusher_drop_chance = 30 // Wow a whole 5% more likely, how generous
/// Don't re-check nearby turfs for this long
COOLDOWN_DECLARE(retarget_turfs_cooldown)
/// List of places we might spawn a tentacle, if we're alive
var/list/tentacle_target_turfs
/mob/living/basic/mining/goliath/ancient/immortal/Life(seconds_per_tick, times_fired)
. = ..()
if (!. || !isturf(loc))
return
if (!LAZYLEN(tentacle_target_turfs) || COOLDOWN_FINISHED(src, retarget_turfs_cooldown))
cache_nearby_turfs()
for (var/turf/target_turf in tentacle_target_turfs)
if (target_turf.is_blocked_turf(exclude_mobs = TRUE))
tentacle_target_turfs -= target_turf
continue
if (prob(10))
new /obj/effect/goliath_tentacle(target_turf)
/mob/living/basic/mining/goliath/ancient/immortal/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change)
. = ..()
if (loc == old_loc || stat == DEAD || !isturf(loc))
return
cache_nearby_turfs()
/// Store nearby turfs in our list so we can pop them out later
/mob/living/basic/mining/goliath/ancient/immortal/proc/cache_nearby_turfs()
COOLDOWN_START(src, retarget_turfs_cooldown, 10 SECONDS)
LAZYCLEARLIST(tentacle_target_turfs)
for(var/turf/open/floor in orange(4, loc))
LAZYADD(tentacle_target_turfs, floor)
/// Use this to ride a goliath
/obj/item/goliath_saddle
name = "goliath saddle"
desc = "This rough saddle will give you a serviceable seat upon a goliath! Provided you can get one to stand still."
icon = 'icons/obj/mining.dmi'
icon_state = "goliath_saddle"