mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-13 11:12:14 +00:00
## About The Pull Request It was removed in https://github.com/tgstation/tgstation/pull/27799 because the spear was broken and the Flans' AI sucked with not-great sprites and was all just one big reference. Original addition: https://github.com/tgstation/tgstation/pull/22270 This re-adds it, updates the map (now using airless turfs) with extra ambiance, using ash whelps (lavaland variation of ice whelps) instead of Flans, re-adds the spear, and adds armor as well this time around. The spear gives you a jump ability to crash down upon a player below you, rather than teleporting to wherever you throw the spear at. You can't attack while mid-air, you can go through tables but not walls/doors, and you also can't un-dualwield or drop the spear mid-jump. Landing on a mob deals double damage to them (36 to unarmored people), while landing on objects deals 150 damage to them (taken from savannah's jump ability, which was in turn taken from hulk's punching) It's also got some extra throw force (24 compared to default spear's 20) The armor has basic security-level armor but covers your whole body. Does not include space protection, and can be worn by Ian. Video demonstration https://github.com/user-attachments/assets/a77c3a0d-17d2-4e8d-88b6-cdbca8b1f2c3 New sprites demonstration https://github.com/user-attachments/assets/0e465351-5484-406f-8adc-ffa1ac180daf Armor demonstration https://github.com/user-attachments/assets/abdfcac6-65bf-443c-bde2-27d157ee3a80 Map  With the changes in https://github.com/tgstation/tgstation/pull/90771 I had to mess with ash whelp abilities a bit, I decided to make them use cold fire instead of hardcoding blue color on top of the fire sprites, and it now acts accordingly too https://github.com/user-attachments/assets/cfca0d70-d13d-4c73-996d-2d4a7519866d The jump was taken from Savannah Ivanov, and Goof's bunny jumping. ##### Code bounty by Ezel/Improvedname ## Why It's Good For The Game This Re-implements a old spear that got removed for its buggyness/bad mapping and on the authors request as well not wanting to deal with it. Re-introduces the SkyBulge as a space ruin, referencing Dragoons from Final Fantasy. this just like any normal spear, but using the savannah jump mechanic, this allows you to close distances with the spear avoiding ranged projectiles in the jump, and if you directly land on your target you will do double the damage. ##### -Ezel/Improvedname ## Changelog 🆑 Ezel/Improvedname, Toriate, JohnFulpWillard add: Re-added the Dragoon Tomb lair, now has a Skybulge spear and Drachen armor. balance: Ice whelps now spit out cold fire. /🆑 --------- Co-authored-by: Jacquerel <hnevard@gmail.com>
446 lines
14 KiB
Plaintext
446 lines
14 KiB
Plaintext
/**
|
|
* Two Handed Component
|
|
*
|
|
* When applied to an item it will make it two handed
|
|
* Only one of the component can exist on an item.
|
|
*/
|
|
/datum/component/two_handed
|
|
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
|
/// Are we holding the two handed item properly
|
|
var/wielded = FALSE
|
|
/// The multiplier applied to force when wielded, does not work with force_wielded, and force_unwielded
|
|
var/force_multiplier = 1
|
|
/// The force of the item when weilded
|
|
var/force_wielded = 0
|
|
/// The force of the item when unweilded
|
|
var/force_unwielded = 0
|
|
/// Boolean whether to play sound when wielded
|
|
var/wieldsound = FALSE
|
|
/// Boolean whether to play sound when unwielded
|
|
var/unwieldsound = FALSE
|
|
/// Boolean whether to play sound on attack, if wielded
|
|
var/attacksound = FALSE
|
|
/// Boolean on whether it has to be held in both hands
|
|
var/require_twohands = FALSE
|
|
/// The icon that will be used when wielded
|
|
var/icon_wielded = FALSE
|
|
/// Reference to the offhand created for the item
|
|
var/obj/item/offhand/offhand_item = null
|
|
/// The amount of increase recived from sharpening the item
|
|
var/sharpened_increase = 0
|
|
/// A callback on the parent to be called when the item is wielded
|
|
var/datum/callback/wield_callback
|
|
/// A callback on the parent to be called when the item is unwielded
|
|
var/datum/callback/unwield_callback
|
|
|
|
/**
|
|
|
|
* Two Handed component
|
|
*
|
|
* vars:
|
|
* * require_twohands (optional) Does the item need both hands to be carried
|
|
* * wieldsound (optional) The sound to play when wielded
|
|
* * unwieldsound (optional) The sound to play when unwielded
|
|
* * attacksound (optional) The sound to play when wielded and attacking
|
|
* * force_multiplier (optional) The force multiplier when wielded, do not use with force_wielded, and force_unwielded
|
|
* * force_wielded (optional) The force setting when the item is wielded, do not use with force_multiplier
|
|
* * force_unwielded (optional) The force setting when the item is unwielded, do not use with force_multiplier
|
|
* * icon_wielded (optional) The icon to be used when wielded
|
|
*/
|
|
/datum/component/two_handed/Initialize(
|
|
require_twohands = FALSE,
|
|
wieldsound = FALSE,
|
|
unwieldsound = FALSE,
|
|
attacksound = FALSE,
|
|
force_multiplier = 1,
|
|
force_wielded = 0,
|
|
force_unwielded = 0,
|
|
icon_wielded = FALSE,
|
|
datum/callback/wield_callback,
|
|
datum/callback/unwield_callback,
|
|
)
|
|
if(!isitem(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
src.require_twohands = require_twohands
|
|
src.wieldsound = wieldsound
|
|
src.unwieldsound = unwieldsound
|
|
src.attacksound = attacksound
|
|
src.force_multiplier = force_multiplier
|
|
src.force_wielded = force_wielded
|
|
src.force_unwielded = force_unwielded
|
|
src.icon_wielded = icon_wielded
|
|
src.wield_callback = wield_callback
|
|
src.unwield_callback = unwield_callback
|
|
|
|
if(require_twohands)
|
|
ADD_TRAIT(parent, TRAIT_NEEDS_TWO_HANDS, ABSTRACT_ITEM_TRAIT)
|
|
|
|
/datum/component/two_handed/Destroy(force)
|
|
offhand_item = null
|
|
wield_callback = null
|
|
unwield_callback = null
|
|
return ..()
|
|
|
|
// Inherit the new values passed to the component
|
|
/datum/component/two_handed/InheritComponent(
|
|
datum/component/two_handed/new_comp,
|
|
original,
|
|
require_twohands,
|
|
wieldsound,
|
|
unwieldsound,
|
|
attacksound,
|
|
force_multiplier,
|
|
force_wielded,
|
|
force_unwielded,
|
|
icon_wielded,
|
|
datum/callback/wield_callback,
|
|
datum/callback/unwield_callback,
|
|
)
|
|
if(!original)
|
|
return
|
|
var/obj/item/parent_item = parent
|
|
if(wielded)
|
|
if(sharpened_increase)
|
|
parent_item.force -= sharpened_increase
|
|
if(force_multiplier)
|
|
parent_item.force /= force_multiplier
|
|
else if(!isnull(force_unwielded))
|
|
parent_item.force = force_unwielded
|
|
if(!isnull(require_twohands))
|
|
src.require_twohands = require_twohands
|
|
if(wieldsound)
|
|
src.wieldsound = wieldsound
|
|
if(unwieldsound)
|
|
src.unwieldsound = unwieldsound
|
|
if(attacksound)
|
|
src.attacksound = attacksound
|
|
if(force_multiplier)
|
|
src.force_multiplier = force_multiplier
|
|
if(!isnull(force_wielded))
|
|
src.force_wielded = force_wielded
|
|
if(isnull(force_unwielded))
|
|
src.force_unwielded = force_unwielded
|
|
if(icon_wielded)
|
|
src.icon_wielded = icon_wielded
|
|
if(wield_callback)
|
|
src.wield_callback = wield_callback
|
|
if(unwield_callback)
|
|
src.unwield_callback = unwield_callback
|
|
if(!wielded)
|
|
return
|
|
if(!isnull(force_multiplier))
|
|
parent_item.force *= force_multiplier
|
|
else if(!isnull(force_wielded))
|
|
parent_item.force = force_wielded
|
|
if(!isnull(sharpened_increase))
|
|
parent_item.force += sharpened_increase
|
|
|
|
// register signals withthe parent item
|
|
/datum/component/two_handed/RegisterWithParent()
|
|
RegisterSignal(parent, COMSIG_ITEM_POST_EQUIPPED, PROC_REF(on_equip))
|
|
RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_drop))
|
|
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(on_attack_self))
|
|
RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(on_attack))
|
|
RegisterSignal(parent, COMSIG_ATOM_UPDATE_ICON, PROC_REF(on_update_icon))
|
|
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved))
|
|
RegisterSignal(parent, COMSIG_ITEM_SHARPEN_ACT, PROC_REF(on_sharpen))
|
|
RegisterSignal(parent, COMSIG_ITEM_APPLY_FANTASY_BONUSES, PROC_REF(apply_fantasy_bonuses))
|
|
RegisterSignal(parent, COMSIG_ITEM_REMOVE_FANTASY_BONUSES, PROC_REF(remove_fantasy_bonuses))
|
|
|
|
// Remove all siginals registered to the parent item
|
|
/datum/component/two_handed/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(
|
|
COMSIG_ITEM_POST_EQUIPPED,
|
|
COMSIG_ITEM_DROPPED,
|
|
COMSIG_ITEM_ATTACK_SELF,
|
|
COMSIG_ITEM_ATTACK,
|
|
COMSIG_ATOM_UPDATE_ICON,
|
|
COMSIG_MOVABLE_MOVED,
|
|
COMSIG_ITEM_SHARPEN_ACT,
|
|
COMSIG_ITEM_APPLY_FANTASY_BONUSES,
|
|
COMSIG_ITEM_REMOVE_FANTASY_BONUSES,
|
|
))
|
|
|
|
/// Triggered on equip of the item containing the component
|
|
/datum/component/two_handed/proc/on_equip(datum/source, mob/user, slot)
|
|
SIGNAL_HANDLER
|
|
|
|
if(HAS_TRAIT(parent, TRAIT_NEEDS_TWO_HANDS) && (slot & ITEM_SLOT_HANDS)) // force equip the item
|
|
wield(user)
|
|
if(!user.is_holding(parent) && wielded && !HAS_TRAIT(parent, TRAIT_NEEDS_TWO_HANDS))
|
|
unwield(user)
|
|
|
|
/// Triggered on drop of item containing the component
|
|
/datum/component/two_handed/proc/on_drop(datum/source, mob/user)
|
|
SIGNAL_HANDLER
|
|
|
|
if(HAS_TRAIT(parent, TRAIT_NEEDS_TWO_HANDS)) //Don't let the item fall to the ground and cause bugs if it's actually being equipped on another slot.
|
|
unwield(user, FALSE, FALSE)
|
|
if(wielded)
|
|
unwield(user)
|
|
if(source == offhand_item && !QDELETED(source))
|
|
offhand_item = null
|
|
qdel(source)
|
|
|
|
/// Triggered on destroy of the component's offhand
|
|
/datum/component/two_handed/proc/on_destroy(datum/source)
|
|
SIGNAL_HANDLER
|
|
offhand_item = null
|
|
|
|
/// Triggered on attack self of the item containing the component
|
|
/datum/component/two_handed/proc/on_attack_self(datum/source, mob/user)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!HAS_TRAIT(parent, TRAIT_NEEDS_TWO_HANDS))
|
|
if(wielded)
|
|
unwield(user)
|
|
else if(user.is_holding(parent))
|
|
wield(user)
|
|
|
|
/**
|
|
* Wield the two handed item in both hands
|
|
*
|
|
* vars:
|
|
* * user The mob/living/carbon that is wielding the item
|
|
*/
|
|
/datum/component/two_handed/proc/wield(mob/living/carbon/user)
|
|
if(wielded)
|
|
return
|
|
|
|
var/atom/atom_parent = parent
|
|
if(HAS_TRAIT(user, TRAIT_NO_TWOHANDING))
|
|
if(HAS_TRAIT(parent, TRAIT_NEEDS_TWO_HANDS))
|
|
atom_parent.balloon_alert(user, "can't wield!")
|
|
user.dropItemToGround(parent, force = TRUE)
|
|
else
|
|
atom_parent.balloon_alert(user, "can't wield with both hands!")
|
|
return COMPONENT_EQUIPPED_FAILED
|
|
if(user.get_inactive_held_item())
|
|
if(HAS_TRAIT(parent, TRAIT_NEEDS_TWO_HANDS))
|
|
atom_parent.balloon_alert(user, "can't carry in one hand!")
|
|
user.dropItemToGround(parent, force = TRUE)
|
|
else
|
|
atom_parent.balloon_alert(user, "holding something in other hand!")
|
|
return COMPONENT_EQUIPPED_FAILED
|
|
if(user.usable_hands < 2)
|
|
if(HAS_TRAIT(parent, TRAIT_NEEDS_TWO_HANDS))
|
|
user.dropItemToGround(parent, force = TRUE)
|
|
atom_parent.balloon_alert(user, "not enough hands!")
|
|
return COMPONENT_EQUIPPED_FAILED
|
|
|
|
// wield update status
|
|
if(SEND_SIGNAL(parent, COMSIG_TWOHANDED_WIELD, user) & COMPONENT_TWOHANDED_BLOCK_WIELD)
|
|
user.dropItemToGround(parent, force = TRUE)
|
|
return COMPONENT_EQUIPPED_FAILED // blocked wield from item
|
|
if (wield_callback?.Invoke(parent, user) & COMPONENT_TWOHANDED_BLOCK_WIELD)
|
|
return
|
|
wielded = TRUE
|
|
ADD_TRAIT(parent, TRAIT_WIELDED, REF(src))
|
|
RegisterSignal(user, COMSIG_MOB_SWAPPING_HANDS, PROC_REF(on_swapping_hands))
|
|
|
|
// update item stats and name
|
|
var/obj/item/parent_item = parent
|
|
if(force_multiplier != 1)
|
|
parent_item.force *= force_multiplier
|
|
else if(force_wielded != force_unwielded)
|
|
parent_item.force = force_wielded
|
|
if(sharpened_increase)
|
|
parent_item.force += sharpened_increase
|
|
parent_item.name = "[parent_item.name] (Wielded)"
|
|
parent_item.update_appearance()
|
|
|
|
if(iscyborg(user))
|
|
to_chat(user, span_notice("You dedicate your module to [parent]."))
|
|
else
|
|
to_chat(user, span_notice("You grab [parent] with both hands."))
|
|
|
|
// Play sound if one is set
|
|
if(wieldsound)
|
|
playsound(parent_item.loc, wieldsound, 50, TRUE)
|
|
|
|
// Let's reserve the other hand
|
|
offhand_item = new(user)
|
|
offhand_item.name = "[parent_item.name] - offhand"
|
|
offhand_item.desc = "Your second grip on [parent_item]."
|
|
offhand_item.wielded = TRUE
|
|
RegisterSignal(offhand_item, COMSIG_ITEM_DROPPED, PROC_REF(on_drop))
|
|
RegisterSignal(offhand_item, COMSIG_QDELETING, PROC_REF(on_destroy))
|
|
user.put_in_inactive_hand(offhand_item)
|
|
|
|
/**
|
|
* Unwield the two handed item
|
|
*
|
|
* vars:
|
|
* * user The mob/living/carbon that is unwielding the item
|
|
* * show_message (option) show a message to chat on unwield
|
|
* * can_drop (option) whether 'dropItemToGround' can be called or not.
|
|
*/
|
|
/datum/component/two_handed/proc/unwield(mob/living/carbon/user, show_message=TRUE, can_drop=TRUE)
|
|
if(!wielded)
|
|
return
|
|
|
|
// wield update status
|
|
wielded = FALSE
|
|
UnregisterSignal(user, COMSIG_MOB_SWAPPING_HANDS)
|
|
SEND_SIGNAL(parent, COMSIG_TWOHANDED_UNWIELD, user)
|
|
REMOVE_TRAIT(parent, TRAIT_WIELDED, REF(src))
|
|
unwield_callback?.Invoke(parent, user)
|
|
|
|
// update item stats
|
|
var/obj/item/parent_item = parent
|
|
if(sharpened_increase)
|
|
parent_item.force -= sharpened_increase
|
|
if(force_multiplier != 1)
|
|
parent_item.force /= force_multiplier
|
|
else if(force_unwielded != force_wielded)
|
|
parent_item.force = force_unwielded
|
|
|
|
// update the items name to remove the wielded status
|
|
var/sf = findtext(parent_item.name, " (Wielded)", -10) // 10 == length(" (Wielded)")
|
|
if(sf)
|
|
parent_item.name = copytext(parent_item.name, 1, sf)
|
|
else
|
|
parent_item.name = "[initial(parent_item.name)]"
|
|
|
|
// Update icons
|
|
parent_item.update_appearance()
|
|
|
|
if(istype(user)) // tk showed that we might not have a mob here
|
|
if(user.get_item_by_slot(ITEM_SLOT_BACK) == parent)
|
|
user.update_worn_back()
|
|
else
|
|
user.update_held_items()
|
|
|
|
// if the item requires two handed drop the item on unwield
|
|
if(HAS_TRAIT(parent, TRAIT_NEEDS_TWO_HANDS) && can_drop)
|
|
user.dropItemToGround(parent, force=TRUE)
|
|
|
|
// Show message if requested
|
|
if(show_message)
|
|
if(iscyborg(user))
|
|
to_chat(user, span_notice("You free up your module."))
|
|
else if(HAS_TRAIT(parent, TRAIT_NEEDS_TWO_HANDS))
|
|
to_chat(user, span_notice("You drop [parent]."))
|
|
else
|
|
to_chat(user, span_notice("You are now carrying [parent] with one hand."))
|
|
|
|
// Play sound if set
|
|
if(unwieldsound)
|
|
playsound(parent_item.loc, unwieldsound, 50, TRUE)
|
|
|
|
// Remove the object in the offhand
|
|
if(offhand_item)
|
|
UnregisterSignal(offhand_item, list(COMSIG_ITEM_DROPPED, COMSIG_QDELETING))
|
|
qdel(offhand_item)
|
|
// Clear any old refrence to an item that should be gone now
|
|
offhand_item = null
|
|
|
|
/**
|
|
* on_attack triggers on attack with the parent item
|
|
*/
|
|
/datum/component/two_handed/proc/on_attack(obj/item/source, mob/living/target, mob/living/user)
|
|
SIGNAL_HANDLER
|
|
if(wielded && attacksound)
|
|
var/obj/item/parent_item = parent
|
|
playsound(parent_item.loc, attacksound, 50, TRUE)
|
|
|
|
/**
|
|
* on_update_icon triggers on call to update parent items icon
|
|
*
|
|
* Updates the icon using icon_wielded if set
|
|
*/
|
|
/datum/component/two_handed/proc/on_update_icon(obj/item/source)
|
|
SIGNAL_HANDLER
|
|
if(!wielded)
|
|
return NONE
|
|
if(!icon_wielded)
|
|
return NONE
|
|
source.icon_state = icon_wielded
|
|
return COMSIG_ATOM_NO_UPDATE_ICON_STATE
|
|
|
|
/**
|
|
* on_moved Triggers on item moved
|
|
*/
|
|
/datum/component/two_handed/proc/on_moved(datum/source, mob/user, dir)
|
|
SIGNAL_HANDLER
|
|
|
|
unwield(user, can_drop=FALSE)
|
|
|
|
/**
|
|
* on_swap_hands Triggers on swapping hands, blocks swap if the other hand is busy
|
|
*/
|
|
/datum/component/two_handed/proc/on_swapping_hands(mob/user, obj/item/held_item)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!held_item)
|
|
return
|
|
if(held_item == parent)
|
|
return COMPONENT_BLOCK_SWAP
|
|
|
|
/**
|
|
* on_sharpen Triggers on usage of a sharpening stone on the item
|
|
*/
|
|
/datum/component/two_handed/proc/on_sharpen(obj/item/item, amount, max_amount)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!item)
|
|
return COMPONENT_BLOCK_SHARPEN_BLOCKED
|
|
if(sharpened_increase)
|
|
return COMPONENT_BLOCK_SHARPEN_ALREADY
|
|
var/wielded_val = 0
|
|
if(force_multiplier)
|
|
var/obj/item/parent_item = parent
|
|
if(wielded)
|
|
wielded_val = parent_item.force
|
|
else
|
|
wielded_val = parent_item.force * force_multiplier
|
|
else
|
|
wielded_val = force_wielded
|
|
if(wielded_val > max_amount)
|
|
return COMPONENT_BLOCK_SHARPEN_MAXED
|
|
sharpened_increase = min(amount, (max_amount - wielded_val))
|
|
return COMPONENT_BLOCK_SHARPEN_APPLIED
|
|
|
|
/datum/component/two_handed/proc/apply_fantasy_bonuses(obj/item/source, bonus)
|
|
SIGNAL_HANDLER
|
|
force_wielded = source.modify_fantasy_variable("force_wielded", force_wielded, bonus)
|
|
force_unwielded = source.modify_fantasy_variable("force_unwielded", force_unwielded, bonus)
|
|
if(wielded && ismob(source.loc))
|
|
unwield(source.loc)
|
|
if(force_multiplier)
|
|
force_multiplier = source.modify_fantasy_variable("force_multiplier", force_multiplier, bonus/10, minimum = 1)
|
|
|
|
/datum/component/two_handed/proc/remove_fantasy_bonuses(obj/item/source, bonus)
|
|
SIGNAL_HANDLER
|
|
force_wielded = source.reset_fantasy_variable("force_wielded", force_wielded)
|
|
force_unwielded = source.reset_fantasy_variable("force_unwielded", force_unwielded)
|
|
if(wielded && ismob(source.loc))
|
|
unwield(source.loc)
|
|
force_multiplier = source.reset_fantasy_variable("force_multiplier", force_multiplier)
|
|
|
|
/**
|
|
* The offhand dummy item for two handed items
|
|
*/
|
|
/obj/item/offhand
|
|
name = "offhand"
|
|
icon = 'icons/obj/weapons/hand.dmi'
|
|
icon_state = "offhand"
|
|
w_class = WEIGHT_CLASS_HUGE
|
|
item_flags = ABSTRACT
|
|
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
|
var/wielded = FALSE // Off Hand tracking of wielded status
|
|
|
|
/obj/item/offhand/Initialize(mapload)
|
|
. = ..()
|
|
ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT)
|
|
|
|
/obj/item/offhand/Destroy()
|
|
wielded = FALSE
|
|
return ..()
|
|
|
|
/obj/item/offhand/equipped(mob/user, slot)
|
|
. = ..()
|
|
if(wielded && !user.is_holding(src) && !QDELETED(src))
|
|
qdel(src)
|