using Content.Shared._EstacaoPirata.Cards.Deck;
using Content.Shared._EstacaoPirata.Cards.Hand;
using Content.Shared._EstacaoPirata.Cards.Stack;
using Content.Shared.Examine;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
using Content.Shared.Verbs;
using Robust.Shared.Containers;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Shared._EstacaoPirata.Cards.Card;
///
/// This handles...
///
public sealed class CardSystem : EntitySystem
{
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly CardStackSystem _cardStack = default!;
[Dependency] private readonly CardDeckSystem _cardDeck = default!;
[Dependency] private readonly CardHandSystem _cardHand = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
///
public override void Initialize()
{
SubscribeLocalEvent>(AddTurnOnVerb);
SubscribeLocalEvent>(OnActivationVerb);
SubscribeLocalEvent(OnExamined);
SubscribeLocalEvent(OnUse);
SubscribeLocalEvent(OnActivate);
}
private void OnExamined(EntityUid uid, CardComponent component, ExaminedEvent args)
{
if (args.IsInDetailsRange && !component.Flipped)
{
args.PushMarkup(Loc.GetString("card-examined", ("target", Loc.GetString(component.Name))));
}
}
private void AddTurnOnVerb(EntityUid uid, CardComponent component, GetVerbsEvent args)
{
if (!args.CanAccess || !args.CanInteract || args.Hands == null)
return;
args.Verbs.Add(new AlternativeVerb()
{
Act = () => FlipCard(uid, component),
Text = Loc.GetString("cards-verb-flip"),
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/flip.svg.192dpi.png")),
Priority = 1
});
if (args.Using == null || args.Using == args.Target)
return;
if (TryComp(args.Using, out var usingStack))
{
args.Verbs.Add(new AlternativeVerb()
{
Act = () => JoinCards(args.User, args.Target, component, (EntityUid)args.Using, usingStack),
Text = Loc.GetString("card-verb-join"),
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/refresh.svg.192dpi.png")),
Priority = 2
});
}
else if (TryComp(args.Using, out var usingCard))
{
var pickup = _hands.IsHolding(args.User, args.Target);
args.Verbs.Add(new AlternativeVerb()
{
Act = () => _cardHand.TrySetupHandOfCards(args.User, args.Target, component, args.Using.Value, usingCard, pickup),
Text = Loc.GetString("card-verb-join"),
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/refresh.svg.192dpi.png")),
Priority = 2
});
}
}
private void OnUse(EntityUid uid, CardComponent comp, UseInHandEvent args)
{
if (args.Handled)
return;
FlipCard(uid, comp);
args.Handled = true;
}
///
/// Server-Side only method to flip card. This starts CardFlipUpdatedEvent event
///
///
///
private void FlipCard(EntityUid uid, CardComponent component)
{
if (_net.IsClient)
return;
component.Flipped = !component.Flipped;
Dirty(uid, component);
RaiseNetworkEvent(new CardFlipUpdatedEvent(GetNetEntity(uid)));
}
private void JoinCards(EntityUid user, EntityUid first, CardComponent firstComp, EntityUid second, CardStackComponent secondStack)
{
if (_net.IsClient)
return;
bool pickup = _hands.IsHolding(user, first);
EntityUid cardStack;
bool? flip = null;
if (HasComp(second))
{
cardStack = SpawnInSameParent(_cardDeck.CardDeckBaseName, first);
}
else if (HasComp(second))
{
cardStack = SpawnInSameParent(_cardHand.CardHandBaseName, first);
if(TryComp(cardStack, out var stackHand))
stackHand.Flipped = firstComp.Flipped;
flip = firstComp.Flipped;
}
else
return;
if (!TryComp(cardStack, out CardStackComponent? stack))
return;
if (!_cardStack.TryInsertCard(cardStack, first, stack))
return;
_cardStack.TransferNLastCardFromStacks(user, secondStack.Cards.Count, second, secondStack, cardStack, stack);
if (flip != null)
_cardStack.FlipAllCards(cardStack, stack, flip); //???
if(pickup)
_hands.TryPickupAnyHand(user, cardStack);
}
// Frontier: tries to spawn an entity with the same parent as another given entity.
// Useful when spawning decks/hands in a backpack, for example.
private EntityUid SpawnInSameParent(EntProtoId prototype, EntityUid uid)
{
if (_container.IsEntityOrParentInContainer(uid) &&
_container.TryGetOuterContainer(uid, Transform(uid), out var container))
{
return SpawnInContainerOrDrop(prototype, container.Owner, container.ID);
}
return Spawn(prototype, Transform(uid).Coordinates);
}
// Frontier: hacky misuse of the activation verb, but allows us a separate way to draw cards without needing additional buttons and event fiddling
private void OnActivationVerb(EntityUid uid, CardComponent component, GetVerbsEvent args)
{
if (!args.CanAccess || !args.CanInteract || args.Hands == null)
return;
if (args.Using == args.Target)
return;
if (HasComp(uid))
return;
if (args.Using == null)
{
args.Verbs.Add(new ActivationVerb()
{
Act = () => _hands.TryPickupAnyHand(args.User, args.Target),
Text = Loc.GetString("cards-verb-draw"),
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")),
Priority = 16
});
}
else if (TryComp(args.Using, out var cardStack))
{
args.Verbs.Add(new ActivationVerb()
{
Act = () => _cardStack.InsertCardOnStack(args.User, args.Using.Value, cardStack, args.Target),
Text = Loc.GetString("cards-verb-draw"),
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")),
Priority = 16
});
}
else if (TryComp(args.Using, out var card))
{
args.Verbs.Add(new ActivationVerb()
{
Act = () => _cardHand.TrySetupHandOfCards(args.User, args.Using.Value, card, args.Target, component, true),
Text = Loc.GetString("cards-verb-draw"),
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")),
Priority = 16
});
}
}
// End Frontier
private void OnActivate(EntityUid uid, CardComponent component, ActivateInWorldEvent args)
{
if (!args.Complex || args.Handled)
return;
if (!TryComp(args.User, out var hands))
return;
// Card stacks are handled differently
if (HasComp(args.Target))
return;
var activeItem = _hands.GetActiveItem((args.User, hands));
if (activeItem == null)
{
_hands.TryPickupAnyHand(args.User, args.Target);
}
else if (TryComp(activeItem, out var cardStack))
{
_cardStack.InsertCardOnStack(args.User, activeItem.Value, cardStack, args.Target);
}
else if (TryComp(activeItem, out var card))
{
_cardHand.TrySetupHandOfCards(args.User, activeItem.Value, card, args.Target, component, true);
}
}
}