mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-11 01:13:18 +00:00
## About The Pull Request Or, how I tried to kill `/datum/forced_movement` but got absolutely clonged. Actually, I did kill `/datum/forced_movement`. It was only used in one spot so I just went ahead and cooked it into a special utility datum that should only be used in one spot. We can optimize the code later or something, but I like the way it is right now (pretty much status quo without the potential of someone using a depreciated framework). Alright, there were also like 3 `TODO`s (4 if you count the move loop comment (which is ehhhh)). I naively tried to tackle them a very hard way, but then I just realized I could use the fancy new datum I cooked up and wow they're all solved now. The hook looks so fucking good now. * The code is overall more streamlined, with all of the post-projectile work being handled by a special datum (I wanted it to be handled by the hook but the timings were all based on SSFastprocess so datum it is). Forced movement is killed but we just salvaged whatever we needed from it. * More traits to ensure we don't cheese in a way we're not supposed to * A very sexy chain will spawn when you drag your kill in (this wasn't there before but I fixeded it :3) * The firer will actually get grounded when they try and shoot the chain out. They get grounded for 0.25 seconds unless they hit something. I don't know how the timing is but I think it's fair. * We also add a unique suicide act, because I noticed we did the "magical" one previously, which big-league sucked. * More traits to ensure less cheese! I like how nice it is now. ## Why It's Good For The Game The meat hook really makes you _feel_ like Roadhog from Overwatch. Resolves a bunch of old TODOs while getting rid of a completely obsolete framework in a really neat way. I don't typically like mixing balances and refactors but these TODOs were getting crusty man i just wanted to get them out of the way ## Changelog 🆑 balance: The Meat Hook will now "ground" you whenever you fire it out at someone. You get a very small immobilization every time you fire, which "upgrades" to a full immobilization whenever you actually hit an atom and start to drag it in. fix: A chain should now show up as you drag in something with the meat hooks. fix: Meat hooks should no longer play the "magical gun" suicide if you were to use it, but instead do their own unique thing. /🆑
121 lines
5.6 KiB
Plaintext
121 lines
5.6 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_SETTLER)) //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)
|
|
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)
|