public void DoInstantAction(InstantActionEventArgs args) { if (!args.Performer.TryGetComponent <SharedActionsComponent>(out var actions)) { return; } // find all IGhostBooAffected nearby and do boo on them var ents = IoCManager.Resolve <IEntityLookup>().GetEntitiesInRange(args.Performer, _radius); var booCounter = 0; foreach (var ent in ents) { var ghostBoo = new GhostBooEvent(); ent.EntityManager.EventBus.RaiseLocalEvent(ent.Uid, ghostBoo); if (ghostBoo.Handled) { booCounter++; } if (booCounter >= _maxTargets) { break; } } actions.Cooldown(args.ActionType, Cooldowns.SecondsFromNow(_cooldown)); }
public void DoInstantAction(InstantActionEventArgs args) { if (!args.Performer.TryGetComponent <SharedActionsComponent>(out var actions)) { return; } // find all IGhostBooAffected nearby and do boo on them var ents = IoCManager.Resolve <IEntityLookup>().GetEntitiesInRange(args.Performer, _radius, false); var booCounter = 0; foreach (var ent in ents) { var boos = ent.GetAllComponents <IGhostBooAffected>().ToList(); foreach (var boo in boos) { if (boo.AffectedByGhostBoo(args)) { booCounter++; } } if (booCounter >= _maxTargets) { break; } } actions.Cooldown(args.ActionType, Cooldowns.SecondsFromNow(_cooldown)); }
public void DoInstantAction(InstantItemActionEventArgs args) { args.Performer.PopupMessageEveryone(Message); if (Cooldown > 0) { args.ItemActions?.Cooldown(args.ActionType, Cooldowns.SecondsFromNow(Cooldown)); } }
public void DoTargetEntityAction(TargetEntityActionEventArgs args) { var disarmedActs = args.Target.GetAllComponents <IDisarmedAct>().ToArray(); if (disarmedActs.Length == 0 || !args.Performer.InRangeUnobstructed(args.Target)) { return; } if (!args.Performer.TryGetComponent <SharedActionsComponent>(out var actions)) { return; } if (args.Target == args.Performer || !args.Performer.CanAttack()) { return; } var random = IoCManager.Resolve <IRobustRandom>(); var audio = EntitySystem.Get <AudioSystem>(); var system = EntitySystem.Get <MeleeWeaponSystem>(); var angle = new Angle(args.Target.Transform.MapPosition.Position - args.Performer.Transform.MapPosition.Position); actions.Cooldown(ActionType.Disarm, Cooldowns.SecondsFromNow(_cooldown)); if (random.Prob(_failProb)) { audio.PlayFromEntity("/Audio/Weapons/punchmiss.ogg", args.Performer, AudioHelpers.WithVariation(0.025f)); args.Performer.PopupMessageOtherClients(Loc.GetString("{0} fails to disarm {1}!", args.Performer.Name, args.Target.Name)); args.Performer.PopupMessageCursor(Loc.GetString("You fail to disarm {0}!", args.Target.Name)); system.SendLunge(angle, args.Performer); return; } system.SendAnimation("disarm", angle, args.Performer, args.Performer, new [] { args.Target }); var eventArgs = new DisarmedActEventArgs() { Target = args.Target, Source = args.Performer, PushProbability = _pushProb }; // Sort by priority. Array.Sort(disarmedActs, (a, b) => a.Priority.CompareTo(b.Priority)); foreach (var disarmedAct in disarmedActs) { if (disarmedAct.Disarmed(eventArgs)) { return; } } audio.PlayFromEntity("/Audio/Effects/thudswoosh.ogg", args.Performer, AudioHelpers.WithVariation(0.025f)); }
public void DoInstantAction(InstantActionEventArgs args) { if (!EntitySystem.Get <ActionBlockerSystem>().CanSpeak(args.Performer)) { return; } if (!args.Performer.TryGetComponent <HumanoidAppearanceComponent>(out var humanoid)) { return; } if (!args.Performer.TryGetComponent <SharedActionsComponent>(out var actions)) { return; } if (_random.Prob(.01f) && !string.IsNullOrWhiteSpace(_wilhelm)) { SoundSystem.Play(Filter.Pvs(args.Performer), _wilhelm, args.Performer, AudioParams.Default.WithVolume(Volume)); } else { switch (humanoid.Sex) { case Sex.Male: if (_male == null) { break; } SoundSystem.Play(Filter.Pvs(args.Performer), _random.Pick(_male), args.Performer, AudioHelpers.WithVariation(Variation).WithVolume(Volume)); break; case Sex.Female: if (_female == null) { break; } SoundSystem.Play(Filter.Pvs(args.Performer), _random.Pick(_female), args.Performer, AudioHelpers.WithVariation(Variation).WithVolume(Volume)); break; default: throw new ArgumentOutOfRangeException(); } } actions.Cooldown(args.ActionType, Cooldowns.SecondsFromNow(_cooldown)); }
public void DoInstantAction(InstantActionEventArgs args) { var entManager = IoCManager.Resolve <IEntityManager>(); if (entManager.TryGetComponent(args.Performer, out GuardianHostComponent? hostComponent) && hostComponent.HostedGuardian != null) { EntitySystem.Get <GuardianSystem>().ToggleGuardian(hostComponent); args.PerformerActions?.Cooldown(args.ActionType, Cooldowns.SecondsFromNow(Cooldown)); } else { args.Performer.PopupMessage(Loc.GetString("guardian-missing-invalid-action")); } }
//Rubber-band snapping items into player's hands, originally was a workaround, later found it works quite well with stuns //Not sure if needs fixing public void DoInstantAction(InstantActionEventArgs args) { var caster = args.Performer; if (!caster.TryGetComponent(out HandsComponent? handsComponent)) { caster.PopupMessage(Loc.GetString("spell-fail-no-hands")); return; } if (!EntitySystem.Get <ActionBlockerSystem>().CanInteract(caster)) { return; } // TODO: Nix when we get EntityPrototype serializers if (!IoCManager.Resolve <IPrototypeManager>().HasIndex <EntityPrototype>(ItemProto)) { Logger.Error($"Invalid prototype {ItemProto} supplied for {nameof(GiveItemSpell)}"); return; } // TODO: Look this is shitty and ideally a test would do it var spawnedProto = caster.EntityManager.SpawnEntity(ItemProto, caster.Transform.MapPosition); if (!spawnedProto.TryGetComponent(out ItemComponent? itemComponent)) { Logger.Error($"Tried to use {nameof(GiveItemSpell)} but prototype has no {nameof(ItemComponent)}?"); spawnedProto.Delete(); return; } args.PerformerActions?.Cooldown(args.ActionType, Cooldowns.SecondsFromNow(CoolDown)); if (CastMessage != null) { caster.PopupMessageEveryone(CastMessage); } handsComponent.PutInHandOrDrop(itemComponent); if (CastSound != null) { SoundSystem.Play(Filter.Pvs(caster), CastSound, caster); } }
public void DoTargetEntityAction(TargetEntityActionEventArgs args) { var disarmedActs = args.Target.GetAllComponents <IDisarmedAct>().ToArray(); if (!args.Performer.InRangeUnobstructed(args.Target)) { return; } if (disarmedActs.Length == 0) { if (args.Performer.TryGetComponent(out ActorComponent? actor)) { // Fall back to a normal interaction with the entity var player = actor.PlayerSession; var coordinates = args.Target.Transform.Coordinates; var target = args.Target.Uid; EntitySystem.Get <InteractionSystem>().HandleUseInteraction(player, coordinates, target); return; } return; } if (!args.Performer.TryGetComponent <SharedActionsComponent>(out var actions)) { return; } if (args.Target == args.Performer || !EntitySystem.Get <ActionBlockerSystem>().CanAttack(args.Performer)) { return; } var random = IoCManager.Resolve <IRobustRandom>(); var system = EntitySystem.Get <MeleeWeaponSystem>(); var diff = args.Target.Transform.MapPosition.Position - args.Performer.Transform.MapPosition.Position; var angle = Angle.FromWorldVec(diff); actions.Cooldown(ActionType.Disarm, Cooldowns.SecondsFromNow(_cooldown)); if (random.Prob(_failProb)) { SoundSystem.Play(Filter.Pvs(args.Performer), PunchMissSound.GetSound(), args.Performer, AudioHelpers.WithVariation(0.025f)); args.Performer.PopupMessageOtherClients(Loc.GetString("disarm-action-popup-message-other-clients", ("performerName", args.Performer.Name), ("targetName", args.Target.Name))); args.Performer.PopupMessageCursor(Loc.GetString("disarm-action-popup-message-cursor", ("targetName", args.Target.Name))); system.SendLunge(angle, args.Performer); return; } system.SendAnimation("disarm", angle, args.Performer, args.Performer, new[] { args.Target }); var eventArgs = new DisarmedActEvent() { Target = args.Target, Source = args.Performer, PushProbability = _pushProb }; IoCManager.Resolve <IEntityManager>().EventBus.RaiseLocalEvent(args.Target.Uid, eventArgs); // Check if the event has been handled, and if so, do nothing else! if (eventArgs.Handled) { return; } // Sort by priority. Array.Sort(disarmedActs, (a, b) => a.Priority.CompareTo(b.Priority)); // TODO: Remove this shit. foreach (var disarmedAct in disarmedActs) { if (disarmedAct.Disarmed(eventArgs)) { return; } } SoundSystem.Play(Filter.Pvs(args.Performer), DisarmSuccessSound.GetSound(), args.Performer.Transform.Coordinates, AudioHelpers.WithVariation(0.025f)); }
public async Task GrantsAndRevokesItemActions() { var serverOptions = new ServerIntegrationOptions { ExtraPrototypes = PROTOTYPES }; var clientOptions = new ClientIntegrationOptions { ExtraPrototypes = PROTOTYPES }; var(client, server) = await StartConnectedServerClientPair(serverOptions : serverOptions, clientOptions : clientOptions); await server.WaitIdleAsync(); await client.WaitIdleAsync(); var serverPlayerManager = server.ResolveDependency <Robust.Server.Interfaces.Player.IPlayerManager>(); var serverEntManager = server.ResolveDependency <IEntityManager>(); var serverGameTiming = server.ResolveDependency <IGameTiming>(); var cooldown = Cooldowns.SecondsFromNow(30, serverGameTiming); ServerActionsComponent serverActionsComponent = null; ClientActionsComponent clientActionsComponent = null; IEntity serverPlayerEnt = null; IEntity serverFlashlight = null; await server.WaitAssertion(() => { serverPlayerEnt = serverPlayerManager.GetAllPlayers().Single().AttachedEntity; serverActionsComponent = serverPlayerEnt.GetComponent <ServerActionsComponent>(); // spawn and give them an item that has actions serverFlashlight = serverEntManager.SpawnEntity("TestFlashlight", new EntityCoordinates(new EntityUid(1), (0, 0))); Assert.That(serverFlashlight.TryGetComponent <ItemActionsComponent>(out var itemActions)); // we expect this only to have a toggle light action initially var actionConfigs = itemActions.ActionConfigs.ToList(); Assert.That(actionConfigs.Count == 1); Assert.That(actionConfigs[0].ActionType == ItemActionType.ToggleLight); Assert.That(actionConfigs[0].Enabled); // grant an extra item action, before pickup, initially disabled itemActions.GrantOrUpdate(ItemActionType.DebugToggle, false); serverPlayerEnt.GetComponent <HandsComponent>().PutInHand(serverFlashlight.GetComponent <ItemComponent>(), false); // grant an extra item action, after pickup, with a cooldown itemActions.GrantOrUpdate(ItemActionType.DebugInstant, cooldown: cooldown); Assert.That(serverActionsComponent.TryGetItemActionStates(serverFlashlight.Uid, out var state)); // they should have been granted all 3 actions Assert.That(state.Count == 3); Assert.That(state.TryGetValue(ItemActionType.ToggleLight, out var toggleLightState)); Assert.That(toggleLightState.Equals(new ActionState(true))); Assert.That(state.TryGetValue(ItemActionType.DebugInstant, out var debugInstantState)); Assert.That(debugInstantState.Equals(new ActionState(true, cooldown: cooldown))); Assert.That(state.TryGetValue(ItemActionType.DebugToggle, out var debugToggleState)); Assert.That(debugToggleState.Equals(new ActionState(false))); }); await server.WaitRunTicks(5); await client.WaitRunTicks(5); // check that client has the actions, and toggle the light on via the action slot it was auto-assigned to var clientPlayerMgr = client.ResolveDependency <IPlayerManager>(); var clientUIMgr = client.ResolveDependency <IUserInterfaceManager>(); var clientEntMgr = client.ResolveDependency <IEntityManager>(); EntityUid clientFlashlight = default; await client.WaitAssertion(() => { var local = clientPlayerMgr.LocalPlayer; var controlled = local.ControlledEntity; clientActionsComponent = controlled.GetComponent <ClientActionsComponent>(); var lightEntry = clientActionsComponent.ItemActionStates() .Where(entry => entry.Value.ContainsKey(ItemActionType.ToggleLight)) .FirstOrNull(); clientFlashlight = lightEntry.Value.Key; Assert.That(lightEntry, Is.Not.Null); Assert.That(lightEntry.Value.Value.TryGetValue(ItemActionType.ToggleLight, out var lightState)); Assert.That(lightState.Equals(new ActionState(true))); Assert.That(lightEntry.Value.Value.TryGetValue(ItemActionType.DebugInstant, out var debugInstantState)); Assert.That(debugInstantState.Equals(new ActionState(true, cooldown: cooldown))); Assert.That(lightEntry.Value.Value.TryGetValue(ItemActionType.DebugToggle, out var debugToggleState)); Assert.That(debugToggleState.Equals(new ActionState(false))); var actionsUI = clientUIMgr.StateRoot.Children.FirstOrDefault(c => c is ActionsUI) as ActionsUI; Assert.That(actionsUI, Is.Not.Null); var toggleLightSlot = actionsUI.Slots.FirstOrDefault(slot => slot.Action is ItemActionPrototype { ActionType: ItemActionType.ToggleLight }); Assert.That(toggleLightSlot, Is.Not.Null); clientActionsComponent.AttemptAction(toggleLightSlot); });
public void DoTargetEntityAction(TargetEntityActionEventArgs args) { var disarmedActs = args.Target.GetAllComponents <IDisarmedAct>().ToArray(); if (!args.Performer.InRangeUnobstructed(args.Target)) { return; } if (disarmedActs.Length == 0) { if (args.Performer.TryGetComponent(out ActorComponent? actor)) { // Fall back to a normal interaction with the entity var player = actor.PlayerSession; var coordinates = args.Target.Transform.Coordinates; var target = args.Target.Uid; EntitySystem.Get <InteractionSystem>().HandleClientUseItemInHand(player, coordinates, target); return; } return; } if (!args.Performer.TryGetComponent <SharedActionsComponent>(out var actions)) { return; } if (args.Target == args.Performer || !args.Performer.CanAttack()) { return; } var random = IoCManager.Resolve <IRobustRandom>(); var audio = EntitySystem.Get <AudioSystem>(); var system = EntitySystem.Get <MeleeWeaponSystem>(); var diff = args.Target.Transform.MapPosition.Position - args.Performer.Transform.MapPosition.Position; var angle = Angle.FromWorldVec(diff); actions.Cooldown(ActionType.Disarm, Cooldowns.SecondsFromNow(_cooldown)); if (random.Prob(_failProb)) { SoundSystem.Play(Filter.Pvs(args.Performer), "/Audio/Weapons/punchmiss.ogg", args.Performer, AudioHelpers.WithVariation(0.025f)); args.Performer.PopupMessageOtherClients(Loc.GetString("{0} fails to disarm {1}!", args.Performer.Name, args.Target.Name)); args.Performer.PopupMessageCursor(Loc.GetString("You fail to disarm {0}!", args.Target.Name)); system.SendLunge(angle, args.Performer); return; } system.SendAnimation("disarm", angle, args.Performer, args.Performer, new [] { args.Target }); var eventArgs = new DisarmedActEventArgs() { Target = args.Target, Source = args.Performer, PushProbability = _pushProb }; // Sort by priority. Array.Sort(disarmedActs, (a, b) => a.Priority.CompareTo(b.Priority)); foreach (var disarmedAct in disarmedActs) { if (disarmedAct.Disarmed(eventArgs)) { return; } } SoundSystem.Play(Filter.Pvs(args.Performer), "/Audio/Effects/thudswoosh.ogg", args.Performer.Transform.Coordinates, AudioHelpers.WithVariation(0.025f)); }