using ShotSimulator.Target; using ShotSimulator.Tool; using ShotSimulator.Train.Info; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using Random = UnityEngine.Random; namespace ShotSimulator.Train { public class MozambiqueTrainHandle : BaseTrainHandle { private MozambiqueHumanoidShotTarget curTarget; private MozambiqueTrainDifficultyData m_DifficultyData; private MozambiqueTrainScoreData m_ScoreData; private TimeTask m_ObserveTimer; private TimeTask m_IntervalTimer; private double m_TotalHitNum; private double TotalHitNum { get { return m_TotalHitNum; } set { m_TotalHitNum = value; UpdatePrecision(); } } private double m_MissHitNum; private double MissHitNum { get { return m_MissHitNum; } set { m_MissHitNum = value; UpdatePrecision(); } } private double totalKillNums; private double mozambiqueKillNums; public MozambiqueTrainHandle(BaseTrainCallBack callBack, BaseTrainInfo info, DifficultyType difficultyType) : base(callBack, info, difficultyType) { SetShotTargetInteractiveEvent(ShotTargetInteractiveType.OnClick, OnShottedTargetEvent); m_DifficultyData = info.GetDifficultyData(m_DifficultyType); m_ScoreData = info.GetScoreData(m_DifficultyType); } #region Train protected override void ResetTrain() { ResetTarget(); m_TotalHitNum = 0; m_MissHitNum = 0; totalKillNums = 0; mozambiqueKillNums = 0; TimerSystem.GetInstance().RemoveTimeTask(m_ObserveTimer); m_ObserveTimer = null; TimerSystem.GetInstance().RemoveTimeTask(m_IntervalTimer); m_IntervalTimer = null; } public override void StartTrain() { base.StartTrain(); GenerateShotTarget(); } public override void PauseTrain() { base.PauseTrain(); if (m_ObserveTimer != null) { m_ObserveTimer.pause = true; } if (m_IntervalTimer != null) { m_IntervalTimer.pause = true; } } public override void ContinueTrain() { base.ContinueTrain(); if (m_ObserveTimer != null) { m_ObserveTimer.pause = false; } if (m_IntervalTimer != null) { m_IntervalTimer.pause = false; } } public override void CalculateTrainResult() { SetResultMetricsDataValue(MetricsType.VisualMemory, mozambiqueKillNums); SetResultMetricsDataValue(MetricsType.Kill_Sec, Math.Round(totalKillNums / TrainInfo.duration, 2)); SetResultMetricsDataValue(MetricsType.KillTotal, totalKillNums); SetResultMetricsDataValue(MetricsType.TimeToKill, Math.Round(TrainInfo.duration / totalKillNums, 2)); SetResultMetricsDataValue(MetricsType.ShotsPerKill, Math.Round((TotalHitNum + MissHitNum) / totalKillNums, 2)); } #endregion #region Target private void OnShottedTargetEvent(BaseShotTarget target) { int baseS = GetCurrentBaseScore(target != null); if (target != null) { HumanoidPartShotTarget part = target as HumanoidPartShotTarget; MozambiqueHumanoidShotTarget dependTarget = part.DependTarget as MozambiqueHumanoidShotTarget; if (dependTarget.Health <= 0) { totalKillNums++; if(IsMozambiqueShotOrder(dependTarget.m_CauseHumanoidPartReduceHPOrder)) { mozambiqueKillNums++; } TimerSystem.GetInstance().RemoveTimeTask(m_ObserveTimer); m_ObserveTimer = null; DestroyShootTarget(dependTarget); } TotalHitNum++; if (!dependTarget.isCurFalseHit) { int bestS = m_IsBestHit ? Mathf.CeilToInt(baseS * m_ScoreData.bestHitMul) : 0; IncreaseScore(baseS + bestS); } else { int missPunitiveS = Mathf.CeilToInt(baseS * m_ScoreData.falsePunitiveMul) + Random.Range(-2, 2); IncreaseScore(missPunitiveS * -1); } StartBestHitTimer(); } else { MissHitNum++; int missPunitiveS = Mathf.CeilToInt(baseS * m_ScoreData.missPunitiveMul) + Random.Range(-3, 3); IncreaseScore(missPunitiveS * -1); } } #endregion public bool IsMozambiqueShotOrder(List order) { if (order == null) return false; if (order.Count != 3) return false; return order[0] == HumanoidPartType.Body && order[1] == HumanoidPartType.Body && order[2] == HumanoidPartType.Head; } private int GetCurrentBaseScore(bool isHit) { int baseS = 0; switch (isHit? curTarget.Health: curTarget.Health - 1) { case 2: baseS = m_ScoreData.firstBaseScore; break; case 1: baseS = m_ScoreData.secondBaseScore; break; case 0: baseS = m_ScoreData.thirdBaseScore; break; default: baseS = m_ScoreData.firstBaseScore; break; } return baseS; } private void GenerateShotTarget() { GameObject obj = GameObject.Instantiate(Resources.Load("Prefabs/MozambiqueHumanoidShotTarget")); obj.transform.rotation = Quaternion.Euler(0, 180, 0); curTarget = obj.GetComponent(); curTarget.InitHumanoidShotTarget(3, RandomPosition()); curTarget.InitMozambiqueHumanoidShotTarget(); m_ObserveTimer = TimerSystem.GetInstance().AddTimeTask(ObserveTimerTimeOut, 5); StartBestHitTimer(); } private void IntervalTimerTimeOut() { GenerateShotTarget(); } private void ObserveTimerTimeOut() { m_ObserveTimer = null; int baseS = GetCurrentBaseScore(false); int missPunitiveS = Mathf.CeilToInt(baseS * m_ScoreData.outTimePunitiveMul) + Random.Range(-2, 2); IncreaseScore(missPunitiveS * -1); DestroyShootTarget(curTarget); } private Vector3 RandomPosition() { Vector2 minOffset = Vector2.zero; Vector2 maxOffset = Vector2.zero; switch (m_DifficultyData.difficultyType) { case DifficultyType.Standard: minOffset = new Vector2(0.2f, 0f); maxOffset = new Vector2(0.8f, 0f); break; case DifficultyType.Advance: minOffset = new Vector2(0.2f, 0.15f); maxOffset = new Vector2(0.8f, 0.4f); break; case DifficultyType.Professional: minOffset = new Vector2(0.2f, 0.15f); maxOffset = new Vector2(0.8f, 0.6f); break; } Vector2 widthLimt = Vector2.zero; Vector2 heightLimt = Vector2.zero; switch (m_DifficultyType) { case DifficultyType.Standard: widthLimt = new Vector2(-3.5f, 3.5f); heightLimt = new Vector2(-1.8f, -1.8f); break; case DifficultyType.Advance: widthLimt = new Vector2(-5, 5); heightLimt = new Vector2(-1.8f, -1f); break; case DifficultyType.Professional: widthLimt = new Vector2(-8, 8); heightLimt = new Vector2(-1.8f, 0f); break; } Vector3 min = ExtraTool.GetScreenOffsetPosition(minOffset, m_DifficultyData.distance, widthLimt, heightLimt); Vector3 max = ExtraTool.GetScreenOffsetPosition(maxOffset, m_DifficultyData.distance, widthLimt, heightLimt); return ExtraTool.RandomPosition(min, max); } private void DestroyShootTarget(HumanoidShotTarget target) { if (target != null) { GameObject.Destroy(target.gameObject); } m_IntervalTimer = TimerSystem.GetInstance().AddTimeTask(IntervalTimerTimeOut, 3f); } private void ResetTarget() { if (curTarget != null) { GameObject.Destroy(curTarget.gameObject); curTarget = null; } } private void UpdatePrecision() { double totalShot = TotalHitNum + MissHitNum; double precision = 0; if (totalShot != 0) { precision = Math.Round(TotalHitNum / totalShot, 2); } SetResultMetricsDataValue(MetricsType.Precision, precision); } } }