2020-08-15 20:38:37 +02:00
using System ;
using Content.Shared.GameObjects.Components.Mobs ;
2019-07-19 10:45:04 +02:00
using JetBrains.Annotations ;
2020-08-15 20:38:37 +02:00
using Robust.Shared.Containers ;
2019-07-19 10:45:04 +02:00
using Robust.Shared.GameObjects.Systems ;
using Robust.Shared.Interfaces.GameObjects ;
2020-08-01 17:37:12 +02:00
using Robust.Shared.Maths ;
using Robust.Shared.Utility ;
2019-07-19 10:45:04 +02:00
namespace Content.Shared.GameObjects.EntitySystems
{
2020-08-01 17:37:12 +02:00
public interface IExamine
{
/// <summary>
/// Returns a status examine value for components appended to the end of the description of the entity
/// </summary>
/// <param name="message">The message to append to which will be displayed.</param>
/// <param name="inDetailsRange">Whether the examiner is within the 'Details' range, allowing you to show information logically only availabe when close to the examined entity.</param>
void Examine ( FormattedMessage message , bool inDetailsRange ) ;
}
2019-07-19 10:45:04 +02:00
public abstract class ExamineSystemShared : EntitySystem
{
2020-04-25 11:37:59 +02:00
public const float ExamineRange = 16f ;
2019-07-19 10:45:04 +02:00
public const float ExamineRangeSquared = ExamineRange * ExamineRange ;
2020-08-01 17:37:12 +02:00
protected const float ExamineDetailsRange = 3f ;
2019-07-19 10:45:04 +02:00
2020-08-15 20:38:37 +02:00
private static bool IsInDetailsRange ( IEntity examiner , IEntity entity )
{
return Get < SharedInteractionSystem > ( )
. InRangeUnobstructed ( examiner . Transform . MapPosition , entity . Transform . MapPosition ,
ExamineDetailsRange , predicate : entity0 = > entity0 = = examiner | | entity0 = = entity ,
ignoreInsideBlocker : true ) & &
examiner . IsInSameOrNoContainer ( entity ) ;
}
2019-07-19 10:45:04 +02:00
[Pure]
protected static bool CanExamine ( IEntity examiner , IEntity examined )
{
if ( ! examiner . TryGetComponent ( out ExaminerComponent examinerComponent ) )
{
return false ;
}
if ( ! examinerComponent . DoRangeCheck )
{
return true ;
}
if ( examiner . Transform . MapID ! = examined . Transform . MapID )
{
return false ;
}
2020-08-15 20:38:37 +02:00
Func < IEntity , bool > predicate = entity = > entity = = examiner | | entity = = examined ;
if ( ContainerHelpers . TryGetContainer ( examiner , out var container ) )
{
predicate + = entity = > entity = = container . Owner ;
}
2020-08-13 14:40:27 +02:00
return Get < SharedInteractionSystem > ( )
2020-05-26 14:23:25 +02:00
. InRangeUnobstructed ( examiner . Transform . MapPosition , examined . Transform . MapPosition ,
2020-08-15 20:38:37 +02:00
ExamineRange , predicate : predicate , ignoreInsideBlocker : true ) ;
2019-07-19 10:45:04 +02:00
}
2020-08-01 17:37:12 +02:00
public static FormattedMessage GetExamineText ( IEntity entity , IEntity examiner )
{
var message = new FormattedMessage ( ) ;
var doNewline = false ;
//Add an entity description if one is declared
if ( ! string . IsNullOrEmpty ( entity . Description ) )
{
message . AddText ( entity . Description ) ;
doNewline = true ;
}
message . PushColor ( Color . DarkGray ) ;
//Add component statuses from components that report one
foreach ( var examineComponent in entity . GetAllComponents < IExamine > ( ) )
{
var subMessage = new FormattedMessage ( ) ;
2020-08-15 20:38:37 +02:00
examineComponent . Examine ( subMessage , IsInDetailsRange ( examiner , entity ) ) ;
2020-08-01 17:37:12 +02:00
if ( subMessage . Tags . Count = = 0 )
continue ;
if ( doNewline )
message . AddText ( "\n" ) ;
message . AddMessage ( subMessage ) ;
doNewline = true ;
}
message . Pop ( ) ;
return message ;
}
2019-07-19 10:45:04 +02:00
}
}