basically the whole game
This commit is contained in:
parent
949135cecb
commit
96dcfa9064
315 changed files with 34386 additions and 396 deletions
|
|
@ -13,12 +13,24 @@ public class Ability : MonoBehaviour
|
|||
public Transform origin;
|
||||
public Vector3 direction;
|
||||
|
||||
public bool TryAbility()
|
||||
[Header("SFX")]
|
||||
[SerializeField] protected AudioClip abilitySound;
|
||||
[SerializeField] protected float volume = 1f;
|
||||
|
||||
[Header("Animation")]
|
||||
[SerializeField] private Animator animator;
|
||||
[SerializeField] private string attackTrigger;
|
||||
|
||||
public virtual bool TryAbility()
|
||||
{
|
||||
if (currentCooldown <= 0)
|
||||
{
|
||||
currentCooldown = cooldown;
|
||||
AbilityEffects();
|
||||
if (animator)
|
||||
{
|
||||
animator.SetTrigger(attackTrigger);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
using UnityEngine;
|
||||
|
||||
public class BossMovesToARandomPositionForNoReason : EnemyAbility
|
||||
{
|
||||
//i hope you like the script name
|
||||
//because the bosses in touhou do this
|
||||
//anyways
|
||||
[SerializeField] private Enemy thisEnemy;
|
||||
protected override void AbilityEffects()
|
||||
{
|
||||
StopCoroutine(thisEnemy.currentMovementRoutine);
|
||||
Vector3 newPosition = WaveManager.instance.GetRandomEnemyPoint();
|
||||
thisEnemy.originalPosition = newPosition;
|
||||
StartCoroutine(thisEnemy.MoveToPosition(thisEnemy.transform.position,
|
||||
newPosition, thisEnemy.moveSpeed));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: da4b31636e5bcca7195f27d578e71ebb
|
||||
104
Assets/Scripts/Abilities/CirnoFreezeDeflect.cs
Normal file
104
Assets/Scripts/Abilities/CirnoFreezeDeflect.cs
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
using System.Collections.Generic;
|
||||
using Core.Extensions;
|
||||
using UnityEngine;
|
||||
|
||||
public class CirnoFreezeDeflect : EnemyAbility
|
||||
{
|
||||
[Header("Direction")]
|
||||
private Vector3 playerPos;
|
||||
[Header("Deflection")]
|
||||
[SerializeField] private float deflectionSpeed;
|
||||
[SerializeField] private float deflectionSpeedVariance;
|
||||
[SerializeField] private float deflectionAngleMin = -48;
|
||||
[SerializeField] private float deflectionAngleMax = 90;
|
||||
public List<Projectile> projectilesInRange = new();
|
||||
public List<Projectile> projectilesAffected = new();
|
||||
[SerializeField] private float deflectionDelay;
|
||||
private float currentDelay;
|
||||
[Header("Effects")]
|
||||
[SerializeField] private ParticleSystem deflectionParticles;
|
||||
[SerializeField] private AudioClip deflectionSound;
|
||||
[SerializeField] private float sweepDissipationTime;
|
||||
private float currentDissipationTime;
|
||||
[SerializeField] private GameObject swordSweepEffect;
|
||||
[SerializeField] private Color freezeColor;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
playerPos = WaveManager.instance.GetRandomPlayerPoint();
|
||||
}
|
||||
|
||||
protected override void AbilityEffects()
|
||||
{
|
||||
projectilesAffected = projectilesInRange;
|
||||
foreach (Projectile projectile in projectilesAffected.ToArray())
|
||||
{
|
||||
if (!projectile)
|
||||
{
|
||||
projectilesInRange.Remove(projectile);
|
||||
continue;
|
||||
}
|
||||
|
||||
projectile.sprite.color = freezeColor;
|
||||
projectile.speed = 0;
|
||||
}
|
||||
currentDelay = deflectionDelay;
|
||||
playerPos = WaveManager.instance.GetRandomPlayerPoint();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
transform.Lookat2D(playerPos);
|
||||
if (currentDelay > 0)
|
||||
{
|
||||
currentDelay -= Time.deltaTime;
|
||||
if (currentDelay <= 0)
|
||||
{
|
||||
DeflectProjectiles();
|
||||
currentDissipationTime = sweepDissipationTime;
|
||||
swordSweepEffect.SetActive(true);
|
||||
}
|
||||
}
|
||||
if (currentDissipationTime > 0)
|
||||
{
|
||||
currentDissipationTime -= Time.deltaTime;
|
||||
if (currentDissipationTime <= 0)
|
||||
{
|
||||
swordSweepEffect.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void DeflectProjectiles()
|
||||
{
|
||||
GameManager.instance.deflections += projectilesInRange.Count;
|
||||
foreach (Projectile projectile in projectilesAffected.ToArray())
|
||||
{
|
||||
if (!projectile)
|
||||
{
|
||||
projectilesAffected.Remove(projectile);
|
||||
continue;
|
||||
}
|
||||
projectile.transform.eulerAngles = new Vector3(0, 0, Random.Range(deflectionAngleMin, deflectionAngleMax));
|
||||
projectile.direction = projectile.transform.right;
|
||||
projectile.tag = tag;
|
||||
projectile.speed = deflectionSpeed + Random.Range(-deflectionSpeedVariance, deflectionSpeedVariance);
|
||||
projectile.Deflected();
|
||||
Instantiate(deflectionParticles, projectile.transform);
|
||||
}
|
||||
projectilesAffected.Clear();
|
||||
WaveManager.instance.audioSource.PlayOneShot(deflectionSound, volume);
|
||||
}
|
||||
|
||||
private void OnTriggerEnter2D(Collider2D other)
|
||||
{
|
||||
if (!other.CompareTag(tag))
|
||||
{
|
||||
if (other.TryGetComponent(out Projectile isProjectile) && isProjectile.deflectable)
|
||||
{
|
||||
projectilesInRange.Add(isProjectile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Abilities/CirnoFreezeDeflect.cs.meta
Normal file
2
Assets/Scripts/Abilities/CirnoFreezeDeflect.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9e06f35db4bdec1eb8b8b6b92a9d463c
|
||||
|
|
@ -3,9 +3,19 @@ using UnityEngine;
|
|||
public class EnemyAbility : Ability
|
||||
{
|
||||
[SerializeField] private float cooldownDelta;
|
||||
void Start()
|
||||
[SerializeField] private bool willLookAtPlayer;
|
||||
protected virtual void Start()
|
||||
{
|
||||
cooldown += Random.Range(-cooldownDelta, cooldownDelta);
|
||||
currentCooldown = Random.Range(0, cooldown);
|
||||
}
|
||||
|
||||
public override bool TryAbility()
|
||||
{
|
||||
if (willLookAtPlayer)
|
||||
{
|
||||
direction = WaveManager.instance.GetRandomPlayerPoint();
|
||||
}
|
||||
return base.TryAbility();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
98
Assets/Scripts/Abilities/EnemyBulletPattern.cs
Normal file
98
Assets/Scripts/Abilities/EnemyBulletPattern.cs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Core.Extensions;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
public class EnemyBulletPattern : EnemyAbility
|
||||
{
|
||||
[Serializable]
|
||||
public class ProjectileDirection
|
||||
{
|
||||
public Projectile projectile;
|
||||
public Transform direction;
|
||||
public float timing;
|
||||
public int amount;
|
||||
public float burstTiming;
|
||||
public float projectileSpeed;
|
||||
public bool aimedShot;
|
||||
}
|
||||
|
||||
[SerializeField] protected ProjectileDirection[] projectileDirections;
|
||||
[SerializeField] private bool randomAim;
|
||||
|
||||
protected override void AbilityEffects()
|
||||
{
|
||||
base.AbilityEffects();
|
||||
transform.Lookat2D(direction);
|
||||
if (randomAim)
|
||||
{
|
||||
transform.eulerAngles = new Vector3(0, 0, Random.Range(0, 360f));
|
||||
}
|
||||
foreach (ProjectileDirection projectileDirection in projectileDirections)
|
||||
{
|
||||
if (projectileDirection.timing <= 0 && projectileDirection.amount <= 1)
|
||||
{
|
||||
ShootProjectile(projectileDirection.projectile, projectileDirection.direction.position, projectileDirection.projectileSpeed, projectileDirection.aimedShot);
|
||||
}
|
||||
else if (projectileDirection.amount > 1)
|
||||
{
|
||||
StartCoroutine(BurstFire(projectileDirection, projectileDirection.amount,
|
||||
projectileDirection.burstTiming));
|
||||
}
|
||||
else
|
||||
{
|
||||
StartCoroutine(DelayedShot(projectileDirection, projectileDirection.timing));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ShootProjectile(Projectile projectile, Vector3 location, float speed, bool aimed)
|
||||
{
|
||||
Projectile newProjectile = Instantiate(projectile, origin.position, Quaternion.identity);
|
||||
Vector3 projectileDirection = location;
|
||||
if (aimed)
|
||||
{
|
||||
projectileDirection = WaveManager.instance.GetRandomPlayerPoint();
|
||||
}
|
||||
newProjectile.transform.Lookat2D(projectileDirection);
|
||||
newProjectile.damage = power;
|
||||
newProjectile.tag = tag;
|
||||
if (speed > 0f)
|
||||
{
|
||||
newProjectile.speed = speed;
|
||||
}
|
||||
}
|
||||
private IEnumerator BurstFire(ProjectileDirection projectile, int burstCount, float burstDelay)
|
||||
{
|
||||
int currentCount = 0;
|
||||
while (currentCount < burstCount)
|
||||
{
|
||||
ShootProjectile(projectile.projectile, projectile.direction.position, projectile.projectileSpeed, projectile.aimedShot);
|
||||
currentCount++;
|
||||
yield return new WaitForSeconds(burstDelay);
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
|
||||
private IEnumerator DelayedShot(ProjectileDirection projectile, float delay)
|
||||
{
|
||||
float currentDelayTiming = 0f;
|
||||
while (currentDelayTiming < delay)
|
||||
{
|
||||
currentDelayTiming += Time.deltaTime;
|
||||
if (currentDelayTiming > delay)
|
||||
{
|
||||
if (projectile.amount > 1)
|
||||
{
|
||||
StartCoroutine(BurstFire(projectile, projectile.amount, projectile.burstTiming));
|
||||
}
|
||||
else
|
||||
{
|
||||
ShootProjectile(projectile.projectile, projectile.direction.position, projectile.projectileSpeed, projectile.aimedShot);
|
||||
}
|
||||
}
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Abilities/EnemyBulletPattern.cs.meta
Normal file
2
Assets/Scripts/Abilities/EnemyBulletPattern.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c037b51b973541048a47ffa9cd8f01c0
|
||||
28
Assets/Scripts/Abilities/EnemyBurstFire.cs
Normal file
28
Assets/Scripts/Abilities/EnemyBurstFire.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
public class EnemyBurstFire : EnemyBulletPattern
|
||||
{
|
||||
[SerializeField] private int burstCount;
|
||||
[SerializeField] private float burstDelay;
|
||||
|
||||
protected override void AbilityEffects()
|
||||
{
|
||||
foreach (ProjectileDirection projectile in projectileDirections)
|
||||
{
|
||||
StartCoroutine(BurstFire(projectile));
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator BurstFire(ProjectileDirection moveDirection)
|
||||
{
|
||||
int currentCount = 0;
|
||||
while (currentCount < burstCount)
|
||||
{
|
||||
//ShootProjectile(moveDirection.projectile, direction);
|
||||
currentCount++;
|
||||
yield return new WaitForSeconds(burstDelay);
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Abilities/EnemyBurstFire.cs.meta
Normal file
2
Assets/Scripts/Abilities/EnemyBurstFire.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 72297b32aef434ec4bc31531226ecf79
|
||||
58
Assets/Scripts/Abilities/EnemyTackle.cs
Normal file
58
Assets/Scripts/Abilities/EnemyTackle.cs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
using UnityEngine;
|
||||
|
||||
public class EnemyTackle : EnemyAbility
|
||||
{
|
||||
private Vector3 originalPosition;
|
||||
private Vector3 movePosition;
|
||||
[SerializeField] private Enemy thisEnemy;
|
||||
public float distanceToReturn;
|
||||
public float distanceToDamage;
|
||||
private bool isCloseToPlayer;
|
||||
private bool returning;
|
||||
[Header("Speeds")]
|
||||
[SerializeField] private float tackleSpeed;
|
||||
[SerializeField] private float returnSpeed;
|
||||
|
||||
protected override void AbilityEffects()
|
||||
{
|
||||
base.AbilityEffects();
|
||||
returning = false;
|
||||
thisEnemy.onTakeDamage += ReturnToPosition;
|
||||
originalPosition = transform.position;
|
||||
movePosition = WaveManager.instance.GetRandomPlayerPoint();
|
||||
thisEnemy.isStalled = true;
|
||||
thisEnemy.preventWobble = true;
|
||||
StopCoroutine(thisEnemy.currentMovementRoutine);
|
||||
thisEnemy.currentMovementRoutine = StartCoroutine(thisEnemy.MoveToPosition(originalPosition, movePosition, tackleSpeed));
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
if (!returning)
|
||||
{
|
||||
if (Vector3.Distance(transform.position, movePosition) < distanceToReturn && !isCloseToPlayer)
|
||||
{
|
||||
isCloseToPlayer = true;
|
||||
}
|
||||
else if (isCloseToPlayer && Vector3.Distance(transform.position, movePosition) < distanceToDamage)
|
||||
{
|
||||
WaveManager.instance.player.TakeDamage(power);
|
||||
ReturnToPosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ReturnToPosition()
|
||||
{
|
||||
thisEnemy.onTakeDamage -= ReturnToPosition;
|
||||
returning = true;
|
||||
if (thisEnemy.currentMovementRoutine != null)
|
||||
{
|
||||
StopCoroutine(thisEnemy.currentMovementRoutine);
|
||||
}
|
||||
thisEnemy.preventWobble = false;
|
||||
thisEnemy.isStalled = true;
|
||||
thisEnemy.currentMovementRoutine = StartCoroutine(thisEnemy.MoveToPosition(transform.position, originalPosition, returnSpeed));
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Abilities/EnemyTackle.cs.meta
Normal file
2
Assets/Scripts/Abilities/EnemyTackle.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 089b592119ba967b4a9972a273c9f625
|
||||
5
Assets/Scripts/Abilities/PlayerAbility.cs
Normal file
5
Assets/Scripts/Abilities/PlayerAbility.cs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
using UnityEngine;
|
||||
|
||||
public class PlayerAbility : Ability
|
||||
{
|
||||
}
|
||||
2
Assets/Scripts/Abilities/PlayerAbility.cs.meta
Normal file
2
Assets/Scripts/Abilities/PlayerAbility.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a5ff6f41c57bf3c338e65eda7d30a2b8
|
||||
|
|
@ -16,6 +16,8 @@ public class ReisenShoot : Ability
|
|||
[SerializeField] private float maxChargeTime;
|
||||
[SerializeField] private float chargeCooldown;
|
||||
private float currentChargeCooldown;
|
||||
[Header("Effects")]
|
||||
[SerializeField] private Transform chargeMeter;
|
||||
protected override void AbilityEffects()
|
||||
{
|
||||
if (currentChargeCooldown > 0)
|
||||
|
|
@ -24,17 +26,20 @@ public class ReisenShoot : Ability
|
|||
}
|
||||
else
|
||||
{
|
||||
isCharging = true;
|
||||
currentMouseHoldTime = mouseHoldTime;
|
||||
}
|
||||
}
|
||||
|
||||
private void ShootBullet(Projectile projectileToShoot, int damage)
|
||||
{
|
||||
WaveManager.instance.audioSource.PlayOneShot(projectileToShoot.projectileShootSFX, projectileToShoot.volume);
|
||||
direction = cam.ScreenToWorldPoint(Input.mousePosition);
|
||||
Projectile newProjectile = Instantiate(projectileToShoot, origin.position, Quaternion.identity);
|
||||
newProjectile.transform.Lookat2D(direction);
|
||||
newProjectile.damage = damage;
|
||||
newProjectile.tag = tag;
|
||||
newProjectile.playerBullet = true;
|
||||
GameManager.instance.projectilesShot++; //i shouldn't be directly modifying the variable but i don't actually care
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
|
|
@ -43,8 +48,9 @@ public class ReisenShoot : Ability
|
|||
if (currentMouseHoldTime >= 0)
|
||||
{
|
||||
currentMouseHoldTime -= Time.deltaTime;
|
||||
if (currentMouseHoldTime <= 0 && Input.GetMouseButton(1) && currentChargeTime <= 0)
|
||||
if (currentMouseHoldTime <= 0 && Input.GetMouseButton(0) && currentChargeTime <= 0)
|
||||
{
|
||||
currentChargeTime += mouseHoldTime;
|
||||
isCharging = true;
|
||||
}
|
||||
else if (Input.GetMouseButtonUp(0))
|
||||
|
|
@ -55,12 +61,13 @@ public class ReisenShoot : Ability
|
|||
if (isCharging && Input.GetMouseButton(0)) //this code REEKS
|
||||
{
|
||||
currentChargeTime += Time.deltaTime;
|
||||
chargeMeter.localScale = new Vector3(Math.Clamp(currentChargeTime, 0, maxChargeTime)/maxChargeTime, 1f, 1f);
|
||||
}
|
||||
else if (isCharging && Input.GetMouseButtonUp(0))
|
||||
else if (currentChargeTime > 0 && isCharging && Input.GetMouseButtonUp(0))
|
||||
{
|
||||
Debug.Log("here");
|
||||
currentChargeTime = 0;
|
||||
ShootBullet(chargedProjectile, power * (int)Math.Clamp(currentChargeTime, 0, maxChargeTime));
|
||||
currentChargeTime = 0;
|
||||
chargeMeter.localScale = new Vector3(0f, 1f, 1f);
|
||||
currentChargeCooldown = chargeCooldown;
|
||||
isCharging = false;
|
||||
}
|
||||
|
|
@ -69,6 +76,6 @@ public class ReisenShoot : Ability
|
|||
{
|
||||
currentChargeCooldown -= Time.deltaTime;
|
||||
}
|
||||
Debug.Log(currentChargeTime);
|
||||
//Debug.Log(currentChargeTime);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
Assets/Scripts/Abilities/SpawnSummon.cs
Normal file
16
Assets/Scripts/Abilities/SpawnSummon.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using UnityEngine;
|
||||
|
||||
public class SpawnSummon : EnemyAbility
|
||||
{
|
||||
[SerializeField] private int amount;
|
||||
[SerializeField] private int amountVariance;
|
||||
[SerializeField] private Enemy summon;
|
||||
protected override void AbilityEffects()
|
||||
{
|
||||
int selectedAmount = amount + Random.Range(-amountVariance, amountVariance);
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
WaveManager.instance.SpawnEnemy(summon);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Abilities/SpawnSummon.cs.meta
Normal file
2
Assets/Scripts/Abilities/SpawnSummon.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 17a599629000237739758466652c275f
|
||||
|
|
@ -1,16 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity.Mathematics;
|
||||
using Core.Extensions;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
public class YoumuDeflect : Ability
|
||||
{
|
||||
[SerializeField] private Camera cam;
|
||||
private List<Projectile> projectilesInRange = new();
|
||||
public float deflectionAngleMin = -48;
|
||||
public float deflectionAngleMax = 90;
|
||||
[Header("Deflection")]
|
||||
[SerializeField] private float deflectionSpeed;
|
||||
[SerializeField] private float deflectionSpeedVariance;
|
||||
[SerializeField] private float deflectionAngleMin = -48;
|
||||
[SerializeField] private float deflectionAngleMax = 90;
|
||||
[SerializeField] private Projectile chargeProjectile;
|
||||
[SerializeField] private float destructionChance;
|
||||
|
||||
[Header("Entity Detection")]
|
||||
[SerializeField] private float detectionRadius;
|
||||
[SerializeField] private LayerMask entityLayer;
|
||||
|
||||
[Header("SlashCharge")]
|
||||
[SerializeField] private float mouseHoldTime;
|
||||
private float currentMouseHoldTime;
|
||||
|
|
@ -20,12 +30,15 @@ public class YoumuDeflect : Ability
|
|||
[SerializeField] private float chargeCooldown;
|
||||
private float currentChargeCooldown;
|
||||
private float currentUnleashedChargeTime;
|
||||
[Header("Charge Effects")]
|
||||
[SerializeField] private AudioClip chargeSlashSFX;
|
||||
[SerializeField] private float chargeVolume = 1f;
|
||||
[SerializeField] private Transform chargeMeter;
|
||||
[Header("Effects")]
|
||||
[SerializeField] private ParticleSystem deflectionParticles;
|
||||
[SerializeField] private GameObject swordSweepEffect;
|
||||
[SerializeField] private GameObject chargeSweepEffect;
|
||||
private float currentDissipationTime = 0f;
|
||||
[SerializeField] private float dissipationTime;
|
||||
[SerializeField] private AudioClip noHitSlashSFX;
|
||||
[SerializeField] private float noHitVolume = 1f;
|
||||
|
||||
|
||||
protected override void AbilityEffects()
|
||||
|
|
@ -38,20 +51,28 @@ public class YoumuDeflect : Ability
|
|||
else
|
||||
{
|
||||
currentMouseHoldTime = mouseHoldTime;
|
||||
currentChargeTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void RegularDeflection()
|
||||
{
|
||||
//Debug.Log("Regular Deflection");
|
||||
swordSweepEffect.gameObject.SetActive(true);
|
||||
currentDissipationTime = dissipationTime;
|
||||
DeflectProjectiles();
|
||||
if (projectilesInRange.Count > 0)
|
||||
{
|
||||
DeflectProjectiles();
|
||||
}
|
||||
else
|
||||
{
|
||||
WaveManager.instance.audioSource.PlayOneShot(noHitSlashSFX, noHitVolume);
|
||||
}
|
||||
foreach (Enemy enemy in DetectEnemies())
|
||||
{
|
||||
enemy.TakeDamage(power);
|
||||
}
|
||||
}
|
||||
|
||||
private void DeflectProjectiles()
|
||||
{
|
||||
GameManager.instance.deflections += projectilesInRange.Count;
|
||||
foreach (Projectile projectile in projectilesInRange.ToList())
|
||||
{
|
||||
if (!projectile)
|
||||
|
|
@ -62,17 +83,28 @@ public class YoumuDeflect : Ability
|
|||
projectile.transform.eulerAngles = new Vector3(0, 0, Random.Range(deflectionAngleMin, deflectionAngleMax));
|
||||
projectile.direction = projectile.transform.right;
|
||||
projectile.tag = tag;
|
||||
projectile.speed = deflectionSpeed + Random.Range(-deflectionSpeedVariance, deflectionSpeedVariance);
|
||||
ParticleSystem newParticles = Instantiate(deflectionParticles, projectile.transform);
|
||||
projectile.Deflected();
|
||||
float destructionRoll = Random.Range(0f, 1f);
|
||||
if (destructionRoll < destructionChance)
|
||||
{
|
||||
Destroy(projectile.gameObject);
|
||||
}
|
||||
projectilesInRange.Remove(projectile);
|
||||
}
|
||||
WaveManager.instance.audioSource.PlayOneShot(abilitySound, volume);
|
||||
}
|
||||
|
||||
|
||||
private void OnTriggerEnter2D(Collider2D other)
|
||||
{
|
||||
if (!other.CompareTag(tag) && other.TryGetComponent(out Projectile isProjectile))
|
||||
if (!other.CompareTag(tag))
|
||||
{
|
||||
projectilesInRange.Add(isProjectile);
|
||||
if (other.TryGetComponent(out Projectile isProjectile) && isProjectile.deflectable)
|
||||
{
|
||||
projectilesInRange.Add(isProjectile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,21 +112,22 @@ public class YoumuDeflect : Ability
|
|||
{
|
||||
if (!other.CompareTag(tag) && other.TryGetComponent(out Projectile isProjectile) && projectilesInRange.Contains(isProjectile))
|
||||
{
|
||||
projectilesInRange.Add(isProjectile);
|
||||
projectilesInRange.Remove(isProjectile);
|
||||
}
|
||||
}
|
||||
|
||||
private void ShootBullet(Projectile projectileToShoot, int damage)
|
||||
{
|
||||
Debug.Log(damage);
|
||||
direction = cam.ScreenToWorldPoint(Input.mousePosition);
|
||||
Projectile newProjectile = Instantiate(projectileToShoot, origin.position, Quaternion.identity);
|
||||
newProjectile.transform.Lookat2D(direction);
|
||||
newProjectile.damage = damage;
|
||||
newProjectile.tag = tag;
|
||||
newProjectile.playerBullet = true;
|
||||
}
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
if (currentDissipationTime > 0)
|
||||
{
|
||||
currentDissipationTime -= Time.deltaTime;
|
||||
if (currentDissipationTime <= 0)
|
||||
{
|
||||
swordSweepEffect.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentMouseHoldTime >= 0)
|
||||
{
|
||||
|
|
@ -102,6 +135,7 @@ public class YoumuDeflect : Ability
|
|||
if (currentMouseHoldTime <= 0 && Input.GetMouseButton(1) && currentChargeTime <= 0)
|
||||
{
|
||||
isCharging = true;
|
||||
currentChargeTime += mouseHoldTime;
|
||||
}
|
||||
else if (Input.GetMouseButtonUp(1))
|
||||
{
|
||||
|
|
@ -111,33 +145,36 @@ public class YoumuDeflect : Ability
|
|||
if (isCharging && Input.GetMouseButton(1)) //this code REEKS
|
||||
{
|
||||
currentChargeTime += Time.deltaTime;
|
||||
chargeMeter.localScale = new Vector3(Math.Clamp(currentChargeTime, 0, maxChargeTime)/maxChargeTime, 1f, 1f);
|
||||
}
|
||||
else if (isCharging && Input.GetMouseButtonUp(1))
|
||||
{
|
||||
Debug.Log("here");
|
||||
chargeSweepEffect.SetActive(true);
|
||||
currentUnleashedChargeTime = Math.Clamp(currentChargeTime, 0, maxChargeTime) * 2;
|
||||
ShootBullet(chargeProjectile, power * (int)Math.Clamp(currentChargeTime, 0, maxChargeTime));
|
||||
currentChargeTime = 0;
|
||||
WaveManager.instance.audioSource.PlayOneShot(chargeSlashSFX, chargeVolume);
|
||||
currentChargeCooldown = chargeCooldown;
|
||||
isCharging = false;
|
||||
chargeMeter.localScale = new Vector3(0f, 1f, 1f);
|
||||
}
|
||||
else if (currentUnleashedChargeTime > 0)
|
||||
{
|
||||
currentUnleashedChargeTime -= Time.deltaTime;
|
||||
if (currentUnleashedChargeTime < 0)
|
||||
{
|
||||
chargeSweepEffect.SetActive(false);
|
||||
}
|
||||
|
||||
if (projectilesInRange.Count > 0)
|
||||
{
|
||||
DeflectProjectiles();
|
||||
}
|
||||
}
|
||||
|
||||
if (currentChargeCooldown > 0)
|
||||
{
|
||||
currentChargeCooldown -= Time.deltaTime;
|
||||
}
|
||||
Debug.Log(currentChargeTime);
|
||||
//Debug.Log(currentChargeTime);
|
||||
}
|
||||
|
||||
private Enemy[] DetectEnemies()
|
||||
{
|
||||
Collider2D[] entitiesFound = Physics2D.OverlapCircleAll(transform.position, detectionRadius, entityLayer);
|
||||
List<Enemy> enemiesFound = new();
|
||||
foreach (Collider2D foundEntity in entitiesFound)
|
||||
{
|
||||
if (!foundEntity.CompareTag(tag) && foundEntity.TryGetComponent(out Enemy isEnemy))
|
||||
{
|
||||
enemiesFound.Add(isEnemy);
|
||||
}
|
||||
}
|
||||
return enemiesFound.ToArray();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
58
Assets/Scripts/CutsceneManager.cs
Normal file
58
Assets/Scripts/CutsceneManager.cs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class CutsceneManager : MonoBehaviour
|
||||
{
|
||||
[Header("Status")]
|
||||
public DialogueScript scriptToShow;
|
||||
public int currentText;
|
||||
[Header("UI")]
|
||||
public TextMeshProUGUI nameText;
|
||||
public TextMeshProUGUI dialogueText;
|
||||
public Image sceneImage;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
StartCutscene(LevelSwitcher.instance.currentScript);
|
||||
}
|
||||
|
||||
public void StartCutscene(DialogueScript newDialogue)
|
||||
{
|
||||
currentText = 0;
|
||||
scriptToShow = newDialogue;
|
||||
DialogueScript.Dialogue currentDialogue = scriptToShow.dialogueList[currentText];
|
||||
nameText.text = currentDialogue.character.name;
|
||||
sceneImage.sprite = currentDialogue.cutsceneImage;
|
||||
dialogueText.text = currentDialogue.text;
|
||||
dialogueText.color = currentDialogue.character.textColor; //probably should make current dialogue a variable lol
|
||||
}
|
||||
|
||||
public void ContinueDialogue()
|
||||
{
|
||||
currentText++;
|
||||
if (currentText >= scriptToShow.dialogueList.Length)
|
||||
{
|
||||
EndDialogue();
|
||||
return;
|
||||
}
|
||||
DialogueScript.Dialogue currentDialogue = scriptToShow.dialogueList[currentText];
|
||||
nameText.text = currentDialogue.character.characterName;
|
||||
sceneImage.sprite = currentDialogue.cutsceneImage;
|
||||
dialogueText.text = currentDialogue.text;
|
||||
}
|
||||
|
||||
public void EndDialogue()
|
||||
{
|
||||
LevelSwitcher.instance.SwitchLevel(scriptToShow.nextScene);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
ContinueDialogue();
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/CutsceneManager.cs.meta
Normal file
2
Assets/Scripts/CutsceneManager.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 246bf6c93c7547c9c94493ab15f0b124
|
||||
8
Assets/Scripts/Dialogue.meta
Normal file
8
Assets/Scripts/Dialogue.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6722406d19757ab7f8f5bbf9d1b16735
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
16
Assets/Scripts/Dialogue/DialogueCharacter.cs
Normal file
16
Assets/Scripts/Dialogue/DialogueCharacter.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using UnityEngine;
|
||||
|
||||
[CreateAssetMenu(fileName = "New Dialogue Character", menuName = "Dialogue/Character")]
|
||||
public class DialogueCharacter : ScriptableObject
|
||||
{
|
||||
public string characterName;
|
||||
public Sprite portrait;
|
||||
public Color textColor;
|
||||
public enum Character
|
||||
{
|
||||
Reisen,
|
||||
Youmu,
|
||||
Enemy
|
||||
}
|
||||
public Character thisCharacter;
|
||||
}
|
||||
2
Assets/Scripts/Dialogue/DialogueCharacter.cs.meta
Normal file
2
Assets/Scripts/Dialogue/DialogueCharacter.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 43267f4230b9e2addaad32ec450743a5
|
||||
120
Assets/Scripts/Dialogue/DialogueManager.cs
Normal file
120
Assets/Scripts/Dialogue/DialogueManager.cs
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
using System;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class DialogueManager : MonoBehaviour
|
||||
{
|
||||
#region Statication
|
||||
|
||||
public static DialogueManager instance;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (instance != null && instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
instance = this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
[Header("Status")]
|
||||
public DialogueScript scriptToShow;
|
||||
public int currentText;
|
||||
public bool dialogueActive;
|
||||
[Header("UI")]
|
||||
[SerializeField] private GameObject dialogueUI;
|
||||
[SerializeField] private Transform bossSpeechBubble;
|
||||
[SerializeField] private Vector3 offset;
|
||||
[SerializeField] private TextMeshProUGUI bossText;
|
||||
[SerializeField] private GameObject youmuSpeechBubble;
|
||||
[SerializeField] private TextMeshProUGUI youmuText;
|
||||
[SerializeField] private GameObject reisenSpeechBubble; //have to change the dialogue for this but it's probably fine
|
||||
[SerializeField] private TextMeshProUGUI reisenText;
|
||||
[Header("Animation")]
|
||||
[SerializeField] private Animator reisenAnimator;
|
||||
[SerializeField] private Animator youmuAnimator;
|
||||
[SerializeField] private string switchToDialogueTrigger;
|
||||
[SerializeField] private string switchToIdleTrigger;
|
||||
[SerializeField] private string changeDialogueTrigger;
|
||||
[SerializeField] private string talkTrigger;
|
||||
|
||||
|
||||
public void StartDialogue(DialogueScript newDialogue)
|
||||
{
|
||||
dialogueUI.SetActive(true);
|
||||
dialogueActive = true;
|
||||
currentText = 0;
|
||||
scriptToShow = newDialogue;
|
||||
DialogueScript.Dialogue currentDialogue = scriptToShow.dialogueList[currentText];
|
||||
bossSpeechBubble.transform.position = WaveManager.instance.bossInstance.transform.position + offset;
|
||||
SetDialogue(currentDialogue);
|
||||
reisenAnimator.SetTrigger(switchToDialogueTrigger);
|
||||
youmuAnimator.SetTrigger(switchToDialogueTrigger);
|
||||
//GameManager.instance.SetPause(true);
|
||||
}
|
||||
|
||||
public void ContinueDialogue()
|
||||
{
|
||||
currentText++;
|
||||
if (currentText >= scriptToShow.dialogueList.Length)
|
||||
{
|
||||
EndDialogue();
|
||||
return;
|
||||
}
|
||||
DialogueScript.Dialogue currentDialogue = scriptToShow.dialogueList[currentText];
|
||||
SetDialogue(currentDialogue);
|
||||
}
|
||||
|
||||
public void EndDialogue()
|
||||
{
|
||||
dialogueActive = false;
|
||||
dialogueUI.SetActive(false);
|
||||
WaveManager.instance.player.isStalled = false;
|
||||
WaveManager.instance.bossInstance.isStalled = false;
|
||||
//GameManager.instance.SetPause(false);
|
||||
reisenAnimator.SetTrigger(switchToIdleTrigger);
|
||||
youmuAnimator.SetTrigger(switchToIdleTrigger);
|
||||
}
|
||||
|
||||
private void SetDialogue(DialogueScript.Dialogue textToShow)
|
||||
{
|
||||
reisenSpeechBubble.SetActive(false);
|
||||
youmuSpeechBubble.SetActive(false);
|
||||
bossSpeechBubble.gameObject.SetActive(false);
|
||||
switch (textToShow.character.thisCharacter) //everyone will hate this code but that's alright
|
||||
{
|
||||
case DialogueCharacter.Character.Reisen:
|
||||
reisenSpeechBubble.SetActive(true);
|
||||
reisenText.text = textToShow.text;
|
||||
youmuAnimator.SetTrigger(changeDialogueTrigger);
|
||||
reisenAnimator.SetTrigger(talkTrigger);
|
||||
break;
|
||||
case DialogueCharacter.Character.Youmu:
|
||||
youmuSpeechBubble.SetActive(true);
|
||||
youmuText.text = textToShow.text;
|
||||
youmuAnimator.SetTrigger(talkTrigger);
|
||||
reisenAnimator.SetTrigger(changeDialogueTrigger);
|
||||
break;
|
||||
case DialogueCharacter.Character.Enemy:
|
||||
bossSpeechBubble.gameObject.SetActive(true);
|
||||
bossText.text = textToShow.text;
|
||||
reisenAnimator.SetTrigger(changeDialogueTrigger);
|
||||
youmuAnimator.SetTrigger(changeDialogueTrigger);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (dialogueActive)
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
ContinueDialogue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Dialogue/DialogueManager.cs.meta
Normal file
2
Assets/Scripts/Dialogue/DialogueManager.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 13ba117626f0a4a9fabe70178e0635be
|
||||
15
Assets/Scripts/Dialogue/DialogueScript.cs
Normal file
15
Assets/Scripts/Dialogue/DialogueScript.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using UnityEngine;
|
||||
|
||||
[CreateAssetMenu(fileName = "New Dialogue Script", menuName = "Dialogue/Script")]
|
||||
public class DialogueScript : ScriptableObject
|
||||
{
|
||||
[System.Serializable]
|
||||
public class Dialogue
|
||||
{
|
||||
public DialogueCharacter character;
|
||||
public string text;
|
||||
public Sprite cutsceneImage; //only for cutscenes lol
|
||||
}
|
||||
public Dialogue[] dialogueList;
|
||||
public int nextScene;
|
||||
}
|
||||
2
Assets/Scripts/Dialogue/DialogueScript.cs.meta
Normal file
2
Assets/Scripts/Dialogue/DialogueScript.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 62aa0cb4b5a429c90801dae416f91cb6
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f2cbcd42dd2fbec84beeadd94b28bc04
|
||||
30
Assets/Scripts/EndlessWaveManager.cs
Normal file
30
Assets/Scripts/EndlessWaveManager.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
using UnityEngine;
|
||||
|
||||
public class EndlessWaveManager : WaveManager
|
||||
{
|
||||
[SerializeField] private Enemy[] enemyList;
|
||||
[SerializeField] private Enemy[] bossList;
|
||||
[SerializeField] private int bossWaveInterval;
|
||||
[Header("Enemy Count Calculations")]
|
||||
[SerializeField] private float baseSpawnAmount;
|
||||
[SerializeField] private float exponentIncrease;
|
||||
protected override void SpawnWave()
|
||||
{
|
||||
waveUI.text = $"Wave: {wave}";
|
||||
int amountToSpawn = Mathf.FloorToInt(baseSpawnAmount * Mathf.Pow(wave, exponentIncrease));
|
||||
for (int i = 0; i < amountToSpawn; i++)
|
||||
{
|
||||
SpawnEnemy(enemyList[Random.Range(0, enemyList.Length)]);
|
||||
}
|
||||
if (wave % bossWaveInterval == 0)
|
||||
{
|
||||
SpawnBoss(bossList[Random.Range(0, bossList.Length)]);
|
||||
}
|
||||
wave++;
|
||||
}
|
||||
|
||||
public override void UpdateKills()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/EndlessWaveManager.cs.meta
Normal file
2
Assets/Scripts/EndlessWaveManager.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d7e96d9fab63b725397efd9b5cfbb3af
|
||||
|
|
@ -1,46 +1,109 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
public class Enemy : Entity
|
||||
{
|
||||
private Ability abilitySelected;
|
||||
public SpriteRenderer sprite;
|
||||
private float currentState = 1;
|
||||
public float colorChangeSpeed;
|
||||
[Header("Movement")]
|
||||
private float currentMovement;
|
||||
public float moveSpeed;
|
||||
public float moveSpeedDelta;
|
||||
[Header("wobble")]
|
||||
public bool preventWobble;
|
||||
public Vector3 originalPosition;
|
||||
[SerializeField] private float variance;
|
||||
public Coroutine currentMovementRoutine;
|
||||
[Header("boss stuff")]
|
||||
[SerializeField] private bool isBossEnemy;
|
||||
[SerializeField] private bool hasStartedDialogue;
|
||||
[Header("Attack")]
|
||||
[SerializeField] private float attackCooldown;
|
||||
private float currentAttackCooldown;
|
||||
[SerializeField] private DialogueScript thisBossDialogue;
|
||||
public event Action onTakeDamage;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
moveSpeed += Random.Range(-moveSpeedDelta, moveSpeedDelta);
|
||||
currentAttackCooldown = Random.Range(0, attackCooldown);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (!isStalled)
|
||||
{
|
||||
foreach (Ability ability in abilities)
|
||||
if (!preventWobble && currentMovementRoutine == null)
|
||||
{
|
||||
ability.direction = WaveManager.instance.GetRandomPlayerPoint();
|
||||
bool success = ability.TryAbility();
|
||||
if (!success && ability.currentCooldown <= 0.5f && currentState >= 1f)
|
||||
//Debug.Log("reset movement");
|
||||
//StopCoroutine(currentMovementRoutine);
|
||||
Vector3 newPosition = new Vector3(originalPosition.x + Random.Range(-variance, variance),
|
||||
originalPosition.y + Random.Range(-variance*0.5f, variance*0.5f));
|
||||
currentMovementRoutine = StartCoroutine(MoveToPosition(transform.position, newPosition, moveSpeed));
|
||||
}
|
||||
if (currentAttackCooldown <= 0)
|
||||
{
|
||||
List<Ability> freeAbilities = new();
|
||||
foreach (Ability ability in abilities)
|
||||
{
|
||||
if (ability.currentCooldown <= 0)
|
||||
{
|
||||
freeAbilities.Add(ability);
|
||||
}
|
||||
}
|
||||
|
||||
if (freeAbilities.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!abilitySelected)
|
||||
{
|
||||
abilitySelected = freeAbilities[Random.Range(0, freeAbilities.Count)];
|
||||
}
|
||||
bool success = abilitySelected.TryAbility();
|
||||
if (!success && abilitySelected.currentCooldown <= 0.5f && currentState >= 1f)
|
||||
{
|
||||
currentState = 0f;
|
||||
StartCoroutine(ImminentAttackAnim());
|
||||
}
|
||||
else
|
||||
{
|
||||
abilitySelected = null;
|
||||
currentAttackCooldown = attackCooldown;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
currentAttackCooldown -= Time.deltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void TakeDamage(int damage)
|
||||
{
|
||||
base.TakeDamage(damage);
|
||||
if (isBossEnemy)
|
||||
{
|
||||
WaveManager.instance.UpdateBossUI(); //this is fucking stupid but it works i guess
|
||||
}
|
||||
onTakeDamage?.Invoke();
|
||||
}
|
||||
|
||||
protected override void OnDeath()
|
||||
{
|
||||
base.OnDeath();
|
||||
Destroy(gameObject);
|
||||
WaveManager.instance.enemiesInPlay.Remove(this);
|
||||
WaveManager.instance.UpdateKills();
|
||||
if (isBossEnemy)
|
||||
{
|
||||
WaveManager.instance.bossUI.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator ImminentAttackAnim()
|
||||
|
|
@ -53,16 +116,25 @@ public class Enemy : Entity
|
|||
}
|
||||
}
|
||||
|
||||
public IEnumerator MoveToPosition(Vector3 moveDirection)
|
||||
public IEnumerator MoveToPosition(Vector3 origin, Vector3 moveDirection, float lerpSpeed)
|
||||
{
|
||||
float currentMovement = 0;
|
||||
while (currentMovement < 1)
|
||||
{
|
||||
currentMovement += Time.deltaTime * moveSpeed;
|
||||
currentMovement += Time.deltaTime * lerpSpeed;
|
||||
if (currentMovement >= 1)
|
||||
{
|
||||
isStalled = false;
|
||||
invulnerable = false;
|
||||
currentMovementRoutine = null;
|
||||
if (isBossEnemy && !hasStartedDialogue)
|
||||
{
|
||||
hasStartedDialogue = true;
|
||||
DialogueManager.instance.StartDialogue(thisBossDialogue); //the worst code ever
|
||||
isStalled = true;
|
||||
}
|
||||
}
|
||||
transform.position = Vector3.Lerp(WaveManager.instance.enemySpawnPoint.position, moveDirection, currentMovement);
|
||||
transform.position = Vector3.Lerp(origin, moveDirection, currentMovement);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,16 @@ public class Entity : MonoBehaviour
|
|||
|
||||
[Header("State")]
|
||||
public bool isStalled;
|
||||
public bool invulnerable;
|
||||
[Header("Abilities")]
|
||||
public List<Ability> abilities = new();
|
||||
|
||||
public virtual void TakeDamage(int damage)
|
||||
{
|
||||
health -= damage;
|
||||
if (!invulnerable)
|
||||
{
|
||||
health -= damage;
|
||||
}
|
||||
if (health <= 0)
|
||||
{
|
||||
OnDeath();
|
||||
|
|
|
|||
|
|
@ -4,24 +4,55 @@ using UnityEngine;
|
|||
|
||||
public class Player : Entity
|
||||
{
|
||||
[Header("Invulnerability")]
|
||||
[SerializeField] private float invulnerabilityLength;
|
||||
private float currentInvulnerabilityTime;
|
||||
[Header("UI")]
|
||||
[SerializeField] private TextMeshProUGUI livesText;
|
||||
|
||||
[Header("SFX")]
|
||||
[SerializeField] private AudioClip hurtSound;
|
||||
[SerializeField] private float hurtVolume = 1f;
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
if (!isStalled)
|
||||
{
|
||||
abilities[0].TryAbility();
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
abilities[0].TryAbility();
|
||||
}
|
||||
if (Input.GetMouseButtonDown(1)) //this way kinda sucks but i'll fix it when i feel like it
|
||||
{
|
||||
abilities[1].TryAbility();
|
||||
}
|
||||
}
|
||||
if (Input.GetMouseButtonDown(1)) //this way kinda sucks but i'll fix it when i feel like it
|
||||
|
||||
if (currentInvulnerabilityTime > 0)
|
||||
{
|
||||
abilities[1].TryAbility();
|
||||
currentInvulnerabilityTime -= Time.deltaTime;
|
||||
if (currentInvulnerabilityTime <= 0)
|
||||
{
|
||||
invulnerable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void TakeDamage(int damage)
|
||||
{
|
||||
base.TakeDamage(damage);
|
||||
if (!invulnerable)
|
||||
{
|
||||
WaveManager.instance.audioSource.PlayOneShot(hurtSound, hurtVolume);
|
||||
currentInvulnerabilityTime = invulnerabilityLength;
|
||||
invulnerable = true;
|
||||
}
|
||||
UpdateLivesUI();
|
||||
GameManager.instance.livesLost++;
|
||||
}
|
||||
|
||||
protected override void OnDeath()
|
||||
{
|
||||
GameManager.instance.LoseGame();
|
||||
}
|
||||
private void UpdateLivesUI()
|
||||
{
|
||||
|
|
|
|||
43
Assets/Scripts/Entities/ZombieFairy.cs
Normal file
43
Assets/Scripts/Entities/ZombieFairy.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
using UnityEngine;
|
||||
|
||||
public class ZombieFairy : Enemy
|
||||
{
|
||||
[SerializeField] private Ability deathAbility;
|
||||
[SerializeField] private bool hasDiedOnce;
|
||||
[SerializeField] private float disappearanceTime;
|
||||
private float currentDisappearanceTime;
|
||||
protected override void OnDeath()
|
||||
{
|
||||
if (!hasDiedOnce)
|
||||
{
|
||||
hasDiedOnce = true;
|
||||
health = maxHealth;
|
||||
invulnerable = true;
|
||||
isStalled = true;
|
||||
currentDisappearanceTime = disappearanceTime;
|
||||
sprite.color = Color.black;
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(gameObject);
|
||||
WaveManager.instance.enemiesInPlay.Remove(this);
|
||||
WaveManager.instance.UpdateKills();
|
||||
}
|
||||
deathAbility.TryAbility();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
if (currentDisappearanceTime > 0)
|
||||
{
|
||||
currentDisappearanceTime -= Time.deltaTime;
|
||||
if (currentDisappearanceTime <= 0)
|
||||
{
|
||||
invulnerable = false;
|
||||
isStalled = false;
|
||||
sprite.color = Color.white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Entities/ZombieFairy.cs.meta
Normal file
2
Assets/Scripts/Entities/ZombieFairy.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f2a09223bdc8572ce868c17f69e123d9
|
||||
121
Assets/Scripts/GameManager.cs
Normal file
121
Assets/Scripts/GameManager.cs
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
using System;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
public class GameManager : MonoBehaviour
|
||||
{
|
||||
#region Statication
|
||||
|
||||
public static GameManager instance;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (instance != null && instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
instance = this;
|
||||
DontDestroyOnLoad(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[Header("Game Stats")]
|
||||
public int continues;
|
||||
public string time;
|
||||
public int wave;
|
||||
public int deflections;
|
||||
public int projectilesShot;
|
||||
public int projectilesHit;
|
||||
public string accuracy;
|
||||
public int livesLost;
|
||||
[Header("Pause UI")]
|
||||
[SerializeField] private GameObject pauseMenu;
|
||||
|
||||
[Header("Game Over")]
|
||||
[SerializeField] private DialogueScript winCutscene;
|
||||
[SerializeField] private GameObject loseUI;
|
||||
[SerializeField] private StatsUI statsUI;
|
||||
private bool gameOver;
|
||||
|
||||
public void EndGame()
|
||||
{
|
||||
SetPause(true);
|
||||
gameOver = true;
|
||||
time = TimeSpan.FromSeconds(Time.timeSinceLevelLoad).ToString(@"mm\:ss");
|
||||
wave = WaveManager.instance.wave-1;
|
||||
accuracy = ((float)projectilesHit / projectilesShot).ToString(@"P");
|
||||
}
|
||||
public void LoseGame()
|
||||
{
|
||||
loseUI.SetActive(true);
|
||||
EndGame();
|
||||
statsUI.SetUI();
|
||||
}
|
||||
|
||||
public void WinGame()
|
||||
{
|
||||
EndGame();
|
||||
LevelSwitcher.instance.SwitchLevel(2, winCutscene);
|
||||
SetPause(false);
|
||||
}
|
||||
|
||||
public void ExitGame()
|
||||
{
|
||||
LevelSwitcher.instance.SwitchLevel(0);
|
||||
SetPause(false);
|
||||
}
|
||||
|
||||
public void RestartGame()
|
||||
{
|
||||
LevelSwitcher.instance.SwitchLevel(1);
|
||||
SetPause(false);
|
||||
}
|
||||
|
||||
public void ContinueGame()
|
||||
{
|
||||
gameOver = false;
|
||||
loseUI.SetActive(false);
|
||||
SetPause(false);
|
||||
WaveManager.instance.player.health = WaveManager.instance.player.maxHealth;
|
||||
continues++;
|
||||
}
|
||||
|
||||
public void SetPause(bool state)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
Time.timeScale = 0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
Time.timeScale = 1f;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPauseMenu()
|
||||
{
|
||||
if (!gameOver && !DialogueManager.instance.dialogueActive)
|
||||
{
|
||||
if (!pauseMenu.activeSelf)
|
||||
{
|
||||
pauseMenu.SetActive(true);
|
||||
SetPause(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
pauseMenu.SetActive(false);
|
||||
SetPause(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.Escape)) //we need to convert this to a better input system
|
||||
{
|
||||
SetPauseMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/GameManager.cs.meta
Normal file
2
Assets/Scripts/GameManager.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 49f68bad15f506ff394c93aee2ec0583
|
||||
28
Assets/Scripts/LevelSwitcher.cs
Normal file
28
Assets/Scripts/LevelSwitcher.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public class LevelSwitcher : MonoBehaviour
|
||||
{
|
||||
#region Statication
|
||||
|
||||
public static LevelSwitcher instance;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (instance != null && instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
instance = this;
|
||||
DontDestroyOnLoad(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public DialogueScript currentScript;
|
||||
public void SwitchLevel(int sceneIndex, DialogueScript scriptToShow = null)
|
||||
{
|
||||
currentScript = scriptToShow;
|
||||
SceneManager.LoadScene(sceneIndex);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/LevelSwitcher.cs.meta
Normal file
2
Assets/Scripts/LevelSwitcher.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 83840282461d85d638ab4881094c2b58
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
|
|
@ -6,13 +7,19 @@ public class MainMenuHandler : MonoBehaviour
|
|||
[SerializeField] private Animator uiAnimator;
|
||||
[SerializeField] private string openUIAction;
|
||||
[SerializeField] private string closeUIAction;
|
||||
[SerializeField] private string gameStartAction;
|
||||
[SerializeField] private Transform uiMovingObject;
|
||||
|
||||
|
||||
[SerializeField] private DialogueScript startingScript;
|
||||
|
||||
|
||||
private void Start()
|
||||
{
|
||||
//uiAnimator.SetTrigger(gameStartAction);
|
||||
}
|
||||
|
||||
public void StartGame()
|
||||
{
|
||||
SceneManager.LoadScene(1);
|
||||
LevelSwitcher.instance.SwitchLevel(2, startingScript);
|
||||
}
|
||||
|
||||
public void StartEndless()
|
||||
|
|
|
|||
13
Assets/Scripts/Projectiles/ClearingProjectile.cs
Normal file
13
Assets/Scripts/Projectiles/ClearingProjectile.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using UnityEngine;
|
||||
|
||||
public class ClearingProjectile : Projectile
|
||||
{
|
||||
protected override void OnTriggerEnter2D(Collider2D other)
|
||||
{
|
||||
base.OnTriggerEnter2D(other);
|
||||
if (!other.CompareTag(tag) && other.TryGetComponent(out Projectile isProjectile))
|
||||
{
|
||||
Destroy(other.gameObject); //should it destroy or reflect?
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Projectiles/ClearingProjectile.cs.meta
Normal file
2
Assets/Scripts/Projectiles/ClearingProjectile.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2b69973b5895ac26eabd31cbb276e1e1
|
||||
42
Assets/Scripts/Projectiles/DelayedAimShot.cs
Normal file
42
Assets/Scripts/Projectiles/DelayedAimShot.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
public class DelayedAimShot : Projectile
|
||||
{
|
||||
[SerializeField] private float aimDelay;
|
||||
[SerializeField] private float aimedSpeed;
|
||||
[SerializeField] private float movementDelay;
|
||||
|
||||
private Vector3 GetAimedDirection()
|
||||
{
|
||||
return (WaveManager.instance.GetRandomPlayerPoint() - transform.position).normalized;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (aimDelay > 0)
|
||||
{
|
||||
aimDelay -= Time.deltaTime;
|
||||
if (aimDelay <= 0)
|
||||
{
|
||||
speed = aimedSpeed;
|
||||
if (movementDelay <= 0)
|
||||
{
|
||||
direction = GetAimedDirection();
|
||||
}
|
||||
else
|
||||
{
|
||||
direction = Vector2.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (movementDelay > 0)
|
||||
{
|
||||
movementDelay -= Time.deltaTime;
|
||||
if (movementDelay <= 0)
|
||||
{
|
||||
direction = GetAimedDirection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Projectiles/DelayedAimShot.cs.meta
Normal file
2
Assets/Scripts/Projectiles/DelayedAimShot.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cb475fb3ab771bcbfb9af55ea0a40838
|
||||
21
Assets/Scripts/Projectiles/DisappearingEffect.cs
Normal file
21
Assets/Scripts/Projectiles/DisappearingEffect.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
public class DisappearingEffect : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private SpriteRenderer sprite;
|
||||
private float currentState;
|
||||
[SerializeField] private float decaySpeed;
|
||||
private Color originalColor;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
originalColor = sprite.color;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
currentState += Time.deltaTime * decaySpeed;
|
||||
sprite.color = Color.Lerp(originalColor, Color.clear, currentState);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Projectiles/DisappearingEffect.cs.meta
Normal file
2
Assets/Scripts/Projectiles/DisappearingEffect.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 825f6d6ee8dd614ca9ad81f57005cad3
|
||||
26
Assets/Scripts/Projectiles/ExplosiveProjectile.cs
Normal file
26
Assets/Scripts/Projectiles/ExplosiveProjectile.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
public class ExplosiveProjectile : Projectile
|
||||
{
|
||||
[SerializeField] private GameObject explosionEffect;
|
||||
[SerializeField] private float blastRadius;
|
||||
[SerializeField] private LayerMask enemyLayer;
|
||||
protected override void OnTriggerEnter2D(Collider2D other)
|
||||
{
|
||||
base.OnTriggerEnter2D(other);
|
||||
if (!other.CompareTag(tag))
|
||||
{
|
||||
GameObject newExplosionEffect = Instantiate(explosionEffect, transform.position, Quaternion.identity);
|
||||
newExplosionEffect.transform.localScale = new Vector3(blastRadius, blastRadius, blastRadius);
|
||||
Collider2D[] enemiesInRange = Physics2D.OverlapCircleAll(transform.position, enemyLayer, enemyLayer);
|
||||
foreach (Collider2D enemy in enemiesInRange)
|
||||
{
|
||||
if (enemy.TryGetComponent(out Entity isEntity))
|
||||
{
|
||||
isEntity.TakeDamage(damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Projectiles/ExplosiveProjectile.cs.meta
Normal file
2
Assets/Scripts/Projectiles/ExplosiveProjectile.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9808930a9222595e791e8c290cd7ea9a
|
||||
|
|
@ -3,14 +3,23 @@ using UnityEngine;
|
|||
|
||||
public class Projectile : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Rigidbody2D rb;
|
||||
[Header("Flags")]
|
||||
public bool deflectable = true;
|
||||
[SerializeField] private bool isPiercing;
|
||||
public bool playerBullet; //bad code
|
||||
[Header("Stats")]
|
||||
[SerializeField] private int projectileHealth = 2;
|
||||
public int damage;
|
||||
public float speed;
|
||||
public float lifetime;
|
||||
[Header("CACHE")]
|
||||
public Vector2 direction;
|
||||
public AudioClip projectileShootSFX;
|
||||
public float volume;
|
||||
[SerializeField] private Rigidbody2D rb;
|
||||
public SpriteRenderer sprite;
|
||||
|
||||
|
||||
private void Start()
|
||||
protected virtual void Start()
|
||||
{
|
||||
Destroy(gameObject, lifetime);
|
||||
direction = transform.right;
|
||||
|
|
@ -21,11 +30,27 @@ public class Projectile : MonoBehaviour
|
|||
rb.linearVelocity = direction * speed;
|
||||
}
|
||||
|
||||
private void OnTriggerEnter2D(Collider2D other)
|
||||
protected virtual void OnTriggerEnter2D(Collider2D other)
|
||||
{
|
||||
if (!other.CompareTag(tag) && other.TryGetComponent(out Entity isEntity))
|
||||
{
|
||||
if (playerBullet)
|
||||
{
|
||||
GameManager.instance.projectilesHit++; //bad. very bad. but i don't care right now
|
||||
}
|
||||
isEntity.TakeDamage(damage);
|
||||
if (!isPiercing)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Deflected()
|
||||
{
|
||||
projectileHealth--;
|
||||
if (projectileHealth <= 0)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
41
Assets/Scripts/SettingsMenu.cs
Normal file
41
Assets/Scripts/SettingsMenu.cs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Audio;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class SettingsMenu : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TextMeshProUGUI sfxLabel;
|
||||
[SerializeField] private Slider sfxSlider;
|
||||
[SerializeField] private TextMeshProUGUI musicLabel;
|
||||
[SerializeField] private Slider musicSlider;
|
||||
[SerializeField] private AudioMixer mainMixer;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (PlayerPrefs.HasKey("SFXVolume"))
|
||||
{
|
||||
sfxSlider.value = PlayerPrefs.GetFloat("SFXVolume");
|
||||
}
|
||||
if (PlayerPrefs.HasKey("MusicVolume"))
|
||||
{
|
||||
musicSlider.value = PlayerPrefs.GetFloat("MusicVolume");
|
||||
}
|
||||
|
||||
UpdateSFX();
|
||||
UpdateMusic();
|
||||
}
|
||||
|
||||
public void UpdateSFX()
|
||||
{
|
||||
sfxLabel.text = $"SFX ({(sfxSlider.value * 100).ToString("F1")}%);";
|
||||
mainMixer.SetFloat("SFXVolume", Mathf.Log10(sfxSlider.value) * 20);
|
||||
PlayerPrefs.SetFloat("SFXVolume", sfxSlider.value);
|
||||
}
|
||||
public void UpdateMusic()
|
||||
{
|
||||
musicLabel.text = $"Music ({(musicSlider.value * 100).ToString("F1")}%);";
|
||||
mainMixer.SetFloat("MusicVolume", Mathf.Log10(musicSlider.value) * 20);
|
||||
PlayerPrefs.SetFloat("MusicVolume", musicSlider.value);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/SettingsMenu.cs.meta
Normal file
2
Assets/Scripts/SettingsMenu.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 86c2d66befa9ade94b4f09786b61bdd6
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using UnityEngine;
|
||||
|
||||
public class DialogueManager : MonoBehaviour
|
||||
public class SpinEffect : MonoBehaviour
|
||||
{
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
2
Assets/Scripts/SpinEffect.cs.meta
Normal file
2
Assets/Scripts/SpinEffect.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f082f0f4c60b74055b2784bcda81d472
|
||||
37
Assets/Scripts/StatsUI.cs
Normal file
37
Assets/Scripts/StatsUI.cs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
public class StatsUI : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TextMeshProUGUI continuesText;
|
||||
[SerializeField] private TextMeshProUGUI timeText;
|
||||
[SerializeField] private TextMeshProUGUI waveText;
|
||||
[SerializeField] private TextMeshProUGUI deflectionText;
|
||||
[SerializeField] private TextMeshProUGUI shotText;
|
||||
[SerializeField] private TextMeshProUGUI hitText;
|
||||
[SerializeField] private TextMeshProUGUI accuracyText;
|
||||
[SerializeField] private TextMeshProUGUI livesText;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
SetUI(); //it does it in game but like i don't think it even matters lol
|
||||
}
|
||||
|
||||
public void SetUI()
|
||||
{
|
||||
continuesText.text = GameManager.instance.continues.ToString();
|
||||
timeText.text = GameManager.instance.time;
|
||||
waveText.text = GameManager.instance.wave.ToString();
|
||||
deflectionText.text = GameManager.instance.deflections.ToString();
|
||||
accuracyText.text = GameManager.instance.accuracy;
|
||||
shotText.text = GameManager.instance.projectilesShot.ToString();
|
||||
hitText.text = GameManager.instance.projectilesHit.ToString();
|
||||
livesText.text = GameManager.instance.livesLost.ToString();
|
||||
}
|
||||
|
||||
public void Exit()
|
||||
{
|
||||
LevelSwitcher.instance.SwitchLevel(0);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/StatsUI.cs.meta
Normal file
2
Assets/Scripts/StatsUI.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: efdd4c13330d79f7f8d0c3bd0ea746ca
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
|
@ -28,8 +29,15 @@ public class WaveManager : MonoBehaviour
|
|||
public class Wave
|
||||
{
|
||||
public Enemy[] enemies;
|
||||
public bool bossWave;
|
||||
public Enemy bossEnemy; //optional
|
||||
public string bossName;
|
||||
public string bossDescription;
|
||||
//public DialogueScript bossDialogue;
|
||||
}
|
||||
[Header("Player Point")]
|
||||
|
||||
[Header("Player Point")]
|
||||
public Player player; //only for continues lol
|
||||
[SerializeField] private Transform tlPoint;
|
||||
[SerializeField] private Transform brPoint;
|
||||
|
||||
|
|
@ -38,18 +46,33 @@ public class WaveManager : MonoBehaviour
|
|||
[SerializeField] private Transform enemyBRPoint;
|
||||
public Transform enemySpawnPoint;
|
||||
[Header("Waves")]
|
||||
[SerializeField] private TextMeshProUGUI waveUI;
|
||||
[SerializeField] protected TextMeshProUGUI waveUI;
|
||||
public int wave = 1;
|
||||
public Wave[] waveList;
|
||||
[Header("Boss")]
|
||||
public Enemy bossInstance;
|
||||
public GameObject bossUI;
|
||||
[SerializeField] private TextMeshProUGUI bossNameUI;
|
||||
[SerializeField] private TextMeshProUGUI bossDescriptionUI;
|
||||
[SerializeField] private Transform bossHPBar;
|
||||
[SerializeField] private TextMeshProUGUI bossHPText;
|
||||
[Header("Enemies")]
|
||||
public Transform enemyFolder;
|
||||
public List<Enemy> enemiesInPlay = new();
|
||||
[SerializeField] private float enemyCheckRadius;
|
||||
[SerializeField] private LayerMask enemyLayer;
|
||||
[Header("Audio")]
|
||||
public AudioSource audioSource;
|
||||
[SerializeField] private AudioSource musicSource;
|
||||
[SerializeField] private AudioClip musicIntro;
|
||||
public float musicVolume;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
SpawnWave();
|
||||
musicSource.volume = musicVolume;
|
||||
musicSource.PlayOneShot(musicIntro, musicVolume);
|
||||
StartCoroutine(WaitForLoop());
|
||||
}
|
||||
|
||||
public Vector3 GetRandomPlayerPoint()
|
||||
|
|
@ -58,7 +81,7 @@ public class WaveManager : MonoBehaviour
|
|||
Random.Range(brPoint.position.y, tlPoint.position.y), 0);
|
||||
}
|
||||
|
||||
private Vector3 GetRandomEnemyPoint()
|
||||
public Vector3 GetRandomEnemyPoint()
|
||||
{
|
||||
Vector3 randomPoint;
|
||||
do
|
||||
|
|
@ -79,24 +102,79 @@ public class WaveManager : MonoBehaviour
|
|||
return false;
|
||||
}
|
||||
|
||||
private void SpawnWave()
|
||||
protected virtual void SpawnWave()
|
||||
{
|
||||
waveUI.text = $"Wave: {wave}";
|
||||
foreach (Enemy enemy in waveList[wave-1].enemies)
|
||||
{
|
||||
Enemy newEnemy = Instantiate(enemy, enemyFolder);
|
||||
newEnemy.StartCoroutine(newEnemy.MoveToPosition(GetRandomEnemyPoint()));
|
||||
enemiesInPlay.Add(newEnemy);
|
||||
newEnemy.isStalled = true;
|
||||
SpawnEnemy(enemy);
|
||||
}
|
||||
|
||||
if (waveList[wave-1].bossWave)
|
||||
{
|
||||
SpawnBoss(waveList[wave-1].bossEnemy);
|
||||
}
|
||||
wave++;
|
||||
}
|
||||
|
||||
public void UpdateKills()
|
||||
protected void SpawnBoss(Enemy boss)
|
||||
{
|
||||
Enemy newBoss = SpawnEnemy(boss);
|
||||
bossInstance = newBoss;
|
||||
bossUI.SetActive(true);
|
||||
bossNameUI.text = waveList[wave - 1].bossName;
|
||||
bossDescriptionUI.text = waveList[wave - 1].bossDescription;
|
||||
UpdateBossUI();
|
||||
player.isStalled = true; //wait for boss to enter then start dialogue
|
||||
}
|
||||
|
||||
public Enemy SpawnEnemy(Enemy enemy)
|
||||
{
|
||||
Enemy newEnemy = Instantiate(enemy, enemyFolder);
|
||||
Vector3 movepos = GetRandomEnemyPoint();
|
||||
newEnemy.currentMovementRoutine = newEnemy.StartCoroutine(newEnemy.MoveToPosition(enemySpawnPoint.position,movepos, newEnemy.moveSpeed));
|
||||
newEnemy.originalPosition = movepos;
|
||||
enemiesInPlay.Add(newEnemy);
|
||||
newEnemy.isStalled = true;
|
||||
newEnemy.invulnerable = true;
|
||||
return newEnemy;
|
||||
}
|
||||
|
||||
public void UpdateBossUI()
|
||||
{
|
||||
bossHPText.text = $"{bossInstance.health}/{bossInstance.maxHealth}";
|
||||
bossHPBar.localScale = new Vector3((float)bossInstance.health / bossInstance.maxHealth, 1f, 1f);
|
||||
}
|
||||
|
||||
public virtual void UpdateKills()
|
||||
{
|
||||
if (enemiesInPlay.Count == 0)
|
||||
{
|
||||
SpawnWave();
|
||||
if (wave > waveList.Length)
|
||||
{
|
||||
GameManager.instance.WinGame();
|
||||
}
|
||||
else
|
||||
{
|
||||
SpawnWave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator WaitForLoop()
|
||||
{
|
||||
bool stopped = false;
|
||||
while (!stopped)
|
||||
{
|
||||
if (musicSource.isPlaying)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
stopped = true;
|
||||
musicSource.Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue