mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-19 19:18:50 +01:00
## About The Pull Request Herculean/Atlas spinal implants allow you to break boulders to process them manually. Doing so also grants athletics experience. They also increase the speed at which you throw objects, and also increase the range further. The Atlas version also allows you to reduce equipment movespeed penalties. (Fikou wanted me to do this for specifically modsuits, but I don't see any reason this can't apply to more than that, modsuits are just generally the slowest equipment you could wear) Boulders have 30 throw force, are by default HUGE, but have no throw range at all and really weak tk throw range. You need a throwing booster to throw boulders around. (They do extra damage to SPECIAL mobs, like lavaland bosses, because it's funny to kill a god-like being with a huge rock while slow as shit) You naturally get athletics experience by doing some actions. Fireman carrying, climbing tables/crates, climbing rope and climbing ladders give you a slow and steady stream of experience. Rope gives a larger amount if only because the process for doing so is destructive in some way (you have to get more climbing rope eventually, so there is an associated cost). Spinal implants now improve climbing speed for climbing over objects. ## Why It's Good For The Game I just had this strange compulsion to make the spinal implant make you good at throwing boulders at lethal speeds. It already has some cool rock-based special effects around you. Having mastery over rock throwing just kind of made sense. Additionally, I thought it would be a funny method for someone to be able to kill a boss via way of thrown boulders. Or some hapless nuclear operative unprepared for a bunch of assistants lobbing boulders at them. Additionally, I also think it letting you break boulders for ore is a fairly minor but fun addition. Pull boulders out of the vents, smash them. Good work out. Particularly for miners. I talked a while ago with I think Jacq about adding some natural methods for accumulating athletics experience over the course of a round that doesn't involve the dedicated weight lifting machinery/boxing bag. I thought any method for doing that should probably be relatively slow and definitely nonviable for significant athletics gains beyond novice level. Mooost people will hit novice on a multi-z map if they go up and down ladders enough. Or climb a lot of tables/crates. The results aren't going to have much noticeable impact, however, as you only gain appreciable benefits above novice. Probably just greater visibility of fitness in a round. (Rather nice for the RD, who gets to show off how swole they are more regularly). <details> <summary>Spoiler warning</summary>  </details> ## Changelog 🆑 balance: Herculean/Atlas spinal implants make you better at climbing tables, throw objects much faster and throw them much further. You can also break boulders with your bare hands. balance: Atlas implants let you offset the weight of worn/carried equipment (like boulders). balance: Boulders have no throw range, but if you can throw them via throwing range boosters (such as the spinal implant), they deal fairly large amounts of damage. Especially to powerful mobs like lavlaand bosses. balance: You naturally gain a small amount of athletics experience doing some tasks, such as climbing rope, ladders and tables/crates, fireman carrying, or smashing open boulders. /🆑
141 lines
6.8 KiB
Plaintext
141 lines
6.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)
|
|
if (!user.CanReach(source))
|
|
return FALSE
|
|
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]..."))
|
|
// Time in deciseoncds it takes to complete the climb do_after()
|
|
var/adjusted_climb_time = climb_time
|
|
// Time in deciseonds that the mob is stunned after climbing successfully.
|
|
var/adjusted_climb_stun = climb_stun
|
|
// Our climbers fitness level, which removes some climb time and speeds up our climbing do_after, assuming they worked out
|
|
var/fitness_level = user.mind?.get_skill_level(/datum/skill/athletics) - 1
|
|
adjusted_climb_time = clamp(adjusted_climb_time - fitness_level, 1, climb_time) //Here we adjust the number of deciseconds we shave off per level of fitness, with a minimum of 1 decisecond and a maximum of climb_time (just in case)
|
|
|
|
var/obj/item/organ/cyberimp/chest/spine/potential_spine = user.get_organ_slot(ORGAN_SLOT_SPINE)
|
|
if(istype(potential_spine))
|
|
adjusted_climb_time *= potential_spine.athletics_boost_multiplier
|
|
adjusted_climb_stun *= potential_spine.athletics_boost_multiplier
|
|
|
|
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)
|
|
user.mind?.adjust_experience(/datum/skill/athletics, 5) //Get a bit fitter with every climb.
|
|
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)) - ICON_SIZE_X/2) * (climbed_thing.dir & WEST ? -1 : 1)
|
|
var/y_dist = (text2num(LAZYACCESS(modifiers, ICON_Y)) - ICON_SIZE_Y/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
|