-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wizard Item Recall Spell #34411
base: master
Are you sure you want to change the base?
Wizard Item Recall Spell #34411
Conversation
would this work if its in someone elses inventory/locker? |
If the item exists, no matter where, it WILL return to you |
thats awesome. hope to see some interactions with storage implanters or something. that would be hilarious. |
Isn't there a freeze on wizard and new spells? |
This has permission from me. |
should it do some damage if it uh... rips a storage implanter out of someone's chest? or is it more of a magical teleport? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not test it in game yet.
Design-wise, did you ask Keron if it should be one or two actions? One for marking, one for recalling. That way you change the mark to another item if you wanted to.
Spoke with Keron, youre not supposed to be able to mark another item(mark is permanent unless item somehow is destroyed) and it should be one action. |
As cool as this sounds, magical teleport |
Only thing that doesn't work is the popup when an item is unmarked, but it's something to do with the action system being weird. |
/// <summary> | ||
/// System for handling the ItemRecall ability for wizards. | ||
/// </summary> | ||
public sealed partial class ItemRecallSystem : SharedItemRecallSystem | ||
{ | ||
[Dependency] private readonly SharedHandsSystem _hands = default!; | ||
[Dependency] private readonly SharedProjectileSystem _proj = default!; | ||
[Dependency] private readonly SharedPopupSystem _popups = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<RecallMarkerComponent, RecallItemEvent>(OnItemRecall); | ||
} | ||
|
||
private void OnItemRecall(Entity<RecallMarkerComponent> ent, ref RecallItemEvent args) | ||
{ | ||
RecallItem(ent); | ||
} | ||
|
||
private void RecallItem(Entity<RecallMarkerComponent> ent) | ||
{ | ||
if (!TryComp<InstantActionComponent>(ent.Comp.MarkedByAction, out var instantAction)) | ||
return; | ||
|
||
var actionOwner = instantAction.AttachedEntity; | ||
|
||
if (actionOwner == null) | ||
return; | ||
|
||
if (TryComp<EmbeddableProjectileComponent>(ent, out var projectile)) | ||
_proj.UnEmbed(ent, projectile, actionOwner.Value); | ||
|
||
_popups.PopupEntity(Loc.GetString("item-recall-item-summon", ("item", ent)), actionOwner.Value, actionOwner.Value); | ||
|
||
_hands.TryForcePickupAnyHand(actionOwner.Value, ent); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All new code needs prediction please.
If your issue is range use pvs session overrides.
|
||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedItemRecallSystem))] | ||
public sealed partial class RecallMarkerComponent : Component | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doc comments.
|
||
private void TryMarkItem(Entity<ItemRecallComponent> ent, EntityUid item, EntityUid markedBy) | ||
{ | ||
EnsureComp<RecallMarkerComponent>(item, out var marker); | ||
ent.Comp.MarkedEntity = item; | ||
Dirty(ent); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is already checked for component existence above but if you're doing ensures then you should actually be checking if the item should be dirtied or not as dirtying is expensive and this might be unnecessary.
|
||
if (TryComp<ItemRecallComponent>(marker.MarkedByAction, out var action)) | ||
{ | ||
// For some reason client thinks the station grid owns the action on client and this doesn't work. It doesn't work in PopupEntity(mispredicts) and PopupPredicted either(doesnt show). | ||
// I don't have the heart to move this code to server because of this small thing. | ||
// This line will only do something once that is fixed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds like a pretty bad bug here that should be fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Messing with the action system is not something I am knowledgable enough to do. Especially since I have no idea what causes this.
|
||
private void UpdateActionAppearance(Entity<ItemRecallComponent> action) | ||
{ | ||
if (!TryComp<InstantActionComponent>(action, out var instantAction)) | ||
return; | ||
|
||
var proto = Prototype(action); | ||
|
||
if (proto == null) | ||
return; | ||
|
||
if (action.Comp.MarkedEntity == null) | ||
{ | ||
_metaData.SetEntityName(action, proto.Name); | ||
_metaData.SetEntityDescription(action, proto.Description); | ||
_actions.SetEntityIcon(action, null, instantAction); | ||
} | ||
else | ||
{ | ||
if (action.Comp.WhileMarkedName != null) | ||
_metaData.SetEntityName(action, Loc.GetString(action.Comp.WhileMarkedName, | ||
("item", action.Comp.MarkedEntity.Value))); | ||
|
||
if (action.Comp.WhileMarkedDescription != null) | ||
_metaData.SetEntityDescription(action, Loc.GetString(action.Comp.WhileMarkedDescription, | ||
("item", action.Comp.MarkedEntity.Value))); | ||
|
||
_actions.SetEntityIcon(action, action.Comp.MarkedEntity, instantAction); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be getting the entity's actual data not prototype data, this can vary significantly as prototypes are only for initialisation values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do mean to get the initial state of the action here though. Since if the item for recall is destroyed the initial sprite should be restored.
|
||
private void TryUnmarkItem(EntityUid item) | ||
{ | ||
if (!TryComp<RecallMarkerComponent>(item, out var marker)) | ||
return; | ||
|
||
if (!TryComp<InstantActionComponent>(item, out var instantAction)) | ||
return; | ||
|
||
var actionOwner = instantAction.AttachedEntity; | ||
|
||
if (actionOwner == null) | ||
return; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the item is being recalled the attached entity can be completely different? Not sure why the action is even being checked here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you use mind swap and then recall an item you would recall it to your old body. This is supposed to recall it to whoever currently holds the action.
// Reset whether the projectile has damaged anything if it successfully was removed | ||
if (TryComp<ProjectileComponent>(uid, out var projectile)) | ||
{ | ||
projectile.Shooter = null; | ||
projectile.Weapon = null; | ||
projectile.DamagedEntity = false; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be getting dirtied, looks like bug in original code.
About the PR
Title.
Why / Balance
Missing feature for wizard.
Technical details
Added an ItemRecallSystem that handles the Item Recall spell.
Added RaiseOnAction to the BaseActionComponent to allow raising events on the action itself.
Media
2025-01-13.23-50-15.mp4
Requirements
Breaking changes
Changelog
not player facing (wizard when :( )