diff options
author | chai <215380520@qq.com> | 2023-11-26 23:52:30 +0800 |
---|---|---|
committer | chai <215380520@qq.com> | 2023-11-26 23:52:30 +0800 |
commit | 626381f061cde0c78564f6336e3131835cf20a5b (patch) | |
tree | d9991d6eda6ae5d7649ac91ecaa3b4dc833cd4c3 /Assembly_CSharp/GamePlay | |
parent | 0e63c4a2c6dec8dfa260501fb7d73750261ea7b7 (diff) |
* move
Diffstat (limited to 'Assembly_CSharp/GamePlay')
38 files changed, 6016 insertions, 0 deletions
diff --git a/Assembly_CSharp/GamePlay/BattleCry.cs b/Assembly_CSharp/GamePlay/BattleCry.cs new file mode 100644 index 0000000..f76a756 --- /dev/null +++ b/Assembly_CSharp/GamePlay/BattleCry.cs @@ -0,0 +1,84 @@ +using UnityEngine; + +public class BattleCry : MonoBehaviour +{ + public enum BattleCryTrigger + { + Death, + Spawn, + NearEnd, + ArmorBreak, + ShieldBreak + } + + [SerializeField] + private LayerMask enemyLayerMask; + + [SerializeField] + private string battleCryText = "Battle Cry!"; + + [SerializeField] + private float cryRadius; + + [SerializeField] + private BattleCryTrigger myTrigger; + + [SerializeField] + private float fortifyTime; + + [SerializeField] + private float hastePercentage; + + [SerializeField] + private GameObject[] enemiesToSpawn; + + private bool triggered; + + public void CheckBattleCry(BattleCryTrigger source) + { + if (source == myTrigger && !triggered) + { + Cry(); + } + } + + private void Cry() + { + if (enemiesToSpawn.Length != 0) + { + Waypoint currentWaypoint = GetComponent<Pathfinder>().currentWaypoint; + GameObject[] array = enemiesToSpawn; + for (int i = 0; i < array.Length; i++) + { + Enemy component = Object.Instantiate(array[i], base.transform.position + new Vector3(Random.Range(-0.5f, 0.5f), 0f, Random.Range(-0.5f, 0.5f)), Quaternion.identity).GetComponent<Enemy>(); + component.SetStats(); + component.SetFirstSpawnPoint(currentWaypoint); + SpawnManager.instance.currentEnemies.Add(component); + } + } + DamageNumber component2 = ObjectPool.instance.SpawnObject(ObjectPool.ObjectType.DamageNumber, base.transform.position, Quaternion.identity).GetComponent<DamageNumber>(); + component2.SetText(battleCryText, "Grey", 1f); + component2.SetHoldTime(2f); + if (myTrigger != 0) + { + component2.transform.parent = base.transform; + } + Collider[] array2 = Physics.OverlapSphere(base.transform.position, cryRadius, enemyLayerMask, QueryTriggerInteraction.Collide); + for (int i = 0; i < array2.Length; i++) + { + Enemy component3 = array2[i].GetComponent<Enemy>(); + if (component3 != null) + { + if (fortifyTime > 0f) + { + component3.Fortify(fortifyTime); + } + if (hastePercentage > 0f) + { + component3.AddHaste(hastePercentage); + } + } + } + triggered = true; + } +} diff --git a/Assembly_CSharp/GamePlay/BiPlane.cs b/Assembly_CSharp/GamePlay/BiPlane.cs new file mode 100644 index 0000000..bcf32e5 --- /dev/null +++ b/Assembly_CSharp/GamePlay/BiPlane.cs @@ -0,0 +1,161 @@ +using UnityEngine; + +public class BiPlane : MonoBehaviour +{ + [SerializeField] + private TowerType towerType; + + [SerializeField] + private float speed; + + [SerializeField] + private float turnTime = 3f; + + [SerializeField] + private float minDistance = 3f; + + [SerializeField] + private float maxDistance = 12f; + + [SerializeField] + private float attackDistance = 6f; + + public GameObject target; + + private int directionMultiplier = 1; + + private Vector3 previousPos; + + private bool flyingTowards = true; + + private float desiredAltitude = 5f; + + private float desiredTilt; + + public int damage; + + public int healthDamage; + + public int armorDamage; + + public int shieldDamage; + + public float rps; + + public float slowPercent; + + public float bleedPercent; + + public float burnPercent; + + public float poisonPercent; + + public float critChance; + + public float stunChance; + + private int ammo; + + [SerializeField] + private int maxAmmo = 20; + + private float timeOfLastShot; + + [SerializeField] + private LayerMask bulletHitMask; + + [SerializeField] + private GameObject projectile; + + [SerializeField] + private float projectileSpeed; + + [SerializeField] + private Transform muzzle; + + [SerializeField] + private Transform artTransform; + + private void Start() + { + ammo = maxAmmo; + } + + private void Update() + { + FlightPath(); + } + + private void FixedUpdate() + { + } + + private void FlightPath() + { + Vector3 vector; + if (target != null) + { + vector = target.transform.position; + } + else + { + vector = Vector3.zero; + vector.y = 5f; + } + if (Vector3.SqrMagnitude(vector - base.transform.position) <= minDistance * minDistance) + { + flyingTowards = false; + Reload(); + } + else if (Vector3.SqrMagnitude(vector - base.transform.position) >= maxDistance * maxDistance) + { + flyingTowards = true; + } + float num = ((!flyingTowards) ? 0f : Vector2.SignedAngle(new Vector2(base.transform.forward.x, base.transform.forward.z), new Vector2(vector.x - base.transform.position.x, vector.z - base.transform.position.z))); + float num2; + if (target != null && flyingTowards && Vector3.SqrMagnitude(vector - base.transform.position) <= attackDistance * attackDistance) + { + desiredAltitude += (Mathf.Min(vector.y, 1f) - desiredAltitude) * Time.deltaTime * 1.5f; + num2 = base.transform.position.y - desiredAltitude; + if (Mathf.Abs(num) < 22.5f) + { + Fire(); + } + } + else + { + desiredAltitude += (5f - desiredAltitude) * Time.deltaTime * 3f; + num2 = base.transform.position.y - desiredAltitude; + } + num = Mathf.Clamp(num * 6f, -90f, 90f); + num2 = Mathf.Clamp(num2 * 6f, -45f, 45f); + base.transform.Rotate(new Vector3(0f, (0f - num) * Time.deltaTime / turnTime, 0f)); + base.transform.eulerAngles = new Vector3(num2, base.transform.eulerAngles.y, 0f); + base.transform.Translate(Vector3.forward * Time.deltaTime * speed); + desiredTilt += (num - desiredTilt) * Time.deltaTime; + artTransform.eulerAngles = new Vector3(base.transform.eulerAngles.x, base.transform.eulerAngles.y, desiredTilt); + } + + private void Reload() + { + ammo = maxAmmo; + } + + private void Fire() + { + if (ammo > 0 && timeOfLastShot + rps <= Time.time) + { + ammo--; + timeOfLastShot = Time.time; + LaunchProjectile(); + } + } + + private void LaunchProjectile() + { + Vector3 position = target.transform.position; + position += new Vector3(Random.Range(-0.33f, 0.33f) + Random.Range(-0.33f, 0.33f), Random.Range(-0.33f, 0.33f) + Random.Range(-0.33f, 0.33f), Random.Range(-0.33f, 0.33f) + Random.Range(-0.33f, 0.33f)); + muzzle.LookAt(position); + Object.Instantiate(projectile, muzzle.position, muzzle.rotation).GetComponent<Projectile>().SetStats(towerType, target, projectileSpeed, damage, healthDamage, armorDamage, shieldDamage, slowPercent, bleedPercent, burnPercent, poisonPercent, critChance, stunChance); + } +} diff --git a/Assembly_CSharp/GamePlay/CameraController.cs b/Assembly_CSharp/GamePlay/CameraController.cs new file mode 100644 index 0000000..2b91184 --- /dev/null +++ b/Assembly_CSharp/GamePlay/CameraController.cs @@ -0,0 +1,96 @@ +using UnityEngine; + +public class CameraController : MonoBehaviour +{ + public static CameraController instance; + + [SerializeField] + private Vector3 velocity = Vector3.zero; + + [SerializeField] + private float cameraSpeed = 10f; + + [SerializeField] + private float cameraBaseZoom = 10f; + + [SerializeField] + private GameObject cameraHolder; + + [SerializeField] + private Transform audioListenerObject; + + [SerializeField] + private LayerMask zeroMask; + + private Vector3 clickMoveOrigin; + + private Vector3 cameraOrigin; + + private void Awake() + { + instance = this; + } + + private void Start() + { + Camera.main.orthographicSize = cameraBaseZoom; + if (audioListenerObject != null) + { + audioListenerObject.position = new Vector3(audioListenerObject.position.x, cameraBaseZoom, audioListenerObject.position.z); + } + } + + private void Update() + { + UpdateMovement(); + UpdateZoom(); + } + + private void UpdateMovement() + { + if (Input.GetKeyDown(KeyCode.C)) + { + base.transform.position = Vector3.zero; + } + if (Input.GetMouseButtonDown(1) && Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out var hitInfo, 2000f, zeroMask, QueryTriggerInteraction.Collide)) + { + clickMoveOrigin = hitInfo.point; + cameraOrigin = base.transform.position; + } + if (Input.GetMouseButton(1)) + { + if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out var hitInfo2, 2000f, zeroMask, QueryTriggerInteraction.Collide)) + { + Vector3 vector = cameraOrigin - 2f * (hitInfo2.point - clickMoveOrigin); + base.transform.position = (base.transform.position + vector) / 2f; + } + return; + } + if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) + { + velocity *= 1f - Time.deltaTime; + velocity += new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")) * Time.deltaTime * 2f; + float num = Mathf.Clamp(Camera.main.orthographicSize / 10f, 1f, 5f); + base.transform.Translate(velocity * Time.deltaTime * cameraSpeed * num); + return; + } + velocity = Vector3.zero; + Vector3 vector2 = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")); + if (vector2.sqrMagnitude > 0.1f) + { + float num2 = Mathf.Clamp(Camera.main.orthographicSize / 10f, 1f, 5f); + base.transform.Translate(vector2.normalized * Time.deltaTime * cameraSpeed * num2); + } + } + + private void UpdateZoom() + { + float num = Mathf.Clamp(Camera.main.orthographicSize - Input.mouseScrollDelta.y, 1f, 50f); + Camera.main.orthographicSize = num; + cameraHolder.transform.localPosition = new Vector3(0f, 5f + 2f * num, -2f * num - 5f); + if (audioListenerObject != null) + { + audioListenerObject.position = new Vector3(audioListenerObject.position.x, (num + 10f) / 2f, audioListenerObject.position.z); + } + } +} diff --git a/Assembly_CSharp/GamePlay/Dropper.cs b/Assembly_CSharp/GamePlay/Dropper.cs new file mode 100644 index 0000000..0dc7a10 --- /dev/null +++ b/Assembly_CSharp/GamePlay/Dropper.cs @@ -0,0 +1,126 @@ +using System.Collections.Generic; +using UnityEngine; + +public class Dropper : Tower +{ + [SerializeField] + private int manaPerSecond; + + [SerializeField] + private float dropHeight = 3f; + + [SerializeField] + private LayerMask dropSetMask; + + [SerializeField] + protected Vector2[] dropPoints; + + [SerializeField] + private bool requireTargetToDrop; + + private int currentLevel; + + public float dropperRPMdisplay; + + private float timeOfNextManaCheck; + + private bool canFire = true; + + protected override void Start() + { + base.Start(); + SetDropPoints(); + } + + public override void SetStats() + { + base.SetStats(); + rps = 60f / rpm * (10f / (10f + (float)dropPoints.Length)); + dropperRPMdisplay = rpm * (10f + (float)dropPoints.Length) / 10f; + } + + private void SetDropPoints() + { + List<Vector2> list = new List<Vector2>(); + for (int i = -(int)base.range; (float)i <= base.range; i++) + { + for (int j = -(int)base.range; (float)j <= base.range; j++) + { + if (Physics.Raycast(new Vector3(base.transform.position.x + (float)i, dropHeight, base.transform.position.z + (float)j), Vector3.down, out var hitInfo, 1.5f * dropHeight, dropSetMask, QueryTriggerInteraction.Ignore) && hitInfo.transform.gameObject.layer == LayerMask.NameToLayer("Path")) + { + list.Add(new Vector2(i, j)); + } + } + } + dropPoints = list.ToArray(); + rps = 60f / rpm * (10f / (10f + (float)dropPoints.Length)); + dropperRPMdisplay = rpm * (10f + (float)dropPoints.Length) / 10f; + } + + protected override void Update() + { + if (SpawnManager.instance.level != currentLevel) + { + SetDropPoints(); + currentLevel = SpawnManager.instance.level; + } + if (currentTarget != null) + { + if (turret != null) + { + AimTurret(); + } + GainXP(); + } + if (manaPerSecond > 0 && Time.time >= timeOfNextManaCheck && SpawnManager.instance.combat) + { + timeOfNextManaCheck = Time.time + 1f; + if (ResourceManager.instance.CheckMana(manaPerSecond)) + { + ResourceManager.instance.SpendMana(manaPerSecond); + canFire = true; + } + else + { + canFire = false; + } + } + timeSinceLastShot += Time.deltaTime; + if (canFire && TargetingCheck() && timeSinceLastShot > rps && SpawnManager.instance.combat) + { + Fire(); + timeSinceLastShot = 0f; + } + } + + private bool TargetingCheck() + { + if (requireTargetToDrop) + { + if (currentTarget != null) + { + return true; + } + return false; + } + return true; + } + + protected override void Fire() + { + if (consumesMana) + { + int manaCost = (int)((float)base.damage * manaConsumptionRate); + if (!ResourceManager.instance.CheckMana(manaCost)) + { + return; + } + ResourceManager.instance.SpendMana(manaCost); + } + if (dropPoints.Length != 0) + { + Vector2 vector = dropPoints[Random.Range(0, dropPoints.Length)]; + Object.Instantiate(projectile, new Vector3(vector.x, dropHeight, vector.y) + base.transform.position, Quaternion.identity).GetComponent<Projectile>().SetStats(towerType, null, projectileSpeed, base.damage, base.healthDamage, base.armorDamage, base.shieldDamage, base.slowPercent, base.bleedPercent, base.burnPercent, base.poisonPercent, base.critChance, base.stunChance); + } + } +} diff --git a/Assembly_CSharp/GamePlay/Encampment.cs b/Assembly_CSharp/GamePlay/Encampment.cs new file mode 100644 index 0000000..eaa8ab7 --- /dev/null +++ b/Assembly_CSharp/GamePlay/Encampment.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +public class Encampment : Dropper +{ + protected override void Fire() + { + if (consumesMana) + { + int manaCost = (int)((float)base.damage * manaConsumptionRate); + if (!ResourceManager.instance.CheckMana(manaCost)) + { + return; + } + ResourceManager.instance.SpendMana(manaCost); + } + if (dropPoints.Length != 0) + { + Vector2 vector = dropPoints[Random.Range(0, dropPoints.Length)]; + Vector3 endPosition = new Vector3(vector.x + Random.Range(-0.125f, 0.125f) + base.transform.position.x, 0f, vector.y + Random.Range(-0.125f, 0.125f) + base.transform.position.z); + GameObject obj = Object.Instantiate(projectile, base.transform.position, Quaternion.identity); + obj.GetComponent<Projectile>().SetStats(towerType, null, projectileSpeed, base.damage, base.healthDamage, base.armorDamage, base.shieldDamage, base.slowPercent, base.bleedPercent, base.burnPercent, base.poisonPercent, base.critChance, base.stunChance); + obj.GetComponent<Landmine>().blastRadius = base.blastRadius; + obj.GetComponent<Landmine>().SetEndPosition(endPosition); + } + } +} diff --git a/Assembly_CSharp/GamePlay/Enemy.cs b/Assembly_CSharp/GamePlay/Enemy.cs new file mode 100644 index 0000000..2e7ce7d --- /dev/null +++ b/Assembly_CSharp/GamePlay/Enemy.cs @@ -0,0 +1,669 @@ +using System.Collections.Generic; +using UnityEngine; + +public class Enemy : MonoBehaviour, IDamageable +{ + [SerializeField] + private Renderer renderer; + + [SerializeField] + private Pathfinder pathfinder; + + [SerializeField] + private HealthBar healthBar; + + [SerializeField] + private GameObject deathObjectSpawn; + + [SerializeField] + private BattleCry[] battleCries; + + [SerializeField] + private GameObject treasureObject; + + [SerializeField] + private Vector2 spawnRange; + + public int level = 1; + + [SerializeField] + private int damageToTower = 1; + + [SerializeField] + private int bonusGoldDrop; + + [SerializeField] + private bool dropsGold = true; + + [SerializeField] + private int hpScaleDegree = 1; + + public int baseHealth; + + public int baseArmor; + + public int baseShield; + + public float baseSpeed; + + public int healthRegen; + + public int armorRegen; + + public int shieldRegen; + + private float timeSinceRegen; + + private float currentSpeed; + + private float currentSlowPercentage; + + private float hastePercentage; + + private float freezeTime; + + private float fortifiedTime; + + private bool fortified; + + private int bleed; + + private int burn; + + private int poison; + + private bool bleeding; + + private bool burning; + + private bool poisoned; + + private float timeSinceBleed; + + private float timeSinceBurn; + + private float timeSincePoison; + + private float dotTick; + + private HashSet<TowerType> typesOfTowers = new HashSet<TowerType>(); + + public Lookout mark; + + private bool dead; + + public int health { get; private set; } + + public int armor { get; private set; } + + public int shield { get; private set; } + + private void Start() + { + CheckBattleCries(BattleCry.BattleCryTrigger.Spawn); + healthBar.UpdateFortified(fortifiedTime); + healthBar.UpdateHaste(hastePercentage); + if (bonusGoldDrop == 0) + { + bonusGoldDrop = ResourceManager.instance.enemyBonusGoldDrop; + } + else + { + bonusGoldDrop += ResourceManager.instance.enemyBonusGoldDrop; + } + } + + public void SetStats() + { + health = baseHealth; + armor = baseArmor; + shield = baseShield; + currentSpeed = baseSpeed + MonsterManager.instance.speedBonus; + pathfinder.speed = currentSpeed; + healthBar.SetHealth(health + armor + shield, health, armor, shield, hpScaleDegree); + } + + public void SetFirstSpawnPoint(Waypoint point) + { + pathfinder.currentWaypoint = point; + } + + private void Update() + { + if (fortifiedTime > 0f) + { + FortifiedUpdate(); + } + if (currentSlowPercentage > 0f || hastePercentage > 0f || freezeTime > 0f) + { + SpeedUpdate(); + } + DOTUpdate(); + RegenUpdate(); + } + + private void SpeedUpdate() + { + float num = freezeTime; + freezeTime = Mathf.Max(0f, freezeTime - Time.deltaTime); + currentSlowPercentage = Mathf.Max(0f, currentSlowPercentage - Time.deltaTime * 0.05f); + hastePercentage = Mathf.Max(0f, hastePercentage - Time.deltaTime * 0.05f); + if (freezeTime > 0f) + { + currentSpeed = 0f; + } + else + { + currentSpeed = (baseSpeed + MonsterManager.instance.speedBonus) * (1f - currentSlowPercentage + hastePercentage); + } + pathfinder.speed = currentSpeed; + if (freezeTime <= 0f && num > 0f && renderer != null) + { + renderer.material.color = Color.white; + } + healthBar.UpdateSlow(currentSlowPercentage); + healthBar.UpdateHaste(hastePercentage); + } + + public void CheckBattleCries(BattleCry.BattleCryTrigger cryType) + { + if (battleCries.Length != 0) + { + BattleCry[] array = battleCries; + for (int i = 0; i < array.Length; i++) + { + array[i].CheckBattleCry(cryType); + } + } + } + + private void AddSlow(float newPercentage) + { + currentSlowPercentage = Mathf.Clamp(currentSlowPercentage + newPercentage, 0f, 0.6f + MonsterManager.instance.slowCapModifier); + } + + public void AddHaste(float amount) + { + hastePercentage = Mathf.Clamp(hastePercentage + amount, 0f, 0.6f + MonsterManager.instance.hasteCapModifier); + if (OptionsMenu.instance.showConditionText) + { + DamageNumber component = ObjectPool.instance.SpawnObject(ObjectPool.ObjectType.DamageNumber, base.transform.position, Quaternion.identity).GetComponent<DamageNumber>(); + component.SetText("HASTED", "Grey", 1f); + component.SetHoldTime(0.5f); + } + } + + public void Freeze() + { + freezeTime = 1f; + if (renderer != null) + { + renderer.material.color = Color.blue; + } + if (OptionsMenu.instance.showConditionText) + { + DamageNumber component = ObjectPool.instance.SpawnObject(ObjectPool.ObjectType.DamageNumber, base.transform.position, Quaternion.identity).GetComponent<DamageNumber>(); + component.SetText("FROZEN", "Grey", 1f); + component.SetHoldTime(0.5f); + } + } + + private void FortifiedUpdate() + { + fortifiedTime = Mathf.Max(fortifiedTime - Time.deltaTime, 0f); + if (fortifiedTime <= 0f) + { + fortified = false; + } + healthBar.UpdateFortified(fortifiedTime); + } + + public void Fortify(float time) + { + fortifiedTime = Mathf.Clamp(fortifiedTime + time, 0f, 12f); + healthBar.UpdateFortified(fortifiedTime); + fortified = true; + if (OptionsMenu.instance.showConditionText) + { + DamageNumber component = ObjectPool.instance.SpawnObject(ObjectPool.ObjectType.DamageNumber, base.transform.position, Quaternion.identity).GetComponent<DamageNumber>(); + component.SetText("FORTIFIED", "Grey", 1f); + component.SetHoldTime(0.5f); + } + } + + private void RegenUpdate() + { + if (timeSinceRegen >= 1f) + { + if (healthRegen > 0 && health > 0) + { + HealHealth(healthRegen); + } + if (armorRegen > 0 && armor > 0) + { + HealArmor(armorRegen); + } + if (shieldRegen > 0 && shield > 0) + { + HealShield(shieldRegen); + } + timeSinceRegen = 0f; + } + else + { + timeSinceRegen += Time.deltaTime; + } + } + + private void HealHealth(int amount) + { + if (health >= baseHealth || bleeding) + { + if (bleeding) + { + DamageTracker.instance.AddDamage(TowerType.DOT, amount, 0, 0); + } + return; + } + if (health + amount >= baseHealth) + { + if (OptionsMenu.instance.showDamageNumbers) + { + DamageNumber component = ObjectPool.instance.SpawnObject(ObjectPool.ObjectType.DamageNumber, base.transform.position, Quaternion.identity).GetComponent<DamageNumber>(); + component.SetText("+" + (baseHealth - health), "Green", 1f); + component.SetHoldTime(0.5f); + } + health = baseHealth; + } + else + { + health += amount; + if (OptionsMenu.instance.showDamageNumbers) + { + DamageNumber component2 = ObjectPool.instance.SpawnObject(ObjectPool.ObjectType.DamageNumber, base.transform.position, Quaternion.identity).GetComponent<DamageNumber>(); + component2.SetText("+" + amount, "Green", 1f); + component2.SetHoldTime(0.5f); + } + } + if (healthBar != null) + { + healthBar.UpdateHealth(health, armor, shield, currentSlowPercentage, bleeding, burning, poisoned, bleed, burn, poison); + } + } + + private void HealArmor(int amount) + { + if (armor >= baseArmor || burning) + { + if (burning) + { + DamageTracker.instance.AddDamage(TowerType.DOT, 0, amount, 0); + } + return; + } + if (armor + amount >= baseArmor) + { + if (OptionsMenu.instance.showDamageNumbers) + { + DamageNumber component = ObjectPool.instance.SpawnObject(ObjectPool.ObjectType.DamageNumber, base.transform.position, Quaternion.identity).GetComponent<DamageNumber>(); + component.SetText("+" + (baseArmor - armor), "Yellow", 1f); + component.SetHoldTime(0.5f); + } + armor = baseArmor; + } + else + { + armor += amount; + if (OptionsMenu.instance.showDamageNumbers) + { + DamageNumber component2 = ObjectPool.instance.SpawnObject(ObjectPool.ObjectType.DamageNumber, base.transform.position, Quaternion.identity).GetComponent<DamageNumber>(); + component2.SetText("+" + amount, "Yellow", 1f); + component2.SetHoldTime(0.5f); + } + } + if (healthBar != null) + { + healthBar.UpdateHealth(health, armor, shield, currentSlowPercentage, bleeding, burning, poisoned, bleed, burn, poison); + } + } + + private void HealShield(int amount) + { + if (shield >= baseShield || poisoned) + { + if (poisoned) + { + DamageTracker.instance.AddDamage(TowerType.DOT, 0, 0, amount); + } + return; + } + if (shield + amount >= baseShield) + { + if (OptionsMenu.instance.showDamageNumbers) + { + DamageNumber component = ObjectPool.instance.SpawnObject(ObjectPool.ObjectType.DamageNumber, base.transform.position, Quaternion.identity).GetComponent<DamageNumber>(); + component.SetText("+" + (baseShield - shield), "Blue", 1f); + component.SetHoldTime(0.5f); + } + shield = baseShield; + } + else + { + shield += amount; + if (OptionsMenu.instance.showDamageNumbers) + { + DamageNumber component2 = ObjectPool.instance.SpawnObject(ObjectPool.ObjectType.DamageNumber, base.transform.position, Quaternion.identity).GetComponent<DamageNumber>(); + component2.SetText("+" + amount, "Blue", 1f); + component2.SetHoldTime(0.5f); + } + } + if (healthBar != null) + { + healthBar.UpdateHealth(health, armor, shield, currentSlowPercentage, bleeding, burning, poisoned, bleed, burn, poison); + } + } + + private void DOTUpdate() + { + if (!dead) + { + BleedCheck(); + BurnCheck(); + PoisonCheck(); + if (poisoned && timeSincePoison <= 0f && dotTick <= 0f) + { + int num = poison; + poison = Mathf.Max(poison - (int)GameManager.instance.dotTick.z, 0); + num -= poison; + int num2 = Mathf.Max(num / 2, 1); + TakeDamage(TowerType.DOT, -999, num2, num2, num, 0f, 0f, 0f, 0f, 0f, 0f); + timeSincePoison = 1f; + dotTick = 0.1f; + } + if (burning && timeSinceBurn <= 0f && dotTick <= 0f) + { + int num3 = burn; + burn = Mathf.Max(burn - (int)(GameManager.instance.dotTick.y * Mathf.Max(1f + MonsterManager.instance.burnSpeedDamagePercentBonus * currentSlowPercentage, 1f)), 0); + num3 -= burn; + int num4 = num3 / 2; + TakeDamage(TowerType.DOT, -999, num4, num3, num4, 0f, 0f, 0f, 0f, 0f, 0f); + timeSinceBurn = 1f; + dotTick = 0.1f; + } + if (bleeding && timeSinceBleed <= 0f && dotTick <= 0f) + { + int num5 = bleed; + bleed = Mathf.Max(bleed - (int)GameManager.instance.dotTick.x, 0); + num5 -= bleed; + int num6 = num5 / 2; + TakeDamage(TowerType.DOT, -999, num5, num6, num6, 0f, 0f, 0f, 0f, 0f, 0f); + timeSinceBleed = 1f; + dotTick = 0.1f; + } + timeSinceBleed -= Time.deltaTime; + timeSinceBurn -= Time.deltaTime; + timeSincePoison -= Time.deltaTime; + dotTick -= Time.deltaTime; + healthBar.UpdateBleed(bleeding, bleed); + healthBar.UpdateBurn(burning, burn); + healthBar.UpdatePoison(poisoned, poison); + } + } + + private int FortifiedCheck() + { + if (fortified) + { + return 5; + } + return 0; + } + + private int BleedCheck() + { + if (bleed > 0) + { + bleeding = true; + return 1 + MonsterManager.instance.bonusDamageOnBleed; + } + bleeding = false; + return 0; + } + + private int BurnCheck() + { + if (burn > 0) + { + burning = true; + return 1 + MonsterManager.instance.bonusDamageOnBurn; + } + burning = false; + return 0; + } + + private int PoisonCheck() + { + if (poison > 0) + { + poisoned = true; + return 1 + MonsterManager.instance.bonusDamageOnPoison; + } + poisoned = false; + return 0; + } + + private int FreezeDmgCheck() + { + if (freezeTime > 0f) + { + return MonsterManager.instance.bonusDamageOnStun; + } + return 0; + } + + public float CurrentHealth() + { + return (float)(health + armor + shield) / (float)(baseHealth + baseArmor + baseShield); + } + + public void TakeDamage(TowerType whoHitMe, int _baseDmg, int healthDmg, int armorDmg, int shieldDmg, float slowPercentage, float bleedPercentage, float burnPercentage, float poisonPercentage, float critChance, float stunChance) + { + if (dead) + { + Debug.Log("Dead enemy taking damage"); + return; + } + typesOfTowers.Add(whoHitMe); + if (Random.Range(0f, 1f) < stunChance) + { + Freeze(); + } + float num = critChance; + if (_baseDmg > -1 && BleedCheck() > 0) + { + num += MonsterManager.instance.bleedingCritChance; + if (mark != null) + { + num += mark.critChance; + } + } + int num2 = _baseDmg; + string text = ""; + float num3 = 1f; + if (Random.Range(0f, 1f) < Mathf.Min(num - 1f, 0.5f)) + { + num2 *= 4; + text = "!!!"; + num3 = 2.5f; + SFXManager.instance.PlaySound(Sound.CritBig, base.transform.position); + } + else if (Random.Range(0f, 1f) < Mathf.Min(num - 0.5f, 0.5f)) + { + num2 *= 3; + text = "!!"; + num3 = 2f; + SFXManager.instance.PlaySound(Sound.CritBig, base.transform.position); + } + else if (Random.Range(0f, 1f) < Mathf.Min(num, 0.5f)) + { + num2 *= 2; + text = "!"; + num3 = 1.5f; + SFXManager.instance.PlaySound(Sound.CritBig, base.transform.position); + } + int num4 = 0; + int num5 = 0; + string color; + if (shield > 0) + { + num4 = Mathf.Max(num2 - FortifiedCheck() + (int)MarkCheck().x + FreezeDmgCheck(), 1) * (shieldDmg + PoisonCheck() + (int)MarkCheck().w); + if (num4 > shield) + { + num5 = (int)((float)(num4 - shield) / (float)shieldDmg); + } + shield -= num4; + color = "Blue"; + DamageTracker.instance.AddDamage(whoHitMe, 0, 0, num4); + shield = Mathf.Max(shield, 0); + if (shield == 0) + { + CheckBattleCries(BattleCry.BattleCryTrigger.ShieldBreak); + } + } + else if (armor > 0) + { + num4 = Mathf.Max(num2 - FortifiedCheck() + (int)MarkCheck().x + FreezeDmgCheck(), 1) * (armorDmg + BurnCheck() + (int)MarkCheck().z); + if (num4 > armor) + { + num5 = (int)((float)(num4 - armor) / (float)armorDmg); + } + armor -= num4; + color = "Yellow"; + DamageTracker.instance.AddDamage(whoHitMe, 0, num4, 0); + armor = Mathf.Max(armor, 0); + if (armor == 0) + { + CheckBattleCries(BattleCry.BattleCryTrigger.ArmorBreak); + } + } + else + { + num4 = Mathf.Max(num2 - FortifiedCheck() + (int)MarkCheck().x + FreezeDmgCheck(), 1) * (healthDmg + BleedCheck() + (int)MarkCheck().y); + if (num4 >= health) + { + DamageTracker.instance.AddDamage(whoHitMe, health, 0, 0); + } + else + { + DamageTracker.instance.AddDamage(whoHitMe, num4, 0, 0); + } + health -= num4; + color = "Red"; + } + if (OptionsMenu.instance.showDamageNumbers) + { + DamageNumber component = ObjectPool.instance.SpawnObject(ObjectPool.ObjectType.DamageNumber, base.transform.position, Quaternion.identity).GetComponent<DamageNumber>(); + component.SetText(num4 + text, color, num3); + component.SetHoldTime(0.25f); + } + if (health <= 0) + { + Die(); + return; + } + bleed += (int)((float)num4 * bleedPercentage); + burn += (int)((float)num4 * burnPercentage); + poison += (int)((float)num4 * poisonPercentage); + if (slowPercentage > 0f) + { + AddSlow((float)num4 * slowPercentage / 100f); + } + if (poisonPercentage > 0f) + { + AddSlow(MonsterManager.instance.poisonSlowPercent * poisonPercentage * (float)num4 / 100f); + } + if (num3 > 1f && _baseDmg > -1 && MonsterManager.instance.bleedPop > 0f && !dead) + { + int num6 = (int)((float)bleed * MonsterManager.instance.bleedPop); + bleed -= num6; + TakeDamage(TowerType.DOT, -999, num6, num6 / 2, num6 / 2, 0f, 0f, 0f, 0f, 0f, 0f); + } + if (num3 > 1f && _baseDmg > -1 && MonsterManager.instance.burnPop > 0f && !dead) + { + int num7 = (int)((float)burn * MonsterManager.instance.burnPop); + burn -= num7; + TakeDamage(TowerType.DOT, -999, num7 / 2, num7, num7 / 2, 0f, 0f, 0f, 0f, 0f, 0f); + } + if (num3 > 1f && _baseDmg > -1 && MonsterManager.instance.poisonPop > 0f && !dead) + { + int num8 = (int)((float)poison * MonsterManager.instance.poisonPop); + poison -= num8; + TakeDamage(TowerType.DOT, -999, num8 / 2, num8 / 2, num8, 0f, 0f, 0f, 0f, 0f, 0f); + } + if (healthBar != null) + { + healthBar.UpdateHealth(health, armor, shield, currentSlowPercentage, bleeding, burning, poisoned, bleed, burn, poison); + } + if (num5 > 0 && !dead) + { + TakeDamage(whoHitMe, num5, healthDmg, armorDmg, shieldDmg, slowPercentage, bleedPercentage, burnPercentage, poisonPercentage, 0f, 0f); + } + } + + private Vector4 MarkCheck() + { + Vector4 zero = Vector4.zero; + if (mark != null) + { + zero.x = mark.damage; + zero.y = mark.healthDamage; + zero.z = mark.armorDamage; + zero.w = mark.shieldDamage; + } + return zero; + } + + public Vector3 GetFuturePosition(float t) + { + float distance = currentSpeed * t; + return pathfinder.GetFuturePosition(distance); + } + + public void AtEnd() + { + GameManager.instance.TakeDamage(damageToTower + MonsterManager.instance.extraTowerDamage); + SpawnManager.instance.currentEnemies.Remove(this); + Object.Destroy(base.gameObject); + } + + private void Die() + { + if (!dead) + { + dead = true; + if (deathObjectSpawn != null) + { + Object.Instantiate(deathObjectSpawn, base.transform.position, Quaternion.identity); + } + if (treasureObject != null && spawnRange.y > 0f) + { + int numberOfDrops = Random.Range((int)spawnRange.x, (int)spawnRange.y + GameManager.instance.gameMode); + Object.Instantiate(treasureObject, base.transform.position, Quaternion.identity).GetComponent<TreasureChest>().numberOfDrops = numberOfDrops; + } + CheckBattleCries(BattleCry.BattleCryTrigger.Death); + typesOfTowers.Remove(TowerType.DOT); + if (dropsGold) + { + int num = level + typesOfTowers.Count + bonusGoldDrop + MonsterManager.instance.extraGoldDrop; + ResourceManager.instance.AddMoney(num); + ResourceManager.instance.AddManaPercentMax(MonsterManager.instance.manaDropOnDeath); + DamageTracker.instance.AddIncome(DamageTracker.IncomeType.Monster, num - MonsterManager.instance.extraGoldDrop); + DamageTracker.instance.AddIncome(DamageTracker.IncomeType.Bonus, MonsterManager.instance.extraGoldDrop); + } + SpawnManager.instance.currentEnemies.Remove(this); + SFXManager.instance.PlaySound(Sound.CoinLong, base.transform.position); + AchievementManager.instance.EnemyKilled(); + Object.Destroy(base.gameObject); + } + } +} diff --git a/Assembly_CSharp/GamePlay/Explosion.cs b/Assembly_CSharp/GamePlay/Explosion.cs new file mode 100644 index 0000000..a01aa17 --- /dev/null +++ b/Assembly_CSharp/GamePlay/Explosion.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +public class Explosion : MonoBehaviour +{ + [SerializeField] + private float duration = 2f; + + [SerializeField] + private Sound sound; + + private void Start() + { + if (sound != 0) + { + SFXManager.instance.PlaySound(sound, base.transform.position); + } + } + + private void FixedUpdate() + { + duration -= Time.fixedDeltaTime; + if (duration <= 0f) + { + Object.Destroy(base.gameObject); + } + } +} diff --git a/Assembly_CSharp/GamePlay/FlameThrower.cs b/Assembly_CSharp/GamePlay/FlameThrower.cs new file mode 100644 index 0000000..d415d88 --- /dev/null +++ b/Assembly_CSharp/GamePlay/FlameThrower.cs @@ -0,0 +1,68 @@ +using UnityEngine; + +public class FlameThrower : Tower +{ + [SerializeField] + private ParticleSystem flames; + + public bool flaming; + + private bool hasMana = true; + + [SerializeField] + private AudioSource audioS; + + private bool soundPlaying; + + protected override void Update() + { + if (hasMana && currentTarget != null && !flaming) + { + flames.Play(); + PlaySound(onOff: true); + flaming = true; + } + else if (!hasMana || (currentTarget == null && flaming)) + { + flames.Stop(); + PlaySound(onOff: false); + flaming = false; + } + base.Update(); + } + + protected override void Fire() + { + if (consumesMana) + { + int manaCost = (int)((float)base.damage * manaConsumptionRate); + if (!ResourceManager.instance.CheckMana(manaCost)) + { + hasMana = false; + return; + } + ResourceManager.instance.SpendMana(manaCost); + hasMana = true; + } + RaycastHit[] array = Physics.SphereCastAll(muzzle.position, base.range / 6f, muzzle.transform.forward, base.range * 1.5f, enemyLayerMask, QueryTriggerInteraction.Collide); + foreach (RaycastHit raycastHit in array) + { + raycastHit.collider.GetComponent<IDamageable>()?.TakeDamage(towerType, base.damage, base.healthDamage, base.armorDamage, base.shieldDamage, base.slowPercent, base.bleedPercent, base.burnPercent, base.poisonPercent, base.critChance, base.stunChance); + } + } + + private void PlaySound(bool onOff) + { + if (onOff && !soundPlaying) + { + audioS.volume = OptionsMenu.instance.masterVolume * OptionsMenu.instance.sfxVolume; + audioS.Play(); + soundPlaying = true; + } + else if (!onOff && soundPlaying) + { + audioS.Stop(); + soundPlaying = false; + } + } +} diff --git a/Assembly_CSharp/GamePlay/GameManager.cs b/Assembly_CSharp/GamePlay/GameManager.cs new file mode 100644 index 0000000..bfa59e1 --- /dev/null +++ b/Assembly_CSharp/GamePlay/GameManager.cs @@ -0,0 +1,476 @@ +using UnityEngine; +using UnityEngine.UI; + +public class GameManager : MonoBehaviour +{ + [SerializeField] + private TileManager tileManager; + + [SerializeField] + private SpawnManager spawnManager; + + public int gameMode = 3; + + [SerializeField] + private TerrainTile singleStartTile; + + [SerializeField] + private Waypoint[] singleStartWaypoints; + + [SerializeField] + private TerrainTile doubleStartTile; + + [SerializeField] + private Waypoint[] doubleStartWaypoints; + + [SerializeField] + private TerrainTile tripleStartTile; + + [SerializeField] + private Waypoint[] tripleStartWaypoints; + + public bool gameOver; + + public int health; + + public int maxHealth; + + private float healthLoss; + + [SerializeField] + private Text healthText; + + [SerializeField] + private Image maskBar; + + [SerializeField] + private Image healthBar; + + [SerializeField] + private Image healthLossBar; + + [SerializeField] + private GameObject gameOverMenu; + + [SerializeField] + private Text levelsCompletedText; + + [SerializeField] + private Text xpGainText; + + [SerializeField] + private Text newRecordText; + + [SerializeField] + private GameObject victoryScreen; + + [SerializeField] + private Text vicLevelsText; + + [SerializeField] + private Text vicLevelXpText; + + [SerializeField] + private Text vicXpBonusText; + + [SerializeField] + private Text vicNewRecordText; + + public Vector3 dotTick = 24f * Vector3.one; + + public int hauntedHouseEfficiency = 1; + + public int universityBonus; + + public static GameManager instance; + + private void Awake() + { + instance = this; + gameMode = PlayerPrefs.GetInt("GameMode", 1); + if (gameMode == 1) + { + singleStartTile.transform.Rotate(0f, 90 * Random.Range(-1, 3), 0f); + singleStartTile.SetCardinalDirections(); + tileManager.startTile = singleStartTile; + spawnManager.initialSpawns = singleStartWaypoints; + doubleStartTile.gameObject.SetActive(value: false); + tripleStartTile.gameObject.SetActive(value: false); + } + else if (gameMode == 2) + { + doubleStartTile.transform.Rotate(0f, 90 * Random.Range(-1, 3), 0f); + doubleStartTile.SetCardinalDirections(); + tileManager.startTile = doubleStartTile; + spawnManager.initialSpawns = doubleStartWaypoints; + singleStartTile.gameObject.SetActive(value: false); + tripleStartTile.gameObject.SetActive(value: false); + } + else if (gameMode == 3) + { + tripleStartTile.transform.Rotate(0f, 90 * Random.Range(-1, 3), 0f); + tripleStartTile.SetCardinalDirections(); + tileManager.startTile = tripleStartTile; + spawnManager.initialSpawns = tripleStartWaypoints; + doubleStartTile.gameObject.SetActive(value: false); + singleStartTile.gameObject.SetActive(value: false); + } + + } + + private void Start() + { + maxHealth = 100 + 10 * (PlayerPrefs.GetInt("TowerHealth1", 0) + PlayerPrefs.GetInt("TowerHealth2", 0) + PlayerPrefs.GetInt("TowerHealth3", 0) + PlayerPrefs.GetInt("TowerHealth4", 0) + PlayerPrefs.GetInt("TowerHealth5", 0) + PlayerPrefs.GetInt("TowerHealth6", 0) + PlayerPrefs.GetInt("TowerHealth7", 0) + PlayerPrefs.GetInt("TowerHealth8", 0) + PlayerPrefs.GetInt("TowerHealth9", 0) + PlayerPrefs.GetInt("TowerHealth10", 0)); + health = maxHealth; + healthLoss = maxHealth; + SetHealthBar(); + int num = 0; + num = PlayerPrefs.GetInt("BalistaPHealth", 0); + if (num > 0) + { + TowerManager.instance.AddBonusHealthDamage(TowerType.Crossbow, num); + } + num = PlayerPrefs.GetInt("BalistaPArmor", 0); + if (num > 0) + { + TowerManager.instance.AddBonusArmorDamage(TowerType.Crossbow, num); + } + num = PlayerPrefs.GetInt("BalistaPShield", 0); + if (num > 0) + { + TowerManager.instance.AddBonusShieldDamage(TowerType.Crossbow, num); + } + num = PlayerPrefs.GetInt("MortarPHealth", 0); + if (num > 0) + { + TowerManager.instance.AddBonusHealthDamage(TowerType.Morter, num); + } + num = PlayerPrefs.GetInt("MortarPArmor", 0); + if (num > 0) + { + TowerManager.instance.AddBonusArmorDamage(TowerType.Morter, num); + } + num = PlayerPrefs.GetInt("MortarPShield", 0); + if (num > 0) + { + TowerManager.instance.AddBonusShieldDamage(TowerType.Morter, num); + } + num = PlayerPrefs.GetInt("TeslaPHealth", 0); + if (num > 0) + { + TowerManager.instance.AddBonusHealthDamage(TowerType.TeslaCoil, num); + } + num = PlayerPrefs.GetInt("TeslaPArmor", 0); + if (num > 0) + { + TowerManager.instance.AddBonusArmorDamage(TowerType.TeslaCoil, num); + } + num = PlayerPrefs.GetInt("TeslaPShield", 0); + if (num > 0) + { + TowerManager.instance.AddBonusShieldDamage(TowerType.TeslaCoil, num); + } + num = PlayerPrefs.GetInt("FrostPHealth", 0); + if (num > 0) + { + TowerManager.instance.AddBonusHealthDamage(TowerType.Frost, num); + } + num = PlayerPrefs.GetInt("FrostPArmor", 0); + if (num > 0) + { + TowerManager.instance.AddBonusArmorDamage(TowerType.Frost, num); + } + num = PlayerPrefs.GetInt("FrostPShield", 0); + if (num > 0) + { + TowerManager.instance.AddBonusShieldDamage(TowerType.Frost, num); + } + num = PlayerPrefs.GetInt("FlamePHealth", 0); + if (num > 0) + { + TowerManager.instance.AddBonusHealthDamage(TowerType.FlameThrower, num); + } + num = PlayerPrefs.GetInt("FlamePArmor", 0); + if (num > 0) + { + TowerManager.instance.AddBonusArmorDamage(TowerType.FlameThrower, num); + } + num = PlayerPrefs.GetInt("FlamePShield", 0); + if (num > 0) + { + TowerManager.instance.AddBonusShieldDamage(TowerType.FlameThrower, num); + } + num = PlayerPrefs.GetInt("PoisonPHealth", 0); + if (num > 0) + { + TowerManager.instance.AddBonusHealthDamage(TowerType.PoisonSprayer, num); + } + num = PlayerPrefs.GetInt("PoisonPArmor", 0); + if (num > 0) + { + TowerManager.instance.AddBonusArmorDamage(TowerType.PoisonSprayer, num); + } + num = PlayerPrefs.GetInt("PoisonPShield", 0); + if (num > 0) + { + TowerManager.instance.AddBonusShieldDamage(TowerType.PoisonSprayer, num); + } + num = PlayerPrefs.GetInt("ShredderPHealth", 0); + if (num > 0) + { + TowerManager.instance.AddBonusHealthDamage(TowerType.Shredder, num); + } + num = PlayerPrefs.GetInt("ShredderPArmor", 0); + if (num > 0) + { + TowerManager.instance.AddBonusArmorDamage(TowerType.Shredder, num); + } + num = PlayerPrefs.GetInt("ShredderPShield", 0); + if (num > 0) + { + TowerManager.instance.AddBonusShieldDamage(TowerType.Shredder, num); + } + num = PlayerPrefs.GetInt("EncampmentPHealth", 0); + if (num > 0) + { + TowerManager.instance.AddBonusHealthDamage(TowerType.Encampment, num); + } + num = PlayerPrefs.GetInt("EncampmentPArmor", 0); + if (num > 0) + { + TowerManager.instance.AddBonusArmorDamage(TowerType.Encampment, num); + } + num = PlayerPrefs.GetInt("EncampmentPShield", 0); + if (num > 0) + { + TowerManager.instance.AddBonusShieldDamage(TowerType.Encampment, num); + } + num = PlayerPrefs.GetInt("LookoutPHealth", 0); + if (num > 0) + { + TowerManager.instance.AddBonusHealthDamage(TowerType.Lookout, num); + } + num = PlayerPrefs.GetInt("LookoutPArmor", 0); + if (num > 0) + { + TowerManager.instance.AddBonusArmorDamage(TowerType.Lookout, num); + } + num = PlayerPrefs.GetInt("LookoutPShield", 0); + if (num > 0) + { + TowerManager.instance.AddBonusShieldDamage(TowerType.Lookout, num); + } + num = PlayerPrefs.GetInt("RadarPHealth", 0); + if (num > 0) + { + TowerManager.instance.AddBonusHealthDamage(TowerType.Radar, num); + } + num = PlayerPrefs.GetInt("RadarPArmor", 0); + if (num > 0) + { + TowerManager.instance.AddBonusArmorDamage(TowerType.Radar, num); + } + num = PlayerPrefs.GetInt("RadarPShield", 0); + if (num > 0) + { + TowerManager.instance.AddBonusShieldDamage(TowerType.Radar, num); + } + num = PlayerPrefs.GetInt("ObeliskPHealth", 0); + if (num > 0) + { + TowerManager.instance.AddBonusHealthDamage(TowerType.Obelisk, num); + } + num = PlayerPrefs.GetInt("ObeliskPArmor", 0); + if (num > 0) + { + TowerManager.instance.AddBonusArmorDamage(TowerType.Obelisk, num); + } + num = PlayerPrefs.GetInt("ObeliskPShield", 0); + if (num > 0) + { + TowerManager.instance.AddBonusShieldDamage(TowerType.Obelisk, num); + } + num = PlayerPrefs.GetInt("ParticleCannonPHealth", 0); + if (num > 0) + { + TowerManager.instance.AddBonusHealthDamage(TowerType.ParticleCannon, num); + } + num = PlayerPrefs.GetInt("ParticleCannonPArmor", 0); + if (num > 0) + { + TowerManager.instance.AddBonusArmorDamage(TowerType.ParticleCannon, num); + } + num = PlayerPrefs.GetInt("ParticleCannonPShield", 0); + if (num > 0) + { + TowerManager.instance.AddBonusShieldDamage(TowerType.ParticleCannon, num); + } + } + + private void Update() + { + if (healthLoss > (float)health) + { + healthLoss = Mathf.Clamp(healthLoss - 4f * Time.deltaTime, health, healthLoss); + healthLossBar.rectTransform.sizeDelta = new Vector2(healthLoss / 10f, 0.25f); + } + } + + public void IncreaseTowerHealth(int amt) + { + maxHealth += amt * 10; + health += amt * 10; + healthLoss = health; + SetHealthBar(); + if (maxHealth / 10 >= 50) + { + AchievementManager.instance.UnlockAchievement("TowerHealth50"); + } + else if (maxHealth / 10 >= 40) + { + AchievementManager.instance.UnlockAchievement("TowerHealth40"); + } + else if (maxHealth / 10 >= 30) + { + AchievementManager.instance.UnlockAchievement("TowerHealth30"); + } + } + + private void SetHealthBar() + { + maskBar.rectTransform.localScale = new Vector3(2000 / maxHealth, 50f, 10f); + maskBar.rectTransform.sizeDelta = new Vector2((float)maxHealth / 10f, 0.25f); + healthLossBar.rectTransform.sizeDelta = new Vector2((float)health / 10f, 0.25f); + UpdateHealthText(); + } + + private void UpdateHealthText() + { + healthText.text = "Tower: " + health / 10 + "/" + maxHealth / 10; + healthBar.rectTransform.sizeDelta = new Vector2((float)health / 10f, 0.25f); + } + + public void TakeDamage(int damage) + { + health = Mathf.Max(health - 10 * damage, 0); + UpdateHealthText(); + if (health <= 0 && !gameOver) + { + gameOver = true; + GameOver(); + } + } + + public void RepairTower(int heal) + { + health = Mathf.Clamp(health + heal, 0, maxHealth); + if (healthLoss < (float)health) + { + healthLoss = health; + } + UpdateHealthText(); + } + + public void GameOverQuit() + { + if (!SpawnManager.instance.combat) + { + SpawnManager.instance.level++; + } + if (Time.timeScale != 1f) + { + Time.timeScale = 1f; + } + gameOver = true; + GameOver(); + } + + public int NaturalSum(int value) + { + return value * (value + 1) / 2; + } + + private void GameOver() + { + gameOverMenu.SetActive(value: true); + DamageTracker.instance.DisplayDamageTotals(); + int num = NaturalSum(SpawnManager.instance.level - 1) * gameMode; + int num2 = 0; + int @int = PlayerPrefs.GetInt("Record" + gameMode, 0); + if (SpawnManager.instance.level - 1 - @int > 0) + { + num2 = (NaturalSum(SpawnManager.instance.level - 1) - NaturalSum(@int)) * 3; + PlayerPrefs.SetInt("Record" + gameMode, SpawnManager.instance.level - 1); + string text = ""; + if (gameMode == 1) + { + text = "single"; + } + else if (gameMode == 2) + { + text = "double"; + } + else if (gameMode == 3) + { + text = "triple"; + } + newRecordText.text = "New " + text + " defense record!\n +" + num2 + " bonus xp"; + } + else + { + newRecordText.text = ""; + } + int int2 = PlayerPrefs.GetInt("XP", 0); + PlayerPrefs.SetInt("XP", int2 + num2); + levelsCompletedText.text = "Defended " + (SpawnManager.instance.level - 1) + " levels"; + xpGainText.text = "+" + num + " xp"; + } + + public void Victory() + { + AchievementManager.instance.CheckTowerTypesVictory(); + victoryScreen.SetActive(value: true); + DamageTracker.instance.DisplayDamageTotals(); + int num = NaturalSum(SpawnManager.instance.level - 1) * gameMode; + int num2 = SpawnManager.instance.lastLevel * gameMode * 10; + int num3 = 0; + int @int = PlayerPrefs.GetInt("Record" + gameMode, 0); + if (SpawnManager.instance.lastLevel - @int > 0) + { + num3 = (NaturalSum(SpawnManager.instance.level - 1) - NaturalSum(@int)) * 3; + PlayerPrefs.SetInt("Record" + gameMode, SpawnManager.instance.lastLevel); + string text = ""; + if (gameMode == 1) + { + text = "single"; + } + else if (gameMode == 2) + { + text = "double"; + } + else if (gameMode == 3) + { + text = "triple"; + } + vicNewRecordText.text = "New " + text + " defense record!\n +" + num3 + " bonus xp"; + } + else + { + vicNewRecordText.text = ""; + } + int int2 = PlayerPrefs.GetInt("XP", 0); + PlayerPrefs.SetInt("XP", int2 + num3 + num2); + vicLevelsText.text = "Defended all " + SpawnManager.instance.lastLevel + " levels"; + vicLevelXpText.text = "+" + num + " xp"; + vicXpBonusText.text = "+" + num2 + " xp"; + } + + public void LoadScene(string sceneName) + { + if (AchievementManager.instance != null) + { + AchievementManager.instance.OnSceneClose(); + } + LevelLoader.instance.LoadLevel(sceneName); + } +} diff --git a/Assembly_CSharp/GamePlay/HauntedHouseUpgrade.cs b/Assembly_CSharp/GamePlay/HauntedHouseUpgrade.cs new file mode 100644 index 0000000..47d4c8a --- /dev/null +++ b/Assembly_CSharp/GamePlay/HauntedHouseUpgrade.cs @@ -0,0 +1,8 @@ +public class HauntedHouseUpgrade : UpgradeCard +{ + public override void Upgrade() + { + base.Upgrade(); + GameManager.instance.hauntedHouseEfficiency++; + } +} diff --git a/Assembly_CSharp/GamePlay/IDamageable.cs b/Assembly_CSharp/GamePlay/IDamageable.cs new file mode 100644 index 0000000..d010ef5 --- /dev/null +++ b/Assembly_CSharp/GamePlay/IDamageable.cs @@ -0,0 +1,4 @@ +public interface IDamageable +{ + void TakeDamage(TowerType whoHitMe, int baseDmg, int healthDmg, int armorDmg, int shieldDmg, float slowPercentage, float bleedPercentage, float burnPercentage, float poisonPercentage, float critChance, float stunChance); +} diff --git a/Assembly_CSharp/GamePlay/IncomeGenerator.cs b/Assembly_CSharp/GamePlay/IncomeGenerator.cs new file mode 100644 index 0000000..9afd8f5 --- /dev/null +++ b/Assembly_CSharp/GamePlay/IncomeGenerator.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +public class IncomeGenerator : MonoBehaviour +{ + public int incomePerRound; + + public float incomeTimesLevel; + + [SerializeField] + private DamageTracker.IncomeType myIncomeType; + + public int netGold { get; private set; } + + protected virtual void Start() + { + SpawnManager.instance.incomeGenerators.Add(this); + netGold = 0; + } + + public virtual void GenerateIncome() + { + int num = incomePerRound + (int)(incomeTimesLevel * (float)SpawnManager.instance.level); + if (num > 0) + { + ResourceManager.instance.AddMoney(num); + netGold += num; + DamageTracker.instance.AddIncome(myIncomeType, num); + SFXManager.instance.PlaySound(Sound.CoinShort, base.transform.position); + DamageNumber component = ObjectPool.instance.SpawnObject(ObjectPool.ObjectType.DamageNumber, base.transform.position, Quaternion.identity).GetComponent<DamageNumber>(); + component.SetText("+" + num + "g", "Grey", 1f); + component.SetHoldTime(2.5f); + } + } + + public void RemoveIncomeGeneration() + { + SpawnManager.instance.incomeGenerators.Remove(this); + } +} diff --git a/Assembly_CSharp/GamePlay/Lookout.cs b/Assembly_CSharp/GamePlay/Lookout.cs new file mode 100644 index 0000000..3abd55b --- /dev/null +++ b/Assembly_CSharp/GamePlay/Lookout.cs @@ -0,0 +1,97 @@ +using UnityEngine; + +public class Lookout : Tower +{ + [SerializeField] + private GameObject markIcon; + + private GameObject currentMark; + + protected override void Update() + { + if (currentTarget != null) + { + markIcon.SetActive(value: true); + UpdateMark(); + GainXP(); + } + else + { + markIcon.SetActive(value: false); + } + } + + private void UpdateMark() + { + if (currentTarget != currentMark) + { + if (currentMark != null) + { + currentMark.GetComponent<Enemy>().mark = null; + } + currentMark = currentTarget; + currentMark.GetComponent<Enemy>().mark = this; + } + markIcon.transform.position = currentMark.transform.position; + } + + protected override GameObject SelectEnemy(Collider[] possibleTargets) + { + GameObject result = null; + float num = -1f; + for (int i = 0; i < possibleTargets.Length; i++) + { + float num2 = 1f; + Enemy component = possibleTargets[i].GetComponent<Enemy>(); + if (!(component.mark != this) || !(component.mark != null)) + { + if (CheckPriority(Priority.Progress)) + { + num2 /= Mathf.Max(0.001f, possibleTargets[i].GetComponent<Pathfinder>().distanceFromEnd); + } + if (CheckPriority(Priority.NearDeath)) + { + num2 /= Mathf.Max(0.001f, component.CurrentHealth()); + } + if (CheckPriority(Priority.MostHealth)) + { + num2 *= (float)Mathf.Max(1, component.health); + } + if (CheckPriority(Priority.MostArmor)) + { + num2 *= (float)Mathf.Max(1, component.armor); + } + if (CheckPriority(Priority.MostShield)) + { + num2 *= (float)Mathf.Max(1, component.shield); + } + if (CheckPriority(Priority.LeastHealth)) + { + num2 /= (float)Mathf.Max(1, component.health); + } + if (CheckPriority(Priority.LeastArmor)) + { + num2 /= (float)Mathf.Max(1, component.armor); + } + if (CheckPriority(Priority.LeastShield)) + { + num2 /= (float)Mathf.Max(1, component.shield); + } + if (CheckPriority(Priority.Fastest)) + { + num2 *= Mathf.Max(0.001f, possibleTargets[i].GetComponent<Pathfinder>().speed); + } + if (CheckPriority(Priority.Slowest)) + { + num2 /= Mathf.Max(0.001f, possibleTargets[i].GetComponent<Pathfinder>().speed); + } + if (num2 > num) + { + result = component.gameObject; + num = num2; + } + } + } + return result; + } +} diff --git a/Assembly_CSharp/GamePlay/MonsterManager.cs b/Assembly_CSharp/GamePlay/MonsterManager.cs new file mode 100644 index 0000000..40a7a35 --- /dev/null +++ b/Assembly_CSharp/GamePlay/MonsterManager.cs @@ -0,0 +1,43 @@ +using UnityEngine; + +public class MonsterManager : MonoBehaviour +{ + public static MonsterManager instance; + + public int extraTowerDamage; + + public int extraGoldDrop; + + public float manaDropOnDeath; + + public float speedBonus; + + public int bonusDamageOnBleed; + + public int bonusDamageOnBurn; + + public int bonusDamageOnPoison; + + public int bonusDamageOnStun; + + public float poisonSlowPercent; + + public float burnSpeedDamagePercentBonus; + + public float bleedingCritChance; + + public float bleedPop; + + public float burnPop; + + public float poisonPop; + + public float slowCapModifier; + + public float hasteCapModifier; + + private void Awake() + { + instance = this; + } +} diff --git a/Assembly_CSharp/GamePlay/Morter.cs b/Assembly_CSharp/GamePlay/Morter.cs new file mode 100644 index 0000000..2170da3 --- /dev/null +++ b/Assembly_CSharp/GamePlay/Morter.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +public class Morter : Tower +{ + protected override void AimTurret() + { + } + + protected override void Fire() + { + if (consumesMana) + { + int manaCost = (int)((float)base.damage * finalManaConsumption); + if (!ResourceManager.instance.CheckMana(manaCost)) + { + return; + } + ResourceManager.instance.SpendMana(manaCost); + } + float num = projectileSpeed * Mathf.Clamp(Vector3.SqrMagnitude(currentTarget.transform.position - base.transform.position) / (2f * baseRange * baseRange), 1f, float.MaxValue); + Vector3 vector = currentTarget.GetComponent<Enemy>().GetFuturePosition(num) - turret.transform.position; + GameObject gameObject = Object.Instantiate(rotation: Quaternion.LookRotation(new Vector3(vector.x, 0f, vector.z), Vector3.up), original: projectile, position: muzzle.position); + gameObject.GetComponent<Projectile>().SetStats(towerType, currentTarget, num, base.damage, base.healthDamage, base.armorDamage, base.shieldDamage, base.slowPercent, base.bleedPercent, base.burnPercent, base.poisonPercent, base.critChance, base.stunChance); + gameObject.GetComponent<MorterShell>().SetMorterPhysics(currentTarget.GetComponent<Enemy>().GetFuturePosition(num)); + gameObject.GetComponent<MorterShell>().blastRadius = base.blastRadius; + if (extraProjectileFX != null) + { + GameObject gameObject2 = Object.Instantiate(extraProjectileFX, gameObject.transform.position, gameObject.transform.rotation); + gameObject2.transform.SetParent(gameObject.transform); + gameObject2.GetComponent<ProjectileFX>().SetFX(base.bleedPercent, base.burnPercent, base.poisonPercent, base.slowPercent, consumesMana); + Projectile component = gameObject.GetComponent<Projectile>(); + if (component.detachOnDestruction == null) + { + component.detachOnDestruction = gameObject2; + component.extraFX = gameObject2.GetComponent<ProjectileFX>(); + } + } + } +} diff --git a/Assembly_CSharp/GamePlay/MorterShell.cs b/Assembly_CSharp/GamePlay/MorterShell.cs new file mode 100644 index 0000000..ce93441 --- /dev/null +++ b/Assembly_CSharp/GamePlay/MorterShell.cs @@ -0,0 +1,81 @@ +using UnityEngine; + +public class MorterShell : Projectile +{ + [SerializeField] + private GameObject artObject; + + [SerializeField] + private LayerMask layersAffectedByBlast; + + public float blastRadius = 1f; + + private Vector3 destination; + + private float timeOfFlight; + + [SerializeField] + private float vSpeed; + + [SerializeField] + private float hSpeed; + + [SerializeField] + private float gravity = 5f; + + [SerializeField] + private GameObject explosion; + + private float lookAhead; + + private Vector3 previousPos; + + public void SetMorterPhysics(Vector3 pos) + { + destination = pos; + timeOfFlight = speed; + vSpeed = gravity * timeOfFlight / 2f; + hSpeed = Vector3.Magnitude(base.transform.position - destination) / timeOfFlight; + lookAhead = vSpeed + hSpeed; + } + + protected override void MoveProjectile() + { + previousPos = base.transform.position; + base.transform.Translate(Vector3.forward * hSpeed * Time.fixedDeltaTime); + base.transform.Translate(Vector3.up * vSpeed * Time.fixedDeltaTime); + vSpeed -= gravity * Time.fixedDeltaTime; + artObject.transform.rotation = Quaternion.LookRotation(base.transform.position - previousPos, Vector3.up); + } + + protected override void CheckForHits() + { + if (!(vSpeed > 0f) && Physics.Raycast(artObject.transform.position, artObject.transform.forward, out var hitInfo, lookAhead * Time.fixedDeltaTime, layermask, QueryTriggerInteraction.Collide)) + { + OnHit(hitInfo); + } + } + + protected override void OnHit(RaycastHit hit) + { + Collider[] array = Physics.OverlapSphere(base.transform.position, blastRadius, layersAffectedByBlast, QueryTriggerInteraction.Collide); + for (int i = 0; i < array.Length; i++) + { + IDamageable component = array[i].GetComponent<IDamageable>(); + if (component != null) + { + DealDamage(component); + } + } + if (detachOnDestruction != null) + { + detachOnDestruction.transform.parent = null; + } + if (extraFX != null) + { + extraFX.OnDetach(); + } + Object.Instantiate(explosion, base.transform.position, Quaternion.identity); + Object.Destroy(base.gameObject); + } +} diff --git a/Assembly_CSharp/GamePlay/Obelisk.cs b/Assembly_CSharp/GamePlay/Obelisk.cs new file mode 100644 index 0000000..549f3b4 --- /dev/null +++ b/Assembly_CSharp/GamePlay/Obelisk.cs @@ -0,0 +1,99 @@ +using UnityEngine; + +public class Obelisk : Tower +{ + [SerializeField] + private GameObject beam; + + [SerializeField] + private AudioSource audioS; + + private bool soundPlaying; + + private IDamageable lastThingIHit; + + private float timeOnTarget; + + protected override void Update() + { + if (currentTarget != null) + { + if (turret != null) + { + AimTurret(); + } + GainXP(); + } + else + { + beam.SetActive(value: false); + PlaySound(onOff: false); + } + timeSinceLastShot += Time.deltaTime; + if (currentTarget != null && timeSinceLastShot > rps) + { + Fire(); + timeSinceLastShot = 0f; + } + } + + protected override void Fire() + { + if (consumesMana) + { + int manaCost = (int)((float)base.damage * manaConsumptionRate); + if (!ResourceManager.instance.CheckMana(manaCost)) + { + beam.SetActive(value: false); + PlaySound(onOff: false); + return; + } + ResourceManager.instance.SpendMana(manaCost); + } + DealDamage(); + } + + protected override void AimTurret() + { + Vector3 forward = currentTarget.transform.position - turret.transform.position + Vector3.up * 0.5f; + Quaternion rotation = Quaternion.LookRotation(forward, Vector3.up); + turret.transform.rotation = rotation; + beam.transform.localScale = new Vector3(1f, 1f, forward.magnitude); + } + + private void DealDamage() + { + IDamageable component = currentTarget.GetComponent<IDamageable>(); + if (component != null) + { + if (component == lastThingIHit) + { + timeOnTarget += rps; + } + else + { + timeOnTarget = 0f; + lastThingIHit = component; + } + int num = Mathf.Clamp(Mathf.FloorToInt(timeOnTarget * TowerManager.instance.obeliskTimeOnTargetMultiplier), 0, base.damage); + component.TakeDamage(towerType, base.damage + num, base.healthDamage, base.armorDamage, base.shieldDamage, base.slowPercent, base.bleedPercent, base.burnPercent, base.poisonPercent, base.critChance, base.stunChance); + beam.SetActive(value: true); + PlaySound(onOff: true); + } + } + + private void PlaySound(bool onOff) + { + if (onOff && !soundPlaying) + { + audioS.volume = OptionsMenu.instance.masterVolume * OptionsMenu.instance.sfxVolume; + audioS.Play(); + soundPlaying = true; + } + else if (!onOff && soundPlaying) + { + audioS.Stop(); + soundPlaying = false; + } + } +} diff --git a/Assembly_CSharp/GamePlay/ParticleBeam.cs b/Assembly_CSharp/GamePlay/ParticleBeam.cs new file mode 100644 index 0000000..6a7bf2a --- /dev/null +++ b/Assembly_CSharp/GamePlay/ParticleBeam.cs @@ -0,0 +1,19 @@ +using UnityEngine; + +public class ParticleBeam : Projectile +{ + [SerializeField] + private GameObject beamTrail; + + protected override void MoveProjectile() + { + base.MoveProjectile(); + beamTrail.transform.position = base.transform.position + new Vector3(Random.Range(-1f, 1f), Random.Range(0f, 1f), Random.Range(-1f, 1f)); + } + + protected new virtual void OnHit(RaycastHit hit) + { + beamTrail.transform.position = hit.point; + base.OnHit(hit); + } +} diff --git a/Assembly_CSharp/GamePlay/Pathfinder.cs b/Assembly_CSharp/GamePlay/Pathfinder.cs new file mode 100644 index 0000000..5426574 --- /dev/null +++ b/Assembly_CSharp/GamePlay/Pathfinder.cs @@ -0,0 +1,91 @@ +using UnityEngine; + +public class Pathfinder : MonoBehaviour +{ + public float distanceFromEnd = 2.1474836E+09f; + + public bool atEnd; + + public float speed = 1f; + + public Waypoint currentWaypoint; + + [SerializeField] + private Enemy enemyScript; + + private void Start() + { + if (enemyScript == null) + { + enemyScript = GetComponent<Enemy>(); + } + } + + private void FixedUpdate() + { + CheckWaypointDistance(); + Move(); + } + + private void Move() + { + Vector3 vector = currentWaypoint.transform.position - base.transform.position; + vector.Normalize(); + base.transform.Translate(vector * speed * Time.fixedDeltaTime); + distanceFromEnd -= speed * Time.fixedDeltaTime; + } + + private void CheckWaypointDistance() + { + if (Vector3.SqrMagnitude(currentWaypoint.transform.position - base.transform.position) < 4f * speed * speed * Time.fixedDeltaTime * Time.fixedDeltaTime && !GetNewWaypoint()) + { + atEnd = true; + enemyScript.AtEnd(); + } + } + + public Vector3 GetFuturePosition(float distance) + { + Vector3 position = base.transform.position; + Waypoint nextWaypoint = currentWaypoint; + float num = distance; + int num2 = 0; + while (num > 0f) + { + if (Vector3.SqrMagnitude(nextWaypoint.transform.position - position) >= num * num) + { + return position + (nextWaypoint.transform.position - position).normalized * num; + } + if (nextWaypoint.GetNextWaypoint() == nextWaypoint) + { + return nextWaypoint.transform.position; + } + num -= Vector3.Magnitude(nextWaypoint.transform.position - position); + position = nextWaypoint.transform.position; + nextWaypoint = nextWaypoint.GetNextWaypoint(); + num2++; + if (num2 > 100) + { + Debug.LogError("GetFuturePosition looping too much"); + break; + } + } + Debug.LogError("GetFuturePosition broken"); + return Vector3.zero; + } + + private bool GetNewWaypoint() + { + if (currentWaypoint.GetNextWaypoint() == currentWaypoint) + { + return false; + } + distanceFromEnd = currentWaypoint.distanceFromEnd; + currentWaypoint = currentWaypoint.GetNextWaypoint(); + if (distanceFromEnd <= 24f) + { + enemyScript.CheckBattleCries(BattleCry.BattleCryTrigger.NearEnd); + } + return true; + } +} diff --git a/Assembly_CSharp/GamePlay/Projectile.cs b/Assembly_CSharp/GamePlay/Projectile.cs new file mode 100644 index 0000000..3c15fe4 --- /dev/null +++ b/Assembly_CSharp/GamePlay/Projectile.cs @@ -0,0 +1,141 @@ +using UnityEngine; + +public class Projectile : MonoBehaviour +{ + [SerializeField] + protected Sound launchSound; + + [SerializeField] + protected Sound hitSound; + + protected TowerType shotBy; + + [SerializeField] + protected LayerMask layermask; + + [SerializeField] + protected float speed; + + [SerializeField] + protected bool homing; + + [SerializeField] + protected float maximumLifeTime = 10f; + + [SerializeField] + public GameObject detachOnDestruction; + + [SerializeField] + public ProjectileFX extraFX; + + protected GameObject target; + + protected int damage; + + protected int healthDamage; + + protected int armorDamage; + + protected int shieldDamage; + + protected float slowPercent; + + protected float bleedPercent; + + protected float burnPercent; + + protected float poisonPercent; + + protected float critChance; + + protected float stunChance; + + protected virtual void Start() + { + if (launchSound != 0) + { + SFXManager.instance.PlaySound(launchSound, base.transform.position); + } + } + + protected virtual void FixedUpdate() + { + maximumLifeTime -= Time.fixedDeltaTime; + if (maximumLifeTime < 0f) + { + Object.Destroy(base.gameObject); + } + CheckForHits(); + MoveProjectile(); + if (homing) + { + AlterCourse(); + } + } + + public virtual void SetStats(TowerType whoShotMe, GameObject _target, float spd, int dmg, int healthDmg, int armorDmg, int shieldDmg, float slow, float bleed, float burn, float poison, float crit, float stun) + { + shotBy = whoShotMe; + target = _target; + speed = spd; + damage = dmg; + healthDamage = healthDmg; + armorDamage = armorDmg; + shieldDamage = shieldDmg; + slowPercent = slow; + bleedPercent = bleed; + burnPercent = burn; + poisonPercent = poison; + critChance = crit; + stunChance = stun; + } + + protected virtual void MoveProjectile() + { + base.transform.Translate(Vector3.forward * speed * Time.fixedDeltaTime); + } + + protected virtual void AlterCourse() + { + if (!(target == null)) + { + Quaternion rotation = Quaternion.LookRotation(0.25f * Vector3.up + target.transform.position - base.transform.position, Vector3.up); + base.transform.rotation = rotation; + } + } + + protected virtual void CheckForHits() + { + if (Physics.Raycast(base.transform.position, base.transform.forward, out var hitInfo, speed * Time.fixedDeltaTime, layermask, QueryTriggerInteraction.Collide)) + { + OnHit(hitInfo); + } + } + + protected virtual void OnHit(RaycastHit hit) + { + IDamageable component = hit.transform.GetComponent<IDamageable>(); + if (component != null) + { + DealDamage(component); + } + if (detachOnDestruction != null) + { + detachOnDestruction.transform.parent = null; + } + if (extraFX != null) + { + extraFX.OnDetach(); + } + Object.Destroy(base.gameObject); + } + + protected virtual void DealDamage(IDamageable target) + { + target.TakeDamage(shotBy, damage, healthDamage, armorDamage, shieldDamage, slowPercent, bleedPercent, burnPercent, poisonPercent, critChance, stunChance); + if (hitSound != 0) + { + SFXManager.instance.PlaySound(hitSound, base.transform.position); + } + } +} diff --git a/Assembly_CSharp/GamePlay/ProjectileFX.cs b/Assembly_CSharp/GamePlay/ProjectileFX.cs new file mode 100644 index 0000000..df82c3d --- /dev/null +++ b/Assembly_CSharp/GamePlay/ProjectileFX.cs @@ -0,0 +1,47 @@ +using System.Collections; +using UnityEngine; + +public class ProjectileFX : MonoBehaviour +{ + [SerializeField] + private GameObject bleedingPS; + + [SerializeField] + private GameObject burrningPS; + + [SerializeField] + private GameObject poisonPS; + + public void SetFX(float bleeding, float burning, float poison, float slow, bool arcane) + { + if (OptionsMenu.instance.extraProjectileEffects) + { + if (bleeding > 0f) + { + bleedingPS.SetActive(value: true); + } + if (burning > 0f) + { + burrningPS.SetActive(value: true); + } + if (poison > 0f) + { + poisonPS.SetActive(value: true); + } + } + } + + public void OnDetach() + { + StartCoroutine(Die()); + } + + private IEnumerator Die() + { + bleedingPS.GetComponent<ParticleSystem>().Stop(withChildren: true); + burrningPS.GetComponent<ParticleSystem>().Stop(withChildren: true); + poisonPS.GetComponent<ParticleSystem>().Stop(withChildren: true); + yield return new WaitForSeconds(1.1f); + Object.Destroy(base.gameObject); + } +} diff --git a/Assembly_CSharp/GamePlay/RadarTower.cs b/Assembly_CSharp/GamePlay/RadarTower.cs new file mode 100644 index 0000000..e0d8d1d --- /dev/null +++ b/Assembly_CSharp/GamePlay/RadarTower.cs @@ -0,0 +1,71 @@ +using UnityEngine; + +public class RadarTower : Tower +{ + [SerializeField] + private GameObject biPlanePrefab; + + [SerializeField] + private BiPlane myPlane; + + protected override void Start() + { + if (myPlane == null) + { + myPlane = Object.Instantiate(biPlanePrefab, base.transform.position + new Vector3(-50f, 5f, 0f), Quaternion.identity).GetComponent<BiPlane>(); + } + base.Start(); + } + + public override void SetStats() + { + base.SetStats(); + if (myPlane == null) + { + myPlane = Object.Instantiate(biPlanePrefab, base.transform.position + new Vector3(-50f, 5f, 0f), Quaternion.identity).GetComponent<BiPlane>(); + } + myPlane.damage = base.damage; + myPlane.healthDamage = base.healthDamage; + myPlane.armorDamage = base.armorDamage; + myPlane.shieldDamage = base.shieldDamage; + myPlane.rps = rps; + myPlane.slowPercent = base.slowPercent; + myPlane.bleedPercent = base.bleedPercent; + myPlane.burnPercent = base.burnPercent; + myPlane.poisonPercent = base.poisonPercent; + myPlane.critChance = base.critChance; + myPlane.stunChance = base.stunChance; + } + + protected override void Update() + { + if (currentTarget != null) + { + if (turret != null) + { + AimTurret(); + } + GainXP(); + } + timeSinceLastShot += Time.deltaTime; + if (currentTarget != null && timeSinceLastShot > 3f) + { + SendTargetInfo(currentTarget); + timeSinceLastShot = 0f; + } + } + + private void SendTargetInfo(GameObject target) + { + if (myPlane.target == null) + { + myPlane.target = target; + } + } + + public override void Demolish() + { + Object.Destroy(myPlane.gameObject); + base.Demolish(); + } +} diff --git a/Assembly_CSharp/GamePlay/Sawblade.cs b/Assembly_CSharp/GamePlay/Sawblade.cs new file mode 100644 index 0000000..19038df --- /dev/null +++ b/Assembly_CSharp/GamePlay/Sawblade.cs @@ -0,0 +1,87 @@ +using System.Collections.Generic; +using UnityEngine; + +public class Sawblade : Projectile +{ + private Pathfinder targetPathfinder; + + private Waypoint nextWaypoint; + + private bool pathMode; + + private HashSet<Collider> targetsHit = new HashSet<Collider>(); + + public override void SetStats(TowerType whoShotMe, GameObject _target, float spd, int dmg, int healthDmg, int armorDmg, int shieldDmg, float slow, float bleed, float burn, float poison, float crit, float stun) + { + base.SetStats(whoShotMe, _target, spd, dmg, healthDmg, armorDmg, shieldDmg, slow, bleed, burn, poison, crit, stun); + targetPathfinder = target.GetComponent<Pathfinder>(); + nextWaypoint = targetPathfinder.currentWaypoint; + } + + protected override void AlterCourse() + { + if (!pathMode && targetPathfinder != null) + { + nextWaypoint = targetPathfinder.currentWaypoint; + } + if (!pathMode && (target == null || Vector3.SqrMagnitude(target.transform.position - base.transform.position) < 0.125f)) + { + nextWaypoint = GetPreviousWaypoint(); + pathMode = true; + } + Vector3 position; + if (!pathMode) + { + position = target.transform.position; + } + else + { + if (Vector3.SqrMagnitude(nextWaypoint.transform.position - base.transform.position) < 0.125f) + { + nextWaypoint = GetPreviousWaypoint(); + } + position = nextWaypoint.transform.position; + } + Quaternion rotation = Quaternion.LookRotation(position - base.transform.position, Vector3.up); + base.transform.rotation = rotation; + } + + protected override void CheckForHits() + { + Collider[] array = Physics.OverlapBox(base.transform.position, Vector3.one * 0.25f, Quaternion.identity, layermask, QueryTriggerInteraction.Collide); + foreach (Collider collider in array) + { + if (!pathMode && collider.gameObject == target) + { + nextWaypoint = GetPreviousWaypoint(); + pathMode = true; + } + if (targetsHit.Contains(collider)) + { + continue; + } + IDamageable component = collider.GetComponent<IDamageable>(); + if (component != null) + { + DealDamage(component); + damage--; + if (damage <= 0) + { + Object.Destroy(base.gameObject); + } + } + targetsHit.Add(collider); + } + } + + private Waypoint GetPreviousWaypoint() + { + Waypoint[] previousWaypoints = nextWaypoint.GetPreviousWaypoints(); + if (previousWaypoints.Length == 0) + { + Object.Destroy(base.gameObject); + return nextWaypoint; + } + return previousWaypoints[Random.Range(0, previousWaypoints.Length)]; + } +} diff --git a/Assembly_CSharp/GamePlay/SlowRotate.cs b/Assembly_CSharp/GamePlay/SlowRotate.cs new file mode 100644 index 0000000..7a0306a --- /dev/null +++ b/Assembly_CSharp/GamePlay/SlowRotate.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class SlowRotate : MonoBehaviour +{ + [SerializeField] + private Vector3 rotation; + + private void Update() + { + base.transform.localEulerAngles += rotation * Time.deltaTime; + } +} diff --git a/Assembly_CSharp/GamePlay/SnowFlake.cs b/Assembly_CSharp/GamePlay/SnowFlake.cs new file mode 100644 index 0000000..238b829 --- /dev/null +++ b/Assembly_CSharp/GamePlay/SnowFlake.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +public class SnowFlake : Projectile +{ + protected override void Start() + { + base.Start(); + base.transform.Translate(new Vector3(Random.Range(-0.25f, 0.25f), Random.Range(-0.25f, 0.25f), Random.Range(-0.25f, 0.25f))); + } + + protected override void MoveProjectile() + { + base.transform.Translate(Vector3.down * speed * Time.fixedDeltaTime); + } + + protected override void CheckForHits() + { + if (Physics.SphereCast(base.transform.position, 0.125f, Vector3.down, out var hitInfo, speed * Time.fixedDeltaTime, layermask, QueryTriggerInteraction.Collide)) + { + OnHit(hitInfo); + } + } +} diff --git a/Assembly_CSharp/GamePlay/SpawnManager.cs b/Assembly_CSharp/GamePlay/SpawnManager.cs new file mode 100644 index 0000000..4e66c04 --- /dev/null +++ b/Assembly_CSharp/GamePlay/SpawnManager.cs @@ -0,0 +1,495 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +public class SpawnManager : MonoBehaviour +{ + public static SpawnManager instance; + + public Waypoint[] initialSpawns; + + private HashSet<Waypoint> spawnPoints = new HashSet<Waypoint>(); + + public HashSet<IncomeGenerator> incomeGenerators = new HashSet<IncomeGenerator>(); + + public HashSet<University> universities = new HashSet<University>(); + + public HashSet<Mine> mines = new HashSet<Mine>(); + + public HashSet<House> houses = new HashSet<House>(); + + public HashSet<GameObject> destroyOnNewLevel = new HashSet<GameObject>(); + + public HashSet<GameObject> tileSpawnUis = new HashSet<GameObject>(); + + public HashSet<Enemy> currentEnemies = new HashSet<Enemy>(); + + public bool combat; + + private float levelTime; + + [SerializeField] + private Text levelText; + + [SerializeField] + private Text scoreText; + + [SerializeField] + private int cardDrawFrequency = 5; + + [SerializeField] + private float baseRepairChance; + + public int level; + + public int lastLevel = 30; + + [SerializeField] + private GameObject level1Enemy; + + [SerializeField] + private GameObject level3Enemy; + + [SerializeField] + private GameObject level5Enemy; + + [SerializeField] + private GameObject level7Enemy; + + [SerializeField] + private GameObject level9Enemy; + + [SerializeField] + private GameObject level12Enemy; + + [SerializeField] + private GameObject level16Enemy; + + [SerializeField] + private GameObject level18Enemy; + + [SerializeField] + private GameObject level20Enemy; + + [SerializeField] + private GameObject level21Enemy; + + [SerializeField] + private GameObject level23Enemy; + + [SerializeField] + private GameObject level26Enemy; + + [SerializeField] + private GameObject level28Enemy; + + [SerializeField] + private GameObject level30Enemy; + + [SerializeField] + private GameObject level32Enemy; + + [SerializeField] + private GameObject level36Enemy; + + [SerializeField] + private GameObject level38Enemy; + + [SerializeField] + private GameObject level40Enemy; + + [SerializeField] + private GameObject level15Boss; + + [SerializeField] + private GameObject level25Boss; + + [SerializeField] + private GameObject level35Boss; + + [SerializeField] + private GameObject level45Boss; + + [SerializeField] + private LightManager lightManager; + + [SerializeField] + private int secondStageLightLevel; + + [SerializeField] + private int thirdStageLightLevel; + + [SerializeField] + private int fourthStageLightLevel; + + private void Awake() + { + instance = this; + } + + private void Start() + { + Waypoint[] array = initialSpawns; + foreach (Waypoint item in array) + { + spawnPoints.Add(item); + } + levelText.text = "Level: " + level; + scoreText.text = "Score: " + 0; + cardDrawFrequency = 3 - PlayerPrefs.GetInt("CardFreq1", 0) - PlayerPrefs.GetInt("CardFreq2", 0); + baseRepairChance = 34f * (float)(PlayerPrefs.GetInt("TowerRepair1", 0) + PlayerPrefs.GetInt("TowerRepair2", 0) + PlayerPrefs.GetInt("TowerRepair3", 0)); + } + + private void Update() + { + if (combat && currentEnemies.Count == 0 && !GameManager.instance.gameOver && levelTime > 2f) + { + EndWave(); + } + else + { + levelTime += Time.deltaTime; + } + } + + private void EndWave() + { + combat = false; + AchievementManager.instance.BeatLevel(level); + int @int = PlayerPrefs.GetInt("XP", 0); + PlayerPrefs.SetInt("XP", @int + level * GameManager.instance.gameMode); + scoreText.text = "Score: " + GameManager.instance.NaturalSum(level) * GameManager.instance.gameMode; + if (level >= lastLevel) + { + GameManager.instance.Victory(); + return; + } + ShowSpawnUIs(state: true); + if (level % cardDrawFrequency == 0) + { + ShowSpawnUIs(state: false); + CardManager.instance.DrawCards(); + } + if (level == 15 || level == 25 || level == 35) + { + MusicManager.instance.FadeOut(6f); + } + else + { + MusicManager.instance.SetIntensity(action: false); + } + GameObject[] array = new GameObject[destroyOnNewLevel.Count]; + destroyOnNewLevel.CopyTo(array); + GameObject[] array2 = array; + foreach (GameObject gameObject in array2) + { + destroyOnNewLevel.Remove(gameObject); + Object.Destroy(gameObject); + } + if (tileSpawnUis.Count == 0) + { + Debug.Log("I GUESS ILL JUST DIE THEN"); + AchievementManager.instance.UnlockAchievement("NoMorePaths"); + StartNextWave(); + } + } + + public void StartNextWave() + { + levelTime = 0f; + UpdateSpawnPoints(); + float num = 1f - (float)(GameManager.instance.health / GameManager.instance.maxHealth); + if (Random.Range(1f, 100f) <= baseRepairChance * num) + { + GameManager.instance.RepairTower(10); + } + level++; + levelText.text = "Level: " + level; + if (level == secondStageLightLevel) + { + lightManager.ChangeColor(2); + } + else if (level == thirdStageLightLevel) + { + lightManager.ChangeColor(3); + } + else if (level == fourthStageLightLevel) + { + lightManager.ChangeColor(4); + } + if (level == 15 || level == 25 || level == 35 || level == 45) + { + SpawnBoss(level); + } + if (level == 16) + { + MusicManager.instance.PlaySong(1, action: true); + } + else if (level == 26) + { + MusicManager.instance.PlaySong(2, action: true); + } + else if (level == 36) + { + MusicManager.instance.PlaySong(3, action: true); + } + else if (level > 1) + { + MusicManager.instance.SetIntensity(action: true); + } + StartCoroutine(Spawn(level * level)); + combat = true; + ShowSpawnUIs(state: false); + foreach (House house in houses) + { + if (house != null) + { + house.CheckTowers(); + } + } + foreach (IncomeGenerator incomeGenerator in incomeGenerators) + { + if (incomeGenerator != null) + { + incomeGenerator.GenerateIncome(); + } + } + foreach (University university in universities) + { + if (university != null) + { + university.Research(); + } + } + foreach (Mine mine in mines) + { + if (mine != null) + { + mine.Repair(); + } + } + } + + public void ShowSpawnUIs(bool state) + { + foreach (GameObject tileSpawnUi in tileSpawnUis) + { + tileSpawnUi.SetActive(state); + } + } + + private void SpawnBoss(int lvl) + { + Waypoint spawnLocation = null; + float num = -1f; + foreach (Waypoint spawnPoint in spawnPoints) + { + if (spawnPoint.distanceFromEnd > num) + { + num = spawnPoint.distanceFromEnd; + spawnLocation = spawnPoint; + } + } + switch (lvl) + { + case 15: + SpawnEnemy(level15Boss, spawnLocation); + break; + case 25: + SpawnEnemy(level25Boss, spawnLocation); + break; + case 35: + SpawnEnemy(level35Boss, spawnLocation); + break; + case 45: + SpawnEnemy(level45Boss, spawnLocation); + break; + } + } + + private IEnumerator Spawn(int num) + { + int safetyCount = level * level + 100; + int count = num; + float t = 0.5f / (float)spawnPoints.Count; + while (count > 0) + { + foreach (Waypoint spawnPoint in spawnPoints) + { + if (count <= 0) + { + break; + } + count -= SpawnSelection(spawnPoint); + yield return new WaitForSeconds(t); + } + safetyCount--; + if (safetyCount <= 0) + { + Debug.LogError("Spawn loop might be looping infinitely"); + break; + } + } + } + + private int SpawnSelection(Waypoint spawnPoint) + { + if (level >= 40 && Random.Range(1f, 100f) < 10f) + { + SpawnEnemy(level40Enemy, spawnPoint); + return 10; + } + if (level >= 38 && Random.Range(1f, 100f) < 10f) + { + SpawnEnemy(level38Enemy, spawnPoint); + return 10; + } + if (level >= 36 && Random.Range(1f, 100f) < 12f) + { + SpawnEnemy(level36Enemy, spawnPoint); + return 9; + } + if (level >= 32 && Random.Range(1f, 100f) < 10f) + { + SpawnEnemy(level32Enemy, spawnPoint); + return 10; + } + if (level >= 30 && Random.Range(1f, 100f) < 10f) + { + SpawnEnemy(level30Enemy, spawnPoint); + return 10; + } + if (level >= 28 && Random.Range(1f, 100f) < 11f) + { + SpawnEnemy(level28Enemy, spawnPoint); + return 10; + } + if (level >= 26 && Random.Range(1f, 100f) < 12f) + { + SpawnEnemy(level26Enemy, spawnPoint); + return 7; + } + if (level >= 23 && Random.Range(1f, 100f) < 9f) + { + SpawnEnemy(level23Enemy, spawnPoint); + return 12; + } + if (level >= 21 && Random.Range(1f, 100f) < 10f) + { + SpawnEnemy(level21Enemy, spawnPoint); + return 10; + } + if (level >= 20 && Random.Range(1f, 100f) < 10f) + { + SpawnEnemy(level20Enemy, spawnPoint); + return 10; + } + if (level >= 18 && Random.Range(1f, 100f) < 12f) + { + SpawnEnemy(level18Enemy, spawnPoint); + return 9; + } + if (level >= 16 && Random.Range(1f, 100f) < 13f) + { + SpawnEnemy(level16Enemy, spawnPoint); + return 8; + } + if (level >= 12 && Random.Range(1f, 100f) < 9f) + { + SpawnEnemy(level12Enemy, spawnPoint); + return 12; + } + if (level >= 9 && Random.Range(1f, 100f) < 12f) + { + SpawnEnemy(level9Enemy, spawnPoint); + return 9; + } + if (level >= 7 && Random.Range(1f, 100f) < 14f) + { + SpawnEnemy(level7Enemy, spawnPoint); + return 7; + } + if (level >= 5 && Random.Range(1f, 100f) < 20f) + { + SpawnEnemy(level5Enemy, spawnPoint); + return 5; + } + if (level >= 3 && Random.Range(1f, 100f) < 34f) + { + SpawnEnemy(level3Enemy, spawnPoint); + return 3; + } + SpawnEnemy(level1Enemy, spawnPoint); + return 1; + } + + private void SpawnEnemy(GameObject unit, Waypoint spawnLocation) + { + Enemy component = Object.Instantiate(unit, spawnLocation.transform.position, Quaternion.identity).GetComponent<Enemy>(); + component.SetStats(); + component.SetFirstSpawnPoint(spawnLocation); + currentEnemies.Add(component); + } + + private void UpdateSpawnPoints() + { + List<Waypoint> list = new List<Waypoint>(); + List<Waypoint> list2 = new List<Waypoint>(); + foreach (Waypoint spawnPoint in spawnPoints) + { + if (!CheckSpawnPoint(spawnPoint)) + { + continue; + } + list.Add(spawnPoint); + foreach (Waypoint newSpawnPoint in GetNewSpawnPoints(spawnPoint, 1)) + { + list2.Add(newSpawnPoint); + } + } + foreach (Waypoint item in list) + { + spawnPoints.Remove(item); + } + foreach (Waypoint item2 in list2) + { + spawnPoints.Add(item2); + } + } + + private bool CheckSpawnPoint(Waypoint point) + { + if (point.GetPreviousWaypoints().Length != 0) + { + return true; + } + return false; + } + + private List<Waypoint> GetNewSpawnPoints(Waypoint start, int count) + { + if (count > 100) + { + Debug.LogError("Possible infinite loop while finding new spawn points (count over 100)"); + return null; + } + Waypoint[] previousWaypoints = start.GetPreviousWaypoints(); + List<Waypoint> list = new List<Waypoint>(); + if (previousWaypoints.Length == 0) + { + list.Add(start); + return list; + } + count++; + Waypoint[] array = previousWaypoints; + foreach (Waypoint start2 in array) + { + foreach (Waypoint newSpawnPoint in GetNewSpawnPoints(start2, count)) + { + list.Add(newSpawnPoint); + } + } + return list; + } +} diff --git a/Assembly_CSharp/GamePlay/SpawnableObject.cs b/Assembly_CSharp/GamePlay/SpawnableObject.cs new file mode 100644 index 0000000..fd7b169 --- /dev/null +++ b/Assembly_CSharp/GamePlay/SpawnableObject.cs @@ -0,0 +1,54 @@ +using UnityEngine; + +public class SpawnableObject : MonoBehaviour, IBuildable +{ + [SerializeField] + private GameObject artStuff; + + [SerializeField] + private bool randomRotation = true; + + [SerializeField] + private float spawnChance; + + [SerializeField] + private Vector2 spawnLevels; + + [SerializeField] + protected GameObject UIObject; + + protected bool spawned; + + protected virtual void Start() + { + if ((float)SpawnManager.instance.level >= spawnLevels.x && (float)SpawnManager.instance.level <= spawnLevels.y && Random.Range(1f, 100f) < 100f * spawnChance) + { + if (randomRotation) + { + artStuff.transform.eulerAngles = new Vector3(0f, Random.Range(0, 4) * 90, 0f); + } + artStuff.SetActive(value: true); + spawned = true; + } + else + { + Object.Destroy(base.gameObject); + } + } + + public void SetStats() + { + } + + public virtual void SpawnUI() + { + if (UIObject != null) + { + Object.Instantiate(UIObject, base.transform.position, Quaternion.identity); + } + } + + public void Demolish() + { + } +} diff --git a/Assembly_CSharp/GamePlay/TerrainTile.cs b/Assembly_CSharp/GamePlay/TerrainTile.cs new file mode 100644 index 0000000..932ff37 --- /dev/null +++ b/Assembly_CSharp/GamePlay/TerrainTile.cs @@ -0,0 +1,87 @@ +using UnityEngine; + +public class TerrainTile : MonoBehaviour +{ + public Waypoint last; + + [SerializeField] + private Waypoint left; + + [SerializeField] + private Waypoint top; + + [SerializeField] + private Waypoint right; + + public Waypoint south; + + public Waypoint west; + + public Waypoint north; + + public Waypoint east; + + public void SetCardinalDirections() + { + if (base.transform.eulerAngles.y == 0f) + { + south = last; + west = left; + north = top; + east = right; + } + else if (base.transform.eulerAngles.y == 90f) + { + south = right; + west = last; + north = left; + east = top; + } + else if (base.transform.eulerAngles.y == 180f) + { + south = top; + west = right; + north = last; + east = left; + } + else if (base.transform.eulerAngles.y == 270f) + { + south = left; + west = top; + north = right; + east = last; + } + else + { + Debug.LogError(base.name + " not at a proper rotation. Current rotation: " + base.transform.eulerAngles.y); + } + } + + public void ConnectToTile(TerrainTile next) + { + if (base.transform.eulerAngles.y == 0f) + { + last.SetNextWaypoint(next.north); + next.north.AddPreviousWaypoint(last); + } + else if (base.transform.eulerAngles.y == 90f) + { + last.SetNextWaypoint(next.east); + next.east.AddPreviousWaypoint(last); + } + else if (base.transform.eulerAngles.y == 180f) + { + last.SetNextWaypoint(next.south); + next.south.AddPreviousWaypoint(last); + } + else if (base.transform.eulerAngles.y == 270f) + { + last.SetNextWaypoint(next.west); + next.west.AddPreviousWaypoint(last); + } + else + { + Debug.LogError(base.name + " not at a proper rotation"); + } + } +} diff --git a/Assembly_CSharp/GamePlay/TileManager.cs b/Assembly_CSharp/GamePlay/TileManager.cs new file mode 100644 index 0000000..592d861 --- /dev/null +++ b/Assembly_CSharp/GamePlay/TileManager.cs @@ -0,0 +1,236 @@ +using System.Collections.Generic; +using UnityEngine; + +public class TileManager : MonoBehaviour +{ + public static TileManager instance; + + [SerializeField] + private GameObject tilePlacementFXObject; + + [SerializeField] + private GameObject[] deadEndTiles; + + [SerializeField] + private GameObject[] Ltiles; + + [SerializeField] + private GameObject[] Ttiles; + + [SerializeField] + private GameObject[] Rtiles; + + [SerializeField] + private GameObject[] LTtiles; + + [SerializeField] + private GameObject[] LRtiles; + + [SerializeField] + private GameObject[] TRtiles; + + [SerializeField] + private GameObject[] LTRtiles; + + public TerrainTile startTile; + + [SerializeField] + private GameObject tileSpawnLocation; + + private int[,] intArray = new int[99, 99]; + + private TerrainTile[,] tileArray = new TerrainTile[99, 99]; + + private void Awake() + { + instance = this; + } + + private void Start() + { + intArray[50, 50] = 1; + tileArray[50, 50] = startTile; + for (int i = 0; i < 99; i++) + { + intArray[0, i] = 1; + intArray[i, 0] = 1; + intArray[98, i] = 1; + intArray[i, 98] = 1; + } + UpdateIntArrayFromTile(startTile, 50, 50); + } + + private void UpdateIntArrayFromTile(TerrainTile tile, int posX, int posY) + { + if (tile.south != null && tile.south != tile.last && intArray[posX, posY - 1] == 0) + { + intArray[posX, posY - 1] = 2; + TileSpawnLocation component = Object.Instantiate(tileSpawnLocation, new Vector3(posX - 50, 0f, posY - 1 - 50) * 7f, Quaternion.identity).GetComponent<TileSpawnLocation>(); + component.eulerAngle = 180; + component.posX = posX; + component.posY = posY - 1; + } + if (tile.west != null && tile.west != tile.last && intArray[posX - 1, posY] == 0) + { + intArray[posX - 1, posY] = 2; + TileSpawnLocation component2 = Object.Instantiate(tileSpawnLocation, new Vector3(posX - 1 - 50, 0f, posY - 50) * 7f, Quaternion.identity).GetComponent<TileSpawnLocation>(); + component2.eulerAngle = 270; + component2.posX = posX - 1; + component2.posY = posY; + } + if (tile.north != null && tile.north != tile.last && intArray[posX, posY + 1] == 0) + { + intArray[posX, posY + 1] = 2; + TileSpawnLocation component3 = Object.Instantiate(tileSpawnLocation, new Vector3(posX - 50, 0f, posY + 1 - 50) * 7f, Quaternion.identity).GetComponent<TileSpawnLocation>(); + component3.eulerAngle = 0; + component3.posX = posX; + component3.posY = posY + 1; + } + if (tile.east != null && tile.east != tile.last && intArray[posX + 1, posY] == 0) + { + intArray[posX + 1, posY] = 2; + TileSpawnLocation component4 = Object.Instantiate(tileSpawnLocation, new Vector3(posX + 1 - 50, 0f, posY - 50) * 7f, Quaternion.identity).GetComponent<TileSpawnLocation>(); + component4.eulerAngle = 90; + component4.posX = posX + 1; + component4.posY = posY; + } + } + + public void SpawnNewTile(int posX, int posY, int eulerAngle) + { + bool flag = false; + bool flag2 = false; + bool flag3 = false; + bool flag4 = false; + if (intArray[posX, posY - 1] == 0) + { + flag = true; + } + if (intArray[posX - 1, posY] == 0) + { + flag2 = true; + } + if (intArray[posX, posY + 1] == 0) + { + flag3 = true; + } + if (intArray[posX + 1, posY] == 0) + { + flag4 = true; + } + bool flag5 = false; + bool flag6 = false; + bool flag7 = false; + switch (eulerAngle) + { + case 0: + flag5 = flag2; + flag6 = flag3; + flag7 = flag4; + break; + case 90: + flag5 = flag3; + flag6 = flag4; + flag7 = flag; + break; + case 180: + flag5 = flag4; + flag6 = flag; + flag7 = flag2; + break; + case 270: + flag5 = flag; + flag6 = flag2; + flag7 = flag3; + break; + default: + Debug.LogError("Trying to spawn a tile at an invalid eulerAngle" + eulerAngle); + break; + } + List<GameObject> list = new List<GameObject>(); + int num = SpawnManager.instance.lastLevel - SpawnManager.instance.level; + int count = SpawnManager.instance.tileSpawnUis.Count; + bool flag8 = false; + bool flag9 = false; + if (count + 3 >= num || SpawnManager.instance.level < 3) + { + flag8 = true; + } + if (count == num) + { + flag9 = true; + } + if (!flag9) + { + if (flag5) + { + list.AddRange(Ltiles); + } + if (flag6) + { + list.AddRange(Ttiles); + } + if (flag7) + { + list.AddRange(Rtiles); + } + if (flag5 && flag6 && !flag8) + { + list.AddRange(LTtiles); + } + if (flag5 && flag7 && !flag8) + { + list.AddRange(LRtiles); + } + if (flag6 && flag7 && !flag8) + { + list.AddRange(TRtiles); + } + if (flag5 && flag6 && flag7 && !flag8) + { + list.AddRange(LTRtiles); + } + } + if (list.Count == 0) + { + list.AddRange(deadEndTiles); + } + GameObject original = list[Random.Range(0, list.Count)]; + Vector3 vector = new Vector3(posX - 50, 0f, posY - 50) * 7f; + GameObject obj = Object.Instantiate(original, vector, Quaternion.identity); + obj.transform.eulerAngles = new Vector3(0f, eulerAngle, 0f); + intArray[posX, posY] = 1; + TerrainTile component = obj.GetComponent<TerrainTile>(); + tileArray[posX, posY] = component; + component.SetCardinalDirections(); + UpdateIntArrayFromTile(component, posX, posY); + TerrainTile terrainTile = null; + switch (eulerAngle) + { + case 0: + terrainTile = tileArray[posX, posY - 1]; + break; + case 90: + terrainTile = tileArray[posX - 1, posY]; + break; + case 180: + terrainTile = tileArray[posX, posY + 1]; + break; + case 270: + terrainTile = tileArray[posX + 1, posY]; + break; + default: + Debug.LogError("Trying to spawn a tile at an invalid eulerAngle" + eulerAngle); + break; + } + if (terrainTile == null) + { + Debug.LogError("Unable to find previous tile"); + } + component.ConnectToTile(terrainTile); + if (tilePlacementFXObject != null) + { + Object.Instantiate(tilePlacementFXObject, vector + Vector3.up, Quaternion.identity).transform.localScale = Vector3.one * 7f; + } + } +} diff --git a/Assembly_CSharp/GamePlay/TileSpawnLocation.cs b/Assembly_CSharp/GamePlay/TileSpawnLocation.cs new file mode 100644 index 0000000..e1575b1 --- /dev/null +++ b/Assembly_CSharp/GamePlay/TileSpawnLocation.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +public class TileSpawnLocation : MonoBehaviour +{ + public int eulerAngle; + + public int posX; + + public int posY; + + private void Start() + { + SpawnManager.instance.tileSpawnUis.Add(base.gameObject); + if (SpawnManager.instance.combat) + { + base.gameObject.SetActive(value: false); + } + } + + public void SpawnTile() + { + TileManager.instance.SpawnNewTile(posX, posY, eulerAngle); + SpawnManager.instance.tileSpawnUis.Remove(base.gameObject); + SpawnManager.instance.StartNextWave(); + Object.Destroy(base.gameObject); + } +} diff --git a/Assembly_CSharp/GamePlay/Tower.cs b/Assembly_CSharp/GamePlay/Tower.cs new file mode 100644 index 0000000..4098bd6 --- /dev/null +++ b/Assembly_CSharp/GamePlay/Tower.cs @@ -0,0 +1,509 @@ +using UnityEngine; + +public class Tower : MonoBehaviour, IBuildable +{ + public enum Priority + { + Progress, + NearDeath, + MostHealth, + MostArmor, + MostShield, + LeastHealth, + LeastArmor, + LeastShield, + Fastest, + Slowest, + Marked + } + + public TowerType towerType; + + public bool squareUI; + + [SerializeField] + protected GameObject towerUI; + + public Priority[] priorities = new Priority[3]; + + [SerializeField] + protected GameObject turret; + + [SerializeField] + protected bool towerVerticalyAims = true; + + [SerializeField] + protected Transform muzzle; + + [SerializeField] + protected GameObject projectile; + + [SerializeField] + protected float projectileSpeed = 10f; + + [SerializeField] + protected GameObject extraProjectileFX; + + [SerializeField] + protected int baseDamage; + + [SerializeField] + protected int baseHealthDamage; + + [SerializeField] + protected int baseArmorDamage; + + [SerializeField] + protected int baseShieldDamage; + + public float rpm; + + protected float rps; + + [SerializeField] + protected float baseRange; + + [SerializeField] + protected float baseSlowPercentage; + + [SerializeField] + protected float baseBleedPercentage; + + [SerializeField] + protected float baseBurnPercentage; + + [SerializeField] + protected float basePoisonPercentage; + + [SerializeField] + protected LayerMask enemyLayerMask; + + [SerializeField] + protected LayerMask buildingLayerMask; + + public bool consumesMana; + + public float manaConsumptionRate; + + public float finalManaConsumption; + + public int upgradeCostMultiplier = 1; + + private int damageUpgrade; + + private int healthDamageUpgrade; + + private int armorDamageUpgrade; + + private int shieldDamageUpgrade; + + private int heightBonus; + + protected float timeSinceLastShot; + + private float lastTargetUpdate = 1f; + + protected GameObject currentTarget; + + [SerializeField] + protected float baseBlastRadius; + + public int level { get; private set; } + + public float healthXP { get; private set; } + + public float armorXP { get; private set; } + + public float shieldXP { get; private set; } + + public int damage { get; private set; } + + public int healthDamage { get; private set; } + + public int armorDamage { get; private set; } + + public int shieldDamage { get; private set; } + + public float range { get; private set; } + + public float slowPercent { get; private set; } + + public float bleedPercent { get; private set; } + + public float burnPercent { get; private set; } + + public float poisonPercent { get; private set; } + + public float critChance { get; private set; } + + public float stunChance { get; private set; } + + public float blastRadius { get; private set; } + + protected virtual void Start() + { + level = 1; + SetStats(); + TowerManager.instance.AddNewTower(this, towerType); + DetectHouses(); + priorities[0] = (priorities[1] = (priorities[2] = Priority.Progress)); + } + + public virtual void SetStats() + { + heightBonus = (int)Mathf.Round(base.transform.position.y * 3f - 1f); + damage = Mathf.Max(baseDamage + heightBonus + damageUpgrade + TowerManager.instance.GetBonusBaseDamage(towerType), 0); + healthDamage = baseHealthDamage + healthDamageUpgrade + TowerManager.instance.GetBonusHealthDamage(towerType); + armorDamage = baseArmorDamage + armorDamageUpgrade + TowerManager.instance.GetBonusArmorDamage(towerType); + shieldDamage = baseShieldDamage + shieldDamageUpgrade + TowerManager.instance.GetBonusShieldDamage(towerType); + rps = 60f / rpm; + range = baseRange + (float)heightBonus / 2f + TowerManager.instance.GetBonusRange(towerType); + slowPercent = baseSlowPercentage + TowerManager.instance.GetBonusSlow(towerType); + bleedPercent = baseBleedPercentage + TowerManager.instance.GetBonusBleed(towerType); + burnPercent = baseBurnPercentage + TowerManager.instance.GetBonusBurn(towerType); + poisonPercent = basePoisonPercentage + TowerManager.instance.GetBonusPoison(towerType); + blastRadius = baseBlastRadius + TowerManager.instance.GetBonusBlast(towerType); + finalManaConsumption = manaConsumptionRate + TowerManager.instance.GetManaConsumptionBonus(towerType); + if (TowerManager.instance.GetManaConsumptionBonus(towerType) > 0f) + { + consumesMana = true; + } + critChance = TowerManager.instance.GetCritChance(towerType) + TowerManager.instance.GetCritChanceLevelMultiplier(towerType) * (float)level / 100f; + stunChance = TowerManager.instance.GetStunChance(towerType); + } + + private void FixedUpdate() + { + if (lastTargetUpdate <= 0f) + { + DetectEnemies(); + } + else + { + lastTargetUpdate -= Time.fixedDeltaTime; + } + } + + protected virtual void Update() + { + if (currentTarget != null) + { + if (turret != null) + { + AimTurret(); + } + GainXP(); + } + timeSinceLastShot += Time.deltaTime; + if (currentTarget != null && timeSinceLastShot > rps) + { + Fire(); + timeSinceLastShot = 0f; + } + } + + private void DetectHouses() + { + if (Physics.Raycast(base.transform.position + new Vector3(1f, 1f, 0f), -base.transform.up, out var hitInfo, 1f, buildingLayerMask, QueryTriggerInteraction.Ignore)) + { + CheckForHouse(hitInfo); + } + if (Physics.Raycast(base.transform.position + new Vector3(-1f, 1f, 0f), -base.transform.up, out hitInfo, 1f, buildingLayerMask, QueryTriggerInteraction.Ignore)) + { + CheckForHouse(hitInfo); + } + if (Physics.Raycast(base.transform.position + new Vector3(0f, 1f, 1f), -base.transform.up, out hitInfo, 1f, buildingLayerMask, QueryTriggerInteraction.Ignore)) + { + CheckForHouse(hitInfo); + } + if (Physics.Raycast(base.transform.position + new Vector3(0f, 1f, -1f), -base.transform.up, out hitInfo, 1f, buildingLayerMask, QueryTriggerInteraction.Ignore)) + { + CheckForHouse(hitInfo); + } + } + + private void CheckForHouse(RaycastHit hit) + { + if (hit.collider.GetComponent<House>() != null && (double)Mathf.Abs(hit.collider.transform.position.y - base.transform.position.y) <= 0.001) + { + hit.collider.GetComponent<House>().AddDefender(this); + } + } + + public void TogglePriority(int index, int direction) + { + priorities[index] = (Priority)(((int)(priorities[index] + direction) % 11 + 11) % 11); + } + + protected virtual void Fire() + { + if (consumesMana) + { + int manaCost = (int)((float)damage * finalManaConsumption); + if (!ResourceManager.instance.CheckMana(manaCost)) + { + return; + } + ResourceManager.instance.SpendMana(manaCost); + } + GameObject gameObject = Object.Instantiate(projectile, muzzle.position, muzzle.rotation); + gameObject.GetComponent<Projectile>().SetStats(towerType, currentTarget, projectileSpeed, damage, healthDamage, armorDamage, shieldDamage, slowPercent, bleedPercent, burnPercent, poisonPercent, critChance, stunChance); + if (extraProjectileFX != null) + { + GameObject gameObject2 = Object.Instantiate(extraProjectileFX, gameObject.transform.position, gameObject.transform.rotation); + gameObject2.transform.SetParent(gameObject.transform); + gameObject2.GetComponent<ProjectileFX>().SetFX(bleedPercent, burnPercent, poisonPercent, slowPercent, consumesMana); + Projectile component = gameObject.GetComponent<Projectile>(); + if (component.detachOnDestruction == null) + { + component.detachOnDestruction = gameObject2; + component.extraFX = gameObject2.GetComponent<ProjectileFX>(); + } + } + } + + protected virtual void AimTurret() + { + Vector3 forward = currentTarget.transform.position - turret.transform.position; + if (!towerVerticalyAims) + { + forward.y = 0f; + } + Quaternion rotation = Quaternion.LookRotation(forward, Vector3.up); + turret.transform.rotation = rotation; + } + + protected void GainXP() + { + Enemy component = currentTarget.GetComponent<Enemy>(); + if (component != null) + { + if (component.shield > 0) + { + shieldXP += Time.deltaTime / (2f * range) + Time.deltaTime / 2f; + } + else if (component.armor > 0) + { + armorXP += Time.deltaTime / (2f * range) + Time.deltaTime / 2f; + } + else + { + healthXP += Time.deltaTime / (2f * range) + Time.deltaTime / 2f; + } + CheckXPAndLevelUp(); + } + } + + private void CheckXPAndLevelUp() + { + if (healthXP >= (float)(10 * level)) + { + healthXP -= 10 * level; + level++; + damageUpgrade++; + healthDamageUpgrade++; + SetStats(); + LevelUpText(); + } + if (armorXP >= (float)(10 * level)) + { + armorXP -= 10 * level; + level++; + damageUpgrade++; + armorDamageUpgrade++; + SetStats(); + LevelUpText(); + } + if (shieldXP >= (float)(10 * level)) + { + shieldXP -= 10 * level; + level++; + damageUpgrade++; + shieldDamageUpgrade++; + SetStats(); + LevelUpText(); + } + } + + private void LevelUpText() + { + Object.Instantiate(BuildingManager.instance.levelUpFX, base.transform.position, Quaternion.identity); + DamageNumber component = ObjectPool.instance.SpawnObject(ObjectPool.ObjectType.DamageNumber, base.transform.position, Quaternion.identity).GetComponent<DamageNumber>(); + component.SetText("LEVEL UP!", "Grey", 1f); + component.SetHoldTime(1f); + AchievementManager.instance.TowerLevel(level); + } + + public void BuyHealthLevel() + { + int num = (10 * level - (int)healthXP) * upgradeCostMultiplier; + if (ResourceManager.instance.CheckMoney(num)) + { + ResourceManager.instance.Spend(num); + DamageTracker.instance.AddCost(towerType, num); + healthXP -= 10 * level - num / upgradeCostMultiplier; + level++; + damageUpgrade++; + healthDamageUpgrade++; + SetStats(); + LevelUpText(); + } + } + + public void BuyArmorLevel() + { + int num = (10 * level - (int)armorXP) * upgradeCostMultiplier; + if (ResourceManager.instance.CheckMoney(num)) + { + ResourceManager.instance.Spend(num); + DamageTracker.instance.AddCost(towerType, num); + armorXP -= 10 * level - num / upgradeCostMultiplier; + level++; + damageUpgrade++; + armorDamageUpgrade++; + SetStats(); + LevelUpText(); + } + } + + public void BuyShieldLevel() + { + int num = (10 * level - (int)shieldXP) * upgradeCostMultiplier; + if (ResourceManager.instance.CheckMoney(num)) + { + ResourceManager.instance.Spend(num); + DamageTracker.instance.AddCost(towerType, num); + shieldXP -= 10 * level - num / upgradeCostMultiplier; + level++; + damageUpgrade++; + shieldDamageUpgrade++; + SetStats(); + LevelUpText(); + } + } + + private void DetectEnemies() + { + Collider[] array = Physics.OverlapSphere(base.transform.position, range, enemyLayerMask, QueryTriggerInteraction.Collide); + if (array.Length != 0) + { + currentTarget = SelectEnemy(array); + } + else + { + currentTarget = null; + } + lastTargetUpdate = Random.Range(0.25f, 1f); + } + + protected bool CheckPriority(Priority check) + { + for (int i = 0; i < priorities.Length; i++) + { + if (check == priorities[i]) + { + return true; + } + } + return false; + } + + protected int PriorityScale(Priority check) + { + for (int i = 0; i < priorities.Length; i++) + { + if (check == priorities[i]) + { + return Mathf.Clamp(3 - i, 1, 3); + } + } + return 1; + } + + protected virtual GameObject SelectEnemy(Collider[] possibleTargets) + { + GameObject result = null; + float num = -1f; + for (int i = 0; i < possibleTargets.Length; i++) + { + float num2 = 1f; + Enemy component = possibleTargets[i].GetComponent<Enemy>(); + if (CheckPriority(Priority.Progress)) + { + float f = Mathf.Max(0.001f, possibleTargets[i].GetComponent<Pathfinder>().distanceFromEnd); + num2 /= Mathf.Pow(f, PriorityScale(Priority.Progress)); + } + if (CheckPriority(Priority.NearDeath)) + { + float f2 = Mathf.Max(0.001f, component.CurrentHealth()); + num2 /= Mathf.Pow(f2, PriorityScale(Priority.NearDeath)); + } + if (CheckPriority(Priority.MostHealth)) + { + float f3 = (float)Mathf.Max(1, component.health) / 1000f; + num2 *= Mathf.Pow(f3, PriorityScale(Priority.MostHealth)); + } + if (CheckPriority(Priority.MostArmor)) + { + float f4 = (float)Mathf.Max(1, component.armor) / 1000f; + num2 *= Mathf.Pow(f4, PriorityScale(Priority.MostArmor)); + } + if (CheckPriority(Priority.MostShield)) + { + float f5 = (float)Mathf.Max(1, component.shield) / 1000f; + num2 *= Mathf.Pow(f5, PriorityScale(Priority.MostShield)); + } + if (CheckPriority(Priority.LeastHealth)) + { + float f6 = Mathf.Max(1, component.health); + num2 /= Mathf.Pow(f6, PriorityScale(Priority.LeastHealth)); + } + if (CheckPriority(Priority.LeastArmor)) + { + float f7 = Mathf.Max(1, component.armor); + num2 /= Mathf.Pow(f7, PriorityScale(Priority.LeastArmor)); + } + if (CheckPriority(Priority.LeastShield)) + { + float f8 = Mathf.Max(1, component.shield); + num2 /= Mathf.Pow(f8, PriorityScale(Priority.LeastShield)); + } + if (CheckPriority(Priority.Fastest)) + { + float f9 = Mathf.Max(0.001f, possibleTargets[i].GetComponent<Pathfinder>().speed); + num2 *= Mathf.Pow(f9, PriorityScale(Priority.Fastest)); + } + if (CheckPriority(Priority.Slowest)) + { + float f10 = Mathf.Max(0.001f, possibleTargets[i].GetComponent<Pathfinder>().speed); + num2 /= Mathf.Pow(f10, PriorityScale(Priority.Slowest)); + } + if (CheckPriority(Priority.Marked)) + { + float f11 = 1f; + if (component.mark != null) + { + f11 = (float)(component.mark.damage * (component.mark.healthDamage + component.mark.armorDamage + component.mark.shieldDamage)) * (1f + component.mark.critChance); + } + num2 *= Mathf.Pow(f11, PriorityScale(Priority.Marked)); + } + if (num2 > num) + { + result = component.gameObject; + num = num2; + } + } + return result; + } + + public void SpawnUI() + { + Object.Instantiate(towerUI, base.transform.position, Quaternion.identity).GetComponent<TowerUI>().SetStats(this); + } + + public virtual void Demolish() + { + TowerManager.instance.RemoveTower(this, towerType); + Object.Destroy(base.gameObject); + } +} diff --git a/Assembly_CSharp/GamePlay/TowerFlyweight.cs b/Assembly_CSharp/GamePlay/TowerFlyweight.cs new file mode 100644 index 0000000..b63f8b4 --- /dev/null +++ b/Assembly_CSharp/GamePlay/TowerFlyweight.cs @@ -0,0 +1,279 @@ +using System.Collections.Generic; +using UnityEngine; + +public class TowerFlyweight : MonoBehaviour +{ + private HashSet<Tower> towers = new HashSet<Tower>(); + + [SerializeField] + private BuildButtonUI myBuildButton; + + [SerializeField] + private int basePrice; + + [SerializeField] + public int priceIncrease; + + [SerializeField] + public int currentPrice; + + [SerializeField] + public int sellPrice; + + [SerializeField] + public float bonusRange; + + [SerializeField] + public int bonusBaseDamage; + + [SerializeField] + public int bonusHealthDamage; + + [SerializeField] + public int bonusArmorDamage; + + [SerializeField] + public int bonusShieldDamage; + + [SerializeField] + public float bonusSlow; + + [SerializeField] + public float bonusBleed; + + [SerializeField] + public float bonusBurn; + + [SerializeField] + public float bonusPoison; + + [SerializeField] + public float bonusBlast; + + [SerializeField] + public float critChance; + + [SerializeField] + public float critChanceLevelMultiplier; + + [SerializeField] + public float stunChance; + + [SerializeField] + public float manaConsumptionAddition; + + [SerializeField] + private TowerType towerTypeForDamageTracker; + + public void AddNewTower(Tower newTower) + { + towers.Add(newTower); + currentPrice = basePrice + towers.Count * priceIncrease; + sellPrice = basePrice + (towers.Count - 1) * priceIncrease; + myBuildButton.UpdatePriceText(); + } + + public void RemoveTower(Tower newTower) + { + towers.Remove(newTower); + currentPrice = basePrice + towers.Count * priceIncrease; + sellPrice = basePrice + (towers.Count - 1) * priceIncrease; + myBuildButton.UpdatePriceText(); + ResourceManager.instance.AddMoney(basePrice + towers.Count * priceIncrease); + DamageTracker.instance.AddCost(towerTypeForDamageTracker, -(basePrice + towers.Count * priceIncrease)); + } + + public void UpdateTowerStats() + { + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddManaAddition(float bonus) + { + manaConsumptionAddition += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddStunChance(float bonus) + { + stunChance += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddCritChance(float bonus) + { + critChance += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddCritChanceLevelMultiplier(float bonus) + { + critChanceLevelMultiplier += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddBonusRange(float bonus) + { + bonusRange += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddBonusBaseDamage(int bonus) + { + bonusBaseDamage += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddBonusHealthDamage(int bonus) + { + bonusHealthDamage += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddBonusArmorDamage(int bonus) + { + bonusArmorDamage += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddBonusShieldDamage(int bonus) + { + bonusShieldDamage += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddBonusSlow(float bonus) + { + bonusSlow += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddBonusBleed(float bonus) + { + bonusBleed += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddBonusBurn(float bonus) + { + bonusBurn += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddBonusPoison(float bonus) + { + bonusPoison += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } + + public void AddBonusBlast(float bonus) + { + bonusBlast += bonus; + foreach (Tower tower in towers) + { + tower.SetStats(); + } + if (myBuildButton != null) + { + myBuildButton.UpdateModifiersText(); + } + } +} diff --git a/Assembly_CSharp/GamePlay/TowerManager.cs b/Assembly_CSharp/GamePlay/TowerManager.cs new file mode 100644 index 0000000..abdca52 --- /dev/null +++ b/Assembly_CSharp/GamePlay/TowerManager.cs @@ -0,0 +1,1386 @@ +using System.Collections.Generic; +using UnityEngine; + +public class TowerManager : MonoBehaviour +{ + public static TowerManager instance; + + [SerializeField] + private TowerFlyweight global; + + [SerializeField] + private TowerFlyweight crossbow; + + [SerializeField] + private TowerFlyweight morter; + + [SerializeField] + private TowerFlyweight teslaCoil; + + [SerializeField] + private TowerFlyweight flameThrower; + + [SerializeField] + private TowerFlyweight poisonSprayer; + + [SerializeField] + private TowerFlyweight frostKeep; + + [SerializeField] + private TowerFlyweight radar; + + [SerializeField] + private TowerFlyweight obelisk; + + [SerializeField] + private TowerFlyweight particleCannon; + + [SerializeField] + private TowerFlyweight shredder; + + [SerializeField] + private TowerFlyweight encampment; + + [SerializeField] + private TowerFlyweight lookout; + + [SerializeField] + private TowerFlyweight siphon; + + public HashSet<TowerType> towersUsed = new HashSet<TowerType>(); + + private bool usedAllTowers; + + public float obeliskTimeOnTargetMultiplier; + + private void Awake() + { + instance = this; + } + + public void AddNewTower(Tower t, TowerType type) + { + if (type != TowerType.Siphon) + { + towersUsed.Add(type); + } + if (!usedAllTowers) + { + usedAllTowers = AchievementManager.instance.CheckAllTowers(); + } + switch (type) + { + case TowerType.Crossbow: + crossbow.AddNewTower(t); + break; + case TowerType.Morter: + morter.AddNewTower(t); + break; + case TowerType.TeslaCoil: + teslaCoil.AddNewTower(t); + break; + case TowerType.FlameThrower: + flameThrower.AddNewTower(t); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddNewTower(t); + break; + case TowerType.Frost: + frostKeep.AddNewTower(t); + break; + case TowerType.Radar: + radar.AddNewTower(t); + break; + case TowerType.Obelisk: + obelisk.AddNewTower(t); + break; + case TowerType.ParticleCannon: + particleCannon.AddNewTower(t); + break; + case TowerType.Shredder: + shredder.AddNewTower(t); + break; + case TowerType.Encampment: + encampment.AddNewTower(t); + break; + case TowerType.Lookout: + lookout.AddNewTower(t); + break; + default: + Debug.LogError("Failed to add tower to flyweight"); + break; + } + } + + public void RemoveTower(Tower t, TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.RemoveTower(t); + break; + case TowerType.Morter: + morter.RemoveTower(t); + break; + case TowerType.TeslaCoil: + teslaCoil.RemoveTower(t); + break; + case TowerType.FlameThrower: + flameThrower.RemoveTower(t); + break; + case TowerType.PoisonSprayer: + poisonSprayer.RemoveTower(t); + break; + case TowerType.Frost: + frostKeep.RemoveTower(t); + break; + case TowerType.Obelisk: + obelisk.RemoveTower(t); + break; + case TowerType.Radar: + radar.RemoveTower(t); + break; + case TowerType.ParticleCannon: + particleCannon.RemoveTower(t); + break; + case TowerType.Shredder: + shredder.RemoveTower(t); + break; + case TowerType.Encampment: + encampment.RemoveTower(t); + break; + case TowerType.Lookout: + lookout.RemoveTower(t); + break; + default: + Debug.LogError("Failed to add tower to flyweight"); + break; + } + } + + public void UpdateAllTowers() + { + crossbow.UpdateTowerStats(); + morter.UpdateTowerStats(); + teslaCoil.UpdateTowerStats(); + flameThrower.UpdateTowerStats(); + poisonSprayer.UpdateTowerStats(); + frostKeep.UpdateTowerStats(); + radar.UpdateTowerStats(); + obelisk.UpdateTowerStats(); + particleCannon.UpdateTowerStats(); + shredder.UpdateTowerStats(); + encampment.UpdateTowerStats(); + lookout.UpdateTowerStats(); + } + + public int GetSellPrice(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return crossbow.sellPrice; + case TowerType.Morter: + return morter.sellPrice; + case TowerType.TeslaCoil: + return teslaCoil.sellPrice; + case TowerType.FlameThrower: + return flameThrower.sellPrice; + case TowerType.PoisonSprayer: + return poisonSprayer.sellPrice; + case TowerType.Frost: + return frostKeep.sellPrice; + case TowerType.Obelisk: + return obelisk.sellPrice; + case TowerType.Radar: + return radar.sellPrice; + case TowerType.ParticleCannon: + return particleCannon.sellPrice; + case TowerType.Shredder: + return shredder.sellPrice; + case TowerType.Encampment: + return encampment.sellPrice; + case TowerType.Lookout: + return lookout.sellPrice; + default: + Debug.LogError("Failed to add tower to flyweight"); + return -1; + } + } + + public float GetManaConsumptionBonus(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.manaConsumptionAddition + crossbow.manaConsumptionAddition; + case TowerType.Morter: + return global.manaConsumptionAddition + morter.manaConsumptionAddition; + case TowerType.TeslaCoil: + return global.manaConsumptionAddition + teslaCoil.manaConsumptionAddition; + case TowerType.FlameThrower: + return global.manaConsumptionAddition + flameThrower.manaConsumptionAddition; + case TowerType.PoisonSprayer: + return global.manaConsumptionAddition + poisonSprayer.manaConsumptionAddition; + case TowerType.Frost: + return global.manaConsumptionAddition + frostKeep.manaConsumptionAddition; + case TowerType.Radar: + return global.manaConsumptionAddition + radar.manaConsumptionAddition; + case TowerType.Obelisk: + return global.manaConsumptionAddition + obelisk.manaConsumptionAddition; + case TowerType.ParticleCannon: + return global.manaConsumptionAddition + particleCannon.manaConsumptionAddition; + case TowerType.Shredder: + return global.manaConsumptionAddition + shredder.manaConsumptionAddition; + case TowerType.Encampment: + return global.manaConsumptionAddition + encampment.manaConsumptionAddition; + case TowerType.Lookout: + return global.manaConsumptionAddition + lookout.manaConsumptionAddition; + default: + Debug.Log("Failed to get global bonus"); + return 0f; + } + } + + public float GetCritChance(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.critChance + crossbow.critChance; + case TowerType.Morter: + return global.critChance + morter.critChance; + case TowerType.TeslaCoil: + return global.critChance + teslaCoil.critChance; + case TowerType.FlameThrower: + return global.critChance + flameThrower.critChance; + case TowerType.PoisonSprayer: + return global.critChance + poisonSprayer.critChance; + case TowerType.Frost: + return global.critChance + frostKeep.critChance; + case TowerType.Radar: + return global.critChance + radar.critChance; + case TowerType.Obelisk: + return global.critChance + obelisk.critChance; + case TowerType.ParticleCannon: + return global.critChance + particleCannon.critChance; + case TowerType.Shredder: + return global.critChance + shredder.critChance; + case TowerType.Encampment: + return global.critChance + encampment.critChance; + case TowerType.Lookout: + return global.critChance + lookout.critChance; + default: + Debug.Log("Failed to get global bonus"); + return 0f; + } + } + + public float GetStunChance(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.stunChance + crossbow.stunChance; + case TowerType.Morter: + return global.stunChance + morter.stunChance; + case TowerType.TeslaCoil: + return global.stunChance + teslaCoil.stunChance; + case TowerType.FlameThrower: + return global.stunChance + flameThrower.stunChance; + case TowerType.PoisonSprayer: + return global.stunChance + poisonSprayer.stunChance; + case TowerType.Frost: + return global.stunChance + frostKeep.stunChance; + case TowerType.Radar: + return global.stunChance + radar.stunChance; + case TowerType.Obelisk: + return global.stunChance + obelisk.stunChance; + case TowerType.ParticleCannon: + return global.stunChance + particleCannon.stunChance; + case TowerType.Shredder: + return global.stunChance + shredder.stunChance; + case TowerType.Encampment: + return global.stunChance + encampment.stunChance; + case TowerType.Lookout: + return global.stunChance + lookout.stunChance; + default: + Debug.Log("Failed to get global bonus"); + return 0f; + } + } + + public float GetCritChanceLevelMultiplier(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.critChanceLevelMultiplier + crossbow.critChanceLevelMultiplier; + case TowerType.Morter: + return global.critChanceLevelMultiplier + morter.critChanceLevelMultiplier; + case TowerType.TeslaCoil: + return global.critChanceLevelMultiplier + teslaCoil.critChanceLevelMultiplier; + case TowerType.FlameThrower: + return global.critChanceLevelMultiplier + flameThrower.critChanceLevelMultiplier; + case TowerType.PoisonSprayer: + return global.critChanceLevelMultiplier + poisonSprayer.critChanceLevelMultiplier; + case TowerType.Frost: + return global.critChanceLevelMultiplier + frostKeep.critChanceLevelMultiplier; + case TowerType.Radar: + return global.critChanceLevelMultiplier + radar.critChanceLevelMultiplier; + case TowerType.Obelisk: + return global.critChanceLevelMultiplier + obelisk.critChanceLevelMultiplier; + case TowerType.ParticleCannon: + return global.critChanceLevelMultiplier + particleCannon.critChanceLevelMultiplier; + case TowerType.Shredder: + return global.critChanceLevelMultiplier + shredder.critChanceLevelMultiplier; + case TowerType.Encampment: + return global.critChanceLevelMultiplier + encampment.critChanceLevelMultiplier; + case TowerType.Lookout: + return global.critChanceLevelMultiplier + lookout.critChanceLevelMultiplier; + default: + Debug.Log("Failed to get global bonus"); + return 0f; + } + } + + public float GetBonusRange(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.bonusRange + crossbow.bonusRange; + case TowerType.Morter: + return global.bonusRange + morter.bonusRange; + case TowerType.TeslaCoil: + return global.bonusRange + teslaCoil.bonusRange; + case TowerType.FlameThrower: + return global.bonusRange + flameThrower.bonusRange; + case TowerType.PoisonSprayer: + return global.bonusRange + poisonSprayer.bonusRange; + case TowerType.Frost: + return global.bonusRange + frostKeep.bonusRange; + case TowerType.Radar: + return global.bonusRange + radar.bonusRange; + case TowerType.Obelisk: + return global.bonusRange + obelisk.bonusRange; + case TowerType.ParticleCannon: + return global.bonusRange + particleCannon.bonusRange; + case TowerType.Shredder: + return global.bonusRange + shredder.bonusRange; + case TowerType.Encampment: + return global.bonusRange + encampment.bonusRange; + case TowerType.Lookout: + return global.bonusRange + lookout.bonusRange; + default: + Debug.Log("Failed to get global bonus"); + return 0f; + } + } + + public int GetBonusBaseDamage(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.bonusBaseDamage + crossbow.bonusBaseDamage; + case TowerType.Morter: + return global.bonusBaseDamage + morter.bonusBaseDamage; + case TowerType.TeslaCoil: + return global.bonusBaseDamage + teslaCoil.bonusBaseDamage; + case TowerType.FlameThrower: + return global.bonusBaseDamage + flameThrower.bonusBaseDamage; + case TowerType.PoisonSprayer: + return global.bonusBaseDamage + poisonSprayer.bonusBaseDamage; + case TowerType.Frost: + return global.bonusBaseDamage + frostKeep.bonusBaseDamage; + case TowerType.Radar: + return global.bonusBaseDamage + radar.bonusBaseDamage; + case TowerType.Obelisk: + return global.bonusBaseDamage + obelisk.bonusBaseDamage; + case TowerType.ParticleCannon: + return global.bonusBaseDamage + particleCannon.bonusBaseDamage; + case TowerType.Shredder: + return global.bonusBaseDamage + shredder.bonusBaseDamage; + case TowerType.Encampment: + return global.bonusBaseDamage + encampment.bonusBaseDamage; + case TowerType.Lookout: + return global.bonusBaseDamage + lookout.bonusBaseDamage; + default: + Debug.Log("Failed to get global bonus"); + return 0; + } + } + + public int GetBonusHealthDamage(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.bonusHealthDamage + crossbow.bonusHealthDamage; + case TowerType.Morter: + return global.bonusHealthDamage + morter.bonusHealthDamage; + case TowerType.TeslaCoil: + return global.bonusHealthDamage + teslaCoil.bonusHealthDamage; + case TowerType.FlameThrower: + return global.bonusHealthDamage + flameThrower.bonusHealthDamage; + case TowerType.PoisonSprayer: + return global.bonusHealthDamage + poisonSprayer.bonusHealthDamage; + case TowerType.Frost: + return global.bonusHealthDamage + frostKeep.bonusHealthDamage; + case TowerType.Radar: + return global.bonusHealthDamage + radar.bonusHealthDamage; + case TowerType.Obelisk: + return global.bonusHealthDamage + obelisk.bonusHealthDamage; + case TowerType.ParticleCannon: + return global.bonusHealthDamage + particleCannon.bonusHealthDamage; + case TowerType.Shredder: + return global.bonusHealthDamage + shredder.bonusHealthDamage; + case TowerType.Encampment: + return global.bonusHealthDamage + encampment.bonusHealthDamage; + case TowerType.Lookout: + return global.bonusHealthDamage + lookout.bonusHealthDamage; + default: + Debug.Log("Failed to get global bonus"); + return 0; + } + } + + public int GetBonusArmorDamage(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.bonusArmorDamage + crossbow.bonusArmorDamage; + case TowerType.Morter: + return global.bonusArmorDamage + morter.bonusArmorDamage; + case TowerType.TeslaCoil: + return global.bonusArmorDamage + teslaCoil.bonusArmorDamage; + case TowerType.FlameThrower: + return global.bonusArmorDamage + flameThrower.bonusArmorDamage; + case TowerType.PoisonSprayer: + return global.bonusArmorDamage + poisonSprayer.bonusArmorDamage; + case TowerType.Frost: + return global.bonusArmorDamage + frostKeep.bonusArmorDamage; + case TowerType.Radar: + return global.bonusArmorDamage + radar.bonusArmorDamage; + case TowerType.Obelisk: + return global.bonusArmorDamage + obelisk.bonusArmorDamage; + case TowerType.ParticleCannon: + return global.bonusArmorDamage + particleCannon.bonusArmorDamage; + case TowerType.Shredder: + return global.bonusArmorDamage + shredder.bonusArmorDamage; + case TowerType.Encampment: + return global.bonusArmorDamage + encampment.bonusArmorDamage; + case TowerType.Lookout: + return global.bonusArmorDamage + lookout.bonusArmorDamage; + default: + Debug.Log("Failed to get global bonus"); + return 0; + } + } + + public int GetBonusShieldDamage(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.bonusShieldDamage + crossbow.bonusShieldDamage; + case TowerType.Morter: + return global.bonusShieldDamage + morter.bonusShieldDamage; + case TowerType.TeslaCoil: + return global.bonusShieldDamage + teslaCoil.bonusShieldDamage; + case TowerType.FlameThrower: + return global.bonusShieldDamage + flameThrower.bonusShieldDamage; + case TowerType.PoisonSprayer: + return global.bonusShieldDamage + poisonSprayer.bonusShieldDamage; + case TowerType.Frost: + return global.bonusShieldDamage + frostKeep.bonusShieldDamage; + case TowerType.Radar: + return global.bonusShieldDamage + radar.bonusShieldDamage; + case TowerType.Obelisk: + return global.bonusShieldDamage + obelisk.bonusShieldDamage; + case TowerType.ParticleCannon: + return global.bonusShieldDamage + particleCannon.bonusShieldDamage; + case TowerType.Shredder: + return global.bonusShieldDamage + shredder.bonusShieldDamage; + case TowerType.Encampment: + return global.bonusShieldDamage + encampment.bonusShieldDamage; + case TowerType.Lookout: + return global.bonusShieldDamage + lookout.bonusShieldDamage; + default: + Debug.Log("Failed to get global bonus"); + return 0; + } + } + + public float GetBonusSlow(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.bonusSlow + crossbow.bonusSlow; + case TowerType.Morter: + return global.bonusSlow + morter.bonusSlow; + case TowerType.TeslaCoil: + return global.bonusSlow + teslaCoil.bonusSlow; + case TowerType.FlameThrower: + return global.bonusSlow + flameThrower.bonusSlow; + case TowerType.PoisonSprayer: + return global.bonusSlow + poisonSprayer.bonusSlow; + case TowerType.Frost: + return global.bonusSlow + frostKeep.bonusSlow; + case TowerType.Radar: + return global.bonusSlow + radar.bonusSlow; + case TowerType.Obelisk: + return global.bonusSlow + obelisk.bonusSlow; + case TowerType.ParticleCannon: + return global.bonusSlow + particleCannon.bonusSlow; + case TowerType.Shredder: + return global.bonusSlow + shredder.bonusSlow; + case TowerType.Encampment: + return global.bonusSlow + encampment.bonusSlow; + case TowerType.Lookout: + return global.bonusSlow + lookout.bonusSlow; + default: + Debug.Log("Failed to get global bonus"); + return 0f; + } + } + + public float GetBonusBleed(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.bonusBleed + crossbow.bonusBleed; + case TowerType.Morter: + return global.bonusBleed + morter.bonusBleed; + case TowerType.TeslaCoil: + return global.bonusBleed + teslaCoil.bonusBleed; + case TowerType.FlameThrower: + return global.bonusBleed + flameThrower.bonusBleed; + case TowerType.PoisonSprayer: + return global.bonusBleed + poisonSprayer.bonusBleed; + case TowerType.Frost: + return global.bonusBleed + frostKeep.bonusBleed; + case TowerType.Radar: + return global.bonusBleed + radar.bonusBleed; + case TowerType.Obelisk: + return global.bonusBleed + obelisk.bonusBleed; + case TowerType.ParticleCannon: + return global.bonusBleed + particleCannon.bonusBleed; + case TowerType.Shredder: + return global.bonusBleed + shredder.bonusBleed; + case TowerType.Encampment: + return global.bonusBleed + encampment.bonusBleed; + case TowerType.Lookout: + return global.bonusBleed + lookout.bonusBleed; + default: + Debug.Log("Failed to get global bonus"); + return 0f; + } + } + + public float GetBonusBurn(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.bonusBurn + crossbow.bonusBurn; + case TowerType.Morter: + return global.bonusBurn + morter.bonusBurn; + case TowerType.TeslaCoil: + return global.bonusBurn + teslaCoil.bonusBurn; + case TowerType.FlameThrower: + return global.bonusBurn + flameThrower.bonusBurn; + case TowerType.PoisonSprayer: + return global.bonusBurn + poisonSprayer.bonusBurn; + case TowerType.Frost: + return global.bonusBurn + frostKeep.bonusBurn; + case TowerType.Radar: + return global.bonusBurn + radar.bonusBurn; + case TowerType.Obelisk: + return global.bonusBurn + obelisk.bonusBurn; + case TowerType.ParticleCannon: + return global.bonusBurn + particleCannon.bonusBurn; + case TowerType.Shredder: + return global.bonusBurn + shredder.bonusBurn; + case TowerType.Encampment: + return global.bonusBurn + encampment.bonusBurn; + case TowerType.Lookout: + return global.bonusBurn + lookout.bonusBurn; + default: + Debug.Log("Failed to get global bonus"); + return 0f; + } + } + + public float GetBonusPoison(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.bonusPoison + crossbow.bonusPoison; + case TowerType.Morter: + return global.bonusPoison + morter.bonusPoison; + case TowerType.TeslaCoil: + return global.bonusPoison + teslaCoil.bonusPoison; + case TowerType.FlameThrower: + return global.bonusPoison + flameThrower.bonusPoison; + case TowerType.PoisonSprayer: + return global.bonusPoison + poisonSprayer.bonusPoison; + case TowerType.Frost: + return global.bonusPoison + frostKeep.bonusPoison; + case TowerType.Radar: + return global.bonusPoison + radar.bonusPoison; + case TowerType.Obelisk: + return global.bonusPoison + obelisk.bonusPoison; + case TowerType.ParticleCannon: + return global.bonusPoison + particleCannon.bonusPoison; + case TowerType.Shredder: + return global.bonusPoison + shredder.bonusPoison; + case TowerType.Encampment: + return global.bonusPoison + encampment.bonusPoison; + case TowerType.Lookout: + return global.bonusPoison + lookout.bonusPoison; + default: + Debug.Log("Failed to get global bonus"); + return 0f; + } + } + + public float GetBonusBlast(TowerType type) + { + switch (type) + { + case TowerType.Crossbow: + return global.bonusBlast + crossbow.bonusBlast; + case TowerType.Morter: + return global.bonusBlast + morter.bonusBlast; + case TowerType.TeslaCoil: + return global.bonusBlast + teslaCoil.bonusBlast; + case TowerType.FlameThrower: + return global.bonusBlast + flameThrower.bonusBlast; + case TowerType.PoisonSprayer: + return global.bonusBlast + poisonSprayer.bonusBlast; + case TowerType.Frost: + return global.bonusBlast + frostKeep.bonusBlast; + case TowerType.Radar: + return global.bonusBlast + radar.bonusBlast; + case TowerType.Obelisk: + return global.bonusBlast + obelisk.bonusBlast; + case TowerType.ParticleCannon: + return global.bonusBlast + particleCannon.bonusBlast; + case TowerType.Shredder: + return global.bonusBlast + shredder.bonusBlast; + case TowerType.Encampment: + return global.bonusBlast + encampment.bonusBlast; + case TowerType.Lookout: + return global.bonusBlast + lookout.bonusBlast; + default: + Debug.Log("Failed to get global bonus"); + return 0f; + } + } + + public void AddManaConsumption(TowerType type, float value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddManaAddition(value); + break; + case TowerType.Morter: + morter.AddManaAddition(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddManaAddition(value); + break; + case TowerType.FlameThrower: + flameThrower.AddManaAddition(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddManaAddition(value); + break; + case TowerType.Frost: + frostKeep.AddManaAddition(value); + break; + case TowerType.Radar: + radar.AddManaAddition(value); + break; + case TowerType.Obelisk: + obelisk.AddManaAddition(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddManaAddition(value); + break; + case TowerType.Shredder: + shredder.AddManaAddition(value); + break; + case TowerType.Encampment: + encampment.AddManaAddition(value); + break; + case TowerType.Lookout: + lookout.AddManaAddition(value); + break; + case TowerType.Global: + global.AddManaAddition(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } + + public void AddCritChance(TowerType type, float value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddCritChance(value); + break; + case TowerType.Morter: + morter.AddCritChance(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddCritChance(value); + break; + case TowerType.FlameThrower: + flameThrower.AddCritChance(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddCritChance(value); + break; + case TowerType.Frost: + frostKeep.AddCritChance(value); + break; + case TowerType.Radar: + radar.AddCritChance(value); + break; + case TowerType.Obelisk: + obelisk.AddCritChance(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddCritChance(value); + break; + case TowerType.Shredder: + shredder.AddCritChance(value); + break; + case TowerType.Encampment: + encampment.AddCritChance(value); + break; + case TowerType.Lookout: + lookout.AddCritChance(value); + break; + case TowerType.Global: + global.AddCritChance(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } + + public void AddStunChance(TowerType type, float value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddStunChance(value); + break; + case TowerType.Morter: + morter.AddStunChance(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddStunChance(value); + break; + case TowerType.FlameThrower: + flameThrower.AddStunChance(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddStunChance(value); + break; + case TowerType.Frost: + frostKeep.AddStunChance(value); + break; + case TowerType.Radar: + radar.AddStunChance(value); + break; + case TowerType.Obelisk: + obelisk.AddStunChance(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddStunChance(value); + break; + case TowerType.Shredder: + shredder.AddStunChance(value); + break; + case TowerType.Encampment: + encampment.AddStunChance(value); + break; + case TowerType.Lookout: + lookout.AddStunChance(value); + break; + case TowerType.Global: + global.AddStunChance(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } + + public void AddCritChanceLevelMultiplier(TowerType type, float value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddCritChanceLevelMultiplier(value); + break; + case TowerType.Morter: + morter.AddCritChanceLevelMultiplier(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddCritChanceLevelMultiplier(value); + break; + case TowerType.FlameThrower: + flameThrower.AddCritChanceLevelMultiplier(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddCritChanceLevelMultiplier(value); + break; + case TowerType.Frost: + frostKeep.AddCritChanceLevelMultiplier(value); + break; + case TowerType.Radar: + radar.AddCritChanceLevelMultiplier(value); + break; + case TowerType.Obelisk: + obelisk.AddCritChanceLevelMultiplier(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddCritChanceLevelMultiplier(value); + break; + case TowerType.Shredder: + shredder.AddCritChanceLevelMultiplier(value); + break; + case TowerType.Encampment: + encampment.AddCritChanceLevelMultiplier(value); + break; + case TowerType.Lookout: + lookout.AddCritChanceLevelMultiplier(value); + break; + case TowerType.Global: + global.AddCritChanceLevelMultiplier(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } + + public void AddBonusRange(TowerType type, float value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddBonusRange(value); + break; + case TowerType.Morter: + morter.AddBonusRange(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddBonusRange(value); + break; + case TowerType.FlameThrower: + flameThrower.AddBonusRange(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddBonusRange(value); + break; + case TowerType.Frost: + frostKeep.AddBonusRange(value); + break; + case TowerType.Radar: + radar.AddBonusRange(value); + break; + case TowerType.Obelisk: + obelisk.AddBonusRange(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddBonusRange(value); + break; + case TowerType.Shredder: + shredder.AddBonusRange(value); + break; + case TowerType.Encampment: + encampment.AddBonusRange(value); + break; + case TowerType.Lookout: + lookout.AddBonusRange(value); + break; + case TowerType.Global: + global.AddBonusRange(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } + + public void AddBonusBaseDamage(TowerType type, int value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddBonusBaseDamage(value); + break; + case TowerType.Morter: + morter.AddBonusBaseDamage(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddBonusBaseDamage(value); + break; + case TowerType.FlameThrower: + flameThrower.AddBonusBaseDamage(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddBonusBaseDamage(value); + break; + case TowerType.Frost: + frostKeep.AddBonusBaseDamage(value); + break; + case TowerType.Radar: + radar.AddBonusBaseDamage(value); + break; + case TowerType.Obelisk: + obelisk.AddBonusBaseDamage(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddBonusBaseDamage(value); + break; + case TowerType.Shredder: + shredder.AddBonusBaseDamage(value); + break; + case TowerType.Encampment: + encampment.AddBonusBaseDamage(value); + break; + case TowerType.Lookout: + lookout.AddBonusBaseDamage(value); + break; + case TowerType.Global: + global.AddBonusBaseDamage(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } + + public void AddBonusHealthDamage(TowerType type, int value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddBonusHealthDamage(value); + break; + case TowerType.Morter: + morter.AddBonusHealthDamage(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddBonusHealthDamage(value); + break; + case TowerType.FlameThrower: + flameThrower.AddBonusHealthDamage(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddBonusHealthDamage(value); + break; + case TowerType.Frost: + frostKeep.AddBonusHealthDamage(value); + break; + case TowerType.Radar: + radar.AddBonusHealthDamage(value); + break; + case TowerType.Obelisk: + obelisk.AddBonusHealthDamage(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddBonusHealthDamage(value); + break; + case TowerType.Shredder: + shredder.AddBonusHealthDamage(value); + break; + case TowerType.Encampment: + encampment.AddBonusHealthDamage(value); + break; + case TowerType.Lookout: + lookout.AddBonusHealthDamage(value); + break; + case TowerType.Global: + global.AddBonusHealthDamage(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } + + public void AddBonusArmorDamage(TowerType type, int value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddBonusArmorDamage(value); + break; + case TowerType.Morter: + morter.AddBonusArmorDamage(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddBonusArmorDamage(value); + break; + case TowerType.FlameThrower: + flameThrower.AddBonusArmorDamage(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddBonusArmorDamage(value); + break; + case TowerType.Frost: + frostKeep.AddBonusArmorDamage(value); + break; + case TowerType.Radar: + radar.AddBonusArmorDamage(value); + break; + case TowerType.Obelisk: + obelisk.AddBonusArmorDamage(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddBonusArmorDamage(value); + break; + case TowerType.Shredder: + shredder.AddBonusArmorDamage(value); + break; + case TowerType.Encampment: + encampment.AddBonusArmorDamage(value); + break; + case TowerType.Lookout: + lookout.AddBonusArmorDamage(value); + break; + case TowerType.Global: + global.AddBonusArmorDamage(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } + + public void AddBonusShieldDamage(TowerType type, int value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddBonusShieldDamage(value); + break; + case TowerType.Morter: + morter.AddBonusShieldDamage(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddBonusShieldDamage(value); + break; + case TowerType.FlameThrower: + flameThrower.AddBonusShieldDamage(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddBonusShieldDamage(value); + break; + case TowerType.Frost: + frostKeep.AddBonusShieldDamage(value); + break; + case TowerType.Radar: + radar.AddBonusShieldDamage(value); + break; + case TowerType.Obelisk: + obelisk.AddBonusShieldDamage(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddBonusShieldDamage(value); + break; + case TowerType.Shredder: + shredder.AddBonusShieldDamage(value); + break; + case TowerType.Encampment: + encampment.AddBonusShieldDamage(value); + break; + case TowerType.Lookout: + lookout.AddBonusShieldDamage(value); + break; + case TowerType.Global: + global.AddBonusShieldDamage(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } + + public void AddBonusSlow(TowerType type, float value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddBonusSlow(value); + break; + case TowerType.Morter: + morter.AddBonusSlow(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddBonusSlow(value); + break; + case TowerType.FlameThrower: + flameThrower.AddBonusSlow(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddBonusSlow(value); + break; + case TowerType.Frost: + frostKeep.AddBonusSlow(value); + break; + case TowerType.Radar: + radar.AddBonusSlow(value); + break; + case TowerType.Obelisk: + obelisk.AddBonusSlow(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddBonusSlow(value); + break; + case TowerType.Shredder: + shredder.AddBonusSlow(value); + break; + case TowerType.Encampment: + encampment.AddBonusSlow(value); + break; + case TowerType.Lookout: + lookout.AddBonusSlow(value); + break; + case TowerType.Global: + global.AddBonusSlow(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } + + public void AddBonusBleed(TowerType type, float value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddBonusBleed(value); + break; + case TowerType.Morter: + morter.AddBonusBleed(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddBonusBleed(value); + break; + case TowerType.FlameThrower: + flameThrower.AddBonusBleed(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddBonusBleed(value); + break; + case TowerType.Frost: + frostKeep.AddBonusBleed(value); + break; + case TowerType.Radar: + radar.AddBonusBleed(value); + break; + case TowerType.Obelisk: + obelisk.AddBonusBleed(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddBonusBleed(value); + break; + case TowerType.Shredder: + shredder.AddBonusBleed(value); + break; + case TowerType.Encampment: + encampment.AddBonusBleed(value); + break; + case TowerType.Lookout: + lookout.AddBonusBleed(value); + break; + case TowerType.Global: + global.AddBonusBleed(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } + + public void AddBonusBurn(TowerType type, float value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddBonusBurn(value); + break; + case TowerType.Morter: + morter.AddBonusBurn(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddBonusBurn(value); + break; + case TowerType.FlameThrower: + flameThrower.AddBonusBurn(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddBonusBurn(value); + break; + case TowerType.Frost: + frostKeep.AddBonusBurn(value); + break; + case TowerType.Radar: + radar.AddBonusBurn(value); + break; + case TowerType.Obelisk: + obelisk.AddBonusBurn(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddBonusBurn(value); + break; + case TowerType.Shredder: + shredder.AddBonusBurn(value); + break; + case TowerType.Encampment: + encampment.AddBonusBurn(value); + break; + case TowerType.Lookout: + lookout.AddBonusBurn(value); + break; + case TowerType.Global: + global.AddBonusBurn(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } + + public void AddBonusPoison(TowerType type, float value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddBonusPoison(value); + break; + case TowerType.Morter: + morter.AddBonusPoison(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddBonusPoison(value); + break; + case TowerType.FlameThrower: + flameThrower.AddBonusPoison(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddBonusPoison(value); + break; + case TowerType.Frost: + frostKeep.AddBonusPoison(value); + break; + case TowerType.Radar: + radar.AddBonusPoison(value); + break; + case TowerType.Obelisk: + obelisk.AddBonusPoison(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddBonusPoison(value); + break; + case TowerType.Shredder: + shredder.AddBonusPoison(value); + break; + case TowerType.Encampment: + encampment.AddBonusPoison(value); + break; + case TowerType.Lookout: + lookout.AddBonusPoison(value); + break; + case TowerType.Global: + global.AddBonusPoison(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } + + public void AddBonusBlast(TowerType type, float value) + { + switch (type) + { + case TowerType.Crossbow: + crossbow.AddBonusBlast(value); + break; + case TowerType.Morter: + morter.AddBonusBlast(value); + break; + case TowerType.TeslaCoil: + teslaCoil.AddBonusBlast(value); + break; + case TowerType.FlameThrower: + flameThrower.AddBonusBlast(value); + break; + case TowerType.PoisonSprayer: + poisonSprayer.AddBonusBlast(value); + break; + case TowerType.Frost: + frostKeep.AddBonusBlast(value); + break; + case TowerType.Radar: + radar.AddBonusBlast(value); + break; + case TowerType.Obelisk: + obelisk.AddBonusBlast(value); + break; + case TowerType.ParticleCannon: + particleCannon.AddBonusBlast(value); + break; + case TowerType.Shredder: + shredder.AddBonusBlast(value); + break; + case TowerType.Encampment: + encampment.AddBonusBlast(value); + break; + case TowerType.Lookout: + lookout.AddBonusBlast(value); + break; + case TowerType.Global: + global.AddBonusBlast(value); + UpdateAllTowers(); + break; + default: + Debug.Log("Failed to set global bonus"); + break; + } + } +} diff --git a/Assembly_CSharp/GamePlay/TowerType.cs b/Assembly_CSharp/GamePlay/TowerType.cs new file mode 100644 index 0000000..9bbc242 --- /dev/null +++ b/Assembly_CSharp/GamePlay/TowerType.cs @@ -0,0 +1,18 @@ +public enum TowerType +{ + Crossbow, + Morter, + TeslaCoil, + Frost, + Obelisk, + FlameThrower, + PoisonSprayer, + Siphon, + Radar, + ParticleCannon, + DOT, + Global, + Shredder, + Encampment, + Lookout +} diff --git a/Assembly_CSharp/GamePlay/TowerUnlockManager.cs b/Assembly_CSharp/GamePlay/TowerUnlockManager.cs new file mode 100644 index 0000000..d96b9d5 --- /dev/null +++ b/Assembly_CSharp/GamePlay/TowerUnlockManager.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using UnityEngine; + +public class TowerUnlockManager : MonoBehaviour +{ + public static TowerUnlockManager instance; + + [SerializeField] + private List<GameObject> unlockedTowers = new List<GameObject>(); + + [SerializeField] + private List<GameObject> unlockedBuildings = new List<GameObject>(); + + private void Awake() + { + instance = this; + } + + private void Start() + { + DisplayButtons(); + } + + public void UnlockTower(GameObject towerUIObject, bool isTower) + { + towerUIObject.SetActive(value: true); + if (isTower) + { + unlockedTowers.Add(towerUIObject); + } + else + { + unlockedBuildings.Add(towerUIObject); + } + DisplayButtons(); + } + + private void DisplayButtons() + { + int num = 0; + int num2 = ((unlockedBuildings.Count > 0) ? 1 : 0); + foreach (GameObject unlockedTower in unlockedTowers) + { + unlockedTower.transform.localPosition = new Vector3(num * 100 - unlockedTowers.Count * 50 + 50, 100 * num2, 0f); + num++; + } + num = 0; + foreach (GameObject unlockedBuilding in unlockedBuildings) + { + unlockedBuilding.transform.localPosition = new Vector3(num * 100 - unlockedBuildings.Count * 50 + 50, 0f, 0f); + num++; + } + } +} diff --git a/Assembly_CSharp/GamePlay/UpgradeManager.cs b/Assembly_CSharp/GamePlay/UpgradeManager.cs new file mode 100644 index 0000000..685308e --- /dev/null +++ b/Assembly_CSharp/GamePlay/UpgradeManager.cs @@ -0,0 +1,120 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +public class UpgradeManager : MonoBehaviour +{ + public static UpgradeManager instance; + + public int xp; + + public int prestige; + + [SerializeField] + private Text xpText; + + [SerializeField] + private GameObject prestigeDisplay; + + [SerializeField] + private Text prestigeText; + + public int unlockedCardCount; + + [SerializeField] + private UpgradeButton[] allButtons; + + [SerializeField] + private List<UpgradeButton> cardsWhichRequireCardCount = new List<UpgradeButton>(); + + private void Awake() + { + instance = this; + } + + private void Start() + { + allButtons = Object.FindObjectsOfType<UpgradeButton>(); + UpgradeButton[] array = allButtons; + foreach (UpgradeButton upgradeButton in array) + { + if (upgradeButton.cardCountRequirement > 0) + { + cardsWhichRequireCardCount.Add(upgradeButton); + } + } + unlockedCardCount = PlayerPrefs.GetInt("UnlockedCardCount", 0); + xp = PlayerPrefs.GetInt("XP", 0); + xpText.text = "XP: " + xp; + prestige = PlayerPrefs.GetInt("Prestige", 0); + if (prestige > 0) + { + prestigeDisplay.SetActive(value: true); + prestigeText.text = "Prestige: " + prestige; + } + } + + public void AddXP(int change) + { + xp += change; + PlayerPrefs.SetInt("XP", xp); + xpText.text = "XP: " + xp; + } + + public void ResetUpgrades() + { + int num = 0; + UpgradeButton[] array = allButtons; + foreach (UpgradeButton upgradeButton in array) + { + if (upgradeButton.enabled) + { + if (upgradeButton.unlocked) + { + num += upgradeButton.xpCost; + } + upgradeButton.ResetUnlock(); + } + } + num += xp / 2; + Debug.Log("Refunded xp: " + num); + PlayerPrefs.SetInt("Prestige", prestige + num / 1000); + xp = 0; + PlayerPrefs.SetInt("XP", 0); + PlayerPrefs.SetInt("UnlockedCardCount", 0); + PlayerPrefs.SetInt("Development", 0); + PlayerPrefs.SetInt("Record1", 0); + PlayerPrefs.SetInt("Record2", 0); + PlayerPrefs.SetInt("Record3", 0); + LevelLoader.instance.LoadLevel("MainMenu"); + } + + public void CountCard(bool countsAsCardUnlock) + { + if (countsAsCardUnlock) + { + unlockedCardCount++; + Debug.Log("Number of unlocked cards: " + unlockedCardCount); + PlayerPrefs.SetInt("UnlockedCardCount", unlockedCardCount); + CheckCardCount(); + } + } + + public void CountDevelopment(bool value) + { + if (value) + { + int @int = PlayerPrefs.GetInt("Development", 0); + PlayerPrefs.SetInt("Development", @int + 1); + Debug.Log("Development: " + (@int + 1)); + } + } + + public void CheckCardCount() + { + foreach (UpgradeButton item in cardsWhichRequireCardCount) + { + item.CheckEnabled(); + } + } +} diff --git a/Assembly_CSharp/GamePlay/WalkAnimator.cs b/Assembly_CSharp/GamePlay/WalkAnimator.cs new file mode 100644 index 0000000..4f2b997 --- /dev/null +++ b/Assembly_CSharp/GamePlay/WalkAnimator.cs @@ -0,0 +1,55 @@ +using System; +using UnityEngine; + +public class WalkAnimator : MonoBehaviour +{ + private Pathfinder p; + + [SerializeField] + private Transform directionalTransform; + + [SerializeField] + private Transform rotationalOffsetTransform; + + [SerializeField] + private Transform artTransform; + + [SerializeField] + private float strideLength = 1f; + + [SerializeField] + private float strideHeight = 1f; + + [SerializeField] + private float sideAngles = 20f; + + [SerializeField] + private float strideVariationPercentage = 0.1f; + + private float step; + + private Vector3 preiviousPosition; + + private Vector3 direction; + + private void Start() + { + strideLength = UnityEngine.Random.Range(strideLength * (1f - strideVariationPercentage), strideLength * (1f + strideVariationPercentage)); + strideHeight = UnityEngine.Random.Range(strideHeight * (1f - strideVariationPercentage), strideHeight * (1f + strideVariationPercentage)); + p = GetComponent<Pathfinder>(); + preiviousPosition = base.transform.position; + } + + private void FixedUpdate() + { + direction = base.transform.position - preiviousPosition; + preiviousPosition = base.transform.position; + if (direction.sqrMagnitude != 0f) + { + directionalTransform.rotation = Quaternion.LookRotation(direction, Vector3.up); + } + step = (step + p.speed * Time.fixedDeltaTime / strideLength) % 2f; + artTransform.localPosition = strideHeight * Vector3.up * Mathf.Abs(Mathf.Cos(step * (float)Math.PI)); + artTransform.localEulerAngles = new Vector3(sideAngles * Mathf.Sin(step * (float)Math.PI), 0f, 0f); + } +} diff --git a/Assembly_CSharp/GamePlay/Waypoint.cs b/Assembly_CSharp/GamePlay/Waypoint.cs new file mode 100644 index 0000000..b250079 --- /dev/null +++ b/Assembly_CSharp/GamePlay/Waypoint.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using UnityEngine; + +public class Waypoint : MonoBehaviour +{ + [SerializeField] + private Waypoint next; + + [SerializeField] + private List<Waypoint> previous = new List<Waypoint>(); + + public float distanceFromEnd; + + public bool trueDistance; + + private void Start() + { + UpdateDistance(); + } + + public Waypoint GetNextWaypoint() + { + if (next != null) + { + return next; + } + return this; + } + + public void SetNextWaypoint(Waypoint newNext) + { + next = newNext; + } + + public void AddPreviousWaypoint(Waypoint previousWaypoint) + { + previous.Add(previousWaypoint); + } + + public Waypoint[] GetPreviousWaypoints() + { + return previous.ToArray(); + } + + public void UpdateDistance() + { + if (next == null) + { + trueDistance = true; + return; + } + if (!next.trueDistance) + { + next.UpdateDistance(); + } + if (!trueDistance) + { + distanceFromEnd = next.distanceFromEnd + Vector3.Magnitude(next.transform.position - base.transform.position); + trueDistance = true; + } + } +} |