private void ServerRemote_CreateUnstuckRequest() { var character = ServerRemoteContext.Character; if (serverRequests.ContainsKey(character)) { this.CallClient(character, _ => _.ClientRemote_UnstuckAlreadyQueued()); return; } if (character.GetPublicState <ICharacterPublicState>() .IsDead) { // character is dead this.CallClient(character, _ => _.ClientRemote_UnstuckFailedDead()); return; } var vehicle = character.SharedGetCurrentVehicle(); if (vehicle != null) { VehicleSystem.ServerCharacterExitCurrentVehicle(character, force: true); if (vehicle.GetPublicState <VehiclePublicState>().PilotCharacter != null) { // cannot quit vehicle here, cannot unstuck this.CallClient(character, _ => _.ClientRemote_UnstuckImpossible()); return; } } var delay = LandClaimSystem.SharedIsPositionInsideOwnedOrFreeArea(character.TilePosition, character) ? UnstuckDelaySecondsTotal : UnstuckDelaySecondsOnEnemyBaseTotal; var unstuckTime = Server.Game.FrameTime + delay; PlayerCharacter.GetPublicState(character).UnstuckExecutionTime = unstuckTime; serverRequests.Add(character, new CharacterUnstuckRequest( unstuckAfter: unstuckTime, initialPosition: character.Position)); }
public static bool SharedValidateCanUnstuck(ICharacter character) { using var tempAreas = Api.Shared.GetTempList <ILogicObject>(); var bounds = new RectangleInt( offset: character.TilePosition - (1, 1), size: (2, 2)); LandClaimSystem.SharedGetAreasInBounds(bounds, tempAreas, addGracePadding: false); if (tempAreas.Any(LandClaimSystem.SharedIsAreaUnderRaid)) { Logger.Info("Cannot unstuck when located in an area under raid", character); LandClaimSystem.SharedSendNotificationActionForbiddenUnderRaidblock(character); return(false); } return(true); }
private static Vector2Ushort?TryFindZoneSpawnPosition( ICharacter character, IServerZone spawnZone, Random random, bool isRespawn) { var characterDeathPosition = Vector2Ushort.Zero; if (isRespawn && character.ProtoCharacter is PlayerCharacter) { characterDeathPosition = PlayerCharacter.GetPrivateState(character) .LastDeathPosition; } for (var attempt = 0; attempt < SpawnInZoneAttempts; attempt++) { var randomPosition = spawnZone.GetRandomPosition(random); if (isRespawn) { var sqrDistance = randomPosition.TileSqrDistanceTo(characterDeathPosition); if (sqrDistance > MaxDistanceWhenRespawnSqr || sqrDistance < MinDistanceWhenRespawnSqr) { // too close or too far for the respawn continue; } } if (LandClaimSystem.SharedGetAreaAtPosition(randomPosition) is ILogicObject area && !LandClaimSystem.ServerIsOwnedArea(area, character)) { // the land is claimed by another player continue; } if (ServerCharacterSpawnHelper.IsPositionValidForCharacterSpawn(randomPosition.ToVector2D(), isPlayer: true)) { // valid position found return(randomPosition); } } return(null); }
protected virtual double ServerCalculateGrowthStageDuration( byte growthStage, TPrivateState privateState, TPublicState publicState) { var objectVegetation = privateState.GameObject; var duration = this.cachedGrowthStageDurationSeconds; if (LandClaimSystem.SharedIsObjectInsideAnyArea((IStaticWorldObject)objectVegetation)) { // don't apply scaled rate to vegetation located inside the land claim areas // (as these are usually planted by players inside their bases and protected) return(duration); } return(ServerSpawnRateScaleHelper.AdjustDurationByRate(duration)); }
private void ServerRemote_LeaderDissolveFaction() { var currentLeader = ServerRemoteContext.Character; var currentLeaderName = currentLeader.Name; ServerValidateHasAccessRights(currentLeader, FactionMemberAccessRights.Leader, out var faction); if (LandClaimSystem.SharedEnumerateAllFactionAreas(SharedGetClanTag(faction)) .Any()) { throw new Exception("The faction cannot be dissolved as it still have land claims."); } Logger.Important("Faction leader dissolved the faction: " + faction, currentLeader); // remove all faction members have been removed var memberEntries = ServerGetFactionMembersReadOnly(faction); while (memberEntries.Count > 0) { var memberName = memberEntries[0].Name; ServerRemoveMemberNoChecks(memberName, faction); if (memberName == currentLeaderName) { continue; } try { var member = Server.Characters.GetPlayerCharacter(memberName); if (member.ServerIsOnline) { this.CallClient(member, _ => _.ClientRemote_RemovedFromFaction(currentLeaderName)); } } catch (Exception ex) { Logger.Exception(ex); } } ServerRemoveFaction(faction); }
public IEnumerable <string> ServerGetLandOwners() { var area = (ILogicObject)this.GameObject; var areasGroup = LandClaimSystem.SharedGetLandClaimAreasGroup(area); if (areasGroup is null) { // perhaps a new area return(this.DirectLandOwners); } var faction = LandClaimAreasGroup.GetPublicState(areasGroup).ServerFaction; return(faction is null ? this.DirectLandOwners : FactionSystem.ServerGetFactionMemberNames(faction)); }
public ObjectLandClaimCanUpgradeCheckResult ServerRemote_UpgradeStructure( IStaticWorldObject oldWorldObjectLandClaim, IProtoObjectLandClaim upgradeStructure) { this.VerifyGameObject(oldWorldObjectLandClaim); var character = ServerRemoteContext.Character; var result = this.SharedCanUpgrade(oldWorldObjectLandClaim, upgradeStructure, character, out var upgradeEntry); if (result != ObjectLandClaimCanUpgradeCheckResult.Success) { return(result); } // consume items upgradeEntry.ServerDestroyRequiredItems(character); // copy all items to temp container var oldStorage = GetPrivateState(oldWorldObjectLandClaim).ItemsContainer; var tempStorageOwner = Server.World.CreateLogicObject <LogicObjectTempItemsContainerHolder>(); var tempStorage = Server.Items.CreateContainer( owner: tempStorageOwner, // we must set an owner, unfortunately slotsCount: (byte)oldStorage.OccupiedSlotsCount); Server.Items.TryMoveAllItems(oldStorage, tempStorage); // upgrade (it will destroy an existing structure and place new in its place) var upgradedWorldObjectLandClaim = LandClaimSystem.ServerUpgrade(oldWorldObjectLandClaim, upgradeStructure, character); // move all items from temp container to the upgraded land claim var newStorage = GetPrivateState(upgradedWorldObjectLandClaim).ItemsContainer; Server.Items.TryMoveAllItems(tempStorage, newStorage); Server.Items.DestroyContainer(tempStorage); Server.World.DestroyObject(tempStorageOwner); // notify client (to play sound) ConstructionPlacementSystem.Instance.ServerOnStructurePlaced(upgradedWorldObjectLandClaim, character); return(result); }
protected override void ServerOnStaticObjectZeroStructurePoints( WeaponFinalCache weaponCache, ICharacter byCharacter, IWorldObject targetObject) { var tilePosition = targetObject.TilePosition; base.ServerOnStaticObjectZeroStructurePoints(weaponCache, byCharacter, targetObject); if (weaponCache != null) { // wall was destroyed (and not deconstructed by a crowbar or any other means) ObjectWallDestroyed.ServerSpawnDestroyedWall(tilePosition, this); LandClaimSystem.ServerOnRaid(((IStaticWorldObject)targetObject).Bounds, byCharacter); } }
protected override double ServerCalculateGrowthStageDuration( byte growthStage, VegetationPrivateState privateState, VegetationPublicState publicState) { var objectTree = (IStaticWorldObject)privateState.GameObject; var duration = base.ServerCalculateGrowthStageDuration(growthStage, privateState, publicState); if (LandClaimSystem.SharedIsObjectInsideAnyArea(objectTree)) { return(duration); } // x1.5 faster growth when not inside any land claim area as this resource // is rare and essential especially for PvP return(duration / 1.5); }
private static bool IsBaseMusicShouldPlay(ICharacter character) { using var tempListAreasNearby = Api.Shared.GetTempList <ILogicObject>(); using var tempListOwnedAreaGroupsNearby = Api.Shared.GetTempList <ILogicObject>(); LandClaimSystem.SharedGetAreasInBounds( new RectangleInt(character.TilePosition.X, character.TilePosition.Y, 1, 1).Inflate(2), tempListAreasNearby, addGracePadding: true); // find owned bases (area groups) nearby foreach (var area in tempListAreasNearby.AsList()) { if (LandClaimSystem.SharedIsOwnedArea(area, character, requireFactionPermission: false)) { var areasGroup = LandClaimSystem.SharedGetLandClaimAreasGroup(area); tempListOwnedAreaGroupsNearby.AddIfNotContains(areasGroup); } } if (tempListOwnedAreaGroupsNearby.Count == 0) { return(false); } var allAreas = (List <ILogicObject>)LandClaimSystem.SharedEnumerateAllAreas(); // check every owned base whether it has at least single T2 or higher tier land claim foreach (var areasGroup in tempListOwnedAreaGroupsNearby.AsList()) { foreach (var area in allAreas) { var areaPublicState = LandClaimArea.GetPublicState(area); if (areaPublicState.LandClaimAreasGroup == areasGroup && areaPublicState.LandClaimTier > 1) { // found an area on the base with land claim tier > 1 return(true); } } } return(false); }
private static void ServerRefreshLandClaimAreasGroup(ILogicObject areasGroup) { var areas = LandClaimAreasGroup.GetPrivateState(areasGroup).ServerLandClaimsAreas; foreach (var area in areas) { var areaBounds = LandClaimSystem.SharedGetLandClaimAreaBounds(area, addGracePadding: true); var owners = LandClaimArea.GetPrivateState(area).LandOwners; foreach (var owner in owners) { var character = Server.Characters.GetPlayerCharacter(owner); if (character == null || !character.ServerIsOnline) { continue; } if (!areaBounds.Contains(character.TilePosition)) { continue; } // the land claim area contains an online owner character ServerResetDecayTimer(); return; } } // helper method to reset the decay timer for all land claim buildings inside this areas group void ServerResetDecayTimer() { var decayDelayDuration = LandClaimSystem.ServerGetDecayDelayDurationForLandClaimAreas(areas); foreach (var area in areas) { var worldObject = LandClaimArea.GetPrivateState(area) .ServerLandClaimWorldObject; StructureDecaySystem.ServerResetDecayTimer( worldObject.GetPrivateState <StructurePrivateState>(), decayDelayDuration); } } }
public ViewModelWindowLandClaim( IStaticWorldObject landClaimWorldObject, ILogicObject area) { this.landClaimWorldObject = landClaimWorldObject; this.privateState = LandClaimArea.GetPrivateState(area); var protoStructureWithOwnersList = ((IProtoObjectWithOwnersList)landClaimWorldObject.ProtoStaticWorldObject); var canEditOwners = protoStructureWithOwnersList .SharedCanEditOwners(landClaimWorldObject, ClientCurrentCharacterHelper.Character); this.ViewModelOwnersEditor = new ViewModelWorldObjectOwnersEditor( this.privateState.LandOwners, callbackServerSetOwnersList: ownersList => LandClaimSystem.ClientSetAreaOwners( area, ownersList), title: AccessListTitle + ":", emptyListMessage: AccessListEmpty, canEditOwners: canEditOwners, // exclude founder name ownersListFilter: name => name != this.FounderName); this.protoObjectLandClaim = (IProtoObjectLandClaim)this.landClaimWorldObject.ProtoStaticWorldObject; var upgrade = this.protoObjectLandClaim.ConfigUpgrade.Entries.FirstOrDefault(); if (upgrade != null) { this.ViewModelStructureUpgrade = new ViewModelStructureUpgrade(upgrade); this.ViewModelProtoLandClaimInfoUpgrade = new ViewModelProtoLandClaimInfo( (IProtoObjectLandClaim)upgrade.ProtoStructure); } this.ViewModelItemsContainerExchange = new ViewModelItemsContainerExchange( landClaimWorldObject.GetPrivateState <ObjectLandClaimPrivateState>().ItemsContainer, callbackTakeAllItemsSuccess: () => { }) { IsContainerTitleVisible = false }; this.ViewModelProtoLandClaimInfoCurrent = new ViewModelProtoLandClaimInfo(this.protoObjectLandClaim); }
protected override double SharedCalculateDamageByWeapon( WeaponFinalCache weaponCache, double damagePreMultiplier, IStaticWorldObject targetObject, out double obstacleBlockDamageCoef) { if (IsServer) { damagePreMultiplier = LandClaimSystem.ServerAdjustDamageToUnprotectedStrongBuilding(weaponCache, targetObject, damagePreMultiplier); } return(base.SharedCalculateDamageByWeapon(weaponCache, damagePreMultiplier, targetObject, out obstacleBlockDamageCoef)); }
public static void ClientLeaderDissolveFaction() { ClientValidateHasAccessRights(FactionMemberAccessRights.Leader); if (LandClaimSystem.ClientEnumerateAllCurrentFactionAreas() .Any()) { NotificationSystem.ClientShowNotification( title: null, CoreStrings.Faction_DialogDissolveFaction_ErrorHasLandClaimsClaims, NotificationColor.Bad); return; } Instance.CallServer( _ => _.ServerRemote_LeaderDissolveFaction()); Logger.Important("Requested faction dissolve"); }
public override bool CanAddItem(CanAddItemContext context) { var character = context.ByCharacter; if (character is null) { return(true); } if (!LandClaimSystem.ValidateIsNotUnderRaidblock(context.Container.OwnerAsStaticObject, character)) { // don't allow to place anything in tinker table while the area is under raid return(false); } return(ItemDisassemblySystem.SharedCanDisassemble(context.Item.ProtoItem)); }
public static string ServerSetOwner(ushort x, ushort y, string newOwnerName) { using var tempList = Api.Shared.GetTempList <ILogicObject>(); LandClaimSystem.SharedGetAreasInBounds(new RectangleInt(x, y, 1, 1), tempList, addGracePadding: false); var landClaimsModified = 0; foreach (var area in tempList.AsList()) { var privateState = LandClaimArea.GetPrivateState(area); privateState.LandClaimFounder = newOwnerName; privateState.LandOwners.Clear(); privateState.LandOwners.Add(newOwnerName); landClaimsModified++; } return($"Modified {landClaimsModified} land claims"); }
private SetOwnersResult ServerRemote_SetOwners(IWorldObject worldObject, List <string> newOwners) { var maxOwners = worldObject.ProtoGameObject is IProtoObjectDoor ? RateDoorOwnersMax.SharedValue : byte.MaxValue; if (newOwners.Count > maxOwners) { return(SetOwnersResult.ErrorAccessListSizeLimitExceeded); } var character = ServerRemoteContext.Character; if (worldObject is IStaticWorldObject staticWorldObject) { if (!staticWorldObject.ProtoStaticWorldObject .SharedCanInteract(character, worldObject, writeToLog: true)) { throw new Exception("Cannot interact with " + worldObject); } if (!SharedIsOwner(character, worldObject)) { throw new Exception("Not an owner"); } var areasGroup = LandClaimSystem.SharedGetLandClaimAreasGroup(staticWorldObject); if (areasGroup is not null && LandClaimAreasGroup.GetPublicState(areasGroup).ServerFaction is not null) { throw new Exception( "Cannot modify owners list for an object within a faction land claim area"); } } else // dynamic world object (a vehicle, etc) { if (!worldObject.ProtoWorldObject.SharedCanInteract(character, worldObject, writeToLog: false)) { throw new Exception("Cannot interact with " + worldObject); } } return(ServerSetOwners(worldObject, newOwners, byOwner: character)); }
public string Execute( ShieldProtectionStatus status, [CurrentCharacterIfNull] ICharacter character = null) { if (!LandClaimShieldProtectionConstants.SharedIsEnabled) { return("S.H.I.E.L.D. protection is not available"); } if (status == ShieldProtectionStatus.Active) { status = ShieldProtectionStatus.Activating; } using var tempAreas = Api.Shared.GetTempList <ILogicObject>(); LandClaimSystem.SharedGetAreasInBounds( new RectangleInt(character.TilePosition, (1, 1)), tempAreas, addGracePadding: false); var area = tempAreas.AsList().FirstOrDefault(); if (area is null) { return("No base exist near " + character.Name); } var areasGroup = LandClaimSystem.SharedGetLandClaimAreasGroup(area); LandClaimShieldProtectionSystem.SharedGetShieldProtectionMaxStatsForBase(areasGroup, out _, out _); var privateState = LandClaimAreasGroup.GetPrivateState(areasGroup); privateState.ShieldProtectionCooldownExpirationTime = 0; var publicState = LandClaimAreasGroup.GetPublicState(areasGroup); publicState.Status = status; publicState.ShieldActivationTime = Server.Game.FrameTime; return($"Status of the S.H.I.E.L.D. changed to {status}."); }
public string Execute([CurrentCharacterIfNull] ICharacter character) { using var tempAreas = Api.Shared.GetTempList <ILogicObject>(); LandClaimSystem.SharedGetAreasInBounds( new RectangleInt(character.TilePosition.X, character.TilePosition.Y, 1, 1), tempAreas, addGracePadding: false); foreach (var logicObject in tempAreas.AsList()) { LandClaimSystem.ServerSetRaidblock(logicObject, byCharacter: null, durationMultiplier: 1.0, isStructureDestroyed: true); } return(string.Empty); }
private static void SetupBoundsForLandClaimsInScope( IClientSceneObject sceneObject, Vector2D sceneObjectPosition, Vector2Ushort originTilePosition, RectangleInt originBounds, IProtoObjectLandClaim originProtoObjectLandClaim) { var landClaims = Api.Client.World.GetStaticWorldObjectsOfProto <IProtoObjectLandClaim>(); foreach (var landClaim in landClaims) { var protoObjectLandClaim = (IProtoObjectLandClaim)landClaim.ProtoGameObject; var landClaimCenterPosition = LandClaimSystem .SharedCalculateLandClaimObjectCenterTilePosition( landClaim.TilePosition, protoObjectLandClaim); var landClaimBounds = LandClaimSystem.SharedCalculateLandClaimAreaBounds( landClaimCenterPosition, protoObjectLandClaim.LandClaimWithGraceAreaSize); var intersectionDepth = CalculateIntersectionDepth(originBounds, landClaimBounds); if (intersectionDepth < 0) { // no intersection continue; } intersectionDepth = (intersectionDepth + 1) / 2; intersectionDepth = Math.Min(intersectionDepth, originProtoObjectLandClaim.LandClaimGraceAreaPaddingSizeOneDirection + 1); var exceptBounds = originBounds.Inflate(-intersectionDepth); using var tempList = Api.Shared.WrapObjectInTempList(exceptBounds); AddBoundLabels(sceneObject, sceneObjectPosition, exceptBounds: tempList.AsList(), protoObjectLandClaim, positionOffset: landClaimCenterPosition.ToVector2D() - originTilePosition.ToVector2D()); } }
private static bool ServerIsNeedDespawn(ICharacter character, double serverTime) { var privateState = character.GetPrivateState <PlayerCharacterPrivateState>(); if (character.ServerIsOnline) { return(false); } // player offline var publicState = character.GetPublicState <PlayerCharacterPublicState>(); if (publicState.IsDead || privateState.IsDespawned) { return(false); } if (character.ProtoCharacter is PlayerCharacterSpectator || Server.Characters.IsSpectator(character)) { return(false); } var offlineSinceTime = privateState.ServerLastActiveTime; if (serverTime < offlineSinceTime + OfflineDurationToDespawn) { // despawn timeout is not reached yet return(false); } if (LandClaimSystem.SharedIsOwnedLand(character.TilePosition, character, requireFactionPermission: false, out _)) { // do not despawn as the player is inside the owned land claim area return(false); } return(true); }
private async void RequestDecayInfoTextAsync() { var result = await LandClaimSystem.ClientGetDecayInfoText(this.landClaimWorldObject); if (this.IsDisposed) { return; } this.DecayInfoText = string.Format( DecayInfoFormat, ClientTimeFormatHelper.FormatTimeDuration( TimeSpan.FromSeconds(result.DecayDelayDuration), trimRemainder: true), ClientTimeFormatHelper.FormatTimeDuration( TimeSpan.FromSeconds(result.DecayDuration), trimRemainder: true), this.ViewModelProtoLandClaimInfoCurrent.CurrentStructureLandClaimDestructionTimeout); }
private void ServerExplode(IStaticWorldObject worldObject, ICharacter character) { Logger.Important(worldObject + " exploded"); this.ServerSendObjectDestroyedEvent(worldObject); ExplosionHelper.ServerExplode( character: character, protoObjectExplosive: this, explosionPreset: this.ExplosionPreset, epicenterPosition: worldObject.TilePosition.ToVector2D() + this.Layout.Center, damageDescriptionCharacters: this.damageDescriptionCharacters, physicsSpace: worldObject.PhysicsBody.PhysicsSpace, executeExplosionCallback: this.ServerExecuteExplosion); Server.World.DestroyObject(worldObject); LandClaimSystem.ServerOnRaid(worldObject.TilePosition, this.DamageRadius, character); }
public override bool CanAddItem(CanAddItemContext context) { var character = context.ByCharacter; if (character is null) { return(true); } if (!LandClaimSystem.ValidateIsNotUnderRaidblock(context.Container.OwnerAsStaticObject, character)) { // don't allow to place anything in a trash can while the area is under raid return(false); } // allow everything return(true); }
private static bool ServerCheckCanSpawn(IProtoWorldObject protoObjectToSpawn, Vector2Ushort spawnPosition) { return(protoObjectToSpawn switch { IProtoCharacterMob => ServerCharacterSpawnHelper.IsPositionValidForCharacterSpawn( spawnPosition.ToVector2D(), isPlayer: false) && !LandClaimSystem.SharedIsLandClaimedByAnyone(spawnPosition), IProtoStaticWorldObject protoStaticWorldObject // Please note: land claim check must be integrated in the object tile requirements => protoStaticWorldObject.CheckTileRequirements( spawnPosition, character: null, logErrors: false), _ => throw new ArgumentOutOfRangeException("Unknown object type to spawn: " + protoObjectToSpawn) });
private static bool IsOwner(ILogicObject areasGroup) { if (areasGroup.ClientHasPrivateState) { return(true); } var areas = LandClaimSystem.ClientGetKnownAreasForGroup(areasGroup); foreach (var area in areas) { if (LandClaimSystem.ClientIsOwnedArea(area)) { return(true); } } return(false); }
private static void ServerUpdate() { ServerNotifiedCharactersForAreasGroups.ProcessAndRemove( removeCondition: key => { // determine whether the raid has ended var areasGroup = key.AreasGroup; return(areasGroup.IsDestroyed || !LandClaimSystem.SharedIsAreasGroupUnderRaid(areasGroup)); }, removeCallback: pair => { // notify all the previously notified players var previouslyNotifiedCharacters = pair.Value; Instance.CallClient(previouslyNotifiedCharacters, _ => _.ClientRemote_AllyBaseRaidEnded( pair.Key.AreasGroup.Id)); }); }
public static async void ClientTakeVehicle(uint vehicleGameObjectId) { var vehicleAssemblyBay = InteractionCheckerSystem.SharedGetCurrentInteraction( ClientCurrentCharacterHelper.Character); var result = await Instance.CallServer(_ => _.ServerRemote_TakeVehicle(vehicleGameObjectId)); if (result == TakeVehicleResult.Success) { Client.Audio.PlayOneShot(SoundResourceTakeVehicle, vehicleAssemblyBay); WindowObjectVehicleAssemblyBay.CloseActiveMenu(); return; } if (result == TakeVehicleResult.BaseUnderRaidblock) { LandClaimSystem.SharedSendNotificationActionForbiddenUnderRaidblock( ClientCurrentCharacterHelper.Character); return; } var error = result.GetDescription(); if (string.IsNullOrEmpty(error)) { return; } var currentInteractionObject = InteractionCheckerSystem.SharedGetCurrentInteraction(ClientCurrentCharacterHelper.Character); if (!(currentInteractionObject?.ProtoWorldObject is IProtoVehicleAssemblyBay protoVehicleAssemblyBay)) { return; } NotificationSystem.ClientShowNotification( Notification_CannotTakeVehicle_Title, error, NotificationColor.Bad, protoVehicleAssemblyBay.Icon); }
private static void Refresh() { var position = ClientCurrentCharacterHelper.Character?.TilePosition ?? Vector2Ushort.Zero; var areasGroup = LandClaimSystem.SharedGetLandClaimAreasGroup(position, addGracePadding: false) ?? LandClaimSystem.SharedGetLandClaimAreasGroup(position, addGracePadding: true); var lastRaidTime = areasGroup is not null ? LandClaimAreasGroup.GetPublicState(areasGroup).LastRaidTime ?? double.MinValue : double.MinValue; var time = Api.Client.CurrentGame.ServerFrameTimeRounded; var timeSinceRaidStart = time - lastRaidTime; var timeRemainsToRaidEnd = LandClaimSystemConstants.SharedRaidBlockDurationSeconds - timeSinceRaidStart; timeRemainsToRaidEnd = Math.Max(timeRemainsToRaidEnd, 0); if (timeRemainsToRaidEnd <= 0) { // no raid here - hide notification currentNotification?.Hide(quick: true); currentNotification = null; return; } // raid here, display/update notification var text = GetNotificationText(timeRemainsToRaidEnd); if (currentNotification is not null && !currentNotification.IsHiding) { currentNotification.Message = text; return; } currentNotification = NotificationSystem.ClientShowNotification( title: Notification_Title, message: text, autoHide: false, // TODO: add custom icon here, currently we're using a placeholder icon icon: Api.GetProtoEntity <ItemBombModern>().Icon, playSound: false); }
public static bool SharedIsOwner(ICharacter who, IWorldObject worldObject, out bool isFactionAccess) { isFactionAccess = false; switch (worldObject) { case IStaticWorldObject staticWorldObject: { var areasGroup = LandClaimSystem.SharedGetLandClaimAreasGroup(staticWorldObject); if (areasGroup is null || LandClaimAreasGroup.GetPublicState(areasGroup).FactionClanTag is not { } clanTag || string.IsNullOrEmpty(clanTag)) { break; } // the static object is inside the faction-owned land claim, // verify permission isFactionAccess = true; return(SharedHasFactionAccessRights(who, FactionMemberAccessRights.LandClaimManagement, clanTag)); } case IDynamicWorldObject when worldObject.ProtoGameObject is IProtoVehicle: { var clanTag = worldObject.GetPublicState <VehiclePublicState>().ClanTag; if (string.IsNullOrEmpty(clanTag)) { break; } // the vehicle is owned by faction // verify whether the character has the access right isFactionAccess = true; return(WorldObjectAccessModeSystem.SharedHasAccess(who, worldObject, writeToLog: true)); } } return(SharedGetDirectOwners(worldObject).Contains(who.Name)); }