You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
550 lines
18 KiB
550 lines
18 KiB
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<GameObstacles> m_triggeredObstacles = new List<GameObstacles>(); |
|
private Animator m_currentAnimator; |
|
public static readonly Dictionary<InGameAbType, InGameAbInfo> MInGameAb = new Dictionary<InGameAbType, InGameAbInfo>(); |
|
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<SkinnedMeshRenderer>().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<InGameAbType, InGameAbInfo> 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<EquipItem> 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<InGameAbType, InGameAbInfo> 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<EndRunDialog>().Init(); |
|
} |
|
else |
|
{ |
|
GameObject dlg = m_gameBoard.StartDialog("AfterDeathDialog"); |
|
dlg.GetComponent<AfterDeathDialog>().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<GameObstacles>(); |
|
if (gameObst) |
|
{ |
|
|
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------------------- |
|
void OnTriggerEnter(Collider other) |
|
{ |
|
GameObstacles gameObst = other.gameObject.GetComponent<GameObstacles>(); |
|
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<GameObstacles>(); |
|
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<GameObstacles>(); |
|
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); |
|
} |
|
}
|
|
|