mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-25 08:34:23 +00:00
## About The Pull Request we have the trait for that ## Why It's Good For The Game Throughout UNDERTALE, we get treated to three story sequences (4 if you include flowey's fakeout but that's not important). The first is the intro story, telling the tale of humans and monsters, which shortly thereafter leads into 201X, and Chara (Toriel's house has “An old calendar from 201X.”) falling into the underground. The second is the waterfall flashback, its contents taking place immediately after the intro segment, as a voice (Asriel) finds the fallen child. And finally, the third takes place in the True Pacifist final boss. We'll get to it in due course, and it will have its own section, but let's address the first two. Regarding the intro, the first thought one might have is that simply, while narratively relevant, is not a diegetic presentation. However, We know that everything after the “201X” frame is Chara's memory (from an outside perspective, that is,) and we also know that UNDERTALE LOVES bringing the non-diegetic, the mechanical, the game, INTO the narrative. Saving, RPG Stats, hell, even the NarratorChara. Surely the intro can be as well? On top of this, what does the intro do for the player, as the player? Well, aside from setting the tone, the intro gives us some setting backstory. It's all important context, and it certainly helps… but it being in the intro sequence is not that important; It's all presented throughout the game via diegetic signs, books, and expositional tortoise war heroes/angry fish guardswomen. The second half is how Chara fell to the underground, and while also setting tone and informing the player how their character arrived. It also creates the false impression for the player that their character is Frisk, feeding into UNDERTALE's meta narrative; “You are not your character, and their happy ending is not yours.” If we weren't playing Chara, this would have no narrative impact. The story beat fails to land by showing us someone elses' character. But, sure. This could be a purely non-diegetic intro sequence. Simply put, The 201X portion of the intro sequence does not make sense from a diegetic or a storytelling perspective unless we play as Chara. Flashback number two is explicitly a canonical, diegetic flashback. It occurs when Frisk escapes Undyne by falling down a massive pit… again. This time, they land in the garbage zone, black out, and have a flashback sequence of the first time Asriel found Chara. While serving the main narrative by setting up Asriel as a character, furthering the final twist of the meta narrative's pacifist route, and neatly transitioning between overworld areas, it's also very explicitly diegetic and cannot be dismissed as an intro sequence. With this in mind, one question is raised. Why do we see this flashback? If the player character is Frisk, this makes little sense, why would we see someone else's flashback and not our own? Same thing applies for a Third Entity, but even more abstract and illogical. What even are we? Sure, you could say Chara is somehow attached to us/Frisk and that somehow we get a flashback from Chara who is somehow knocked unconscious by Frisk also being knocked unconscious. I used the word somehow three times. That's not good storytelling. A simpler answer, at least in my view, is that We Are Chara. When Frisk is knocked unconscious, we, being ostensibly linked to them as a Spirit/Ghost/Reincarnation/Possessing Dead Frisk/Demon/Insert fan-theory here/SOUL Fragment, have our only connection to the world temporarily disabled, rendering us effectively unconscious and prompting a flashback. Nothing weird with multiple entities or memory sharing. The waterfall flashback is simply our memory. Simple. The simplest answers are usually the correct ones. <details> <summary>DO NOT RESEARCH</summary> The third sequence is a connection/extension of the first two, displayed when we SAVE “Someone Else” during the true pacifist battle with Asriel. To refresh everyone, here is the direct quotes, taken from the Wiki: [SAVE]: Someone Else Strangely, as your friends remembered you... Something else began resonating within the SOUL, stronger and stronger. It seems that there's still one last person that needs to be saved. But who...? ... Suddenly, you realize. You reach out and call their name. Asriel: “Huh? What are you doing...?” s It's at this point that the sequence plays. There's no narration, but we see the sequence of interactions between Asriel and Chara. There are no panels (except for the first) that don't contain the both of them. Following this, we get: You feel your friends' SOULs resonating within ASRIEL! [This is the generic flavour text for saving all 6, before “Someone Else”, and appears at the asterisk above as well] [SAVE]: Asriel Dreemurr Asriel: > “Wh... what did you do...?” “What's this feeling…? What's happening to me?” Etc. etc. let me win… During my first and consecutive playthroughs of UNDERTALE, I came to the conclusion that Asriel's soul still “Had Some Chara In It.” Saving “Someone Else” was saving Chara, and then you save Asriel Dreemurr after the story sequence. This interpretation no longer feels particularly potent to me, but in the spirit of completeness I'll address it alongside the more reasonable “You just save Asriel.” Assuming for a moment though, that we do “Save Chara”, it's not unreasonable to assume that some of Chara's ‘essence' (or whatever) was merged with Asriel's and by SAVING them, we're SAVING the part of them that's inside Asriel. But I don't like that theory. Let's talk about SAVING Asriel for a moment. What is the motivation for doing that? Why would we, in universe, wish to SAVE him, something that the narration explicitly prompts us to do? He tried and probably succeeded to kill us, at least once, he wants to reset the entire timeline, he wants to erase all our friendships, all our progress. So, why? Well, it's simple. He's our brother. And we know better than anyone that he's worth saving. And at the very least, there's something about Frisk (who appears to have absolutely no personality) that reminds him of Chara, of us. This is, by his own admission, weird; Asriel: “Frisk… You really ARE different from Chara. In fact, though you have similar, uh, fashion choices… I don't know why I ever acted as if you were the same person.” To summarise. The player SAVING Asriel Dreemurr works best if they are Chara, it becomes Chara encouraging Frisk to SAVE Asriel too. Asriel recognises Frisk as Chara throughout the True Pacifist battle (And Beyond), despite his own admission that this is basically unfounded. Something is causing this recognition. In Alphys' true lab, there lies a dusty TV and a stack of VHSes. On them, lie some of the last words Chara had ever heard from their father. [Asgore] Chara! You have to stay determined! You can't give up... You are the future of humans and monsters... These tapes are not the first time they are heard. Sleeping in Toriel's guest bed, we dream about them. Suffering a fatal injury, they echo in our ears. Watching the tape is yet another reveal. It's the chilling truth that in fact, the words we (if we die a lot) are so familiar with, are in fact the words we hear on our deathbed. Storytelling-wise, this reveal; like all the others, fails if we do not play as Chara. Aside from Asriel's dialogue, Chara's genocide Narration, and the coffin in Asgore's basement, this is the only time we hear Chara's name. That and, this following exchange. [Flowey] Hi. … Monsters have returned to the surface Peace and prosperity will rule across the land. … Well. There is one last thing. … One being with the power to erase EVERYTHING… … I'm talking about YOU. … So, please. Just let them go. Let Frisk be happy. … Well, that's all. See you later… Chara. This, I think, is pretty explicitly definitive. Flowey comes to you. To us. Tells us to take a deep breath and leave the happy ending intact, then bids us farewell by our own name. Regardless of anything else, this definitively proves Chara is the entity with the power to reset everything by the end of True Pacifist (Which is a power we have). Flowey positively identifies us as “Chara”, despite his mistake we discussed in 3C. He's not talking to Frisk, because he refers to them in the third person. He is talking to Us. Chara. I don't want to discuss Flowey's use of “Chara” in Genocide all that much, because the counter-argument is blindingly simple. “By the time Flowey first says that name, Chara has overtaken Frisk by feeding on the power we create for them.” Of course, under PlayerChara, Flowey's lines still make sense, and arguably more. Implications At this point, I believe the evidence is sufficient to support the theory. With this in mind, I want to discuss the implications this has on the narrative and meta-narrative. This is where all those funny glossary terms come into play. The pacifist route in UNDERTALE, as discussed above, is textually quite simple when accepting PlayerChara. The meta-text is also relatively simple. Meta textually, the Pacifist Route is a dissection of the suspension of disbelief, examining how we emotionally place ourselves within fictional worlds, and are often-times torn away from those worlds as the game comes to an end, left wanting the true emotional connection, wanting a happy ending that cannot be good enough for us because we're real and it's not. The reflection of this meta narrative in the textual narrative, quite naturally flows. We, Chara, want a happy ending. But we can't have it, it's not our happy ending. We're gone. We've been gone a long time. Frisk's happy ending can't be good enough for us, because we won't be around to see it. So, we're left with a choice. To let Frisk live happily? To accept an ending that might leave us emotionally wanting, yet preserves our emotional journey? To reset? To refuse an ending and satiate our emotional emptiness, yet destroy that very emotional journey we took in the process? The choice is the same. There is practically no separation between the diegetic and the meta. “Can a happy ending be good enough for you?” This question applies to us, as the real world player running UNDERTALE.exe on our computer, and us, Chara, the long deceased human who can do little but watch as Frisk lives the life they wish they still had, or can destroy everything for a hollow mimicry of that very life. This message, however, breaks down under one specific circumstance. Where we force a Third Entity into the mix. This one decision fractures the cohesion and creates a meta-textually dissonant mess. Now, all of a sudden, “Can a happy ending be good enough for you?” no longer runs parallel through both narratives. There is no reason for the Player Entity to wish to remain, the happy ending should automatically be good enough because it's the happy ending. Meanwhile, Chara, despite being an inextricable representation of “A happy ending I can't achieve,” gets absolutely nothing to do with this meta-narrative because they're just… not you. “we are mario in Super Mario 64, but when he says "Thank you so much for playing my game!" that doesn't mean we aren't still playing as mario” - PopitTart This is where things get weird. See, in the Genocide route.. Well, we see Chara. On Screen. Talk to us. Now, it can easily be argued that this completely shatters the theory, but I would disagree. I'm going to endeavour to present a textual explanation (or two) for this. But first, I want to dissect the meta-text here. Now, I'm sure the idea that “The Genocide Route's Meta-Narratve is Fading Emotional Investment and the way emotional connection with video games can lead to the very sabotage of that emotional connection” is not revolutionary. However, what's conspicuously absent from all of the third entity theorising is the way that this meta-text is mirrored in the textual narrative. Once satisfied with a game, having extracted all lines of dialogue and stat boosts, once reaching all endings, a user will close the game down. And at some point, perhaps to make room for a new game or perhaps on a new device, will leave the game uninstalled, either deliberately, or simply as a consequence of time. Textually, what happens in the Genocide ending? Now we have reached the absolute. There is nothing left for us here. Let us erase this pointless world, and move on to the next. The world is destroyed. So much is left unanswered here. Who is Chara talking to? Where did Frisk go? How do they have this much power? Why would they want this? If we ‘corrupted' them, what the hell does that even mean? What is Chara? For now, let's talk about who Chara is talking to. The simplest answer is “Perspective switch.” Suddenly, we're not Chara anymore, now we are Frisk. This meets all the dialogue options and even vaguely mirrors the meta-text. It also manages to avoid bringing a third entity along and so is automatically better! But, I find myself still not fully enjoying this idea. Remember what I said about Occam's Razor? I think there's another option. One that doesn't involve three entities, or even two entities, just Chara. One that mirrors the meta-text to a degree only Toby Fox could pull off. It's a weird one, and I don't fault you if you don't get it on your first read, but bear with me here, because things are about to get A little Fucking Abstract Let's discard any and all pre-concieved notions of anything and hold one singular truth above all else. “Chara Is The Player.” What does this mean for this cutscene? Well… it means the player is talking to… THe player? It also neatly answers the question of motive, so let's throw that out the skeleton-shaped hole in the window for now. If the player is talking to the player, this frames Chara's words in a whole new light. Every time a number increases, that feeling… That's me. “Chara.” This line becomes explicitly literal. The Chara on-screen is literally the player's feeling of satisfaction watching stat increases. But this is all meta-textual, right? What does this mean for the textual narrative? Here's the thing. It can't mean anything, yet means everything. There is no way to reconcile the fact that a Textually Real character is directly talking about what the player feels when playing a game to completion. The barrier between Meta and Textual no longer exists. It can't. Not here. And with this revelation, everything begins to make sense. Your power awakened me from death. Our power. Our desire to complete UNDERTALE awakens Chara from death. They become startlingly real. We imbue this fictional character with the real world desire to consume fiction, destroying enemies and worlds as we go, increasing our power and our stats. Video Game Accomplishments. And UNDERTALE has just finished being consumed. My “human soul”... My “determination”... They were not mine, but YOURS. Chara, the textual player, acknowledges the meta-textual player's control over the game world. A control that we surrendered. By engaging in UNDERTALE in a fully immersed way, we have fed the Diegetic character that is our player character, Chara. This has continued until we haul ourself out of the Internal Mode and into the External Mode, revoking our immersion to make the consumption of content easier, to distance ourself from the killing. Raising our LV. The more we distance ourselves, the less real UNDERTALE's world appears to us. Once it's done, we're ready to erase this pointless world and move onto the next. There's just one problem. UNDERTALE knows about us. It knows we exist and it will abuse that to convey meaning. By revoking our immersion in UNDERTALE, we end up shattering the barrier between Meta and Textual, and this occurs because revoking our immersion is a diegetic decision. Without this barrier, WE, as a character, gain control of UNDERTALE and use this external mode control to Erase the world. To uninstall. This code doesn't actually work, of course. That was pretty obvious by the fact that it didn't delete your game. But still, this exists in the code that makes the game window shake when Chara attacks it. This is, quite literally, intent for Chara to delete UNDERTALE. If you didn't think Chara was capable of uninstalling your game before, you should now. Who is chara talking to? Us. How do hey have this much power? We gave it to them. We Are them, and we deleted UNDERTALE when we were done with it. Why would they want this? We wanted to move onto a new game. What is Chara? Us. ( I'll come back to this.) But wait! What about soulless pacifist? Well, at that point, you've surrendered Frisk's SOUL to Chara, as in, you the real player has revoked your emotional attachment to UNDERTALE and accepted that Chara can have control over the game. You've revoked your immersion AS Chara, you no longer see yourself a Chara and as such Chara becomes their own being. You've surrendered, basically. But they let you play through it. Because why not. You might get attached again, but that's fine. All that means is that the happy ending that was once Frisk's, that you, the player, and you, Chara, both once lamented not being able to live, has now been surrendered to Chara. A warped, completionist, Chara. You don't get your happy ending. But Chara does. You don't even get the solace of knowing someone gets their happy ending. Because Chara gets it. Frankly, outside of being “The Player”, I don't think the exact nature of “Chara” is that crucial. My personal thought is that they're a SOUL fragment, absorbed by Frisk when they fell on Chara's grave (Frisk could absorb a human SOUL fragment because said fragment was part monster SOUL). This fragment gives Frisk the final edge of determination needed to SAVE. But, ultimately, that's little more than a fanfiction. And frankly, I think that's okay. Not everything needs to be impenetrable, as long as there's enough there to build a stable foundation. I'd also like to address the nature of SAVING quickly, specifically the normal version, not the Asriel fight version. People have asked “Why do we save if it's Frisk's SOUL.” There could be many reasons. Frisk might just defer control to us. Because we're pushing Frisk over that Determination limit, we might be privileged to have that control. </details> ## Changelog not player visible
385 lines
13 KiB
Plaintext
385 lines
13 KiB
Plaintext
/**
|
|
* Two Handed Component
|
|
*
|
|
* When applied to an item it will make it two handed
|
|
*
|
|
*/
|
|
/datum/component/two_handed
|
|
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS // Only one of the component can exist on an item
|
|
var/wielded = FALSE /// Are we holding the two handed item properly
|
|
var/force_multiplier = 0 /// The multiplier applied to force when wielded, does not work with force_wielded, and force_unwielded
|
|
var/force_wielded = 0 /// The force of the item when weilded
|
|
var/force_unwielded = 0 /// The force of the item when unweilded
|
|
var/wieldsound = FALSE /// Play sound when wielded
|
|
var/unwieldsound = FALSE /// Play sound when unwielded
|
|
var/attacksound = FALSE /// Play sound on attack when wielded
|
|
var/require_twohands = FALSE /// Does it have to be held in both hands
|
|
var/icon_wielded = FALSE /// The icon that will be used when wielded
|
|
var/obj/item/offhand/offhand_item = null /// Reference to the offhand created for the item
|
|
var/sharpened_increase = 0 /// The amount of increase recived from sharpening the item
|
|
/// 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=0, 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, silent)
|
|
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
|
|
if(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(force_wielded)
|
|
src.force_wielded = force_wielded
|
|
if(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
|
|
|
|
// register signals withthe parent item
|
|
/datum/component/two_handed/RegisterWithParent()
|
|
RegisterSignal(parent, COMSIG_ITEM_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))
|
|
|
|
/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)
|
|
|
|
// Remove all siginals registered to the parent item
|
|
/datum/component/two_handed/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED,
|
|
COMSIG_ITEM_DROPPED,
|
|
COMSIG_ITEM_ATTACK_SELF,
|
|
COMSIG_ITEM_ATTACK,
|
|
COMSIG_ATOM_UPDATE_ICON,
|
|
COMSIG_MOVABLE_MOVED,
|
|
COMSIG_ITEM_SHARPEN_ACT))
|
|
|
|
/// Triggered on equip of the item containing the component
|
|
/datum/component/two_handed/proc/on_equip(datum/source, mob/user, slot)
|
|
SIGNAL_HANDLER
|
|
|
|
if(require_twohands && (slot & ITEM_SLOT_HANDS)) // force equip the item
|
|
wield(user)
|
|
if(!user.is_holding(parent) && wielded && !require_twohands)
|
|
unwield(user)
|
|
|
|
/// Triggered on drop of item containing the component
|
|
/datum/component/two_handed/proc/on_drop(datum/source, mob/user)
|
|
SIGNAL_HANDLER
|
|
|
|
if(require_twohands) //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(!require_twohands)
|
|
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
|
|
if(user.get_inactive_held_item())
|
|
if(require_twohands)
|
|
to_chat(user, span_notice("[parent] is too cumbersome to carry in one hand!"))
|
|
user.dropItemToGround(parent, force=TRUE)
|
|
else
|
|
to_chat(user, span_warning("You need your other hand to be empty!"))
|
|
return
|
|
if(user.usable_hands < 2)
|
|
if(require_twohands)
|
|
user.dropItemToGround(parent, force=TRUE)
|
|
to_chat(user, span_warning("You don't have enough intact hands."))
|
|
return
|
|
|
|
// wield update status
|
|
if(SEND_SIGNAL(parent, COMSIG_TWOHANDED_WIELD, user) & COMPONENT_TWOHANDED_BLOCK_WIELD)
|
|
return // blocked wield from item
|
|
wielded = TRUE
|
|
ADD_TRAIT(parent, TRAIT_WIELDED, REF(src))
|
|
RegisterSignal(user, COMSIG_MOB_SWAPPING_HANDS, PROC_REF(on_swapping_hands))
|
|
wield_callback?.Invoke(parent, user)
|
|
|
|
// update item stats and name
|
|
var/obj/item/parent_item = parent
|
|
if(force_multiplier)
|
|
parent_item.force *= force_multiplier
|
|
else if(force_wielded)
|
|
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)
|
|
parent_item.force /= force_multiplier
|
|
else if(force_unwielded)
|
|
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(require_twohands && 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(require_twohands)
|
|
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
|
|
|
|
/**
|
|
* 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)
|