using System.Collections.Generic; using UnityEngine; public class MouseInMap : MonoBehaviour { public float targetDistanceThreshold = 6f; public float enemyDistanceThreshold = 1f; [SerializeField] private Camera playCamera; [SerializeField] private GameObject AgentObj; [SerializeField] private GameObject environmentObj; [SerializeField] private GameObject mousePreviewObj; [SerializeField] private GameObject enemyContainerObj; [SerializeField] private GameObject sceneBlockContainerObj; [SerializeField] private GameObject targetControllerObj; [SerializeField] private GameObject HUDObj; private Vector3 nowHitPosition = Vector3.zero; private Vector3 nowHitPositionRelative = Vector3.zero; private LayerMask groundMask; private int blockNum; private CommonParameterContainer commonParamCon; private GameObject previewModel; private TargetController targetCon; private MousePreview mousePreviewCon; private EnemyContainer enemyCon; private SceneBlockContainer sceneBlockCon; private MessageBoxController messageCon; private TargetUIController targetUICon; private const string ErrorMessageColor = "#800000ff"; private const string LevelTooHighError = "[Error]MouseInMap:ChangeBlockLevelTo:"; private const string AttackLevelErrorMsg = "Attack Level is too high!"; private const string GotoLevelErrorMsg = "Goto Level is too high!"; public enum MouseMode { Default, AttackSet, GotoSet, EnemySet } public MouseMode mouseMode = MouseMode.Default; public int blockLevel = 0; private void Start() { commonParamCon = CommonParameterContainer.Instance; groundMask = LayerMask.GetMask("Ground"); targetCon = targetControllerObj.GetComponent(); mousePreviewCon = mousePreviewObj.GetComponent(); enemyCon = enemyContainerObj.GetComponent(); sceneBlockCon = sceneBlockContainerObj.GetComponent(); targetUICon = HUDObj.GetComponent(); messageCon = HUDObj.GetComponent(); } private void Update() { nowHitPosition = GetMouseOnMapPosition(); nowHitPositionRelative = nowHitPosition - environmentObj.transform.position; // if mouse position in area, update mouseInMapPosition as nowHitPosition if (nowHitPositionRelative.x < targetCon.maxAgentAreaX && nowHitPositionRelative.x > targetCon.minAgentAreaX && nowHitPositionRelative.z < targetCon.maxEnemyAreaZ && nowHitPositionRelative.z > targetCon.minAgentAreaZ) { mousePreviewCon.UpdatePreviewPosition(nowHitPosition); // Mouse button R pressed if (Input.GetMouseButtonDown(1)) { switch (mouseMode) { case MouseMode.AttackSet: if (IsAgentorEnemyWithinDistance(targetDistanceThreshold)) { // if agent or enemy is nearby, do not create new block messageCon.PushMessage(new List { "Agent or Enemy is too close!" }, new List { messageCon.errorColor }); } else { // if agent or enemy is not nearby, create new block sceneBlockCon.CreateNewBlock(Targets.Attack, blockLevel, blockNum, nowHitPositionRelative); sceneBlockCon.InitializeBlock(environmentObj); targetCon.AttackModeChange(nowHitPositionRelative); ChangeMouseMode(MouseMode.Default); } break; case MouseMode.GotoSet: if (IsAgentorEnemyWithinDistance(targetDistanceThreshold)) { // if agent or enemy is nearby, do not create new block messageCon.PushMessage(new List { "Agent or Enemy is too close!" }, new List { messageCon.errorColor }); } else { // if agent or enemy is not nearby, create new block sceneBlockCon.CreateNewBlock(Targets.Go, blockLevel, blockNum, nowHitPositionRelative); sceneBlockCon.InitializeBlock(environmentObj); targetCon.GotoModeChange(nowHitPositionRelative); ChangeMouseMode(MouseMode.Default); } break; case MouseMode.EnemySet: if (IsAgentorEnemyWithinDistance(enemyDistanceThreshold)) { messageCon.PushMessage(new List { "Agent or Enemy is too close!" }, new List { messageCon.errorColor }); } else { enemyCon.InitEnemyAtHere(new Vector3(nowHitPositionRelative.x, 1, nowHitPositionRelative.z)); } break; default: break; } } } } // change mouse mode, level and PreviewModel public void ChangeMouseMode(MouseMode mouseMode, int level = -1, int blockNum = -1) { this.mouseMode = mouseMode; Targets nowTargetType; switch (mouseMode) { case MouseMode.AttackSet: case MouseMode.GotoSet: // set target type nowTargetType = GetTargetTypeByMouseMode(mouseMode); // set blockLevel or send error message if (level < 0) { // while blockLevel is not set, send error message messageCon.PushMessage(new List { "[ERROR]MouseInMap:ChangeMouseMode:", "Level not set!", "mouseMode=", mouseMode.ToString() }, new List { messageCon.errorColor }); blockLevel = commonParamCon.scenePrefabSet.GetLevelNumber(nowTargetType); } else { // while blockLevel is set blockLevel = level; } blockLevel = level; // set blockNum or random choose attack scene block type if (blockNum < 0) { // while blockNum is not set, random choose block type this.blockNum = Random.Range(0, commonParamCon.scenePrefabSet.GetBlockNumber(blockLevel, nowTargetType)); } else { // while blockNum is set this.blockNum = blockNum; } // set previewModel previewModel = commonParamCon.scenePrefabSet.GetPrefab(blockLevel, this.blockNum, nowTargetType); mousePreviewCon.ChangePreviewTo(previewModel); break; case MouseMode.EnemySet: // set enemy as preview previewModel = enemyCon.enemyPrefab; mousePreviewCon.ChangePreviewTo(previewModel, true); break; default: // default mode, delete all preview model mousePreviewCon.DeleteAllPreviewModele(); break; } } // get mouse position on map, return an absolute Vector3 coordinate public Vector3 GetMouseOnMapPosition() { // shoot raycast from mainCamera center to mousepositon RaycastHit nowHit; Ray ray = playCamera.ScreenPointToRay(Input.mousePosition); // if raycast hit gameobject if (Physics.Raycast(ray, out nowHit, Mathf.Infinity, groundMask)) { //draw raycast Debug.DrawRay(ray.origin, ray.direction * 100, Color.red); return nowHit.point; } else { return Vector3.zero; } } // check if agent or enemy is too close to nowHitPosition private bool IsAgentorEnemyWithinDistance(float distance) { // check all child object in enemyContainerObj // if any child object is near by nowHitPosition in 10, return true Vector3 playerPosition = Vector3.zero; for (int i = 0; i < enemyContainerObj.transform.childCount; i++) { //set enemy Position's y as 0 playerPosition = enemyContainerObj.transform.GetChild(i).position; playerPosition.y = 0; // check if enemy near by nowHitPositionRelative in distance, return true if (Vector3.Distance(playerPosition, nowHitPosition) < distance) { return true; } } // set agentObj position's y as 0 playerPosition = AgentObj.transform.position; playerPosition.y = 0; // check if agentObj near by nowHitPositionRelative in distance, return true if (Vector3.Distance(playerPosition, nowHitPosition) < distance) { return true; } // if no enemy or agent near by, return false return false; } // change to TargetType from MouseMode private Targets GetTargetTypeByMouseMode(MouseMode mode) { switch (mode) { case MouseMode.AttackSet: return Targets.Attack; case MouseMode.GotoSet: return Targets.Go; default: messageCon.PushMessage(new List { "[Error]MouseInMap:GetTargetTypeByMouseMode:", "Mouse Mode not found!", "mode=", mode.ToString() }, new List { messageCon.errorColor }); return Targets.Num; } } }