using System; using System.Collections.Generic; using Ai; using UnityEngine; using Ability; using Dialogs; using Equip; using Game; using Meta; using Player; using TMPro; using UnityEngine.SceneManagement; using Utils; public enum CharacterState { DEFAULT, MOVE_STATE, } public class MainCharacter : MonoBehaviour { GameBoard m_gameBoard = null; CharacterState m_state = CharacterState.DEFAULT; [SerializeField] GameObject[] _skinObj; [SerializeField] Material _racconSkin; [SerializeField] Material _foxSkin; [SerializeField] Material _skunkSkin; [SerializeField] float m_speed = 2; [SerializeField] int m_startHealth = 500; [SerializeField] Rigidbody m_rigidbody; [SerializeField] private MainCharacter m_self; [Header("Animations")] [SerializeField] private Animator[] m_characterAnimator; [SerializeField] private string m_runName; [SerializeField] private string m_shootName; [SerializeField] private string m_deathName; [Header("Shooting Mechanics")] [SerializeField] private Shooting m_shooting; [SerializeField] private ShootingManager m_shootingManager; [Header("Other Stuff")] [SerializeField] private HealthBar m_bar; [SerializeField] private TextMeshPro m_health; public static int MCurrentHealth = -1; public static Vector3 MCurrentPosition = Vector3.zero; public static int MMaxHealth = -1; public static bool MainAbilityApplied; public static bool Respawned; float m_slowMult = 1f; float m_timeToSpikesDamege = 0f; bool m_isDead = false; bool m_needUpdateSpikesDmg = false; Vector3 m_moveDir = new Vector3(0, 0, 1); Vector3 m_dirDotStartPos; List m_triggeredObstacles = new List(); private Animator m_currentAnimator; public static readonly Dictionary MInGameAb = new Dictionary(); public static bool Equipped; //----------------------------------------------------------------------------------------- private void OnEnable() { if (SceneManager.GetActiveScene().name != "MainMenu") { if (MMaxHealth < 0) MMaxHealth = m_startHealth; AiController.Instance.Player = this; PlayerResources.Instance.Player = this; } Repaint(); } public void Repaint() { SetCurrentSkin(); Equip(); } //----------------------------------------------------------------------------------------- private void SetCurrentSkin() { PlayerResources.Instance.SkinExp = 0; Material mat = _racconSkin; SkinType type = GlobalsVar.gUser.CurrentSkin; if (type == SkinType.RACCOON) mat = _racconSkin; else if (type == SkinType.FOX) { mat = _foxSkin; PlayerResources.Instance.SkinExp = 0.1f; } else if (type == SkinType.SKUNK) { mat = _skunkSkin; if (MCurrentHealth > 0) MCurrentHealth = Mathf.Min(MMaxHealth, MCurrentHealth + 50); } foreach (var obj in _skinObj) { obj.GetComponent().material = mat; } } //----------------------------------------------------------------------------------------- private void Equip() { var items = EquipSettings.GetItems(); if (m_currentAnimator != null) m_currentAnimator.gameObject.SetActive(false); m_currentAnimator = m_characterAnimator[0]; m_currentAnimator.gameObject.SetActive(true); m_shootingManager.SetShoota(0); foreach (var item in items) { if (item.WeaponType != WeaponType.Gun) { m_currentAnimator.gameObject.SetActive(false); m_currentAnimator = m_characterAnimator[(int) item.WeaponType]; m_currentAnimator.gameObject.SetActive(true); m_shootingManager.SetShoota((int) item.WeaponType); } if (!Equipped && SceneManager.GetActiveScene().name != "MainMenu") { MMaxHealth += (int)item.AddHp; } m_shootingManager.ApplyEquip(item); } Equipped = true; } //----------------------------------------------------------------------------------------- public void Init() { MCurrentPosition = transform.position; PlayerResources.Instance.Repaint(); foreach (KeyValuePair ability in MInGameAb) ApplyAbility(ability.Key, ability.Value); foreach (MainAbilityType mainAbType in Enum.GetValues(typeof(MainAbilityType))) ApplyMainAb(mainAbType); MainAbilityApplied = true; m_shootingManager.ShootEvent += OnShoot; SetHealthProgress(); } //----------------------------------------------------------------------------------------- void OnShoot() { if (GlobalsVar.gBoard.DialogsCount > 0) return; m_currentAnimator.SetTrigger(m_shootName); PlayShotSound(); } //----------------------------------------------------------------------------------------- private void PlayShotSound() { List weapon = EquipSettings.GetItems(); string shotName = ""; if (weapon[0].WeaponType == WeaponType.Gun) shotName = "shot_revolver"; else if (weapon[0].WeaponType == WeaponType.Auto) shotName = "shot_rifle"; else if (weapon[0].WeaponType == WeaponType.Shotgun) shotName = "shot_shotgun"; else if (weapon[0].WeaponType == WeaponType.Rocket) shotName = "shot_bazuka"; SoundsManager.Instance.PlaySound(shotName); } //----------------------------------------------------------------------------------------- public GameBoard GameBoard { set { m_gameBoard = value; } } //----------------------------------------------------------------------------------------- public bool IsDead { get { return m_isDead; } } //----------------------------------------------------------------------------------------- public Dictionary InGameAb { get { return MInGameAb; } } //----------------------------------------------------------------------------------------- public bool NeedRollAb(InGameAbType type) { if (MInGameAb.ContainsKey(type)) { if (MInGameAb[type].m_lvlUp < MInGameAb[type].m_maxLvlUp) return true; else return false; } return true; } //----------------------------------------------------------------------------------------- public void AddAbility(InGameAbType type) { if (MInGameAb.ContainsKey(type)) { MInGameAb[type].m_lvlUp++; } else { if (GlobalsVar.gInGameAbilities == null) { GlobalsVar.gInGameAbilities = new InGameAbilities(); GlobalsVar.gInGameAbilities.Init(); } InGameAbInfo info = GlobalsVar.gInGameAbilities.GetAbilityInfoByType(type); if (type != InGameAbType.ADD_HEALTH && type != InGameAbType.HEAL && type != InGameAbType.DECAY && type != InGameAbType.ADD_DROP_GOLD && type != InGameAbType.ADD_XP) MInGameAb.Add(type, info); ApplyAbility(type, info); } } //----------------------------------------------------------------------------------------- private void ApplyAbility(InGameAbType type, InGameAbInfo info) { m_shootingManager.AddAbility(type, info.m_value); switch (type) { case InGameAbType.ADD_XP: PlayerResources.Instance.ExpMult += info.m_value; break; case InGameAbType.ADD_DROP_GOLD: PlayerResources.Instance.CoinsMult += info.m_value; break; case InGameAbType.ADD_HEALTH: MCurrentHealth += (int) info.m_value; FlyingText.Init((int) info.m_value, FlyingText.State.Heal, transform.position); MMaxHealth += (int) info.m_value; SetHealthProgress(); break; case InGameAbType.HEAL: var healValue = Mathf.Min(MMaxHealth, MCurrentHealth + (int) (MMaxHealth * 0.3f)); if (MCurrentHealth != healValue) FlyingText.Init(healValue - MCurrentHealth, FlyingText.State.Heal, transform.position); MCurrentHealth = healValue; SetHealthProgress(); break; case InGameAbType.DECAY: var decayValue = Mathf.Max(1, MCurrentHealth - (int) (MMaxHealth * 0.2f)); if (MCurrentHealth != decayValue) FlyingText.Init(-(MCurrentHealth - decayValue), FlyingText.State.Danger, transform.position); MCurrentHealth = decayValue; SetHealthProgress(); break; } } //----------------------------------------------------------------------------------------- private void ApplyMainAb(MainAbilityType type) { float mainAbValue = GlobalsVar.gMainAbilities.GetAbilityValueByType(type); m_shootingManager.AddMainAbility(type, mainAbValue); switch (type) { case MainAbilityType.ADD_EQUIP: if (!MainAbilityApplied) PlayerResources.Instance.EquipChance += mainAbValue; break; case MainAbilityType.ADD_DROP_GOLD: if (!MainAbilityApplied) PlayerResources.Instance.CoinsMult += mainAbValue; break; case MainAbilityType.ADD_HEALTH: if (!MainAbilityApplied) MMaxHealth += (int)mainAbValue; if (MCurrentHealth < 0) MCurrentHealth = MMaxHealth; break; } } //----------------------------------------------------------------------------------------- void SetHealthProgress() { float progress = MCurrentHealth / (float)MMaxHealth; if (progress > 1f) progress = 1f; else if (progress < 0f) progress = 0f; m_health.text = MCurrentHealth.ToString(); m_bar.SetPercent(progress); } //----------------------------------------------------------------------------------------- public void TakeDamage(int damage) { if (m_isDead) return; SoundsManager.Instance.PlaySound("damage"); MCurrentHealth -= damage; FlyingText.Init(-damage, FlyingText.State.Normal, transform.position); SetHealthProgress(); if (MCurrentHealth <= 0) { m_isDead = true; if (m_gameBoard != null) { m_gameBoard.SetStickDefault(); m_gameBoard.StopRunSound(); } m_currentAnimator.SetTrigger(m_deathName); LeanTween.delayedCall(2f, () => { if (Respawned) { GameObject dlg = m_gameBoard.StartDialog("EndRunDialog"); dlg.GetComponent().Init(); } else { GameObject dlg = m_gameBoard.StartDialog("AfterDeathDialog"); dlg.GetComponent().Init(); Respawned = true; } }); } } //----------------------------------------------------------------------------------------- public void SetState(CharacterState state) { if (state != m_state) { m_currentAnimator.SetBool(m_runName, state == CharacterState.MOVE_STATE); m_state = state; if (state == CharacterState.DEFAULT) m_shootingManager.ShootPermamently(); } m_state = state; } //----------------------------------------------------------------------------------------- public CharacterState GetState() { return m_state; } //----------------------------------------------------------------------------------------- public void SetDir(Vector3 dir, float arrowYScale) { m_moveDir = dir; if (dir == Vector3.zero) return; dir.y = dir.z; dir.z = 0; float angle = Vector3.Angle(dir, new Vector3(0, 1, 0)); if (dir.x < 0) angle = -angle; Vector3 characterAngle = transform.eulerAngles; characterAngle.y = angle; transform.eulerAngles = characterAngle; } //----------------------------------------------------------------------------------------- void FixedUpdate () { if (m_isDead) return; if (m_state == CharacterState.MOVE_STATE) UpdateMoveState(); UpdateSpikesDamage(); } //----------------------------------------------------------------------------------------- void UpdateSpikesDamage() { if (!m_needUpdateSpikesDmg) return; GameObstacles obst = GetTriggeredObstacleByType(GameObstaclesType.SPIKES_FLOOR); m_timeToSpikesDamege -= Time.deltaTime; if (m_timeToSpikesDamege <= 0f) { m_timeToSpikesDamege = obst.TimeToDamage; float abilityVal = GlobalsVar.gMainAbilities.GetAbilityValueByType(Ability.MainAbilityType.ADD_ARMOR_COLLISION_TRAP); abilityVal /= 100f; float damage = obst.SpikesDamage - obst.SpikesDamage * abilityVal; TakeDamage(obst.SpikesDamage); } } //----------------------------------------------------------------------------------------- void UpdateMoveState() { m_rigidbody.MovePosition(m_rigidbody.position + m_moveDir * (m_speed * Time.deltaTime * m_slowMult)); } //----------------------------------------------------------------------------------------- void OnCollisionEnter(Collision collision) { GameObstacles gameObst = collision.gameObject.GetComponent(); if (gameObst) { } } //----------------------------------------------------------------------------------------- void OnTriggerEnter(Collider other) { GameObstacles gameObst = other.gameObject.GetComponent(); if (gameObst) { if (gameObst.Type == GameObstaclesType.SLOW_FLOOR) { m_slowMult = gameObst.SlowMult; if (!m_triggeredObstacles.Contains(gameObst)) m_triggeredObstacles.Add(gameObst); } else if (gameObst.Type == GameObstaclesType.SPIKES_FLOOR) { m_needUpdateSpikesDmg = true; if (!m_triggeredObstacles.Contains(gameObst)) m_triggeredObstacles.Add(gameObst); } } else { if (other.gameObject.name == "active_laser_part") { GameObstacles laserObst = other.transform.parent.GetComponent(); float abilityVal = GlobalsVar.gMainAbilities.GetAbilityValueByType(Ability.MainAbilityType.ADD_ARMOR_COLLISION_TRAP); abilityVal /= 100f; float damage = laserObst.LaserDamage - laserObst.LaserDamage * abilityVal; TakeDamage((int)damage); } } } //----------------------------------------------------------------------------------------- void OnTriggerExit(Collider other) { GameObstacles gameObst = other.gameObject.GetComponent(); if (gameObst) { if (gameObst.Type == GameObstaclesType.SLOW_FLOOR) { m_triggeredObstacles.Remove(gameObst); if (GetOtherCollisionsCountByType(gameObst.Type) == 0) m_slowMult = 1f; } else if (gameObst.Type == GameObstaclesType.SPIKES_FLOOR) { m_triggeredObstacles.Remove(gameObst); if (GetOtherCollisionsCountByType(gameObst.Type) == 0) m_needUpdateSpikesDmg = false; } } } //----------------------------------------------------------------------------------------- int GetOtherCollisionsCountByType( GameObstaclesType type ) { int collisionsCount = 0; for (int i = 0; i < m_triggeredObstacles.Count; ++i) { if (m_triggeredObstacles[i].Type == type) collisionsCount++; } return collisionsCount; } //----------------------------------------------------------------------------------------- GameObstacles GetTriggeredObstacleByType(GameObstaclesType type) { for (int i = 0; i < m_triggeredObstacles.Count; ++i) { if (m_triggeredObstacles[i].Type == type) return m_triggeredObstacles[i]; } CommonFunctions.myassert(false); return null; } public static void Clear() { MInGameAb.Clear(); MCurrentHealth = -1; MMaxHealth = -1; MainAbilityApplied = false; Respawned = false; Equipped = false; } public void Reload() { MCurrentHealth = -1; var character = Instantiate(m_self); Destroy(gameObject); character.transform.position = MCurrentPosition; GameBoard.Instance.InitMainCharacter(character); } }