Files
Bubberstation/code/datums/elements/climbable.dm
Joshua Kidder 94cf89f2d7 Settler partially atomized into traits, ashwalkers given some settler traits (#84090)
## About The Pull Request

So my previous PR was to give ashwalker the settler trait so they'd get
some of the benefits of settler (better riding, fishing, and taming) but
it was suggested that Settler be atomized into different traits instead.
I've done that here.

Ashwalkers now get
TRAIT_ROUGHRIDER
TRAIT_BEAST_EMPATHY
TRAIT_EXPERT_FISHER

which will, respectively, make them better riders, better tamers, and
better at fishing. I also made a small change to the riding code that
references riding speed boosts for people with the ROUGHRIDER trait
(would, at the moment, only be ashwalkers and settlers) that gives
ashwalkers the maximum bonus, to represent their primal connection with
the beasts in the area.

## Why It's Good For The Game

Ashwalkers are described in the lore as being denizens of lavaland, the
same as all the other messed up shit down there. This change brings them
in line with that. The improvements to the handling of the settler trait
will also open up avenues for expanding or improving on related systems

## Changelog
🆑 Bisar
add: Ashwalkers are now better at riding, taming animals, and fishing.
code: Behavior for the settler trait has been partially atomized into
several traits instead.
/🆑

---------

Co-authored-by: necromanceranne <40847847+necromanceranne@users.noreply.github.com>
Co-authored-by: Jacquerel <hnevard@gmail.com>
2024-06-20 20:10:08 +01:00

127 lines
5.8 KiB
Plaintext

/datum/element/climbable
element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH_ON_HOST_DESTROY // Detach for turfs
argument_hash_start_idx = 2
///Time it takes to climb onto the object
var/climb_time
///Stun duration for when you get onto the object
var/climb_stun
///Assoc list of object being climbed on - climbers. This allows us to check who needs to be shoved off a climbable object when its clicked on.
var/list/current_climbers
/datum/element/climbable/Attach(
datum/target,
climb_time = 2 SECONDS,
climb_stun = 2 SECONDS,
)
. = ..()
if(!isatom(target) || isarea(target))
return ELEMENT_INCOMPATIBLE
src.climb_time = climb_time
src.climb_stun = climb_stun
RegisterSignal(target, COMSIG_ATOM_ATTACK_HAND, PROC_REF(attack_hand))
RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
RegisterSignal(target, COMSIG_MOUSEDROPPED_ONTO, PROC_REF(mousedrop_receive))
ADD_TRAIT(target, TRAIT_CLIMBABLE, ELEMENT_TRAIT(type))
/datum/element/climbable/Detach(datum/target)
UnregisterSignal(target, list(COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_EXAMINE, COMSIG_MOUSEDROPPED_ONTO, COMSIG_ATOM_BUMPED))
REMOVE_TRAIT(target, TRAIT_CLIMBABLE, ELEMENT_TRAIT(type))
return ..()
/datum/element/climbable/proc/on_examine(atom/source, mob/user, list/examine_texts)
SIGNAL_HANDLER
examine_texts += span_notice("[source] looks climbable.")
/datum/element/climbable/proc/can_climb(atom/source, mob/user)
var/dir_step = get_dir(user, source.loc)
//To jump over a railing you have to be standing next to it, not far behind it.
if(source.flags_1 & ON_BORDER_1 && user.loc != source.loc && (dir_step & source.dir) == source.dir)
return FALSE
return TRUE
/datum/element/climbable/proc/attack_hand(atom/climbed_thing, mob/user)
SIGNAL_HANDLER
var/list/climbers = LAZYACCESS(current_climbers, climbed_thing)
for(var/i in climbers)
var/mob/living/structure_climber = i
if(structure_climber == user)
return
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(climbed_thing)
structure_climber.Paralyze(40)
structure_climber.visible_message(span_warning("[structure_climber] is knocked off [climbed_thing]."), span_warning("You're knocked off [climbed_thing]!"), span_hear("You hear a cry from [structure_climber], followed by a slam."))
/datum/element/climbable/proc/climb_structure(atom/climbed_thing, mob/living/user, params)
if(!can_climb(climbed_thing, user))
return
climbed_thing.add_fingerprint(user)
user.visible_message(span_warning("[user] starts climbing onto [climbed_thing]."), \
span_notice("You start climbing onto [climbed_thing]..."))
var/adjusted_climb_time = climb_time
var/adjusted_climb_stun = climb_stun
if(HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) //climbing takes twice as long without help from the hands.
adjusted_climb_time *= 2
if(isalien(user))
adjusted_climb_time *= 0.25 //aliens are terrifyingly fast
if(HAS_TRAIT(user, TRAIT_FREERUNNING)) //do you have any idea how fast I am???
adjusted_climb_time *= 0.8
adjusted_climb_stun *= 0.8
if(HAS_TRAIT(user, TRAIT_STUBBY_BODY)) //hold on, gimme a moment, my tiny legs can't get over the goshdamn table
adjusted_climb_time *= 1.5
adjusted_climb_stun *= 1.5
LAZYADDASSOCLIST(current_climbers, climbed_thing, user)
if(do_after(user, adjusted_climb_time, climbed_thing))
if(QDELETED(climbed_thing)) //Checking if structure has been destroyed
return
if(do_climb(climbed_thing, user, params))
user.visible_message(span_warning("[user] climbs onto [climbed_thing]."), \
span_notice("You climb onto [climbed_thing]."))
log_combat(user, climbed_thing, "climbed onto")
if(adjusted_climb_stun)
user.Stun(adjusted_climb_stun)
var/atom/movable/buckle_target = climbed_thing
if(istype(buckle_target))
if(buckle_target.is_buckle_possible(user))
buckle_target.buckle_mob(user)
else
to_chat(user, span_warning("You fail to climb onto [climbed_thing]."))
LAZYREMOVEASSOC(current_climbers, climbed_thing, user)
/datum/element/climbable/proc/do_climb(atom/climbed_thing, mob/living/user, params)
if(!can_climb(climbed_thing, user))
return
climbed_thing.set_density(FALSE)
var/dir_step = get_dir(user, climbed_thing.loc)
var/same_loc = climbed_thing.loc == user.loc
// on-border objects can be vaulted over and into the next turf.
// The reverse dir check is for when normal behavior should apply instead (e.g. John Doe hops east of a railing facing west, ending on the same turf as it).
if(climbed_thing.flags_1 & ON_BORDER_1 && (same_loc || !(dir_step & REVERSE_DIR(climbed_thing.dir))))
//it can be vaulted over in two different cardinal directions. we choose one.
if(ISDIAGONALDIR(climbed_thing.dir) && same_loc)
if(params) //we check the icon x and y parameters of the click-drag to determine step_dir.
var/list/modifiers = params2list(params)
var/x_dist = (text2num(LAZYACCESS(modifiers, ICON_X)) - world.icon_size/2) * (climbed_thing.dir & WEST ? -1 : 1)
var/y_dist = (text2num(LAZYACCESS(modifiers, ICON_Y)) - world.icon_size/2) * (climbed_thing.dir & SOUTH ? -1 : 1)
dir_step = (x_dist >= y_dist ? (EAST|WEST) : (NORTH|SOUTH)) & climbed_thing.dir
else
dir_step = get_dir(user, get_step(climbed_thing, climbed_thing.dir))
. = step(user, dir_step)
climbed_thing.set_density(TRUE)
///Handles climbing onto the atom when you click-drag
/datum/element/climbable/proc/mousedrop_receive(atom/climbed_thing, atom/movable/dropped_atom, mob/user, params)
SIGNAL_HANDLER
if(user != dropped_atom || !isliving(dropped_atom))
return
if(!HAS_TRAIT(dropped_atom, TRAIT_FENCE_CLIMBER) && !HAS_TRAIT(dropped_atom, TRAIT_CAN_HOLD_ITEMS)) // If you can hold items you can probably climb a fence
return
var/mob/living/living_target = dropped_atom
if(living_target.mobility_flags & MOBILITY_MOVE)
INVOKE_ASYNC(src, PROC_REF(climb_structure), climbed_thing, living_target, params)
return COMPONENT_CANCEL_MOUSEDROPPED_ONTO