Merge branch 'master' into 2020-04-28-tool-component
# Conflicts: # Content.Server/GameObjects/Components/AnchorableComponent.cs # Content.Server/GameObjects/Components/Construction/ConstructionComponent.cs # Content.Server/GameObjects/Components/Doors/AirlockComponent.cs # Content.Server/GameObjects/Components/Gravity/GravityGeneratorComponent.cs # Content.Server/GameObjects/Components/Interactable/Tools/CrowbarComponent.cs # Content.Server/GameObjects/Components/Power/PowerTransferComponent.cs # Content.Server/GameObjects/Components/WiresComponent.cs
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Content.Server.GameObjects.Components.Interactable;
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
@@ -30,26 +30,26 @@ using Robust.Shared.Players;
|
||||
namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
/// <summary>
|
||||
/// This interface gives components behavior when being clicked on or "attacked" by a user with an object in their hand
|
||||
/// This interface gives components behavior when being clicked on by a user with an object in their hand
|
||||
/// who is in range and has unobstructed reach of the target entity (allows inside blockers).
|
||||
/// </summary>
|
||||
public interface IAttackBy
|
||||
public interface IInteractUsing
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when using one object on another when user is in range of the target entity.
|
||||
/// </summary>
|
||||
bool AttackBy(AttackByEventArgs eventArgs);
|
||||
bool InteractUsing(InteractUsingEventArgs eventArgs);
|
||||
}
|
||||
|
||||
public class AttackByEventArgs : EventArgs, ITargetedAttackEventArgs
|
||||
public class InteractUsingEventArgs : EventArgs, ITargetedInteractEventArgs
|
||||
{
|
||||
public IEntity User { get; set; }
|
||||
public GridCoordinates ClickLocation { get; set; }
|
||||
public IEntity AttackWith { get; set; }
|
||||
public IEntity Attacked { get; set; }
|
||||
public IEntity Using { get; set; }
|
||||
public IEntity Target { get; set; }
|
||||
}
|
||||
|
||||
public interface ITargetedAttackEventArgs
|
||||
public interface ITargetedInteractEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Performer of the attack
|
||||
@@ -58,45 +58,46 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
/// <summary>
|
||||
/// Target of the attack
|
||||
/// </summary>
|
||||
IEntity Attacked { get; }
|
||||
IEntity Target { get; }
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This interface gives components behavior when being clicked on or "attacked" by a user with an empty hand
|
||||
/// This interface gives components behavior when being clicked on by a user with an empty hand
|
||||
/// who is in range and has unobstructed reach of the target entity (allows inside blockers).
|
||||
/// </summary>
|
||||
public interface IAttackHand
|
||||
public interface IInteractHand
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when a player directly interacts with an empty hand when user is in range of the target entity.
|
||||
/// </summary>
|
||||
bool AttackHand(AttackHandEventArgs eventArgs);
|
||||
bool InteractHand(InteractHandEventArgs eventArgs);
|
||||
}
|
||||
|
||||
public class AttackHandEventArgs : EventArgs, ITargetedAttackEventArgs
|
||||
public class InteractHandEventArgs : EventArgs, ITargetedInteractEventArgs
|
||||
{
|
||||
public IEntity User { get; set; }
|
||||
public IEntity Attacked { get; set; }
|
||||
public IEntity Target { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This interface gives components behavior when being clicked by objects outside the range of direct use
|
||||
/// This interface gives components behavior when being clicked on by a user with an object
|
||||
/// outside the range of direct use
|
||||
/// </summary>
|
||||
public interface IRangedAttackBy
|
||||
public interface IRangedInteract
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when we try to interact with an entity out of range
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool RangedAttackBy(RangedAttackByEventArgs eventArgs);
|
||||
bool RangedInteract(RangedInteractEventArgs eventArgs);
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public class RangedAttackByEventArgs : EventArgs
|
||||
public class RangedInteractEventArgs : EventArgs
|
||||
{
|
||||
public IEntity User { get; set; }
|
||||
public IEntity Weapon { get; set; }
|
||||
public IEntity Using { get; set; }
|
||||
public GridCoordinates ClickLocation { get; set; }
|
||||
}
|
||||
|
||||
@@ -104,19 +105,19 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
/// This interface gives components a behavior when clicking on another object and no interaction occurs,
|
||||
/// at any range.
|
||||
/// </summary>
|
||||
public interface IAfterAttack
|
||||
public interface IAfterInteract
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when we interact with nothing, or when we interact with an entity out of range that has no behavior
|
||||
/// </summary>
|
||||
void AfterAttack(AfterAttackEventArgs eventArgs);
|
||||
void AfterInteract(AfterInteractEventArgs eventArgs);
|
||||
}
|
||||
|
||||
public class AfterAttackEventArgs : EventArgs
|
||||
public class AfterInteractEventArgs : EventArgs
|
||||
{
|
||||
public IEntity User { get; set; }
|
||||
public GridCoordinates ClickLocation { get; set; }
|
||||
public IEntity Attacked { get; set; }
|
||||
public IEntity Target { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -148,10 +149,10 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
void Activate(ActivateEventArgs eventArgs);
|
||||
}
|
||||
|
||||
public class ActivateEventArgs : EventArgs, ITargetedAttackEventArgs
|
||||
public class ActivateEventArgs : EventArgs, ITargetedInteractEventArgs
|
||||
{
|
||||
public IEntity User { get; set; }
|
||||
public IEntity Attacked { get; set; }
|
||||
public IEntity Target { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -384,7 +385,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
}
|
||||
|
||||
// all activates should only fire when in range / unbostructed
|
||||
var activateEventArgs = new ActivateEventArgs {User = user, Attacked = used};
|
||||
var activateEventArgs = new ActivateEventArgs {User = user, Target = used};
|
||||
if (InteractionChecks.InRangeUnobstructed(activateEventArgs))
|
||||
{
|
||||
activateComp.Activate(activateEventArgs);
|
||||
@@ -480,8 +481,14 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
|
||||
var item = hands.GetActiveHand?.Owner;
|
||||
|
||||
if(ActionBlockerSystem.CanChangeDirection(player))
|
||||
playerTransform.LocalRotation = new Angle(coordinates.ToMapPos(_mapManager) - playerTransform.MapPosition.Position);
|
||||
if (ActionBlockerSystem.CanChangeDirection(player))
|
||||
{
|
||||
var diff = coordinates.ToMapPos(_mapManager) - playerTransform.MapPosition.Position;
|
||||
if (diff.LengthSquared > 0.01f)
|
||||
{
|
||||
playerTransform.LocalRotation = new Angle(diff);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ActionBlockerSystem.CanInteract(player))
|
||||
{
|
||||
@@ -495,8 +502,8 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
// After attack: Check if we clicked on an empty location, if so the only interaction we can do is AfterAttack
|
||||
InteractAfterAttack(player, item, coordinates);
|
||||
// After attack: Check if we clicked on an empty location, if so the only interaction we can do is AfterInteract
|
||||
InteractAfter(player, item, coordinates);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -521,7 +528,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
}
|
||||
}
|
||||
|
||||
// RangedAttack/AfterAttack: Check distance between user and clicked item, if too large parse it in the ranged function
|
||||
// RangedInteract/AfterInteract: Check distance between user and clicked item, if too large parse it in the ranged function
|
||||
// TODO: have range based upon the item being used? or base it upon some variables of the player himself?
|
||||
var distance = (playerTransform.WorldPosition - attacked.Transform.WorldPosition).LengthSquared;
|
||||
if (distance > InteractionRangeSquared)
|
||||
@@ -532,16 +539,16 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
return;
|
||||
}
|
||||
|
||||
return; // Add some form of ranged AttackHand here if you need it someday, or perhaps just ways to modify the range of AttackHand
|
||||
return; // Add some form of ranged InteractHand here if you need it someday, or perhaps just ways to modify the range of InteractHand
|
||||
}
|
||||
|
||||
// We are close to the nearby object and the object isn't contained in our active hand
|
||||
// AttackBy/AfterAttack: We will either use the item on the nearby object
|
||||
// InteractUsing/AfterInteract: We will either use the item on the nearby object
|
||||
if (item != null)
|
||||
{
|
||||
Interaction(player, item, attacked, coordinates);
|
||||
}
|
||||
// AttackHand/Activate: Since our hand is empty we will use AttackHand/Activate
|
||||
// InteractHand/Activate: Since our hand is empty we will use InteractHand/Activate
|
||||
else
|
||||
{
|
||||
Interaction(player, attacked);
|
||||
@@ -549,9 +556,9 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We didn't click on any entity, try doing an AfterAttack on the click location
|
||||
/// We didn't click on any entity, try doing an AfterInteract on the click location
|
||||
/// </summary>
|
||||
private void InteractAfterAttack(IEntity user, IEntity weapon, GridCoordinates clickLocation)
|
||||
private void InteractAfter(IEntity user, IEntity weapon, GridCoordinates clickLocation)
|
||||
{
|
||||
var message = new AfterAttackMessage(user, weapon, null, clickLocation);
|
||||
RaiseLocalEvent(message);
|
||||
@@ -560,18 +567,18 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
return;
|
||||
}
|
||||
|
||||
var afterAttacks = weapon.GetAllComponents<IAfterAttack>().ToList();
|
||||
var afterAttackEventArgs = new AfterAttackEventArgs {User = user, ClickLocation = clickLocation};
|
||||
var afterInteracts = weapon.GetAllComponents<IAfterInteract>().ToList();
|
||||
var afterInteractEventArgs = new AfterInteractEventArgs {User = user, ClickLocation = clickLocation};
|
||||
|
||||
foreach (var afterAttack in afterAttacks)
|
||||
foreach (var afterInteract in afterInteracts)
|
||||
{
|
||||
afterAttack.AfterAttack(afterAttackEventArgs);
|
||||
afterInteract.AfterInteract(afterInteractEventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses a weapon/object on an entity
|
||||
/// Finds components with the AttackBy interface and calls their function
|
||||
/// Finds components with the InteractUsing interface and calls their function
|
||||
/// </summary>
|
||||
public void Interaction(IEntity user, IEntity weapon, IEntity attacked, GridCoordinates clickLocation)
|
||||
{
|
||||
@@ -582,10 +589,10 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
return;
|
||||
}
|
||||
|
||||
var attackBys = attacked.GetAllComponents<IAttackBy>().ToList();
|
||||
var attackByEventArgs = new AttackByEventArgs
|
||||
var attackBys = attacked.GetAllComponents<IInteractUsing>().ToList();
|
||||
var attackByEventArgs = new InteractUsingEventArgs
|
||||
{
|
||||
User = user, ClickLocation = clickLocation, AttackWith = weapon, Attacked = attacked
|
||||
User = user, ClickLocation = clickLocation, Using = weapon, Target = attacked
|
||||
};
|
||||
|
||||
// all AttackBys should only happen when in range / unobstructed, so no range check is needed
|
||||
@@ -593,9 +600,9 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
foreach (var attackBy in attackBys)
|
||||
{
|
||||
if (attackBy.AttackBy(attackByEventArgs))
|
||||
if (attackBy.InteractUsing(attackByEventArgs))
|
||||
{
|
||||
// If an AttackBy returns a status completion we finish our attack
|
||||
// If an InteractUsing returns a status completion we finish our attack
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -609,21 +616,21 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
}
|
||||
|
||||
// If we aren't directly attacking the nearby object, lets see if our item has an after attack we can do
|
||||
var afterAttacks = weapon.GetAllComponents<IAfterAttack>().ToList();
|
||||
var afterAttackEventArgs = new AfterAttackEventArgs
|
||||
var afterAttacks = weapon.GetAllComponents<IAfterInteract>().ToList();
|
||||
var afterAttackEventArgs = new AfterInteractEventArgs
|
||||
{
|
||||
User = user, ClickLocation = clickLocation, Attacked = attacked
|
||||
User = user, ClickLocation = clickLocation, Target = attacked
|
||||
};
|
||||
|
||||
foreach (var afterAttack in afterAttacks)
|
||||
{
|
||||
afterAttack.AfterAttack(afterAttackEventArgs);
|
||||
afterAttack.AfterInteract(afterAttackEventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses an empty hand on an entity
|
||||
/// Finds components with the AttackHand interface and calls their function
|
||||
/// Finds components with the InteractHand interface and calls their function
|
||||
/// </summary>
|
||||
public void Interaction(IEntity user, IEntity attacked)
|
||||
{
|
||||
@@ -634,17 +641,17 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
return;
|
||||
}
|
||||
|
||||
var attackHands = attacked.GetAllComponents<IAttackHand>().ToList();
|
||||
var attackHandEventArgs = new AttackHandEventArgs {User = user, Attacked = attacked};
|
||||
var attackHands = attacked.GetAllComponents<IInteractHand>().ToList();
|
||||
var attackHandEventArgs = new InteractHandEventArgs {User = user, Target = attacked};
|
||||
|
||||
// all attackHands should only fire when in range / unbostructed
|
||||
if (InteractionChecks.InRangeUnobstructed(attackHandEventArgs))
|
||||
{
|
||||
foreach (var attackHand in attackHands)
|
||||
{
|
||||
if (attackHand.AttackHand(attackHandEventArgs))
|
||||
if (attackHand.InteractHand(attackHandEventArgs))
|
||||
{
|
||||
// If an AttackHand returns a status completion we finish our attack
|
||||
// If an InteractHand returns a status completion we finish our attack
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -892,18 +899,18 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
if (rangedMsg.Handled)
|
||||
return;
|
||||
|
||||
var rangedAttackBys = attacked.GetAllComponents<IRangedAttackBy>().ToList();
|
||||
var rangedAttackByEventArgs = new RangedAttackByEventArgs
|
||||
var rangedAttackBys = attacked.GetAllComponents<IRangedInteract>().ToList();
|
||||
var rangedAttackByEventArgs = new RangedInteractEventArgs
|
||||
{
|
||||
User = user, Weapon = weapon, ClickLocation = clickLocation
|
||||
User = user, Using = weapon, ClickLocation = clickLocation
|
||||
};
|
||||
|
||||
// See if we have a ranged attack interaction
|
||||
foreach (var t in rangedAttackBys)
|
||||
{
|
||||
if (t.RangedAttackBy(rangedAttackByEventArgs))
|
||||
if (t.RangedInteract(rangedAttackByEventArgs))
|
||||
{
|
||||
// If an AttackBy returns a status completion we finish our attack
|
||||
// If an InteractUsing returns a status completion we finish our attack
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -913,16 +920,16 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
if (afterAtkMsg.Handled)
|
||||
return;
|
||||
|
||||
var afterAttacks = weapon.GetAllComponents<IAfterAttack>().ToList();
|
||||
var afterAttackEventArgs = new AfterAttackEventArgs
|
||||
var afterAttacks = weapon.GetAllComponents<IAfterInteract>().ToList();
|
||||
var afterAttackEventArgs = new AfterInteractEventArgs
|
||||
{
|
||||
User = user, ClickLocation = clickLocation, Attacked = attacked
|
||||
User = user, ClickLocation = clickLocation, Target = attacked
|
||||
};
|
||||
|
||||
//See if we have a ranged attack interaction
|
||||
foreach (var afterAttack in afterAttacks)
|
||||
{
|
||||
afterAttack.AfterAttack(afterAttackEventArgs);
|
||||
afterAttack.AfterInteract(afterAttackEventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user