2 using FarseerPhysics.Dynamics;
3 using FarseerPhysics.Dynamics.Contacts;
4 using FarseerPhysics.Dynamics.Joints;
5 using Microsoft.Xna.Framework;
8 using System.Collections.Generic;
10 using System.Xml.Linq;
21 LeftLeg,
RightLeg,
LeftFoot,
RightFoot,
Head,
Torso,
Tail,
Legs,
RightThigh,
LeftThigh,
Waist,
Jaw
41 set =>
Joint.Enabled = value;
50 get =>
Joint.WorldAnchorA;
51 set =>
Joint.WorldAnchorA = value;
56 get =>
Joint.WorldAnchorB;
57 set =>
Joint.WorldAnchorB = value;
148 MaxMotorTorque = 0.25f
151 Joint.CollideConnected =
false;
163 if (
float.IsNaN(
Params.LowerLimit))
167 if (
float.IsNaN(
Params.UpperLimit))
225 private FixedMouseJoint pullJoint;
229 private bool ignoreCollisions;
232 get {
return ignoreCollisions; }
235 ignoreCollisions = value;
238 if (ignoreCollisions)
247 body.
CollidesWith = Physics.CollisionAll & ~Physics.CollisionCharacter & ~Physics.CollisionItem & ~Physics.CollisionItemBlocking;
253 private bool isSevered;
254 private float severedFadeOutTimer;
256 private Vector2? mouthPos;
261 mouthPos ??=
Params.MouthPos;
262 return mouthPos.Value;
271 public List<DamageModifier>
DamageModifiers {
get;
private set; } =
new List<DamageModifier>();
352 get {
return isSevered; }
355 if (isSevered == value) {
return; }
360 SeveredFadeOutTime = Math.Max(
Params.SeveredFadeOutTime, connectedLimbs.Any() ? connectedLimbs.Max(l => l.SeveredFadeOutTime) : 0);
373 severedFadeOutTimer = 0.0f;
378 damageOverlayStrength = 1.0f;
386 private bool _hidden;
389 get => _hidden ||
Params.Hide;
390 set => _hidden = value;
407 get {
return ConvertUnits.ToDisplayUnits(
body?.
SimPosition ?? Vector2.Zero); }
417 DebugConsole.ThrowError(
"Attempted to access a removed limb.\n" + Environment.StackTrace.CleanupStackTrace());
419 GameAnalyticsManager.AddErrorEventOnce(
"Limb.LinearVelocity:SimPosition", GameAnalyticsManager.ErrorSeverity.Error,
420 "Attempted to access a removed limb.\n" + Environment.StackTrace.CleanupStackTrace());
435 DebugConsole.ThrowError(
"Attempted to access a removed limb.\n" + Environment.StackTrace.CleanupStackTrace());
437 GameAnalyticsManager.AddErrorEventOnce(
"Limb.LinearVelocity:DrawPosition", GameAnalyticsManager.ErrorSeverity.Error,
438 "Attempted to access a removed limb.\n" + Environment.StackTrace.CleanupStackTrace());
452 DebugConsole.ThrowError(
"Attempted to access a removed limb.\n" + Environment.StackTrace.CleanupStackTrace());
454 GameAnalyticsManager.AddErrorEventOnce(
"Limb.LinearVelocity:SimPosition", GameAnalyticsManager.ErrorSeverity.Error,
455 "Attempted to access a removed limb.\n" + Environment.StackTrace.CleanupStackTrace());
472 DebugConsole.ThrowError(
"Attempted to access a removed limb.\n" + Environment.StackTrace.CleanupStackTrace());
474 GameAnalyticsManager.AddErrorEventOnce(
"Limb.Mass:AccessRemoved", GameAnalyticsManager.ErrorSeverity.Error,
475 "Attempted to access a removed limb.\n" + Environment.StackTrace.CleanupStackTrace());
491 DebugConsole.ThrowError(
"Attempted to access a removed limb.\n" + Environment.StackTrace.CleanupStackTrace());
493 GameAnalyticsManager.AddErrorEventOnce(
"Limb.LinearVelocity:AccessRemoved", GameAnalyticsManager.ErrorSeverity.Error,
494 "Attempted to access a removed limb.\n" + Environment.StackTrace.CleanupStackTrace());
503 get {
return (dir ==
Direction.Left) ? -1.0f : 1.0f; }
514 private float _alpha = 1.0f;
523 _alpha = MathHelper.Clamp(value, 0.0f, 1.0f);
529 public readonly List<WearableSprite>
WearingItems =
new List<WearableSprite>();
531 public readonly List<WearableSprite>
OtherWearables =
new List<WearableSprite>();
535 get {
return pullJoint.Enabled; }
536 set { pullJoint.Enabled = value; }
541 get {
return pullJoint.MaxForce; }
542 set { pullJoint.MaxForce = value; }
547 get {
return pullJoint.WorldAnchorA; }
550 if (!MathUtils.IsValid(value))
552 string errorMsg =
"Attempted to set the anchor A of a limb's pull joint to an invalid value (" + value +
")\n" + Environment.StackTrace.CleanupStackTrace();
553 GameAnalyticsManager.AddErrorEventOnce(
"Limb.SetPullJointAnchorA:InvalidValue", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
555 DebugConsole.ThrowError(errorMsg);
560 if (Vector2.DistanceSquared(
SimPosition, value) > 50.0f * 50.0f)
563 string errorMsg =
"Attempted to move the anchor A of a limb's pull joint extremely far from the limb (diff: " + diff +
566 + Environment.StackTrace.CleanupStackTrace();
567 GameAnalyticsManager.AddErrorEventOnce(
"Limb.SetPullJointAnchorA:ExcessiveValue", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
569 DebugConsole.ThrowError(errorMsg);
574 pullJoint.WorldAnchorA = value;
580 get {
return pullJoint.WorldAnchorB; }
583 if (!MathUtils.IsValid(value))
585 string errorMsg =
"Attempted to set the anchor B of a limb's pull joint to an invalid value (" + value +
")\n" + Environment.StackTrace.CleanupStackTrace();
586 GameAnalyticsManager.AddErrorEventOnce(
"Limb.SetPullJointAnchorB:InvalidValue", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
588 DebugConsole.ThrowError(errorMsg);
593 if (Vector2.DistanceSquared(pullJoint.WorldAnchorA, value) > 50.0f * 50.0f)
595 Vector2 diff = value - pullJoint.WorldAnchorA;
596 string errorMsg =
"Attempted to move the anchor B of a limb's pull joint extremely far from the limb (diff: " + diff +
599 + Environment.StackTrace.CleanupStackTrace();
600 GameAnalyticsManager.AddErrorEventOnce(
"Limb.SetPullJointAnchorB:ExcessiveValue", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
602 DebugConsole.ThrowError(errorMsg);
607 pullJoint.WorldAnchorB = value;
613 get {
return pullJoint.LocalAnchorA; }
643 bool canBeSevered =
Params.CanBeSeveredAlive;
669 private readonly Dictionary<ActionType, List<StatusEffect>> statusEffects =
new Dictionary<ActionType, List<StatusEffect>>();
671 public Dictionary<ActionType, List<StatusEffect>>
StatusEffects {
get {
return statusEffects; } }
677 this.Params = limbParams;
680 type = limbParams.Type;
683 pullJoint =
new FixedMouseJoint(
body.
FarseerBody, ConvertUnits.ToSimUnits(limbParams.PullPos *
Scale))
688 MaxForce = 1000 *
Mass
693 var element = limbParams.Element;
697 foreach (var subElement
in element.Elements())
699 switch (subElement.Name.ToString().ToLowerInvariant())
719 if (
character is { VariantOf.IsEmpty:
false })
722 if (attackElement !=
null)
730 case "damagemodifier":
735 if (statusEffect !=
null)
737 if (!statusEffects.ContainsKey(statusEffect.type))
739 statusEffects.Add(statusEffect.type,
new List<StatusEffect>());
741 statusEffects[statusEffect.type].Add(statusEffect);
749 InitProjSpecific(element);
753 public void MoveToPos(Vector2 pos,
float force,
bool pullFromCenter =
false)
758 pullPos = pullJoint.WorldAnchorA;
768 pullJoint.LocalAnchorA =
new Vector2(-pullJoint.LocalAnchorA.X, pullJoint.LocalAnchorA.Y);
771 public AttackResult AddDamage(Vector2 simPosition,
float damage,
float bleedingDamage,
float burnDamage,
bool playSound)
773 List<Affliction> afflictions =
new List<Affliction>();
778 return AddDamage(simPosition, afflictions, playSound);
781 private readonly List<DamageModifier> appliedDamageModifiers =
new List<DamageModifier>();
782 private readonly List<DamageModifier> tempModifiers =
new List<DamageModifier>();
783 private readonly List<Affliction> afflictionsCopy =
new List<Affliction>();
784 public AttackResult AddDamage(Vector2 simPosition, IEnumerable<Affliction> afflictions,
bool playSound,
float damageMultiplier = 1,
float penetration = 0f,
Character attacker =
null)
786 appliedDamageModifiers.Clear();
787 afflictionsCopy.Clear();
788 foreach (var affliction
in afflictions)
790 tempModifiers.Clear();
791 var newAffliction = affliction;
792 float random = Rand.Value(Rand.RandSync.Unsynced);
793 bool foundMatchingModifier =
false;
794 bool applyAffliction =
true;
798 foundMatchingModifier =
true;
801 applyAffliction =
false;
806 tempModifiers.Add(damageModifier);
814 foundMatchingModifier =
true;
817 applyAffliction =
false;
822 tempModifiers.Add(damageModifier);
826 if (!foundMatchingModifier && random > affliction.Probability) {
continue; }
827 float finalDamageModifier = damageMultiplier;
844 damageModifierValue = MathHelper.Lerp(damageModifierValue, 1f, penetration);
846 finalDamageModifier *= damageModifierValue;
848 if (affliction.MultiplyByMaxVitality)
852 if (!MathUtils.NearlyEqual(finalDamageModifier, 1.0f))
854 newAffliction = affliction.CreateMultiplied(finalDamageModifier, affliction);
858 newAffliction.SetStrength(affliction.NonClampedStrength);
860 if (attacker !=
null)
863 attacker.CheckTalents(
AbilityEffectType.OnAddDamageAffliction, abilityAfflictionCharacter);
864 newAffliction = abilityAfflictionCharacter.Affliction;
868 afflictionsCopy.Add(newAffliction);
869 newAffliction.Source ??= attacker;
871 appliedDamageModifiers.AddRange(tempModifiers);
873 var result =
new AttackResult(afflictionsCopy,
this, appliedDamageModifiers);
874 if (result.Afflictions.None())
878 AddDamageProjSpecific(playSound, result);
880 float bleedingDamage = 0;
883 foreach (var affliction
in result.Afflictions)
890 if (bleedingDamage > 0)
892 float bloodDecalSize = MathHelper.Clamp(bleedingDamage / 5, 0.1f, 1.0f);
903 partial
void AddDamageProjSpecific(
bool playSound,
AttackResult result);
905 public bool SectorHit(Vector2 armorSector, Vector2 simPosition)
907 if (armorSector == Vector2.Zero) {
return false; }
909 if (Math.Abs(armorSector.Y - armorSector.X) >= MathHelper.TwoPi) {
return true; }
911 float offset = (MathHelper.PiOver2 - MathUtils.GetMidAngle(armorSector.X, armorSector.Y)) *
Dir;
912 float hitAngle = VectorExtensions.Angle(VectorExtensions.Forward(rotation + offset),
SimPosition - simPosition);
914 return hitAngle < sectorSize / 2;
919 return Math.Abs(armorSector.X - armorSector.Y);
924 UpdateProjSpecific(deltaTime);
935 severedFadeOutTimer += deltaTime;
947 if (
Params.BlinkFrequency > 0)
958 if (reEnableTimer > 0)
960 reEnableTimer -= deltaTime;
962 else if (reEnableTimer > -1)
971 private bool temporarilyDisabled;
972 private float reEnableTimer = -1;
973 private bool originalIgnoreCollisions;
977 temporarilyDisabled =
true;
984 reEnableTimer = duration;
987 if (
Hidden && LightSource !=
null)
989 LightSource.Enabled =
false;
996 if (!temporarilyDisabled) {
return; }
997 temporarilyDisabled =
false;
1004 partial
void UpdateProjSpecific(
float deltaTime);
1006 private readonly List<Body> contactBodies =
new List<Body>();
1012 attackResult =
default;
1014 float dist = distance > -1 ? distance : ConvertUnits.ToDisplayUnits(Vector2.Distance(simPos, attackSimPos));
1037 bool wasHit =
false;
1038 Body structureBody =
null;
1039 if (damageTarget !=
null)
1046 Vector2 rayStart = simPos;
1047 Vector2 rayEnd = attackSimPos;
1050 rayStart -= spatialEntity.Submarine.SimPosition;
1051 rayEnd -= spatialEntity.Submarine.SimPosition;
1054 if (damageTarget is
Item i && i.GetComponent<Items.
Components.Door>() !=
null)
1060 else if (damageTarget is
Structure wall && structureBody !=
null &&
1069 wasHit = structureBody ==
null;
1074 contactBodies.Clear();
1075 if (damageTarget is
Character targetCharacter)
1077 foreach (
Limb limb
in targetCharacter.AnimController.Limbs)
1082 else if (damageTarget is
Structure targetStructure)
1086 contactBodies.Add(targetStructure.Submarine.PhysicsBody.FarseerBody);
1090 contactBodies.AddRange(targetStructure.Bodies);
1093 else if (damageTarget is
Item)
1095 Item targetItem = damageTarget as
Item;
1099 while (contactEdge !=
null)
1101 if (contactEdge.Contact !=
null &&
1102 contactEdge.Contact.IsTouching &&
1103 contactBodies.Any(b => b == contactEdge.Contact.FixtureA?.Body || b == contactEdge.Contact.FixtureB?.Body))
1105 structureBody = contactBodies.LastOrDefault();
1109 contactEdge = contactEdge.Next;
1117 wasHit = damageTarget !=
null;
1128 attackLimb:
this, targetEntity: damageTarget, targetLimb: targetLimb,
1129 targetSimPos: attackSimPos));
1146 if (diff == Vector2.Zero) {
continue; }
1148 Vector2 forcePos = limb.pullJoint ==
null ? limb.
body.
SimPosition : limb.pullJoint.WorldAnchorA;
1152 else if (diff != Vector2.Zero)
1155 Vector2 forcePos = pullJoint ==
null ?
body.
SimPosition : pullJoint.WorldAnchorA;
1175 bool playSound =
false;
1177 playSound = LastAttackSoundTime < Timing.TotalTime - SoundInterval;
1180 LastAttackSoundTime = SoundInterval;
1183 if (damageTarget is
Character targetCharacter && targetLimb !=
null)
1211 private WeldJoint attachJoint;
1212 private WeldJoint colliderJoint;
1219 private void StickTo(Body target, Vector2 from, Vector2 to)
1221 if (attachJoint !=
null)
1224 if (attachJoint.BodyB == target) {
return; }
1235 mainLimbLocalFront.X = -mainLimbLocalFront.X;
1237 Vector2 mainLimbFront = mainLimbBody.
FarseerBody.GetWorldPoint(mainLimbLocalFront);
1240 colliderJoint =
new WeldJoint(colliderBody, mainLimbBody.
FarseerBody, mainLimbFront, mainLimbFront,
true)
1242 KinematicBodyB =
true,
1243 CollideConnected =
false
1251 DampingRatio = 0.5f,
1252 KinematicBodyB =
true,
1253 CollideConnected =
false
1263 if (colliderJoint !=
null)
1266 colliderJoint =
null;
1270 private readonly List<ISerializableEntity> targets =
new List<ISerializableEntity>();
1273 if (!statusEffects.TryGetValue(actionType, out var statusEffectList)) {
return; }
1274 foreach (
StatusEffect statusEffect
in statusEffectList)
1299 foreach (var limbType
in statusEffect.
targetLimbs)
1306 if (limb.IsSevered) {
continue; }
1307 if (limb.type == limbType)
1309 ApplyToLimb(actionType, deltaTime, statusEffect,
character, limb);
1319 ApplyToLimb(actionType, deltaTime, statusEffect,
character, limb);
1325 Limb limb =
ragdoll.
Limbs.LastOrDefault(l => l.type == limbType && !l.IsSevered && !l.Hidden);
1328 ApplyToLimb(actionType, deltaTime, statusEffect,
character, limb);
1338 if (limb.IsSevered) {
continue; }
1339 ApplyToLimb(actionType, deltaTime, statusEffect,
character, limb);
1348 ApplyToLimb(actionType, deltaTime, statusEffect,
character, limb:
this);
1354 statusEffect.
Apply(actionType, deltaTime, entity:
character, target: limb);
1363 private float TotalBlinkDurationOut =>
Params.BlinkDurationOut +
Params.BlinkHoldTime;
1381 float t = ToolBox.GetEasing(
Params.BlinkTransitionIn, MathUtils.InverseLerp(1, 0,
BlinkPhase /
Params.BlinkDurationIn));
1383 if (
Params.UseTextureOffsetForBlinking)
1386 ActiveSprite.RelativeOrigin = Vector2.Lerp(
Params.BlinkTextureOffsetOut,
Params.BlinkTextureOffsetIn, t);
1401 float t = ToolBox.GetEasing(
Params.BlinkTransitionOut, MathUtils.InverseLerp(0, 1, (-
BlinkPhase -
Params.BlinkHoldTime) /
Params.BlinkDurationOut));
1403 if (
Params.UseTextureOffsetForBlinking)
1406 ActiveSprite.RelativeOrigin = Vector2.Lerp(
Params.BlinkTextureOffsetIn,
Params.BlinkTextureOffsetOut, t);
1428 var connectedLimbs =
new HashSet<Limb>();
1432 foreach (
LimbJoint connectedJoint
in connectedJoints)
1434 if (otherJoints.Contains(connectedJoint))
1436 connectedLimbs.Add(limb);
1440 return connectedLimbs;
1448 if (pullJoint !=
null)
1457 RemoveProjSpecific();
1461 partial
void RemoveProjSpecific();
1465 pullJoint.LocalAnchorA = ConvertUnits.ToSimUnits(
Params.PullPos *
Scale);
1466 LoadParamsProjSpecific();
1469 partial
void LoadParamsProjSpecific();
AbilityAfflictionCharacter(Affliction affliction, Character character)
AbilityReduceAffliction(Character character, float value)
A special affliction type that increases the character's Bloodloss affliction with a rate relative to...
AfflictionPrefab is a prefab that defines a type of affliction that can be applied to a character....
Affliction Instantiate(float strength, Character source=null)
static AfflictionPrefab InternalDamage
static AfflictionPrefab Burn
static AfflictionPrefab Bleeding
static readonly Identifier ParalysisType
static readonly Identifier EMPType
static readonly Identifier PoisonType
AnimationParams? CurrentAnimationParams
Attacks are used to deal damage to characters, structures and items. They can be defined in the weapo...
AttackResult DoDamageToLimb(Character attacker, Limb targetLimb, Vector2 worldPosition, float deltaTime, bool playSound=true, PhysicsBody sourceBody=null, Limb sourceLimb=null)
void UpdateCoolDown(float deltaTime)
float RangeMultiplier
Used for multiplying all the ranges.
void SetCoolDown(bool applyRandom)
TransitionMode RootTransitionEasing
readonly List< int > ForceOnLimbIndices
Vector2 CalculateAttackPhase(TransitionMode easing=TransitionMode.Linear)
float ImpactMultiplier
Used for multiplying the physics forces.
void UpdateAttackTimer(float deltaTime, Character character)
float DamageMultiplier
Used for multiplying all the damage.
AttackResult DoDamage(Character attacker, IDamageable target, Vector2 worldPosition, float deltaTime, bool playSound=true, PhysicsBody sourceBody=null, Limb sourceLimb=null)
HitDetection HitDetectionType
readonly CharacterParams Params
CharacterHealth CharacterHealth
virtual AIController AIController
override Vector2? SimPosition
float GetStatValue(StatTypes statType, bool includeSaved=true)
void Kill(CauseOfDeathType causeOfDeath, Affliction causeOfDeathAffliction, bool isNetworkMessage=false, bool log=true)
static Character Controlled
readonly AnimController AnimController
float PoisonVulnerability
bool MatchesAffliction(string identifier, string type)
Returns true if the type or the identifier matches the defined types/identifiers.
Vector2 ArmorSectorInRadians
float ProbabilityMultiplier
static NetworkMember NetworkMember
Decal AddDecal(UInt32 decalId, Vector2 worldPosition, float scale, bool isNetworkEvent, int? spriteIndex=null)
static Hull FindHull(Vector2 position, Hull guess=null, bool useWorldCoordinates=true, bool inclusive=true)
Returns the hull which contains the point (or null if it isn't inside any)
List< ItemComponent > Components
AttackResult AddDamage(Vector2 simPosition, float damage, float bleedingDamage, float burnDamage, bool playSound)
readonly Ragdoll ragdoll
Note that during the limb initialization, character.AnimController returns null, whereas this field i...
readonly Character character
List< DamageModifier > DamageModifiers
IEnumerable< Limb > GetConnectedLimbs()
void ApplyStatusEffects(ActionType actionType, float deltaTime)
readonly LimbParams Params
Dictionary< ActionType, List< StatusEffect > > StatusEffects
readonly List< WearableSprite > WearingItems
void MoveToPos(Vector2 pos, float force, bool pullFromCenter=false)
void Update(float deltaTime)
Vector2 PullJointWorldAnchorB
Vector2 PullJointWorldAnchorA
float GetArmorSectorSize(Vector2 armorSector)
bool SectorHit(Vector2 armorSector, Vector2 simPosition)
bool UpdateAttack(float deltaTime, Vector2 attackSimPos, IDamageable damageTarget, out AttackResult attackResult, float distance=-1, Limb targetLimb=null)
Returns true if the attack successfully hit something. If the distance is not given,...
IEnumerable< LimbJoint > GetConnectedJoints()
Limb(Ragdoll ragdoll, Character character, LimbParams limbParams)
Items.Components.Rope AttachedRope
void UpdateBlink(float deltaTime, float referenceRotation)
void ExecuteAttack(IDamageable damageTarget, Limb targetLimb, out AttackResult attackResult)
AttackResult AddDamage(Vector2 simPosition, IEnumerable< Affliction > afflictions, bool playSound, float damageMultiplier=1, float penetration=0f, Character attacker=null)
readonly List< WearableSprite > OtherWearables
Dictionary< Identifier, SerializableProperty > SerializableProperties
float Alpha
Can be used by status effects
Vector2 PullJointLocalAnchorA
void HideAndDisable(float duration=0, bool ignoreCollisions=true)
readonly WeldJoint weldJoint
LimbJoint(Limb limbA, Limb limbB, JointParams jointParams, Ragdoll ragdoll)
readonly JointParams Params
LimbJoint(Limb limbA, Limb limbB, Vector2 anchor1, Vector2 anchor2, bool weld=false)
readonly RevoluteJoint revoluteJoint
void ApplyTorque(float torque)
void ApplyLinearImpulse(Vector2 impulse)
bool SetTransform(Vector2 simPosition, float rotation, bool setPrevTransform=true)
Vector2 GetLocalFront(float? spritesheetRotation=null)
Returns the farthest point towards the forward of the body. For capsules and circles,...
void ApplyWaterForces()
Applies buoyancy, drag and angular drag caused by water
void MoveToPos(Vector2 simPosition, float force, Vector2? pullPos=null)
Category CollisionCategories
float TransformedRotation
Takes flipping (Dir) into account.
void SmoothRotate(float targetRotation, float force=10.0f, bool wrapAngle=true)
Rotate the body towards the target rotation in the "shortest direction", taking into account the curr...
abstract RagdollParams RagdollParams
Limb GetLimb(LimbType limbType, bool excludeSevered=true, bool excludeLimbsWithSecondaryType=false, bool useSecondaryType=false)
Note that if there are multiple limbs of the same type, only the first (valid) limb is returned.
bool? SimplePhysicsEnabled
void SubtractMass(Limb limb)
static Dictionary< Identifier, SerializableProperty > GetProperties(object obj)
StatusEffects can be used to execute various kinds of effects: modifying the state of some entity in ...
bool HasTargetType(TargetType targetType)
bool ShouldWaitForInterval(Entity entity, float deltaTime)
static StatusEffect Load(ContentXElement element, string parentDebugName)
void AddNearbyTargets(Vector2 worldPosition, List< ISerializableEntity > targets)
readonly bool OnlyWhenDamagedByPlayer
If enabled, the effect only executes when the entity receives damage from a player character (a chara...
bool HasRequiredAfflictions(AttackResult attackResult)
readonly LimbType[] targetLimbs
Which types of limbs this effect can target? Only valid when targeting characters or limbs.
virtual void Apply(ActionType type, float deltaTime, Entity entity, ISerializableEntity target, Vector2? worldPosition=null)
Submarine(SubmarineInfo info, bool showErrorMessages=true, Func< Submarine, List< MapEntity >> loadEntities=null, IdRemap linkedRemap=null)
static Body CheckVisibility(Vector2 rayStart, Vector2 rayEnd, bool ignoreLevel=false, bool ignoreSubs=false, bool ignoreSensors=true, bool ignoreDisabledWalls=true, bool ignoreBranches=true, Predicate< Fixture > blocksVisibilityPredicate=null)
Check visibility between two points (in sim units).
override Vector2? Position
Wearable WearableComponent
ActionType
ActionTypes define when a StatusEffect is executed.
StatTypes
StatTypes are used to alter several traits of a character. They are mostly used by talents.