/// <summary> /// Causes the squad to move to hack the context indicator target. /// One squad member is randomly chosen to hack while the others occupy cover points /// near the target. /// </summary> /// <param name="_context"></param> void SquadHackCommand(CurrentContext _context) { HackableConsole console = _context.indicator_hit.GetComponent <HackableConsole>(); if (console.hacked) { return; } order_target_bobber.SetTarget(console.transform); squad_sense.hacker_squaddie = squad_sense.squaddies[Random.Range(0, num_squaddies)]; for (int i = 0; i < num_squaddies; ++i) { SquaddieAI squaddie = squad_sense.squaddies[i]; squaddie.knowledge.order_console = console; if (squaddie == squad_sense.hacker_squaddie) { // Hacker squaddie moves to hack. squaddie.knowledge.current_order = OrderType.HACK; squaddie.nav.destination = console.hack_point.position; } else { // The other squaddies move to defend. Vector3 pos = JHelper.PosToCirclePos(console.hack_point.position, num_squaddies, i, 5); squaddie.knowledge.current_order = OrderType.GUARD; squaddie.MoveToCoverNearPosition(pos); } } }
public override bool Decide(SquaddieAI _squaddie) { bool enemies_nearby = _squaddie.knowledge.nearby_targets.Count > 0; bool squad_target_exists = _squaddie.knowledge.squad_sense.squad_target != null; return(enemies_nearby || squad_target_exists); }
public override bool Decide(SquaddieAI _squaddie) { bool order_obeyed = true; switch (_squaddie.knowledge.current_order) { case OrderType.MOVE: { order_obeyed &= (!_squaddie.nav.hasPath && !_squaddie.nav.pathPending); } break; case OrderType.FOLLOW: { order_obeyed = false; } break; case OrderType.ATTACK: { order_obeyed &= _squaddie.knowledge.order_target == null; } break; case OrderType.HACK: { order_obeyed &= _squaddie.knowledge.order_console.hacked; } break; case OrderType.GUARD: { order_obeyed &= _squaddie.knowledge.squad_sense.hacker_squaddie == null; } break; } return(order_obeyed); }
bool FindNewFollowTarget(SquaddieAI _squaddie) { if (_squaddie.knowledge.follow_target == null) { foreach (SquaddieAI ally in _squaddie.knowledge.squad_sense.squaddies) { if (ally == _squaddie || ally.knowledge.follow_target == _squaddie.transform) { continue; } _squaddie.knowledge.follow_target = ally.transform; break; } } if (_squaddie.knowledge.follow_target == null) { Transform follow_target = GameManager.scene.perspective_manager.FPSModeActive() ? GameManager.scene.player.transform : GameManager.scene.context_scanner.indicator_transform; _squaddie.knowledge.follow_target = follow_target; } return(_squaddie.knowledge.follow_target != null); }
public override void Act(SquaddieAI _squaddie) { _squaddie.knowledge.crouched = _squaddie.knowledge.in_cover && _squaddie.knowledge.current_target_visible; _squaddie.knowledge.crouched &= !_squaddie.nav.hasPath; }
public override void Trigger(SquaddieAI _squaddie) { _squaddie.knowledge.current_order = OrderType.NONE; _squaddie.knowledge.order_waypoint = Vector3.zero; _squaddie.knowledge.hacking = false; _squaddie.knowledge.squad_sense.hacker_squaddie = null; }
void CheckTransitions(SquaddieAI _squaddie) { foreach (Transition transition in transitions) { bool decision_success = transition.decision.Decide(_squaddie); State target_state = decision_success ? transition.true_state : transition.false_state; if (target_state == null) { continue; } if (decision_success) { foreach (TransitionTrigger trigger in transition.true_triggers) { trigger.Trigger(_squaddie); } } else { foreach (TransitionTrigger trigger in transition.false_triggers) { trigger.Trigger(_squaddie); } } _squaddie.TransitionToState(target_state); } }
/// <summary> /// Constructs an individual squaddie with the passed faction settings. /// </summary> /// <param name="_faction">The faction of the squaddie.</param> /// <param name="_pos">The location the squaddie should be placed.</param> /// <returns>A reference to the instantiated squaddie.</returns> public SquaddieAI CreateSquaddie(FactionSettings _faction, Vector3 _pos) { GameObject clone = Instantiate(squaddie_prefab, _pos, Quaternion.identity); SquaddieAI squaddie = clone.GetComponent <SquaddieAI>(); squaddie.Init(_faction); return(squaddie); }
public void Hack(SquaddieAI _squaddie) { if (hacked) { return; } hack_timer = time_to_reset; }
public static bool SameFaction(SquaddieAI _a, FactionSettings _b) { if (_a == null || _b == null) { return(false); } return(SameFaction(_a.stats.faction_settings, _b)); }
public Color state_color = Color.grey; // Debug gizmo colour. public void UpdateState(SquaddieAI _squaddie) { _squaddie.knowledge.state_time_elapsed += Time.deltaTime; DoActions(_squaddie); CheckTransitions(_squaddie); _squaddie.knowledge.prev_state_time_elapsed = _squaddie.knowledge.state_time_elapsed; }
void ShootEnemy(SquaddieAI _squaddie) { Quaternion rot = Quaternion.LookRotation(_squaddie.knowledge.current_target.torso_transform.position - _squaddie.torso_transform.position); _squaddie.torso_transform.rotation = Quaternion.RotateTowards(_squaddie.torso_transform.rotation, rot, (_squaddie.nav.angularSpeed * 2) * Time.deltaTime); _squaddie.knowledge.chain_gun.cycle = _squaddie.knowledge.current_target_visible; }
void DoActions(SquaddieAI _squaddie) { foreach (Action action in actions) { if (!action.PreconditionsMet(_squaddie)) { continue; } action.Act(_squaddie); } }
public void AddSquaddie(SquaddieAI _squaddie_ai) { if (squad_sense.squaddies.Contains(_squaddie_ai)) { return; } _squaddie_ai.Init(squad_faction); _squaddie_ai.LinkSquadSense(ref squad_sense); squad_sense.squaddies.Add(_squaddie_ai); }
public override bool PreconditionsMet(SquaddieAI _squaddie) { bool ordered_to_hack = _squaddie.knowledge.current_order == OrderType.HACK; bool nearby_console_exists = _squaddie.knowledge.nearby_console != null; if (!ordered_to_hack || !nearby_console_exists) { _squaddie.knowledge.hacking = false; return(false); } return(true); }
public override void Act(SquaddieAI _squaddie) { if (_squaddie.knowledge.follow_target == null) { if (!FindNewFollowTarget(_squaddie)) { return; } } _squaddie.nav.isStopped = _squaddie.nav.remainingDistance <= _squaddie.nav.stoppingDistance; _squaddie.nav.destination = _squaddie.knowledge.follow_target.position; }
/// <summary> /// Cause the agent to seek a position that allows it to safely engage the target. /// </summary> /// <param name="_target">The flank target.</param> public void MoveToFlankEnemy(SquaddieAI _target) { var cover_points = GameManager.scene.tactical_assessor.FindFlankingPositions( this, _target, settings.cover_search_radius); if (cover_points.Count == 0) { nav.destination = _target.transform.position; } else { nav.destination = EvaluateUniqueCoverPoint(cover_points); } }
/// <summary> /// Creates a new squad with the passed faction settings. /// The squaddies are arranged in a circular pattern at the passed position, based on the squad size. /// </summary> /// <param name="_faction">The faction of the squad.</param> /// <param name="_num_squaddies">The size of the squad.</param> /// <param name="_pos">The where the squad should be arranged.</param> /// <returns>A reference to the instantiated squad.</returns> public SquadManager CreateSquad(FactionSettings _faction, int _num_squaddies, Vector3 _pos) { SquadManager squad_manager = new SquadManager(_faction); for (int i = 0; i < _num_squaddies; ++i) { SquaddieAI squaddie = CreateSquaddie(_faction, _pos); squaddie.transform.position = JHelper.PosToCirclePos(_pos, _num_squaddies, i, _num_squaddies * 0.5f); squad_manager.AddSquaddie(squaddie); } return(squad_manager); }
void MoveToPosition(SquaddieAI _squaddie) { UpdateHackPosition(_squaddie); if (_squaddie.nav.hasPath && _squaddie.nav.remainingDistance <= _squaddie.nav.stoppingDistance) { _squaddie.nav.isStopped = true; _squaddie.nav.ResetPath(); } else { _squaddie.nav.isStopped = false; } }
void UpdateHackPosition(SquaddieAI _squaddie) { if (_squaddie.knowledge.current_order == OrderType.HACK) { HackableConsole console = _squaddie.knowledge.order_console; float dist = Vector3.Distance(_squaddie.transform.position, console.transform.position); if (dist > _squaddie.nav.stoppingDistance) { _squaddie.nav.destination = console.hack_point.position; _squaddie.nav.isStopped = false; } } }
public override bool PreconditionsMet(SquaddieAI _squaddie) { bool target_exists = _squaddie.knowledge.current_target != null; bool target_visible = _squaddie.knowledge.current_target_visible; bool target_in_range = _squaddie.knowledge.current_target_in_range; bool hacking = _squaddie.knowledge.hacking; if (!target_exists || !target_visible || !target_in_range || hacking) { _squaddie.knowledge.chain_gun.cycle = false; return(false); } return(true); }
// CollisionEventForwarder event. public void TriggerEnter(Collider _other) { if (!_other.CompareTag("DamageableBody")) { return; } SquaddieAI squaddie = _other.GetComponentInParent <SquaddieAI>(); if (squaddie == null || JHelper.SameFaction(squaddie, this)) { return; } knowledge.nearby_targets.Add(squaddie); }
public override bool PreconditionsMet(SquaddieAI _squaddie) { OrderType current_order = _squaddie.knowledge.current_order; bool eligible_to_engage = current_order == OrderType.NONE || current_order == OrderType.ATTACK; if (!eligible_to_engage || _squaddie.knowledge.current_target == null || (_squaddie.knowledge.current_target_visible && _squaddie.knowledge.current_target_in_range)) { return(false); } return(true); }
void DestroyMouseOverSquaddie() { RaycastHit hit; var success = JHelper.RaycastMousePosToLayer("Damageable", out hit); if (!success) { return; } SquaddieAI squaddie = hit.collider.transform.root.GetComponent <SquaddieAI>(); if (squaddie != null) { Destroy(squaddie.gameObject); } }
/// <summary> /// Causes the squad to engage the context indicator target. /// </summary> /// <param name="_context">The current context.</param> void SquadAttackCommand(CurrentContext _context) { SquaddieAI attack_target = _context.indicator_hit.GetComponent <SquaddieAI>(); order_target_bobber.SetTarget(attack_target.transform); foreach (SquaddieAI squaddie in squad_sense.squaddies) { if (JHelper.SameFaction(squaddie, attack_target)) { continue; } squaddie.knowledge.order_target = attack_target; squaddie.knowledge.current_order = OrderType.ATTACK; } }
/// <summary> /// Evaluates advantageous engagement positions from the flanker to the flank target, within /// the passed radius. /// </summary> /// <param name="_flanker">The flanking squaddie.</param> /// <param name="_flank_target">The target of the flank.</param> /// <param name="_radius">The radius to search for cover points around the flanker and flank target.</param> /// <returns>A list of cover points in descending order based on their distance to the flank target.</returns> public List <CoverPoint> FindFlankingPositions(SquaddieAI _flanker, SquaddieAI _flank_target, float _radius) { // Consider nearby cover points, as well as those near the enemy. var cover_to_consider = ClosestCoverPoints(_flanker.transform.position, _radius); cover_to_consider.AddRange(ClosestCoverPoints(_flank_target.transform.position, _radius)); // The actual points that will be returned. List <CoverPoint> flanking_positions = new List <CoverPoint>(); foreach (CoverPoint cover_point in cover_to_consider) { float distance = Vector3.Distance(_flank_target.transform.position, cover_point.position); bool too_far = distance > _flanker.settings.maximum_engage_distance; bool too_close = distance < _flanker.settings.minimum_engage_distance; if (too_far || too_close) { continue; } bool bad_flank = !_flanker.TestSightToPosition(cover_point.position, _flank_target.torso_transform.position); bool enemy_los = _flank_target.TestSightToPosition(cover_point.position); if (bad_flank || enemy_los) { continue; } // The further from the flank target the better. cover_point.weighting -= distance; // Encourage squad cohesion. cover_point.weighting += (cover_point.position - _flanker.knowledge.squad_sense.squad_center).magnitude; flanking_positions.Add(cover_point); } // The furthest flanking positions should appear first in the list. flanking_positions = flanking_positions.OrderBy(elem => elem.weighting).ToList(); return(flanking_positions); }
// CollisionEventForwarder event. public void TriggerExit(Collider _other) { if (!_other.CompareTag("DamageableBody")) { return; } SquaddieAI squaddie = _other.GetComponentInParent <SquaddieAI>(); if (squaddie == null) { return; } if (knowledge.nearby_targets.Contains(squaddie)) { knowledge.nearby_targets.Remove(squaddie); } }
void EvaluateClosestTarget() { SquaddieAI closest_target = null; float closest = Mathf.Infinity; knowledge.nearby_targets.RemoveAll(elem => elem == null); foreach (SquaddieAI enemy in knowledge.nearby_targets) { float distance = (enemy.transform.position - transform.position).sqrMagnitude; if (distance > closest) { continue; } closest = distance; closest_target = enemy; } knowledge.closest_target = closest_target; }
public override bool PreconditionsMet(SquaddieAI _squaddie) { OrderType current_order = _squaddie.knowledge.current_order; bool eligible_to_reposition = current_order == OrderType.NONE || current_order == OrderType.ATTACK || current_order == OrderType.GUARD; if (!eligible_to_reposition || _squaddie.knowledge.current_target == null) { return(false); } bool moving = _squaddie.nav.hasPath; if (!moving && (!_squaddie.knowledge.in_cover || _squaddie.knowledge.position_compromised)) { return(true); } return(false); }
public override void Trigger(SquaddieAI _squaddie) { _squaddie.knowledge.chain_gun.cycle = false; }