mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-10 00:43:14 +00:00
This PR kills off the transforming subtype of /obj/item/melee and replaces it with a component to handle the transforming behavior, /datum/component/transforming.
The transforming component handles updating the variables of an item when it's transformed. Things like force, sharpness, whetstone force bonus, and attack verbs. Similar to the two-handed component, but instead of transforming into a two-hander it remains a one handed weapon.
The "nemesis" behavior (dealing addition damage to certain factions) of the transforming subtype was moved to the cleaving saw only, since it was the only transforming item that used it. In the future, this can be made into a bespoke element/component as well.
The following weapons and items have been updated to use this component:
Energy Swords / Sabers / Bananium Energy Sword
Energy Circular Saw
Energy Dagger
Energy Axe
Toy Energy Sword
Holographic Energy Sword
Switchblade
Advanced Medical Tools (Laser scalpel, Mechanical Pinches, Searing Tool)
Advanced Engineering Tools (Hand Drill, Jaws of Life / Syndicate Jaws of Life)
Combat Wrench
Cleaving Saw
Telescopic Batons / Contractor Batons
Roasting Stick
Telescopic Riot Shield
Energy Shield / Bananium Energy Shield
This PR also touches up the code around the various above items.
254 lines
8.9 KiB
Plaintext
254 lines
8.9 KiB
Plaintext
/*
|
|
* Transforming weapon component. For weapons that swap between states.
|
|
* For example: Energy swords, cleaving saws, switch blades.
|
|
*
|
|
* Used to easily make an item that can be attack_self'd to gain force or change mode.
|
|
*
|
|
* Only values passed on initialize will update when the item is activated (except the icon_state).
|
|
* The icon_state of the item will swap between "[icon_state]" and "[icon_state]_on".
|
|
*/
|
|
/datum/component/transforming
|
|
/// Whether the weapon is transformed
|
|
var/active = FALSE
|
|
/// Cooldown on transforming this item back and forth
|
|
var/transform_cooldown_time
|
|
/// Force of the weapon when active
|
|
var/force_on
|
|
/// Throwforce of the weapon when active
|
|
var/throwforce_on
|
|
/// Throw speed of the weapon when active
|
|
var/throw_speed_on
|
|
/// Weight class of the weapon when active
|
|
var/w_class_on
|
|
/// The sharpness of the weapon when active
|
|
var/sharpness_on
|
|
/// Hitsound played when active
|
|
var/hitsound_on
|
|
/// List of the original continuous attack verbs the item has.
|
|
var/list/attack_verb_continuous_off
|
|
/// List of the original simple attack verbs the item has.
|
|
var/list/attack_verb_simple_off
|
|
/// List of continuous attack verbs used when the weapon is enabled
|
|
var/list/attack_verb_continuous_on
|
|
/// List of simple attack verbs used when the weapon is enabled
|
|
var/list/attack_verb_simple_on
|
|
/// Whether clumsy people need to succeed an RNG check to turn it on without hurting themselves
|
|
var/clumsy_check
|
|
/// If we get sharpened with a whetstone, save the bonus here for later use if we un/redeploy
|
|
var/sharpened_bonus = 0
|
|
/// Cooldown in between transforms
|
|
COOLDOWN_DECLARE(transform_cooldown)
|
|
|
|
/datum/component/transforming/Initialize(
|
|
start_transformed = FALSE,
|
|
transform_cooldown_time = 0 SECONDS,
|
|
force_on = 0,
|
|
throwforce_on = 0,
|
|
throw_speed_on = 2,
|
|
sharpness_on = NONE,
|
|
hitsound_on = 'sound/weapons/blade1.ogg',
|
|
w_class_on = WEIGHT_CLASS_BULKY,
|
|
clumsy_check = TRUE,
|
|
list/attack_verb_continuous_on,
|
|
list/attack_verb_simple_on,
|
|
)
|
|
|
|
if(!isitem(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
var/obj/item/item_parent = parent
|
|
|
|
src.transform_cooldown_time = transform_cooldown_time
|
|
src.force_on = force_on
|
|
src.throwforce_on = throwforce_on
|
|
src.throw_speed_on = throw_speed_on
|
|
src.sharpness_on = sharpness_on
|
|
src.hitsound_on = hitsound_on
|
|
src.w_class_on = w_class_on
|
|
src.clumsy_check = clumsy_check
|
|
|
|
if(attack_verb_continuous_on)
|
|
src.attack_verb_continuous_on = attack_verb_continuous_on
|
|
attack_verb_continuous_off = item_parent.attack_verb_continuous
|
|
if(attack_verb_simple_on)
|
|
src.attack_verb_simple_on = attack_verb_simple_on
|
|
attack_verb_simple_off = item_parent.attack_verb_simple
|
|
|
|
if(start_transformed)
|
|
toggle_active(parent)
|
|
|
|
/datum/component/transforming/RegisterWithParent()
|
|
var/obj/item/item_parent = parent
|
|
|
|
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/on_attack_self)
|
|
if(item_parent.sharpness || sharpness_on)
|
|
RegisterSignal(parent, COMSIG_ITEM_SHARPEN_ACT, .proc/on_sharpen)
|
|
|
|
/datum/component/transforming/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(COMSIG_ITEM_ATTACK_SELF, COMSIG_ITEM_SHARPEN_ACT))
|
|
|
|
/*
|
|
* Called on [COMSIG_ITEM_ATTACK_SELF].
|
|
*
|
|
* Check if we can transform our weapon, and if so, call [do_transform].
|
|
* Sends signal [COMSIG_TRANSFORMING_PRE_TRANSFORM], and stops the transform action if it returns [COMPONENT_BLOCK_TRANSFORM].
|
|
* And, if [do_transform] was successful, do a clumsy effect from [clumsy_transform_effect].
|
|
*
|
|
* source - source of the signal, the item being transformed / parent
|
|
* user - the mob transforming the weapon
|
|
*/
|
|
/datum/component/transforming/proc/on_attack_self(obj/item/source, mob/user)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!COOLDOWN_FINISHED(src, transform_cooldown))
|
|
to_chat(user, span_warning("Wait a bit before trying to use [source] again!"))
|
|
return
|
|
|
|
if(SEND_SIGNAL(source, COMSIG_TRANSFORMING_PRE_TRANSFORM, user, active) & COMPONENT_BLOCK_TRANSFORM)
|
|
return
|
|
|
|
if(do_transform(source, user))
|
|
clumsy_transform_effect(user)
|
|
. = COMPONENT_CANCEL_ATTACK_CHAIN
|
|
|
|
/*
|
|
* Transform the weapon into its alternate form, calling [toggle_active].
|
|
*
|
|
* Sends signal [COMSIG_TRANSFORMING_ON_TRANSFORM], and calls [default_transform_message] if it does not return [COMPONENT_NO_DEFAULT_MESSAGE].
|
|
* Also starts the [transform_cooldown] if we have a set [transform_cooldown_time].
|
|
*
|
|
* source - the item being transformed / parent
|
|
* user - the mob transforming the item
|
|
*
|
|
* returns TRUE.
|
|
*/
|
|
/datum/component/transforming/proc/do_transform(obj/item/source, mob/user)
|
|
toggle_active(source)
|
|
if(!(SEND_SIGNAL(source, COMSIG_TRANSFORMING_ON_TRANSFORM, user, active) & COMPONENT_NO_DEFAULT_MESSAGE))
|
|
default_transform_message(source, user)
|
|
|
|
if(isnum(transform_cooldown_time))
|
|
COOLDOWN_START(src, transform_cooldown, transform_cooldown_time)
|
|
if(user)
|
|
source.add_fingerprint(user)
|
|
return TRUE
|
|
|
|
/*
|
|
* The default feedback message and sound effect for an item transforming.
|
|
*
|
|
* source - the item being transformed / parent
|
|
* user - the mob transforming the item
|
|
*/
|
|
/datum/component/transforming/proc/default_transform_message(obj/item/source, mob/user)
|
|
source.balloon_alert(user, "[active ? "enabled" : "disabled"] [source]")
|
|
playsound(user ? user : source.loc, 'sound/weapons/batonextend.ogg', 50, TRUE)
|
|
|
|
/*
|
|
* Toggle active between true and false, and call
|
|
* either set_active or set_inactive depending on whichever state is toggled.
|
|
*
|
|
* source - the item being transformed / parent
|
|
*/
|
|
/datum/component/transforming/proc/toggle_active(obj/item/source)
|
|
active = !active
|
|
if(active)
|
|
set_active(source)
|
|
else
|
|
set_inactive(source)
|
|
|
|
/*
|
|
* Set our transformed item into its active state.
|
|
* Updates all the values that were passed from init and the icon_state.
|
|
*
|
|
* source - the item being transformed / parent
|
|
*/
|
|
/datum/component/transforming/proc/set_active(obj/item/source)
|
|
if(sharpness_on)
|
|
source.sharpness = sharpness_on
|
|
if(force_on)
|
|
source.force = force_on + (source.sharpness ? sharpened_bonus : 0)
|
|
if(throwforce_on)
|
|
source.throwforce = throwforce_on + (source.sharpness ? sharpened_bonus : 0)
|
|
if(throw_speed_on)
|
|
source.throw_speed = throw_speed_on
|
|
|
|
if(LAZYLEN(attack_verb_continuous_on))
|
|
source.attack_verb_continuous = attack_verb_continuous_on
|
|
if(LAZYLEN(attack_verb_simple_on))
|
|
source.attack_verb_simple = attack_verb_simple_on
|
|
|
|
source.hitsound = hitsound_on
|
|
source.w_class = w_class_on
|
|
source.icon_state = "[source.icon_state]_on"
|
|
|
|
/*
|
|
* Set our transformed item into its inactive state.
|
|
* Updates all the values back to the item's initial values.
|
|
*
|
|
* source - the item being un-transformed / parent
|
|
*/
|
|
/datum/component/transforming/proc/set_inactive(obj/item/source)
|
|
if(sharpness_on)
|
|
source.sharpness = initial(source.sharpness)
|
|
if(force_on)
|
|
source.force = initial(source.force) + (source.sharpness ? sharpened_bonus : 0)
|
|
if(throwforce_on)
|
|
source.throwforce = initial(source.throwforce) + (source.sharpness ? sharpened_bonus : 0)
|
|
if(throw_speed_on)
|
|
source.throw_speed = initial(source.throw_speed)
|
|
|
|
if(LAZYLEN(attack_verb_continuous_on))
|
|
source.attack_verb_continuous = attack_verb_continuous_off
|
|
if(LAZYLEN(attack_verb_simple_off))
|
|
source.attack_verb_simple = attack_verb_simple_off
|
|
|
|
source.hitsound = initial(source.hitsound)
|
|
source.w_class = initial(source.w_class)
|
|
source.icon_state = initial(source.icon_state)
|
|
|
|
/*
|
|
* If [clumsy_check] is set to TRUE, attempt to cause a side effect for clumsy people activating this item.
|
|
* Called after the transform is done, meaning [active] var has already updated.
|
|
*
|
|
* user - the clumsy mob, transforming our item (parent)
|
|
*
|
|
* Returns TRUE if side effects happened, FALSE otherwise
|
|
*/
|
|
/datum/component/transforming/proc/clumsy_transform_effect(mob/living/user)
|
|
if(!clumsy_check)
|
|
return FALSE
|
|
|
|
if(!HAS_TRAIT(user, TRAIT_CLUMSY))
|
|
return FALSE
|
|
|
|
if(active && prob(50))
|
|
var/hurt_self_verb_simple = LAZYLEN(attack_verb_simple_on) ? pick(attack_verb_simple_on) : "hit"
|
|
var/hurt_self_verb_continuous = LAZYLEN(attack_verb_continuous_on) ? pick(attack_verb_continuous_on) : "hits"
|
|
user.visible_message(
|
|
span_warning("[user] triggers [parent] while holding it backwards and [hurt_self_verb_continuous] themself, like a doofus!"),
|
|
span_warning("You trigger [parent] while holding it backwards and [hurt_self_verb_simple] yourself, like a doofus!")
|
|
)
|
|
user.take_bodypart_damage(10)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/*
|
|
* Called on [COMSIG_ITEM_SHARPEN_ACT].
|
|
* We need to track our sharpened bonus here, so we correctly apply and unapply it
|
|
* if our item's sharpness state changes from transforming.
|
|
*
|
|
* source - the item being sharpened / parent
|
|
* increment - the amount of force added
|
|
* max - the maximum force that the item can be adjusted to.
|
|
*
|
|
* Does not return naturally [COMPONENT_BLOCK_SHARPEN_APPLIED] as this is only to track our sharpened bonus between transformation.
|
|
*/
|
|
/datum/component/transforming/proc/on_sharpen(obj/item/source, increment, max)
|
|
SIGNAL_HANDLER
|
|
|
|
if(sharpened_bonus)
|
|
return COMPONENT_BLOCK_SHARPEN_ALREADY
|
|
if(force_on + increment > max)
|
|
return COMPONENT_BLOCK_SHARPEN_MAXED
|
|
sharpened_bonus = increment
|