mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-14 19:03:21 +00:00
Makes the code compatible with 515.1594+
Few simple changes and one very painful one.
Let's start with the easy:
* puts call behind `LIBCALL` define, so call_ext is properly used in 515
* Adds `NAMEOF_STATIC(_,X)` macro for nameof in static definitions since
src is now invalid there.
* Fixes tgui and devserver. From 515 onward the tmp3333{procid} cache
directory is not appened to base path in browser controls so we don't
check for it in base js and put the dev server dummy window file in
actual directory not the byond root.
* Renames the few things that had /final/ in typepath to ultimate since
final is a new keyword
And the very painful change:
`.proc/whatever` format is no longer valid, so we're replacing it with
new nameof() function. All this wrapped in three new macros.
`PROC_REF(X)`,`TYPE_PROC_REF(TYPE,X)`,`GLOBAL_PROC_REF(X)`. Global is
not actually necessary but if we get nameof that does not allow globals
it would be nice validation.
This is pretty unwieldy but there's no real alternative.
If you notice anything weird in the commits let me know because majority
was done with regex replace.
@tgstation/commit-access Since the .proc/stuff is pretty big change.
Co-authored-by: san7890 <the@san7890.com>
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
260 lines
8.7 KiB
Plaintext
260 lines
8.7 KiB
Plaintext
/**
|
|
* Tippable component. For making mobs able to be tipped, like cows and medibots.
|
|
*/
|
|
/datum/component/tippable
|
|
/// Time it takes to tip the mob. Can be 0, for instant tipping.
|
|
var/tip_time = 3 SECONDS
|
|
/// Time it takes to untip the mob. Can also be 0, for instant untip.
|
|
var/untip_time = 1 SECONDS
|
|
/// Time it takes for the mob to right itself. Can be 0 for instant self-righting, or null, to never self-right.
|
|
var/self_right_time = 60 SECONDS
|
|
/// Whether the mob is currently tipped.
|
|
var/is_tipped = FALSE
|
|
/// Callback to additional behavior before being tipped (on try_tip). Return anything from this callback to cancel the tip.
|
|
var/datum/callback/pre_tipped_callback
|
|
/// Callback to additional behavior after successfully tipping the mob.
|
|
var/datum/callback/post_tipped_callback
|
|
/// Callback to additional behavior after being untipped.
|
|
var/datum/callback/post_untipped_callback
|
|
/// Callback to any extra roleplay behaviour
|
|
var/datum/callback/roleplay_callback
|
|
///The timer given until they untip themselves
|
|
var/self_untip_timer
|
|
|
|
///Should we accept roleplay?
|
|
var/roleplay_friendly
|
|
///Have we roleplayed?
|
|
var/roleplayed = FALSE
|
|
///List of emotes that will half their untip time
|
|
var/list/roleplay_emotes
|
|
|
|
/datum/component/tippable/Initialize(
|
|
tip_time = 3 SECONDS,
|
|
untip_time = 1 SECONDS,
|
|
self_right_time = 60 SECONDS,
|
|
datum/callback/pre_tipped_callback,
|
|
datum/callback/post_tipped_callback,
|
|
datum/callback/post_untipped_callback,
|
|
roleplay_friendly = FALSE,
|
|
roleplay_emotes,
|
|
datum/callback/roleplay_callback,
|
|
)
|
|
|
|
if(!isliving(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
src.tip_time = tip_time
|
|
src.untip_time = untip_time
|
|
src.self_right_time = self_right_time
|
|
src.pre_tipped_callback = pre_tipped_callback
|
|
src.post_tipped_callback = post_tipped_callback
|
|
src.post_untipped_callback = post_untipped_callback
|
|
src.roleplay_friendly = roleplay_friendly
|
|
src.roleplay_emotes = roleplay_emotes
|
|
src.roleplay_callback = roleplay_callback
|
|
|
|
/datum/component/tippable/RegisterWithParent()
|
|
RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND_SECONDARY, PROC_REF(interact_with_tippable))
|
|
if (roleplay_friendly)
|
|
RegisterSignal(parent, COMSIG_MOB_EMOTE, PROC_REF(accept_roleplay))
|
|
|
|
|
|
/datum/component/tippable/UnregisterFromParent()
|
|
UnregisterSignal(parent, COMSIG_ATOM_ATTACK_HAND_SECONDARY)
|
|
|
|
/datum/component/tippable/Destroy()
|
|
if(pre_tipped_callback)
|
|
QDEL_NULL(pre_tipped_callback)
|
|
if(post_tipped_callback)
|
|
QDEL_NULL(post_tipped_callback)
|
|
if(post_untipped_callback)
|
|
QDEL_NULL(post_untipped_callback)
|
|
if(roleplay_callback)
|
|
QDEL_NULL(roleplay_callback)
|
|
return ..()
|
|
|
|
/**
|
|
* Attempt to interact with [source], either tipping it or helping it up.
|
|
*
|
|
* source - the mob being tipped over
|
|
* user - the mob interacting with source
|
|
*/
|
|
/datum/component/tippable/proc/interact_with_tippable(mob/living/source, mob/user)
|
|
SIGNAL_HANDLER
|
|
|
|
var/mob/living/living_user = user
|
|
if(DOING_INTERACTION_WITH_TARGET(user, source))
|
|
return
|
|
if(istype(living_user) && !living_user.combat_mode)
|
|
return
|
|
|
|
if(is_tipped)
|
|
INVOKE_ASYNC(src, PROC_REF(try_untip), source, user)
|
|
else
|
|
INVOKE_ASYNC(src, PROC_REF(try_tip), source, user)
|
|
|
|
return COMPONENT_SECONDARY_CANCEL_ATTACK_CHAIN
|
|
|
|
/**
|
|
* Try to tip over [tipped_mob].
|
|
* If the mob is dead, or optional callback returns a value, or our do-after fails, we don't tip the mob.
|
|
* Otherwise, upon completing of the do_after, tip over the mob.
|
|
*
|
|
* tipped_mob - the mob being tipped over
|
|
* tipper - the mob tipping the tipped_mob
|
|
*/
|
|
/datum/component/tippable/proc/try_tip(mob/living/tipped_mob, mob/tipper)
|
|
if(tipped_mob.stat != CONSCIOUS)
|
|
return
|
|
|
|
if(pre_tipped_callback?.Invoke(tipper))
|
|
return
|
|
|
|
if(tip_time > 0)
|
|
to_chat(tipper, span_warning("You begin tipping over [tipped_mob]..."))
|
|
tipped_mob.visible_message(
|
|
span_warning("[tipper] begins tipping over [tipped_mob]."),
|
|
span_userdanger("[tipper] begins tipping you over!"),
|
|
ignored_mobs = tipper
|
|
)
|
|
|
|
if(!do_after(tipper, tip_time, target = tipped_mob))
|
|
if(!isnull(tipped_mob.client))
|
|
tipped_mob.log_message("was attempted to tip over by [key_name(tipper)]", LOG_VICTIM, log_globally = FALSE)
|
|
tipper.log_message("failed to tip over [key_name(tipped_mob)]", LOG_ATTACK)
|
|
to_chat(tipper, span_danger("You fail to tip over [tipped_mob]."))
|
|
return
|
|
do_tip(tipped_mob, tipper)
|
|
|
|
/**
|
|
* Actually tip over the mob, setting it to tipped.
|
|
* Also invoking any callbacks we have, with the tipper as the argument,
|
|
* and set a timer to right our self-right our tipped mob if we can.
|
|
*
|
|
* tipped_mob - the mob who was tipped
|
|
* tipper - the mob who tipped the tipped_mob
|
|
*/
|
|
/datum/component/tippable/proc/do_tip(mob/living/tipped_mob, mob/tipper)
|
|
if(QDELETED(tipped_mob))
|
|
CRASH("Tippable component: do_tip() called with QDELETED tipped_mob!")
|
|
|
|
to_chat(tipper, span_warning("You tip over [tipped_mob]."))
|
|
if (!isnull(tipped_mob.client))
|
|
tipped_mob.log_message("has been tipped over by [key_name(tipper)].", LOG_ATTACK)
|
|
tipper.log_message("has tipped over [key_name(tipped_mob)].", LOG_ATTACK)
|
|
tipped_mob.visible_message(
|
|
span_warning("[tipper] tips over [tipped_mob]."),
|
|
span_userdanger("You are tipped over by [tipper]!"),
|
|
ignored_mobs = tipper
|
|
)
|
|
|
|
set_tipped_status(tipped_mob, TRUE)
|
|
post_tipped_callback?.Invoke(tipper)
|
|
if(isnull(self_right_time))
|
|
return
|
|
else if(self_right_time <= 0)
|
|
right_self(tipped_mob)
|
|
else
|
|
self_untip_timer = addtimer(CALLBACK(src, PROC_REF(right_self), tipped_mob), self_right_time, TIMER_UNIQUE | TIMER_STOPPABLE)
|
|
|
|
/**
|
|
* Try to untip a mob that has been tipped.
|
|
* After a do-after is completed, we untip the mob.
|
|
*
|
|
* tipped_mob - the mob who is tipped
|
|
* untipper - the mob who is untipping the tipped_mob
|
|
*/
|
|
/datum/component/tippable/proc/try_untip(mob/living/tipped_mob, mob/untipper)
|
|
if(untip_time > 0)
|
|
to_chat(untipper, span_notice("You begin righting [tipped_mob]..."))
|
|
tipped_mob.visible_message(
|
|
span_notice("[untipper] begins righting [tipped_mob]."),
|
|
span_notice("[untipper] begins righting you."),
|
|
ignored_mobs = untipper
|
|
)
|
|
|
|
if(!do_after(untipper, untip_time, target = tipped_mob))
|
|
to_chat(untipper, span_warning("You fail to right [tipped_mob]."))
|
|
return
|
|
|
|
do_untip(tipped_mob, untipper)
|
|
|
|
/**
|
|
* Actually untip over the mob, setting it to untipped.
|
|
* Also invoke any untip callbacks we have, with the untipper as the argument.
|
|
*
|
|
* tipped_mob - the mob who was tipped
|
|
* tipper - the mob who tipped the tipped_mob
|
|
*/
|
|
/datum/component/tippable/proc/do_untip(mob/living/tipped_mob, mob/untipper)
|
|
if(QDELETED(tipped_mob))
|
|
return
|
|
|
|
to_chat(untipper, span_notice("You right [tipped_mob]."))
|
|
tipped_mob.visible_message(
|
|
span_notice("[untipper] rights [tipped_mob]."),
|
|
span_notice("You are righted by [untipper]!"),
|
|
ignored_mobs = untipper
|
|
)
|
|
|
|
if(self_untip_timer)
|
|
deltimer(self_untip_timer)
|
|
set_tipped_status(tipped_mob, FALSE)
|
|
post_untipped_callback?.Invoke(untipper)
|
|
|
|
/**
|
|
* Proc called after a timer to have a tipped mob un-tip itself after a certain length of time.
|
|
* Sets our mob to untipped and invokes the untipped callback without any arguments if we have one.
|
|
*
|
|
* tipped_mob - the mob who was tipped, and is freeing itself
|
|
*/
|
|
/datum/component/tippable/proc/right_self(mob/living/tipped_mob)
|
|
if(!is_tipped || QDELETED(tipped_mob))
|
|
return
|
|
|
|
set_tipped_status(tipped_mob, FALSE)
|
|
post_untipped_callback?.Invoke()
|
|
|
|
tipped_mob.visible_message(
|
|
span_notice("[tipped_mob] rights itself."),
|
|
span_notice("You right yourself.")
|
|
)
|
|
|
|
/**
|
|
* Toggles our tipped status between tipped or untipped (TRUE or FALSE)
|
|
* also handles rotating our mob and adding immobilization traits
|
|
*
|
|
* tipped_mob - the mob we're setting to tipped or untipped
|
|
* new_status - the tipped status we're setting the mob to - TRUE for tipped, FALSE for untipped
|
|
*/
|
|
/datum/component/tippable/proc/set_tipped_status(mob/living/tipped_mob, new_status = FALSE)
|
|
is_tipped = new_status
|
|
if(is_tipped)
|
|
tipped_mob.transform = turn(tipped_mob.transform, 180)
|
|
ADD_TRAIT(tipped_mob, TRAIT_IMMOBILIZED, TIPPED_OVER)
|
|
else
|
|
tipped_mob.transform = turn(tipped_mob.transform, -180)
|
|
REMOVE_TRAIT(tipped_mob, TRAIT_IMMOBILIZED, TIPPED_OVER)
|
|
|
|
/**
|
|
* Accepts "roleplay" in the form of emotes, which removes a quarter of the remaining time left to untip ourself.
|
|
*
|
|
* Arguments:
|
|
* * mob/living/user - The tipped mob
|
|
* * datum/emote/emote - The emote used by the mob
|
|
*/
|
|
/datum/component/tippable/proc/accept_roleplay(mob/living/user, datum/emote/emote)
|
|
SIGNAL_HANDLER
|
|
|
|
if (!is_tipped)
|
|
return
|
|
if (roleplayed)
|
|
return
|
|
if (!is_type_in_list(emote, roleplay_emotes))
|
|
return
|
|
var/time_left = timeleft(self_untip_timer)
|
|
deltimer(self_untip_timer)
|
|
self_untip_timer = addtimer(CALLBACK(src, PROC_REF(right_self), user), time_left * 0.75, TIMER_UNIQUE | TIMER_STOPPABLE)
|
|
roleplayed = TRUE
|
|
roleplay_callback?.Invoke(user)
|