Files
tbd-station-14/Content.Server/Tabletop/TabletopSystem.cs
eclips_e 01a0e2002a Librarian gameplay (DND, but in SS14) (#17041)
* D&D character sheets

* Tabletop improvements

* Grass battlemap

* You can now put shit inside of the board

* change variable name

* make the grass tabletop better, again

* update the damn thing AGAIN

* update the shit AGAIN

* You can now take stuff out of tabletops

* Make it use parenting to avoid zany bugs

* MORE battlemaps! Battlemaps for everyone!

* You can now dump out pieces + cleanup

* All (most) non-game pieces should fall to the ground

* make the verb a bit more responsive

* Librarian content officially done

* fix tests i think

* i forgot the sheet

* Smidgen of refactoring

* You can no longer put high risk items inside of boards

* no boardgame defusal

* minor refactoring

* hoplogrma

* doc

* fix rt
2023-07-17 03:03:18 -06:00

197 lines
7.5 KiB
C#

using Content.Server.Popups;
using Content.Server.Tabletop.Components;
using Content.Shared.Examine;
using Content.Shared.Hands.Components;
using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Tabletop;
using Content.Shared.Tabletop.Components;
using Content.Shared.Tabletop.Events;
using Content.Shared.Verbs;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
using Robust.Server.Player;
using Robust.Shared.Enums;
using Robust.Shared.Map;
using Robust.Shared.Utility;
namespace Content.Server.Tabletop
{
[UsedImplicitly]
public sealed partial class TabletopSystem : SharedTabletopSystem
{
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly ViewSubscriberSystem _viewSubscriberSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeNetworkEvent<TabletopStopPlayingEvent>(OnStopPlaying);
SubscribeLocalEvent<TabletopGameComponent, ActivateInWorldEvent>(OnTabletopActivate);
SubscribeLocalEvent<TabletopGameComponent, ComponentShutdown>(OnGameShutdown);
SubscribeLocalEvent<TabletopGamerComponent, PlayerDetachedEvent>(OnPlayerDetached);
SubscribeLocalEvent<TabletopGamerComponent, ComponentShutdown>(OnGamerShutdown);
SubscribeLocalEvent<TabletopGameComponent, GetVerbsEvent<ActivationVerb>>(AddPlayGameVerb);
SubscribeLocalEvent<TabletopGameComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeNetworkEvent<TabletopRequestTakeOut>(OnTabletopRequestTakeOut);
InitializeMap();
}
private void OnTabletopRequestTakeOut(TabletopRequestTakeOut msg, EntitySessionEventArgs args)
{
if (args.SenderSession is not IPlayerSession playerSession)
return;
if (!TryComp(msg.TableUid, out TabletopGameComponent? tabletop) || tabletop.Session is not { } session)
return;
if (!msg.Entity.IsValid())
return;
if (!TryComp(msg.Entity, out TabletopHologramComponent? hologram))
{
_popupSystem.PopupEntity(Loc.GetString("tabletop-error-remove-non-hologram"), msg.TableUid, args.SenderSession);
return;
}
// Check if player is actually playing at this table
if (!session.Players.ContainsKey(playerSession))
return;
// Find the entity, remove it from the session and set it's position to the tabletop
session.Entities.TryGetValue(msg.Entity, out var result);
session.Entities.Remove(result);
_entityManager.QueueDeleteEntity(result);
}
private void OnInteractUsing(EntityUid uid, TabletopGameComponent component, InteractUsingEvent args)
{
if (!EntityManager.TryGetComponent(args.User, out HandsComponent? hands))
return;
if (component.Session is not { } session)
return;
if (hands.ActiveHand == null)
return;
if (hands.ActiveHand.HeldEntity == null)
return;
var handEnt = hands.ActiveHand.HeldEntity.Value;
if (!TryComp<ItemComponent>(handEnt, out var item))
return;
var meta = MetaData(handEnt);
var protoId = meta.EntityPrototype?.ID;
var hologram = _entityManager.SpawnEntity(protoId, session.Position.Offset(-1, 0));
// Make sure the entity can be dragged and can be removed, move it into the board game world and add it to the Entities hashmap
EnsureComp<TabletopDraggableComponent>(hologram);
EnsureComp<TabletopHologramComponent>(hologram);
session.Entities.Add(hologram);
_popupSystem.PopupEntity(Loc.GetString("tabletop-added-piece"), uid, args.User);
}
protected override void OnTabletopMove(TabletopMoveEvent msg, EntitySessionEventArgs args)
{
if (args.SenderSession is not IPlayerSession playerSession)
return;
if (!TryComp(msg.TableUid, out TabletopGameComponent? tabletop) || tabletop.Session is not { } session)
return;
// Check if player is actually playing at this table
if (!session.Players.ContainsKey(playerSession))
return;
base.OnTabletopMove(msg, args);
}
/// <summary>
/// Add a verb that allows the player to start playing a tabletop game.
/// </summary>
private void AddPlayGameVerb(EntityUid uid, TabletopGameComponent component, GetVerbsEvent<ActivationVerb> args)
{
if (!args.CanAccess || !args.CanInteract)
return;
if (!EntityManager.TryGetComponent<ActorComponent?>(args.User, out var actor))
return;
var playVerb = new ActivationVerb()
{
Text = Loc.GetString("tabletop-verb-play-game"),
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/die.svg.192dpi.png")),
Act = () => OpenSessionFor(actor.PlayerSession, uid)
};
args.Verbs.Add(playVerb);
}
private void OnTabletopActivate(EntityUid uid, TabletopGameComponent component, ActivateInWorldEvent args)
{
// Check that a player is attached to the entity.
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
return;
OpenSessionFor(actor.PlayerSession, uid);
}
private void OnGameShutdown(EntityUid uid, TabletopGameComponent component, ComponentShutdown args)
{
CleanupSession(uid);
}
private void OnStopPlaying(TabletopStopPlayingEvent msg, EntitySessionEventArgs args)
{
CloseSessionFor((IPlayerSession)args.SenderSession, msg.TableUid);
}
private void OnPlayerDetached(EntityUid uid, TabletopGamerComponent component, PlayerDetachedEvent args)
{
if(component.Tabletop.IsValid())
CloseSessionFor(args.Player, component.Tabletop);
}
private void OnGamerShutdown(EntityUid uid, TabletopGamerComponent component, ComponentShutdown args)
{
if (!EntityManager.TryGetComponent(uid, out ActorComponent? actor))
return;
if(component.Tabletop.IsValid())
CloseSessionFor(actor.PlayerSession, component.Tabletop);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
foreach (var gamer in EntityManager.EntityQuery<TabletopGamerComponent>())
{
if (!EntityManager.EntityExists(gamer.Tabletop))
continue;
if (!EntityManager.TryGetComponent(gamer.Owner, out ActorComponent? actor))
{
EntityManager.RemoveComponent<TabletopGamerComponent>(gamer.Owner);
return;
}
var gamerUid = (gamer).Owner;
if (actor.PlayerSession.Status != SessionStatus.InGame || !CanSeeTable(gamerUid, gamer.Tabletop))
CloseSessionFor(actor.PlayerSession, gamer.Tabletop);
}
}
}
}