public void Update(float elapsed, GravityGun gun) { if (Constants.IS_ME_ALONE) { m_debugText.SetWorldPosition(Player.GetWorldPosition()); m_debugText.SetText(ScriptHelper.ToDisplayString(m_state + "\n", Player.IsInputEnabled + "\n", Player.GetBotBehaviorSet().RangedWeaponUsage + "\n", GetNeareastObject(gun) == null)); } else { Bot.LogDebug(m_state, Player.IsInputEnabled, Player.GetBotBehaviorSet().RangedWeaponUsage); } if (m_state == State.Normal || m_state == State.Cooldown) { // Trick the bot to use this weapon only when there are objects around // and stop using it when there is nothing to shoot with UpdateWeaponUsage(gun); } else { m_timeout += elapsed; if (m_timeout >= 3000f) { Stop("State timeout"); } if (Player.IsStaggering || Player.IsStunned || !Player.IsOnGround || Player.IsBurningInferno) { Stop("Player is stunned"); } } if (Game.IsEditorTest) { var o = GetNeareastObject(gun); if (o != null) { Game.DrawArea(o.GetAABB(), Color.Red); } if (NearestObject != null) { Game.DrawArea(NearestObject.GetAABB(), Color.Magenta); } foreach (var p in SearchedEnemies) { Game.DrawArea(p.GetAABB(), Color.Cyan); } if (m_targetEnemy != null) { Game.DrawArea(m_targetEnemy.GetAABB(), Color.Green); } Game.DrawArea(DangerArea, Color.Red); Game.DrawCircle(gun.GetHoldPosition(false), GravityGun.Range); Game.DrawArea(GetMimimumRange(), Color.Cyan); } //ScriptHelper.Stopwatch(() => //{ switch (m_state) { case State.Normal: { if (!ScriptHelper.IsElapsed(m_stateDelay, 30)) { break; } m_stateDelay = Game.TotalElapsedGameTime; if (EnemiesNearby()) { if (!Player.IsInputEnabled) { Player.SetInputEnabled(true); } break; } var enemies = SearchedEnemies; if (enemies.Count() > 0 && NearestObject == null) { NearestObject = gun.IsSupercharged ? enemies.First() : GetNeareastObject(gun); } if (NearestObject != null && !m_executeOnce && Player.IsOnGround && !Player.IsStaggering && !Player.IsStunned && !Player.IsHoldingPlayerInGrab) { Player.SetInputEnabled(false); if (Player.CurrentWeaponDrawn != gun.Type) { if (gun.Type == WeaponItemType.Rifle) { Player.AddCommand(new PlayerCommand(PlayerCommandType.DrawRifle)); } if (gun.Type == WeaponItemType.Handgun) { Player.AddCommand(new PlayerCommand(PlayerCommandType.DrawHandgun)); } ChangeState(State.Drawing); break; } if (GetCurrentAmmo(gun) == 0) { Player.AddCommand(new PlayerCommand(PlayerCommandType.Reload)); ChangeState(State.Reloading); break; } Player.AddCommand(new PlayerCommand(PlayerCommandType.StartAimAtPrecise, NearestObject.UniqueID)); m_executeOnce = true; } if (NearestObject != null && Player.CurrentWeaponDrawn == gun.Type && GetCurrentAmmo(gun) > 0) { ChangeState(State.AimingTargetedObject); } break; } case State.Drawing: { if (!Player.IsDrawingWeapon) { ChangeState(State.Normal); } break; } case State.Reloading: { if (!Player.IsReloading) { ChangeState(State.Normal); } break; } case State.AimingTargetedObject: { var rangeLimit = GetRangeLimit(); var holdPosition = gun.GetHoldPosition(false); if (NearestObject.IsRemoved || !ScriptHelper.IntersectCircle(NearestObject.GetAABB(), holdPosition, GravityGun.Range, rangeLimit[0], rangeLimit[1])) { Stop("NearestObject not in range"); break; } if (Player.IsManualAiming && MaybeLockTarget(gun, NearestObject) && IsObjectInRange(gun, NearestObject)) { gun.PickupObject(); ChangeState(State.Retrieving); } break; } case State.Retrieving: { if (gun.TargetedObject == null || IsObjectStuck(gun.TargetedObject)) { Stop(gun.TargetedObject == null ? "TargetedObject = null" : "TargetedObject is stuck"); break; } if (gun.IsTargetedObjectStabilized && gun.TargetedObject.GetLinearVelocity().Length() < 1) { var enemies = SearchedEnemies; if (enemies.Count() > 0 || m_nearestObjectIsPlayer) { if (enemies.Count() > 1 && m_nearestObjectIsPlayer) { foreach (var enemy in enemies) { if (enemy.UniqueID != NearestObject.UniqueID) { m_targetEnemy = enemy; break; } } } else if (enemies.Count() > 0) { m_targetEnemy = enemies.First(); } if (m_targetEnemy != null) { Player.AddCommand(new PlayerCommand(PlayerCommandType.StartAimAtPrecise, m_targetEnemy.UniqueID)); } ChangeState(State.AimingEnemy); var botBehaviorSet = Player.GetBotBehaviorSet(); m_shootDelayTimeThisTurn = RandomHelper.Between( botBehaviorSet.RangedWeaponPrecisionAimShootDelayMin, botBehaviorSet.RangedWeaponPrecisionAimShootDelayMax); } else { Stop("No enemies to shoot"); } } break; } case State.AimingEnemy: { if (gun.TargetedObject == null || m_targetEnemy != null && (m_targetEnemy.IsDead || m_targetEnemy.IsRemoved)) { Stop(gun.TargetedObject == null ? "Already Shot" : "Enemy already dead"); break; } if (IsPlayerInRange(gun, m_targetEnemy) || m_nearestObjectIsPlayer) { m_shootDelayTime += elapsed; if (m_shootDelayTime >= m_shootDelayTimeThisTurn) { if (!m_nearestObjectIsPlayer && NearestObject.GetLinearVelocity().Length() < 1 || m_nearestObjectIsPlayer) { Player.AddCommand(new PlayerCommand(PlayerCommandType.AttackOnce)); m_shootDelayTime = 0f; } } } break; } case State.Cooldown: { if (ScriptHelper.IsElapsed(m_cooldownTime, CooldownTime)) { ChangeState(State.Normal); } break; } } // return m_state.ToString(); //}); }