protected override void PrepareProtoStatusEffect() { base.PrepareProtoStatusEffect(); // cache the tile offsets // but select only every third tile (will help to reduce the load without damaging accuracy too much) this.serverTileOffsetsCircle = ShapeTileOffsetsHelper .GenerateOffsetsCircle(EnvironmentalTileHeatLookupAreaDiameter) .ToArray(); this.serverTileOffsetsCircle = ShapeTileOffsetsHelper.SelectOffsetsWithRate( this.serverTileOffsetsCircle, rate: 3); this.serverProtoTileLava = Api.GetProtoEntity <TileLava>(); this.serverProtoTileVolcano = Api.GetProtoEntity <TileVolcanic>(); }
protected void ServerSetMobInput( ICharacter character, Vector2F movementDirection, double rotationAngleRad) { var movementDirectionNormalized = new Vector2D( ClampDirection(movementDirection.X), ClampDirection(movementDirection.Y)).Normalized; var moveSpeed = character.SharedGetFinalStatValue(StatName.MoveSpeed); moveSpeed *= ProtoTile.SharedGetTileMoveSpeedMultiplier(character.Tile); Server.Characters.SetMoveSpeed(character, moveSpeed); var moveVelocity = movementDirectionNormalized * moveSpeed; Server.Characters.SetVelocity(character, moveVelocity); var statePublic = GetPublicState(character); statePublic.AppliedInput.Set( new CharacterInput() { MoveModes = CharacterMoveModesHelper.CalculateMoveModes(movementDirectionNormalized), RotationAngleRad = (float)rotationAngleRad, }, moveSpeed); double ClampDirection(double dir) { const double directionThreshold = 0.1; if (dir > directionThreshold) { return(1); } if (dir < -directionThreshold) { return(-1); } return(0); } }
protected void ServerSetMobInput( ICharacter character, Vector2F movementDirection, double rotationAngleRad) { var movementDirectionNormalized = new Vector2D( ClampDirection(movementDirection.X), ClampDirection(movementDirection.Y)).Normalized; double moveSpeed; if (movementDirection.X != 0 && movementDirection.Y != 0) { moveSpeed = character.SharedGetFinalStatValue(StatName.MoveSpeed); moveSpeed *= ProtoTile.SharedGetTileMoveSpeedMultiplier(character.Tile); } else { moveSpeed = 0; } Server.World.SetDynamicObjectMoveSpeed(character, moveSpeed); var moveAcceleration = movementDirectionNormalized * this.PhysicsBodyAccelerationCoef * moveSpeed; Server.World.SetDynamicObjectPhysicsMovement(character, moveAcceleration, targetVelocity: moveSpeed); var statePublic = GetPublicState(character); statePublic.AppliedInput.Set( new CharacterInput() { MoveModes = CharacterMoveModesHelper.CalculateMoveModes(movementDirectionNormalized), RotationAngleRad = (float)rotationAngleRad, }, moveSpeed);
protected void SharedApplyInput( ICharacter character, PlayerCharacterPrivateState privateState, PlayerCharacterPublicState publicState) { var characterIsOffline = !character.ServerIsOnline; if (characterIsOffline) { privateState.Input = default; } var vehicle = publicState.CurrentVehicle; if (vehicle is not null) { if (!vehicle.IsInitialized) { return; } var protoVehicle = (IProtoVehicle)vehicle.ProtoGameObject; protoVehicle.SharedApplyInput(vehicle, character, privateState, publicState); return; } // please note - input is a structure so actually we're implicitly copying it here var input = privateState.Input; // please note - applied input is a class and we're getting it by reference here var appliedInput = publicState.AppliedInput; var hasRunningFlag = (input.MoveModes & CharacterMoveModes.ModifierRun) != 0; var isRunning = hasRunningFlag; if (isRunning) { var stats = publicState.CurrentStatsExtended; var wasRunning = (appliedInput.MoveModes & CharacterMoveModes.ModifierRun) != 0; var staminaCurrent = stats.StaminaCurrent; if (!wasRunning) { // can start running only when the current energy is at least on 10% isRunning = staminaCurrent >= 0.1 * stats.StaminaMax; } else // if was running { // can continue to run while has energy isRunning = staminaCurrent > 0; } //Logger.WriteDev($"Was running: {wasRunning}; now running: {isRunning}; stamina: {staminaCurrent}"); } double moveSpeed; if (characterIsOffline || (privateState.CurrentActionState?.IsBlockingMovement ?? false)) { // offline or current action blocks movement moveSpeed = 0; isRunning = false; input.MoveModes = CharacterMoveModes.None; } else { var characterFinalStateCache = privateState.FinalStatsCache; moveSpeed = characterFinalStateCache[StatName.MoveSpeed]; moveSpeed *= ProtoTile.SharedGetTileMoveSpeedMultiplier(character.Tile); if (isRunning) { if (characterFinalStateCache.HasPerk(StatName.PerkCannotRun)) { isRunning = false; } else { var moveSpeedMultiplier = characterFinalStateCache[StatName.MoveSpeedRunMultiplier]; if (moveSpeedMultiplier > 0) { moveSpeed = moveSpeed * moveSpeedMultiplier; } else { isRunning = false; } } } } if (!isRunning) { // cannot run - remove running flag input.MoveModes &= ~CharacterMoveModes.ModifierRun; } if (appliedInput.MoveModes == input.MoveModes && appliedInput.RotationAngleRad == input.RotationAngleRad && publicState.AppliedInput.MoveSpeed == moveSpeed) { // input is not changed return; } // apply new input appliedInput.Set(input, moveSpeed); var moveModes = input.MoveModes; double directionX = 0, directionY = 0; if ((moveModes & CharacterMoveModes.Up) != 0) { directionY = 1; } if ((moveModes & CharacterMoveModes.Down) != 0) { directionY = -1; } if ((moveModes & CharacterMoveModes.Left) != 0) { directionX = -1; } if ((moveModes & CharacterMoveModes.Right) != 0) { directionX = 1; } if (directionX == 0 && directionY == 0) { moveSpeed = 0; } Vector2D directionVector = (directionX, directionY); var moveAcceleration = directionVector.Normalized * this.PhysicsBodyAccelerationCoef * moveSpeed; if (IsServer) { Server.World.SetDynamicObjectPhysicsMovement(character, moveAcceleration, targetVelocity: moveSpeed); character.PhysicsBody.Friction = this.PhysicsBodyFriction; } else // if client { if (ClientCurrentCharacterLagPredictionManager.IsLagPredictionEnabled) { Client.World.SetDynamicObjectPhysicsMovement(character, moveAcceleration, targetVelocity: moveSpeed); character.PhysicsBody.Friction = this.PhysicsBodyFriction; } } }
protected void SharedApplyInput( ICharacter character, PlayerCharacterPrivateState privateState, PlayerCharacterPublicState publicState) { var characterIsOffline = !character.IsOnline; if (characterIsOffline) { privateState.Input = default; } // please note - input is a structure so actually we're implicitly copying it here var input = privateState.Input; // please note - applied input is a class and we're getting it by reference here var appliedInput = publicState.AppliedInput; var hasRunningFlag = (input.MoveModes & CharacterMoveModes.ModifierRun) != 0; var isRunning = hasRunningFlag; if (isRunning) { var stats = publicState.CurrentStatsExtended; var wasRunning = (appliedInput.MoveModes & CharacterMoveModes.ModifierRun) != 0; var staminaCurrent = stats.StaminaCurrent; if (!wasRunning) { // can start running only when the current energy is at least on 10% isRunning = staminaCurrent >= 0.1 * stats.StaminaMax; } else // if was running { // can continue to run while has energy isRunning = staminaCurrent > 0; } //Logger.WriteDev($"Was running: {wasRunning}; now running: {isRunning}; stamina: {staminaCurrent}"); } double moveSpeed; if (characterIsOffline) { moveSpeed = 0; isRunning = false; } else { var characterFinalStateCache = privateState.FinalStatsCache; moveSpeed = characterFinalStateCache[StatName.MoveSpeed]; moveSpeed *= ProtoTile.SharedGetTileMoveSpeedMultiplier(character.Tile); if (isRunning) { var moveSpeedMultiplier = characterFinalStateCache[StatName.MoveSpeedRunMultiplier]; if (moveSpeedMultiplier > 0) { moveSpeed = moveSpeed * moveSpeedMultiplier; } else { isRunning = false; } } } if (!isRunning) { // cannot run - remove running flag input.MoveModes &= ~CharacterMoveModes.ModifierRun; } if (appliedInput.MoveModes == input.MoveModes && appliedInput.RotationAngleRad == input.RotationAngleRad && publicState.AppliedInput.MoveSpeed == moveSpeed) { // input is not changed return; } // apply new input appliedInput.Set(input, moveSpeed); var moveModes = input.MoveModes; double directionX = 0, directionY = 0; if ((moveModes & CharacterMoveModes.Up) != 0) { directionY = 1; } if ((moveModes & CharacterMoveModes.Down) != 0) { directionY = -1; } if ((moveModes & CharacterMoveModes.Left) != 0) { directionX = -1; } if ((moveModes & CharacterMoveModes.Right) != 0) { directionX = 1; } Vector2D directionVector = (directionX, directionY); var moveVelocity = directionVector.Normalized * moveSpeed; if (IsServer) { Server.Characters.SetVelocity(character, moveVelocity); } else // if client { if (ClientCurrentCharacterLagPredictionManager.IsLagPredictionEnabled) { Client.Characters.SetVelocity(character, moveVelocity); } } }