Initial Commit

This commit is contained in:
Simeon Radivoev 2022-02-12 12:53:50 +02:00
commit ee5c2f922d
Signed by: simeonradivoev
GPG key ID: 7611A451D2A5D37A
2255 changed files with 547750 additions and 0 deletions

View file

@ -0,0 +1,38 @@
using Unity.Entities;
using UnityEngine;
using UnityEngine.EventSystems;
using Zenject;
namespace DefaultNamespace
{
[UpdateInGroup(typeof(PresentationSystemGroup))]
public class PlayerActionMapSystem : InjectableComponentSystem
{
[Inject] private EventSystem eventSystem;
protected override void OnSystemUpdate()
{
Entities.ForEach(
(ref PlayerInput input) =>
{
input.HorizontalInput = Input.GetAxis("Horizontal");
input.Attacking = Input.GetButton("Fire1");
input.AttackPressed = Input.GetButtonDown("Fire1");
input.Pickup = Input.GetButtonDown("PickUp");
input.ScrollInput = Mathf.RoundToInt(Mathf.Sign(Input.GetAxis("Mouse ScrollWheel"))) *
Mathf.CeilToInt(Mathf.Abs(Input.GetAxis("Mouse ScrollWheel")));
input.Jump = Input.GetButton("Jump");
input.JumpPressed = Input.GetButtonDown("Jump");
input.Reload = Input.GetButtonDown("Reload");
input.UseItem = Input.GetButtonDown("UseItem");
input.OverUi = eventSystem.IsPointerOverGameObject();
input.Melee = Input.GetButtonDown("Melee");
input.Grenade = Input.GetButtonDown("Grenade");
input.Drag = Input.GetMouseButton(0);
input.Heal = Input.GetButtonDown("Heal");
input.Run = Input.GetButton("Run");
input.Vault = Input.GetButtonDown("Vault");
});
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dcac359cadd69dd4bbe80b4a061eae8d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,33 @@
using DefaultNamespace;
using Unity.Entities;
using UnityEngine;
using Zenject;
[UpdateInGroup(typeof(PresentationSystemGroup)), UpdateAfter(typeof(PlayerActionMapSystem)), UpdateAfter(typeof(PlayerMoveSystem))]
public class PlayerAnimationSystem : InjectableComponentSystem
{
//[Inject] private PlayerGroup playerGroup;
[Inject] private readonly Hashes hashes;
protected override void OnSystemUpdate()
{
Entities.WithAll<Animator>()
.ForEach(
(
Transform transform,
ref RigidBody2DData rigidBodyData,
ref ActorData actorData,
ref PlayerInput input,
ref AnimatorStateData animationState,
ref ActorAnimationData animation) =>
{
float walkDir = Mathf.Sign(transform.right.x) == Mathf.Sign(input.HorizontalInput) ? -1 : 1;
animation.WalkDir = walkDir;
});
}
private class Hashes : IHashes
{
public readonly int AttackSpeed;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 55d43c6c8c8cb9b448b8695696fb9504
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,167 @@
using System;
using Tween;
using Unity.Entities;
using UnityEngine;
using Zenject;
namespace DefaultNamespace
{
[UpdateInGroup(typeof(PresentationSystemGroup)), UpdateBefore(typeof(WeaponFiringSystem))]
public class PlayerCoverSystem : InjectableComponentSystem
{
[Serializable]
public class Settings
{
public AnimationCurve AccuracyLossCurve;
[Range(0, 1)] public float AccuracyLossMultiply;
public float CheckDistance;
public float MaxVaultAngle;
public float MaxVaultFromAngle;
public float MinVaultHeight;
public float Offset;
}
[Inject] private readonly Settings settings;
[Inject] private TweenSystem tweenSystem;
protected override void OnSystemUpdate()
{
Entities.WithAllReadOnly<RigidBody2DData, ActorData>()
.ForEach(
(
Entity entity,
ActorBodyParts parts,
ref ActorCoverRaycastData raycast,
ref ActorWeaponReferenceData weapon,
ref PlayerInput input,
ref Rotation2D rotation,
ref ActorBoundsData bounds) =>
{
var actor = EntityManager.GetComponentData<ActorData>(entity);
var rigidbody = EntityManager.GetComponentData<RigidBody2DData>(entity);
var weaponAccuracy = EntityManager.GetComponentData<WeaponAccuracyData>(weapon.Weapon);
var height = Mathf.Clamp(
raycast.TopHit.y + settings.Offset - parts.WeaponContainer.transform.position.y,
0,
settings.CheckDistance);
var heightPercent = Mathf.Clamp01(height / settings.CheckDistance);
weaponAccuracy.Accuracy *=
Mathf.Clamp01(1 - settings.AccuracyLossCurve.Evaluate(heightPercent) * settings.AccuracyLossMultiply);
var hasCover = raycast.UpDistance + raycast.TopDistance >= 0.1f && raycast.HadTopHit;
var canVault = raycast.Height >= settings.MinVaultHeight &&
raycast.UpDistance + raycast.TopDistance >= bounds.Rect.height &&
!tweenSystem.HasTween(entity) &&
Vector2.Angle(Vector2.up, raycast.TopNormal) <= settings.MaxVaultAngle &&
Vector2.Angle(actor.GroundUp, Vector2.up) <= settings.MaxVaultFromAngle;
var halfWidth = bounds.Rect.width * 0.5f;
var offset = Vector2.right * rotation.Axis * halfWidth;
var topRight = new Vector2(raycast.ForwardHit.x, raycast.TopHit.y);
PostUpdateCommands.KeepData(EntityManager, hasCover, entity, new PlayerCoverData());
PostUpdateCommands.KeepData(EntityManager, canVault, entity, new PlayerVaultData { VaultPoint = topRight });
if (input.Vault && canVault)
{
topRight += offset;
var topLeft = raycast.TopHit;
var bottomRight = new Vector2(raycast.ForwardHit.x, raycast.TopHit.y - raycast.Height) + offset;
var playerPos = rigidbody.Position;
var path = Vector2.Distance(playerPos, bottomRight) >= halfWidth
? new[] { playerPos, bottomRight, topRight, topLeft }
: new[] { bottomRight, topRight, topLeft };
PostUpdateCommands.StartTween(entity, 0.6f, EaseType.easeInOutQuart, TweenFollowPath.Build(path, Space.World));
}
PostUpdateCommands.SetComponent(weapon.Weapon, weaponAccuracy);
});
}
}
[UpdateInGroup(typeof(PresentationSystemGroup)), UpdateBefore(typeof(PlayerWeaponSystem)), UpdateBefore(typeof(ActorIkSystem))]
public class PlayerCoverSystemWeaponAdjust : InjectableComponentSystem
{
[Inject] private readonly PlayerCoverSystem.Settings settings;
protected override void OnSystemUpdate()
{
Entities.ForEach(
(ActorBodyParts parts, ref ActorCoverRaycastData raycast, ref PlayerCoverData coverData) =>
{
var height = Mathf.Clamp(
raycast.TopHit.y + settings.Offset - parts.WeaponContainer.transform.position.y,
0,
settings.CheckDistance);
parts.WeaponContainer.transform.position += new Vector3(0, height, 0);
coverData.WeaponOffset = height;
});
}
}
[UpdateInGroup(typeof(SimulationSystemGroup))]
public class PlayerCoverSystemRaycast : InjectableComponentSystem
{
[Inject] private readonly PlayerCoverSystem.Settings settings;
protected override void OnSystemUpdate()
{
Entities.WithAllReadOnly<ActorBodyParts>()
.WithNone<ActorCoverRaycastData>()
.ForEach(entity => { PostUpdateCommands.AddComponent(entity, new ActorCoverRaycastData()); });
Entities.ForEach(
(ref ActorCoverRaycastData raycast, ref Rotation2D rotation, ref ActorBoundsData bounds) =>
{
var boundsSize = bounds.Rect.size;
var boundsCenter = bounds.Rect.center;
var forward = boundsCenter + Vector2.left * rotation.Axis * 0.5f + Vector2.up * boundsSize.y * 0.5f;
var bottomHit = Physics2D.BoxCast(
forward,
new Vector2(boundsSize.x, 0.05f),
0,
Vector2.down,
boundsSize.y,
LayerMask.GetMask("Ground"));
var forwardHit = Physics2D.BoxCast(
boundsCenter,
boundsSize * 0.9f,
0,
Vector2.left * rotation.Axis,
1,
LayerMask.GetMask("Ground"));
var topHit = Physics2D.BoxCast(
forward,
new Vector2(boundsSize.x, 0.05f),
0,
Vector2.up,
boundsSize.y,
LayerMask.GetMask("Ground"));
var hasBottom = bottomHit.collider != null;
var hasForward = forwardHit.collider != null;
var hitDistance = hasBottom ? bottomHit.distance + 0.05f : boundsSize.y;
var height = Mathf.Max(boundsSize.y - hitDistance, 0);
raycast.Height = height;
raycast.TopHit = hasBottom ? bottomHit.point : forward + Vector2.down * boundsSize.y;
raycast.TopNormal = hasBottom ? bottomHit.normal : Vector2.up;
raycast.HadTopHit = hasBottom;
raycast.TopDistance = hasBottom ? bottomHit.distance : boundsSize.y;
raycast.ForwardDistance = hasForward ? forwardHit.distance : 1;
raycast.ForwardHit = hasForward ? forwardHit.point : boundsCenter + Vector2.left * rotation.Axis;
raycast.ForwardNormal = hasForward ? forwardHit.normal : Vector2.right * rotation.Axis;
raycast.HadForwardHit = hasForward;
raycast.UpDistance = topHit.collider != null ? topHit.distance : boundsSize.y;
});
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7292f583249350144bdce9b1071a6df4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,41 @@
using Events;
using System;
using UnityEngine;
using UnityEngine.AddressableAssets;
using Zenject;
using Entity = Unity.Entities.Entity;
using Hash128 = Unity.Entities.Hash128;
namespace DefaultNamespace
{
public class PlayerDeathSystem : InjectableComponentSystem
{
[Serializable]
public class Settings
{
public AssetReferenceGameObject DeathParticles;
public SoundLibrary DeathSounds;
}
[Inject] private readonly ParticleSystemFactory particleFactory;
[Inject] private readonly Settings settings;
[Inject] private readonly SoundManager soundManager;
protected override void OnSystemUpdate()
{
Entities.ForEach(
(Entity entity, ref PlayerData player, ref ActorData actor, ref RigidBody2DData rigidBody) =>
{
if (actor.Health <= 0)
{
var pos = rigidBody.Position;
particleFactory.Create(new Hash128(settings.DeathParticles.AssetGUID)).Completed += operation =>
operation.Result.GetComponent<ParticleSystem>().Emit(new ParticleSystem.EmitParams { position = pos }, 1);
soundManager.PlayClip(PostUpdateCommands, settings.DeathSounds, rigidBody.Position);
PostUpdateCommands.AddComponent(entity, new EntityDeathEvent());
}
});
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a4494fd3c0723cc43a1236b7f520171e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,69 @@
using System;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
using Zenject;
namespace DefaultNamespace
{
/// <summary>
/// Changes emotion states based on animation triggers.
/// It also swaps the face sprites for each emotion.
/// </summary>
[UpdateInGroup(typeof(PresentationSystemGroup)), UpdateAfter(typeof(PlayerWeaponSystem)), UpdateBefore(typeof(ActorAnimationSystem))]
// Triggers the attack animation trigger
// Resets animation triggers, and we use them
public class PlayerEmotionSystem : InjectableComponentSystem
{
[Serializable]
public class Settings
{
public float EmotionDuration = 1;
[Tooltip("Emotions")] public Sprite NormalEmotion;
public Sprite AngryEmotion;
}
[Inject] private Settings settings;
#region Overrides of InjectableComponentSystem
protected override void OnSystemUpdate()
{
Entities.WithAllReadOnly<ActorBodyParts>()
.ForEach(
(Entity entity, ref ActorAnimationData animationData) =>
{
EntityManager.TryGetComponentObject<ActorBodyParts>(entity, out var actorBodyParts);
if (!actorBodyParts.EmotionRenderer)
{
return;
}
animationData.EmotionTimer = math.saturate(animationData.EmotionTimer - Time.DeltaTime);
if ((animationData.Triggers & AnimationTriggerType.Attack) != 0 || (animationData.Triggers & AnimationTriggerType.Melee) != 0)
{
animationData.Emotion = EmotionType.Angry;
animationData.EmotionTimer = settings.EmotionDuration;
}
if (animationData.EmotionTimer <= 0)
{
animationData.Emotion = EmotionType.Neutral;
}
switch (animationData.Emotion)
{
case EmotionType.Angry:
actorBodyParts.EmotionRenderer.sprite = settings.AngryEmotion;
break;
default:
actorBodyParts.EmotionRenderer.sprite = settings.NormalEmotion;
break;
}
});
}
#endregion
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 331d28c3b2d44a43a692314b74bcd323
timeCreated: 1642631929

View file

@ -0,0 +1,64 @@
using Cinemachine;
using Events;
using Markers;
using System;
using UnityEngine;
using Zenject;
namespace DefaultNamespace
{
public class PlayerLookSystem : InjectableComponentSystem, IInitializable
{
[Serializable]
public class Settings
{
public float GunCameraFollowSmoothing;
public float MinMouseDistance;
}
[Inject] private readonly Camera camera;
[Inject] private readonly CinemachineVirtualCamera followCamera;
[Inject] private readonly PlayerFacade playerFacade;
[Inject] private readonly Settings settings;
private CapsuleCollider2D playerCollider;
public void Initialize()
{
playerCollider = playerFacade.GetComponent<CapsuleCollider2D>();
}
protected override void OnSystemUpdate()
{
var enabledWindowsCount = Entities.WithAllReadOnly<WindowComponentData, EnabledComponentData>().ToEntityQuery().CalculateEntityCount();
Entities.ForEach(
(ref Rotation2D rotation, ref PlayerData player, ref ActorData actor, ref PlayerInput input) =>
{
Vector2 lookPoint = camera.ScreenToWorldPoint(Input.mousePosition);
if (CanAim(lookPoint) && !input.OverUi && enabledWindowsCount <= 0)
{
actor.Aim = lookPoint;
actor.Look = lookPoint;
}
else if (input.OverUi)
{
actor.Look = lookPoint;
}
var oldScrenX = followCamera.GetCinemachineComponent<CinemachineFramingTransposer>().m_ScreenX;
var newScreenX = 0.5f + 0.1f * rotation.Axis;
followCamera.GetCinemachineComponent<CinemachineFramingTransposer>().m_ScreenX = Mathf.MoveTowards(
oldScrenX,
newScreenX,
Time.DeltaTime * settings.GunCameraFollowSmoothing);
});
}
public bool CanAim(Vector2 worldPoint)
{
var mouseDistance = Vector2.Distance(playerCollider.bounds.ClosestPoint(worldPoint), worldPoint);
return !playerCollider.OverlapPoint(worldPoint) && mouseDistance >= settings.MinMouseDistance;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6f6a5c3f34ce5b947881478a63e4d587
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,258 @@
using DefaultNamespace;
using Polycrime;
using System;
using Trive.Core;
using Trive.Mono.Utils;
using Tween;
using Unity.Entities;
using UnityEngine;
using Zenject;
[UpdateInGroup(typeof(SimulationSystemGroup)), UpdateAfter(typeof(PlayerActionMapSystem))]
public class PlayerMoveSystem : InjectableComponentSystem, IInitializable
{
[Serializable]
public class Settings
{
public float FallGravityMultiply = 2.5f;
public float GroundSnapForce;
public float JumpDirForcePercent = 1;
public float JumpHeight;
public ParticleSystem JumpParticles;
public float LowJumpGravityMultiply = 2.5f;
public float MaxAirForce = 1;
public float MaxForce = 1;
public float MaxGroundAngle = 45;
public float MaxGroundSnapDistance;
public float moveForce = 1;
public PIDFloat movePid;
public PIDFloat movePidVertical;
public float ObsticleJumpTime = 0.2f;
public AnimationCurve SlopeMoveForce;
public LayerMask StepAssistMask;
public float StepAssistMaxHeight;
[Tooltip("The maximum angle the player can vault from")] public float VaultFromAngleMax;
public float VaultMaxAngle;
public Vector2 VaultObsicleRange;
}
[Inject] private readonly AudioListener audioListener;
[Inject] private readonly PlayerFacade playerFacade;
[Inject] private readonly Settings settings;
private Transform head;
private float lastDir;
private float lastStepSign;
private float stepTimer;
[Inject] private TweenSystem tweenSystem;
private float DeltaTime => Time.fixedDeltaTime;
public void Initialize()
{
head = playerFacade.FindChildGlobal<Transform>("$Head");
}
protected override void OnSystemUpdate()
{
Entities.WithAllReadOnly<ActorBoundsData, Rotation2D>()
.ForEach(
(
Entity entity,
Rigidbody2D rigidbody,
ref PlayerData player,
ref ActorData actor,
ref AnimatorStateData animationState,
ref PlayerInput input,
ref ActorAnimationData animation) =>
{
var bounds = EntityManager.GetComponentData<ActorBoundsData>(entity);
var rotation = EntityManager.GetComponentData<Rotation2D>(entity);
if (actor.Grounded)
{
player.AirControlAmount = 1;
}
audioListener.transform.position = head.transform.position;
UpdateVelocity(rigidbody, actor, input, animationState, ref animation, rotation, player);
if (Mathf.Abs(input.HorizontalInput) > 0)
{
lastDir = Mathf.Sign(input.HorizontalInput);
}
float snapMultiply = 1;
ManageVaulting(entity, rigidbody, bounds, actor, rotation, ref animation, ref input, ref snapMultiply, ref player);
ManageJumping(ref input, rigidbody, bounds, ref actor, ref animation);
SnapToGround(rigidbody, actor, snapMultiply);
});
}
private void ManageJumping(
ref PlayerInput input,
Rigidbody2D rigidbody,
ActorBoundsData bounds,
ref ActorData actor,
ref ActorAnimationData animation)
{
if (actor.Grounded)
{
if (input.JumpPressed)
{
var boundsSize = bounds.Rect.size;
var boundsCenter = bounds.Rect.center;
var rayStart = boundsCenter + Vector2.up * boundsSize.y * 0.5f;
var hit = Physics2D.CircleCast(rayStart, boundsSize.x * 0.5f, Vector2.up, settings.JumpHeight, settings.StepAssistMask);
var maxJumpHeight = Mathf.Min(settings.JumpHeight, hit.collider != null ? hit.distance + boundsSize.x : settings.JumpHeight);
var jumpVelY = Mathf.Sqrt(0 - 2 * Physics2D.gravity.y * maxJumpHeight);
Vector3 jumpForce = Vector2.up * jumpVelY + new Vector2(input.HorizontalInput, 0) * settings.JumpDirForcePercent * jumpVelY;
rigidbody.AddForce(jumpForce * rigidbody.mass, ForceMode2D.Impulse);
actor.Grounded = false;
settings.JumpParticles.Emit(new ParticleSystem.EmitParams { position = rigidbody.position }, 1);
animation.Triggers |= AnimationTriggerType.Jump;
}
}
}
private float CalculateSlopeSpeed(Vector2 slopeNormal, float input, float rotationAxis)
{
var slotDer = Mathf.Sign(Vector2.SignedAngle(slopeNormal, Vector2.up));
var slopeAngle = Vector2.Angle(slopeNormal, Vector2.up);
//must be looking in the same direction as the input for it to go negative
return settings.SlopeMoveForce.Evaluate(
slopeAngle / settings.MaxGroundAngle * (Mathf.Sign(input) == slotDer ? Mathf.Sign(rotationAxis) != Mathf.Sign(input) ? -1 : 1 : 1));
}
private void UpdateVelocity(
Rigidbody2D rigidbody,
ActorData actor,
PlayerInput input,
AnimatorStateData animationState,
ref ActorAnimationData animation,
Rotation2D rotation,
PlayerData playerData)
{
var slopeSpeedMultiply = CalculateSlopeSpeed(actor.GroundUp, input.HorizontalInput, rotation.Axis);
var walkMultiply = Mathf.Min(Mathf.Abs(input.HorizontalInput), Mathf.Abs(rigidbody.velocity.x));
animation.WalkMultiply = walkMultiply * slopeSpeedMultiply;
rigidbody.gravityScale = actor.Grounded ? 1 :
rigidbody.velocity.y > 0 ? input.Jump ? 1 : settings.LowJumpGravityMultiply : settings.FallGravityMultiply;
var desiredMoveForce = input.HorizontalInput *
settings.moveForce *
(animationState.State.IsTag("Interactive") || animationState.State.IsTag("CanMove") ? 1 : 0);
var force = -Vector2.Perpendicular(actor.GroundUp) * desiredMoveForce * slopeSpeedMultiply;
var groundOrientation = Vector2.SignedAngle(actor.GroundUp, Vector2.up);
var rotatedVelocity = rigidbody.velocity.Rotate(groundOrientation);
var actualLocalForce = rigidbody.velocity.x;
var actualLocalVerticalForce = rigidbody.velocity.y;
var maxForce = Mathf.Lerp(settings.MaxAirForce, settings.MaxForce, actor.Grounded ? 1 : 0) * playerData.AirControlAmount;
var forceDelta = settings.movePid.Update(force.x, actualLocalForce, DeltaTime);
var forceDeltaVertical = settings.movePidVertical.Update(force.y, actualLocalVerticalForce, DeltaTime);
forceDelta = Mathf.Clamp(forceDelta, -maxForce, maxForce);
forceDeltaVertical = Mathf.Clamp(forceDeltaVertical, -settings.MaxForce, settings.MaxForce) *
(actor.GroundDinstance >= 0 ? 1 - Mathf.Clamp01(actor.GroundDinstance / settings.MaxGroundSnapDistance) : 0);
rigidbody.AddForce(Vector2.right * forceDelta);
rigidbody.AddForce(Vector2.up * forceDeltaVertical);
}
private void SnapToGround(Rigidbody2D rigidbody, ActorData actor, float snapMultiply)
{
if (actor.GroundDinstance > 0 && actor.Grounded)
{
var inverseGroundDistance = 1 - Mathf.Clamp01(actor.GroundDinstance / settings.MaxGroundSnapDistance);
rigidbody.AddForce(-actor.GroundUp * settings.GroundSnapForce * snapMultiply);
}
}
private void ManageVaulting(
Entity entity,
Rigidbody2D rigidbody,
ActorBoundsData bounds,
ActorData actor,
Rotation2D rotation,
ref ActorAnimationData animation,
ref PlayerInput playerInput,
ref float snapMultiply,
ref PlayerData playerData)
{
var boundsSize = bounds.Rect.size;
var boundsCenter = bounds.Rect.center;
var floorAxis = Mathf.FloorToInt(Mathf.Abs(playerInput.HorizontalInput));
var axisSign = (int)Mathf.Sign(playerInput.HorizontalInput);
var axisAndLookAreSame = Mathf.Sign(playerInput.HorizontalInput) != rotation.Axis;
var forwardTop = boundsCenter +
Vector2.left * rotation.Axis * boundsSize.x * (axisSign * floorAxis * -rotation.Axis * (axisAndLookAreSame ? 1 : 0)) +
Vector2.up * boundsSize.y * 0.5f;
RaycastHit2D topHit, bottomHit;
topHit = Physics2D.CircleCast(forwardTop, boundsSize.x * 0.5f, Vector2.up, boundsSize.y, settings.StepAssistMask);
bottomHit = Physics2D.CircleCast(
forwardTop,
boundsSize.x * 0.5f,
Vector2.down,
boundsSize.y + settings.VaultObsicleRange.y,
settings.StepAssistMask);
var topDistance = topHit.collider != null ? topHit.distance + boundsSize.x * 0.5f : boundsSize.y;
var bottomDistance = bottomHit.collider != null ? bottomHit.distance + boundsSize.x * 0.5f : boundsSize.y;
var groundAngle = Vector2.Angle(bottomHit.normal, Vector2.up);
var currentAngle = Vector2.Angle(actor.GroundUp, Vector2.up);
var totalSize = topDistance + bottomDistance;
var obsticleHeight = boundsSize.y - Mathf.Min(bottomDistance, boundsSize.y);
var obsticleDepth = Mathf.Max(bottomDistance - boundsSize.y, 0);
//Debug.DrawLine(forwardTop + Vector2.up * Vector2.up, forwardTop + Vector2.down * bottomDistance, Color.red);
Debug.DrawLine(forwardTop + Vector2.down * boundsSize.y, forwardTop + Vector2.down * boundsSize.y + Vector2.up * obsticleHeight, Color.green);
if (groundAngle <= settings.VaultMaxAngle &&
currentAngle <= settings.VaultFromAngleMax &&
totalSize > boundsSize.y &&
!tweenSystem.HasTween(entity))
{
if (obsticleHeight <= settings.StepAssistMaxHeight)
{
rigidbody.AddForce(Vector2.up * obsticleHeight * rigidbody.mass * 2, ForceMode2D.Impulse);
snapMultiply = 0;
}
else if (true)
{
var target = Vector2.zero;
var jumpedFlag = false;
if (obsticleHeight >= settings.VaultObsicleRange.x && obsticleHeight <= settings.VaultObsicleRange.y && actor.Grounded)
{
target = forwardTop + Vector2.down * Mathf.Min(bottomDistance, boundsSize.y);
jumpedFlag = true;
}
if (jumpedFlag)
{
var vel = TrajectoryMath.CalculateVelocityWithHeight(
rigidbody.position,
target,
Mathf.Abs(rigidbody.position.y - target.y) + 0.5f,
settings.FallGravityMultiply);
//var vel = TrajectoryMath.CalculateVelocity(rigidbody.position, target,settings.ObsticleJumpTime, settings.FallGravityMultiply);
var velDelta = vel - rigidbody.velocity;
rigidbody.AddForce(velDelta * rigidbody.mass, ForceMode2D.Impulse);
//PostUpdateCommands.StartTween(entity,0.5f,EaseType.linear,TweenFollowPath.Build(new []{rigidbody.position,rigidbody.position + new Vector2(0,target.y - rigidbody.position.y),target},Space.World));
animation.Triggers |= AnimationTriggerType.JumpObsticle;
}
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ffff4ebe0bd4a144f9487327a951843a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,24 @@
using Events;
using Unity.Entities;
namespace DefaultNamespace
{
public class PlayerQuickActionsSystem : ComponentSystem
{
protected override void OnUpdate()
{
Entities.WithAllReadOnly<Slot>()
.ForEach(
(Entity entity, ref PlayerInput input) =>
{
var inv = EntityManager.GetBuffer<Slot>(entity);
if (input.Heal && inv.Begin().Any(s => s.Type == SlotType.Health) && !EntityManager.HasComponent<ItemUseEventData>(entity))
{
PostUpdateCommands.AddComponent(
entity,
new ItemUseEventData { Inventory = entity, Slot = inv.Begin().IndexOf(e => e.Type == SlotType.Health) });
}
});
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 808342b0f69f2914d860ba12339c1179
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,49 @@
using System;
using UnityEngine;
using Zenject;
namespace DefaultNamespace
{
public class PlayerVitalsSystem : InjectableComponentSystem
{
[Serializable]
public class Settings
{
public float MaxRegenHealth;
public float RegenCooldown;
public AnimationCurve RegenCurve;
public float RegenSpeed;
}
[Inject] private readonly Settings settings;
private float lastPlayerHealth;
protected override void OnSystemUpdate()
{
Entities.ForEach(
(ref PlayerData player, ref ActorData actor) =>
{
player.RegenTimer = Mathf.Max(0, player.RegenTimer - Time.DeltaTime);
if (actor.Health < settings.MaxRegenHealth && actor.Health > 0)
{
if (actor.Health < lastPlayerHealth)
{
player.RegenTimer = settings.RegenCooldown;
}
else if (player.RegenTimer <= 0)
{
actor.Health = Mathf.Min(
settings.MaxRegenHealth,
actor.Health +
Time.DeltaTime *
settings.RegenSpeed *
settings.RegenCurve.Evaluate(Mathf.Clamp01(actor.Health / settings.MaxRegenHealth)));
}
lastPlayerHealth = actor.Health;
}
});
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 88710d1be70ba804c89ecbadead6ddef
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,83 @@
using Items;
using Unity.Entities;
using UnityEngine;
using UnityEngine.AddressableAssets;
namespace DefaultNamespace
{
public class PlayerWeaponSwitcherSystem : AdvancedComponentSystem
{
protected override void OnSystemUpdate()
{
Entities.WithAllReadOnly<Slot>()
.ForEach(
(Entity entity, ActorWeaponPropertiesData weapon, ref ActorWeaponReferenceData weaponReference) =>
{
var inventory = EntityManager.GetBuffer<Slot>(entity);
var weaponEntity = weaponReference.Weapon;
var weaponSlotIndex = inventory.Length - 1;
if (weaponSlotIndex >= 0)
{
var inventoryWeapon = inventory[weaponSlotIndex];
if (!inventoryWeapon.Item.Item.IsValid)
{
RemoveWeapon(entity, weaponEntity);
}
else if (inventoryWeapon.Item.Item != weapon.Id)
{
RemoveWeapon(entity, weaponEntity);
}
}
else
{
RemoveWeapon(entity, weaponEntity);
}
});
Entities.WithAll<Slot>()
.WithNone<ActorWeaponPropertiesData>()
.ForEach(
entity =>
{
var inventory = EntityManager.GetBuffer<Slot>(entity);
var weaponSlotIndex = inventory.Length - 1;
if (weaponSlotIndex >= 0 && inventory[weaponSlotIndex].Item.Item.IsValid)
{
var itemOperation = Addressables.LoadAssetAsync<ItemPrefab>(inventory[weaponSlotIndex].Item.Item.ToString());
if (itemOperation.IsValid() && itemOperation.IsDone && itemOperation.Result is RangedWeaponItem weaponItem)
{
PostUpdateCommands.AddSharedComponent(
entity,
new ActorWeaponPropertiesData { Weapon = weaponItem, Id = inventory[weaponSlotIndex].Item.Item });
}
}
});
}
private void RemoveWeaponComponents(Entity entity, Entity weaponEntity)
{
PostUpdateCommands.RemoveComponent<ActorWeaponPropertiesData>(entity);
PostUpdateActions.Enqueue(
() =>
{
EntityManager.DestroyEntityWithObjects(weaponEntity);
if (EntityManager.HasComponent<Animator>(entity))
{
var animator = EntityManager.GetComponentObject<Animator>(entity);
var overrideController = animator.runtimeAnimatorController as AnimatorOverrideController;
if (overrideController != null)
{
animator.runtimeAnimatorController = overrideController.runtimeAnimatorController;
}
}
});
}
private void RemoveWeapon(Entity entity, Entity weaponEntity)
{
PostUpdateCommands.RemoveComponent<ActorWeaponReferenceData>(entity);
RemoveWeaponComponents(entity, weaponEntity);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4c0681d7883313f4caff5b7794d4e1e6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,137 @@
using Events;
using Markers;
using System;
using Unity.Entities;
using UnityEngine;
using Zenject;
namespace DefaultNamespace
{
[UpdateInGroup(typeof(PresentationSystemGroup)), UpdateAfter(typeof(PlayerActionMapSystem))]
public class PlayerWeaponSystem : InjectableComponentSystem
{
[Serializable]
public class Settings
{
public LayerMask BulletLayerMask;
public LayerMask ProjectileCheckLayerMask;
public float ShotScreenShakeAmount;
}
[Inject] private readonly PlayerFacade playerFacade;
[Inject] private readonly Settings settings;
protected override void OnSystemUpdate()
{
var enabledWindowsCount = Entities.WithAllReadOnly<WindowComponentData, EnabledComponentData>().ToEntityQuery().CalculateEntityCount();
Entities.WithAll<Slot>()
.WithAllReadOnly<ActorWeaponReferenceData, ActorWeaponPropertiesData, ActorGrenadeComponent, AnimatorStateData, PlayerInput>()
.ForEach(
(
Entity entity,
ActorMeleeSharedData meleeShared,
ref PlayerData playerData,
ref ActorAnimationData animation,
ref ActorMeleeData melee,
ref ActorGrenadeData grenadeData) =>
{
var inventory = EntityManager.GetBuffer<Slot>(entity);
var weaponReference = EntityManager.GetComponentData<ActorWeaponReferenceData>(entity);
var weapon = EntityManager.GetSharedComponentData<ActorWeaponPropertiesData>(entity);
var animationState = EntityManager.GetComponentData<AnimatorStateData>(entity);
var input = EntityManager.GetComponentData<PlayerInput>(entity);
var weaponEntity = weaponReference.Weapon;
var grenade = EntityManager.GetComponentObject<ActorGrenadeComponent>(entity);
var weaponAnimationState = EntityManager.GetComponentData<AnimatorStateData>(weaponEntity);
var isInteractiveWeaponAnimation = weaponAnimationState.State.IsTag("Interactive");
var inInteractiveAnimation = animationState.State.IsTag("Interactive");
animation.AttackSpeed = weapon.Weapon.Data.RateOfFire;
if (input.Melee && melee.MeleeTimer <= 0 && inInteractiveAnimation && isInteractiveWeaponAnimation)
{
animation.Triggers |= AnimationTriggerType.Melee;
melee.MeleeTimer = meleeShared.Cooldown;
}
if (inventory.Begin().Any(id => id.Type == SlotType.Grenade) &&
input.Grenade &&
grenadeData.GrenadeTimer <= 0 &&
inInteractiveAnimation &&
isInteractiveWeaponAnimation &&
!EntityManager.HasComponent<ItemUseEventData>(entity))
{
PostUpdateCommands.AddComponent(
entity,
new ItemUseEventData { Inventory = entity, Slot = inventory.Begin().IndexOf(e => e.Type == SlotType.Grenade) });
grenadeData.GrenadeTimer = grenade.Cooldown;
}
if (EntityManager.Exists(weaponEntity))
{
if (EntityManager.TryGetComponentData<WeaponData>(weaponEntity, out var weaponData))
{
if ((input.Reload || weaponData.ClipAmmo <= 0) &&
weaponData.ReloadTimer <= 0 &&
!EntityManager.HasComponent<ReloadEvent>(weaponEntity) &&
inInteractiveAnimation &&
isInteractiveWeaponAnimation &&
weaponData.Ammo > 0 &&
weaponData.ClipAmmo < weapon.Weapon.Data.ClipCapacity)
{
PostUpdateCommands.AddComponent(weaponEntity, new ReloadEvent());
}
if (EntityManager.HasComponent<WeaponPartsData>(weaponEntity))
{
var weaponParts = EntityManager.GetSharedComponentData<WeaponPartsData>(weaponEntity);
var animator = EntityManager.GetComponentObject<Animator>(weaponEntity);
if (CanFire(weaponParts.Barrel.position) &&
inInteractiveAnimation &&
enabledWindowsCount <= 0 &&
!input.OverUi &&
(weapon.Weapon.Data.Automatic ? input.Attacking : input.AttackPressed) &&
weaponData.FireTimer <= 0 &&
weaponData.ClipAmmo > 0 &&
weaponData.ReloadTimer <= 0)
{
PostUpdateCommands.PostEntityEvent(
EntityManager,
weaponEntity,
new FireWeaponEvent
{
LayerMask = settings.BulletLayerMask, ScreenShake = weapon.Weapon.Data.ScreenShake
});
animation.Triggers |= AnimationTriggerType.Attack;
if (animator)
{
animator.SetBool("Firing", true);
}
if (EntityManager.TryGetComponentData<ActorWeaponAccuracyData>(entity, out var accuracy))
{
accuracy.Accuracy += weapon.Weapon.Data.AccuracyDegrade;
accuracy.AccuracyAttackTime += weapon.Weapon.Data.AccuracyAttackTime;
accuracy.AccuracyRegainSpeed = weapon.Weapon.Data.AccuracyRegainSpeed;
EntityManager.SetComponentData(entity, accuracy);
}
}
else if (weaponData.FireTimer <= 0 && animator != null && animator.isActiveAndEnabled)
{
animator.SetBool("Firing", false);
}
}
}
}
});
}
public bool CanFire(Vector2 pos)
{
return !Physics2D.OverlapCircle(pos, 0.05f, settings.ProjectileCheckLayerMask);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d87ffa8d5902b754a808764f801a728c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: