protected override void ServerUpdateMob(ServerUpdateData data) { var character = data.GameObject; ServerCharacterAiHelper.ProcessRetreatingAi( character, distanceRetreat: 4, out var movementDirection, out var rotationAngleRad); this.ServerSetMobInput(character, movementDirection, rotationAngleRad); }
protected override void ServerUpdateMob(ServerUpdateData data) { var character = data.GameObject; ServerCharacterAiHelper.ProcessAggressiveAi( character, isRetreating: false, distanceRetreat: 0, distanceEnemyTooClose: 1, distanceEnemyTooFar: 10, out var movementDirection, out var rotationAngleRad); this.ServerSetMobInput(character, movementDirection, rotationAngleRad); }
protected override void ServerUpdateMob(ServerUpdateData data) { var character = data.GameObject; var currentStats = data.PublicState.CurrentStats; ServerCharacterAiHelper.ProcessAggressiveAi( character, isRetreating: currentStats.HealthCurrent < currentStats.HealthMax / 3, distanceRetreat: 7, distanceEnemyTooClose: 1, distanceEnemyTooFar: 5, out var movementDirection, out var rotationAngleRad); this.ServerSetMobInput(character, movementDirection, rotationAngleRad); }
protected override void ServerUpdateMob(ServerUpdateData data) { var character = data.GameObject; ServerCharacterAiHelper.ProcessAggressiveAi( character, isRetreating: false, isRetreatingForHeavyVehicles: this.AiIsRunAwayFromHeavyVehicles, distanceRetreat: 0, distanceEnemyTooClose: 1, distanceEnemyTooFar: 4, movementDirection: out var movementDirection, rotationAngleRad: out var rotationAngleRad); this.ServerSetMobInput(character, movementDirection, rotationAngleRad); }
protected override void ServerUpdateMob(ServerUpdateData data) { var character = data.GameObject; var currentStats = data.PublicState.CurrentStats; ServerCharacterAiHelper.ProcessAggressiveAi( character, isRetreating: currentStats.HealthCurrent < currentStats.HealthMax / 4, isRetreatingForHeavyVehicles: this.AiIsRunAwayFromHeavyVehicles, distanceRetreat: 10, distanceEnemyTooClose: 1, distanceEnemyTooFar: 8, movementDirection: out var movementDirection, rotationAngleRad: out var rotationAngleRad); this.ServerSetMobInput(character, movementDirection, rotationAngleRad); }
protected override void ServerUpdateMob(ServerUpdateData data) { var character = data.GameObject; ServerCharacterAiHelper.ProcessAggressiveAi( character, targetCharacter: ServerCharacterAiHelper.GetClosestTargetPlayer(character), isRetreating: false, isRetreatingForHeavyVehicles: false, distanceRetreat: 0, distanceEnemyTooClose: 1, distanceEnemyTooFar: 8, movementDirection: out var movementDirection, rotationAngleRad: out var rotationAngleRad, attackFarOnlyIfAggro: true); this.ServerSetMobInput(character, movementDirection, rotationAngleRad); }
protected override void ServerUpdateMob(ServerUpdateData data) { var character = data.GameObject; ServerCharacterAiHelper.ProcessAggressiveAi( character, targetCharacter: ServerCharacterAiHelper.GetClosestTargetPlayer(character), isRetreating: false, isRetreatingForHeavyVehicles: this.AiIsRunAwayFromHeavyVehicles, distanceRetreat: 0, distanceEnemyTooClose: 1, distanceEnemyTooFar: 10, movementDirection: out var movementDirection, rotationAngleRad: out var rotationAngleRad); this.ServerSetMobInput(character, movementDirection, rotationAngleRad); IWorldServerService ServerWorldService = Api.IsServer ? Api.Server.World : null; }
protected override void ServerUpdateMob(ServerUpdateData data) { if (data.PublicState.IsDead) { return; } var character = data.GameObject; ServerCharacterAiHelper.ProcessAggressiveAi( character, isRetreating: false, isRetreatingForHeavyVehicles: false, distanceRetreat: 0, distanceEnemyTooClose: 1, distanceEnemyTooFar: 16, movementDirection: out var movementDirection, rotationAngleRad: out var rotationAngleRad); this.ServerSetMobInput(character, movementDirection, rotationAngleRad); }
protected virtual void ServerUpdateTurret(ServerUpdateData data, TurretMode turretMode) { var character = data.GameObject; var privateState = data.PrivateState; var publicState = GetPublicState(character); var weaponState = privateState.WeaponState; if (privateState.WeaponState.ProtoWeapon is ProtoItemWeaponTurretWithAmmo protoItemWeaponTurretWithAmmo) { protoItemWeaponTurretWithAmmo.ServerUpdateCurrentAmmo(character, weaponState); // attack range may change if the ammo type has changed privateState.AttackRange = weaponState.WeaponCache?.RangeMax ?? 0; } ServerCharacterAiHelper.ProcessAggressiveAi( character, targetCharacter: ServerTurretAiHelper.GetClosestTargetPlayer(character, turretMode, privateState), isRetreating: false, isRetreatingForHeavyVehicles: false, distanceRetreat: 0, distanceEnemyTooClose: 1, distanceEnemyTooFar: 8, movementDirection: out _, rotationAngleRad: out var rotationAngleRad, attackFarOnlyIfAggro: true, customIsValidTargetCallback: IsValidTargetCallback); var currentRotationAngleRad = (double)publicState.AppliedInput.RotationAngleRad; rotationAngleRad = MathHelper.LerpAngle(currentRotationAngleRad, rotationAngleRad, data.DeltaTime, this.BarrelRotationRate); publicState.AppliedInput.Set( new CharacterInput() { MoveModes = CharacterMoveModes.None, RotationAngleRad = (float)rotationAngleRad }, moveSpeed: 0); if (weaponState.SharedGetInputIsFiring() && !ServerCharacterAiHelper.CanHitAnyTargetWithRangedWeapon( character, rotationAngleRad, privateState, isValidTargetCallback: IsValidTargetForceAttackNeutralsCallback)) { // don't shoot as not pointing on the target right now weaponState.SharedSetInputIsFiring(false); } bool IsValidTargetCallback(IWorldObject worldObject) => ServerTurretAiHelper.IsValidTarget(character, worldObject, turretMode, forceAttackNeutrals: false); bool IsValidTargetForceAttackNeutralsCallback(IWorldObject worldObject) => ServerTurretAiHelper.IsValidTarget(character, worldObject, turretMode, forceAttackNeutrals: true); }
protected override void ServerUpdateMob(ServerUpdateData data) { var character = data.GameObject; var publicState = data.PublicState; if (publicState.IsDead) { return; } var privateState = data.PrivateState; var lastTargetCharacter = privateState.CurrentTargetCharacter; var deltaTime = data.DeltaTime; // Regenerate the health points a bit on every frame // if there was no damage dealt to boss recently. // Please note: the difficulty coefficient doesn't apply there // as the boss HP doesn't change with difficulty - only damage // to it is modified by the difficulty coefficient. if (Server.Game.FrameTime >= privateState.LastDamageTime + RegenerationDelaySeconds) { publicState.CurrentStats.ServerSetHealthCurrent( (float)(publicState.CurrentStats.HealthCurrent + HealthRegenerationPerSecond * deltaTime)); } var weaponList = this.ServerSelectWeaponsList(privateState, deltaTime, out var isSwitchingToNovaAttack); ServerCharacterAiHelper.ProcessBossAi( character, weaponList, distanceEnemyTooClose: 7.5, distanceEnemyTooFar: 15.5, movementDirection: out var movementDirection, rotationAngleRad: out var rotationAngleRad); if (movementDirection != default && !ServerCanMoveInDirection(character.TilePosition.ToVector2D(), movementDirection, privateState.HoldPosition.ToVector2D())) { // cannot move in desired direction - too far from the position to hold movementDirection = default; } this.ServerSetMobInput(character, movementDirection, rotationAngleRad); if (lastTargetCharacter is null && privateState.CurrentTargetCharacter != null // is the last attack happened not too recently? && privateState.TimeToNextNovaAttack < NovaAttackInterval.Max - 8) { //Logger.Dev("Boss acquired target! Will use a nova attack in the next 2-4 seconds!"); privateState.TimeToNextNovaAttack = RandomHelper.Next(2, 4); } if (isSwitchingToNovaAttack) { privateState.WeaponState.SharedSetInputIsFiring(false); } }