/// <summary> /// Object initialization /// </summary> public override void Awake() { _info = Info.get.of(race, type); _auto = this; Troop = null; // Call GameEntity awake base.Awake(); // Get DetourAgent and set basic variables _detourAgent = GetComponent <DetourAgent>(); }
public override void controlUnits(Squad squad) { if (!isEnabled || squad.Units.Count == 0) { return; } if (squad.Units[0].type == Storage.UnitTypes.HERO && squad.Units.Count == 1 && Time.time > HERO_GO_TO_BASE && !destinatedToBase) { squad.Units[0].moveTo(new Vector3(ai.rootBasePosition.x + 30f, ai.rootBasePosition.y, ai.rootBasePosition.z + 10f)); this.destinatedToBase = true; return; } if (squad.Units[0].type == Storage.UnitTypes.HERO && destinatedToBase) { return; } // Update squads exploring ++numberSquadsExploring; if (fowManager.Enabled) { bool lostHero = (heroLastPos != Vector3.zero && !heroVisible); // Static values FOWManager.visible[] grid = fowManager.aiVision; Vector2 gridSize = fowManager.getGridSize(); // Get a random unit as a reference point Unit reference = squad.Units[D6.get.rollN(squad.Units.Count)]; DetourAgent agent = reference.Agent; if (agent.TargetState == DetourAgent.MoveRequestState.DT_CROWDAGENT_TARGET_REQUESTING || agent.TargetState == DetourAgent.MoveRequestState.DT_CROWDAGENT_TARGET_WAITING_FOR_PATH || agent.TargetState == DetourAgent.MoveRequestState.DT_CROWDAGENT_TARGET_WAITING_FOR_QUEUE) { return; } // Check if target is already explored Vector3 direction = (agent.TargetPoint - reference.transform.position).normalized; // Set the further point as the targetPoint + sighRange - offset Vector3 targetFOWPos = agent.TargetPoint + direction * (reference.info.attributes.sightRange - RescheduleSightRange); Vector2 targetGrid = fowManager.CoordtoGrid(targetFOWPos); // Check grid status bool targetExplored = ((FOWManager.visible.explored & grid[(int)(targetGrid.x + targetGrid.y * gridSize.y)]) == FOWManager.visible.explored); // If we are moving to a not seen target, don't reschedule at first, otherwise go to a random position in a circle around current position RescheduleType reschedule = RescheduleType.RANDOM_IN_CURRENT_POSITION; if (targetExplored && agent.IsMoving) { reschedule = RescheduleType.RANDOM_IN_DIRECTION; } else if (agent.IsMoving) { reschedule = RescheduleType.NONE; } // Throw a dice int diceValue = D6.get.rollN(ReschuduleDiceFaces); if (diceValue >= RescheduleRandomPointValue) { // Change target point taking into account current direction (but not distance!) reschedule = RescheduleType.RANDOM_IN_DIRECTION; } else if (diceValue >= RescheduleRandomAroundTargetValue && knownPositions.Count > 0) { reschedule = RescheduleType.RANDOM_AROUND_TARGET; } else if (diceValue >= RescheduleRandomDirectionValue) { // Change target point taking into account distance (but not direction!) // Do note that direction is implicitelly taken into account because FOWManager reports // some areas as explored reschedule = RescheduleType.RANDOM_IN_CURRENT_TARGET; } // If we are moving and we don't have to reschedule, skip this squad if (agent.IsMoving && !targetExplored && reschedule == RescheduleType.NONE) { return; } // If we've lost the hero, seek it with the closer unit, regardless of what FOWManager tells us if (lostHero) { float dist = (reference.transform.position - heroLastPos).sqrMagnitude; if (dist < reference.info.attributes.sightRange) // Nota, aixo implica "distancia_actual < sqrt(sightRange)" { heroLastPos = Vector3.zero; lostHero = false; } } // Switch to current reschedule type and find a target point bool result = false; switch (reschedule) { case RescheduleType.NONE: return; case RescheduleType.RANDOM_IN_DIRECTION: result = findPlaceToExplore(grid, gridSize, out targetPos, true, reference.transform.position, agent.TargetPoint); break; case RescheduleType.RANDOM_IN_CURRENT_TARGET: result = findPlaceToExplore(grid, gridSize, out targetPos, agent.TargetPoint, 25f); break; case RescheduleType.RANDOM_IN_CURRENT_POSITION: result = findPlaceToExplore(grid, gridSize, out targetPos, reference.transform.position, 75f); break; case RescheduleType.RANDOM_AROUND_TARGET: result = findPlaceToExplore(grid, gridSize, out targetPos, knownPositions[D6.get.rollN(knownPositions.Count)], 5f); break; } // If we failed to find a valid target and we are not moving (thus we are IDLE), find a random point along all the map if (!result && (!agent.IsMoving || targetExplored)) { result = findPlaceToExplore(fowManager.aiVision, fowManager.getGridSize(), out targetPos); } if (!result) { return; } if (lostHero) { squad.MoveTo(heroLastPos, u => { if (AIController.AI_DEBUG_ENABLED) { ai.aiDebug.registerDebugInfoAboutUnit(u, agentName); } }); } else { targetPos.y = terrain.SampleHeight(targetPos); squad.MoveTo(targetPos, u => { if (AIController.AI_DEBUG_ENABLED) { ai.aiDebug.registerDebugInfoAboutUnit(u, agentName); } }); } } }