public static void OnCharacterDeath(ICharacter deadCharacter) { var publicState = deadCharacter.GetPublicState <ICharacterPublicState>(); if (!publicState.IsDead) { publicState.CurrentStats.ServerSetHealthCurrent(0); return; } // recreate physics (as dead character doesn't have any physics) deadCharacter.ProtoCharacter.SharedCreatePhysics(deadCharacter); if (deadCharacter.ProtoCharacter is IProtoCharacterMob protoCharacterMob) { Api.SafeInvoke(() => CharacterDeath?.Invoke(deadCharacter)); protoCharacterMob.ServerOnDeath(deadCharacter); return; } // player character death // remember the death position (useful for the respawn) var privateState = PlayerCharacter.GetPrivateState(deadCharacter); privateState.LastDeathPosition = deadCharacter.TilePosition; privateState.LastDeathTime = Api.Server.Game.FrameTime; ServerTimersSystem.AddAction( delaySeconds: PlayerTeleportToGraveyardDelaySeconds, () => { if (!publicState.IsDead) { // player has already respawned return; } CharacterDespawnSystem.ServerTeleportPlayerCharacterToServiceArea(deadCharacter); CharacterRespawnSystem.ServerRemoveStatusEffectsOnRespawn(deadCharacter); }); var isPvPdeath = CharacterDamageTrackingSystem.ServerGetPvPdamagePercent(deadCharacter) >= 0.5; // register death (required even if the player is not a newbie) NewbieProtectionSystem.ServerRegisterDeath(deadCharacter, isPvPdeath, out var shouldSufferDeathConsequences); if (shouldSufferDeathConsequences) { DropPlayerLoot(deadCharacter); } else { Api.Logger.Important("Player character is dead - newbie PvP case, no loot drop or other consequences", deadCharacter); } Api.SafeInvoke(() => CharacterDeath?.Invoke(deadCharacter)); }
protected override bool ServerIsCompleted(ICharacter character, PlayerTaskState state) { if (!character.ServerIsOnline || character.TilePosition == CharacterDespawnSystem.ServerGetServiceAreaPosition()) { return(false); } return(character.Tile.ProtoTile == this.ProtoTile); }
/// <summary> /// Barrier (a circle impenetrable area) is present only in PvE to prevent players from rushing /// into the boss area before the boss is spawned. /// </summary> private void ServerCreateBossAreaBarrier(ILogicObject worldEvent) { var publicState = GetPublicState(worldEvent); if (publicState.ServerBarrierPhysicsBody is not null) { return; } // create the barrier publicState.ServerBarrierPhysicsBody = this.SharedCreateBarrierPhysicsBody(worldEvent); var activeEventPosition = publicState.AreaCirclePosition; var barrierRadius = this.AreaBarrierRadius + 1; if (barrierRadius > byte.MaxValue) { Logger.Error( "The boss area circle should never have a radius larger than 255 tiles as it prevents players despawn in PvE: " + worldEvent); barrierRadius = byte.MaxValue; } var barrierRadiusSqr = barrierRadius * barrierRadius; // despawn all player characters inside the barrier or very close to it using var tempCharacters = Api.Shared.GetTempList <ICharacter>(); Server.World.GetCharactersInRadius(activeEventPosition, tempCharacters, (byte)barrierRadius, onlyPlayers: true); foreach (var character in tempCharacters.AsList()) { CharacterDespawnSystem.DespawnCharacter(character); } // despawn all vehicles inside the barrier or very close to it using var tempListVehicles = Api.Shared.GetTempList <IDynamicWorldObject>(); foreach (var protoVehicle in Api.FindProtoEntities <IProtoVehicle>()) { tempListVehicles.Clear(); protoVehicle.GetAllGameObjects(tempListVehicles.AsList()); foreach (var vehicle in tempListVehicles.AsList()) { if (vehicle.TilePosition.TileSqrDistanceTo(activeEventPosition) <= barrierRadiusSqr) { VehicleGarageSystem.ServerPutIntoGarage(vehicle); } } } // Please note: NPC characters that are stuck inside the area are pushed outside it by the physics engine }
public override void SharedUpdate(double deltaTime) { this.timeRemains -= deltaTime; if (this.timeRemains > 0) { return; } PlayerCharacter.GetPrivateState(this.Character).SetCurrentActionState(null); if (Api.IsServer) { CharacterDespawnSystem.DespawnCharacter(this.Character); } }
public static void SpawnPlayer(ICharacter character, bool isRespawn) { ServerAddTorchItemIfNoItems(character); if (character.IsInitialized && CharacterCreationSystem.SharedIsCharacterCreated(character)) { PlacePlayer(character, isRespawn); } else { // first time spawn, requires character creation CharacterDespawnSystem.DespawnCharacter(character); } }
public static void OnCharacterInitialize(ICharacter character) { if (character.IsNpc) { return; } if (PlayerCharacter.GetPublicState(character).IsDead) { CharacterDespawnSystem.ServerTeleportPlayerCharacterToServiceArea(character); CharacterRespawnSystem.ServerRemoveStatusEffectsOnRespawn(character); } else if (PlayerCharacter.GetPrivateState(character).IsDespawned) { CharacterDespawnSystem.ServerTeleportPlayerCharacterToServiceArea(character); } }
public override void ServerInitialize(IServerConfiguration serverConfiguration) { base.ServerInitialize(serverConfiguration); CharacterStyleSystem.ServerCharacterAppearanceSelected += ServerCharacterAppearanceSelectedHandler; foreach (var character in Server.Characters.EnumerateAllPlayerCharacters(onlyOnline: false)) { var privateState = PlayerCharacter.GetPrivateState(character); if (!privateState.IsDespawned && !SharedIsCharacterCreated(character)) { // despawn all invalid characters CharacterDespawnSystem.DespawnCharacter(character); } } }
public string Execute([CurrentCharacterIfNull] ICharacter player) { CharacterDespawnSystem.DespawnCharacter(player); return(player + " despawned"); }