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); foreach (var area in tempAreas.AsList()) { if (LandClaimSystem.SharedIsAreaUnderRaid(area)) { Logger.Info("Cannot unstuck when located in an area under raid", character); LandClaimSystem.SharedSendNotificationActionForbiddenUnderRaidblock(character); return(false); } if (LandClaimShieldProtectionSystem.SharedIsAreaUnderShieldProtection(area)) { Logger.Info("Cannot unstuck when located in an area under shield protection", character); LandClaimShieldProtectionSystem.SharedSendNotificationActionForbiddenUnderShieldProtection(character); return(false); } } return(true); }
protected sealed override void ServerUpdate(ServerUpdateData data) { var character = data.GameObject; var privateState = data.PrivateState; var publicState = data.PublicState; var objectTurret = privateState.ObjectTurret; if (objectTurret is null) { return; } var objectTurretPrivateState = objectTurret.GetPrivateState <ObjectTurretPrivateState>(); var turretMode = objectTurretPrivateState.TurretMode; if (turretMode == TurretMode.Disabled) { return; } var objectTurretPublicState = objectTurret.GetPublicState <ObjectTurretPublicState>(); if (objectTurretPublicState.ElectricityConsumerState != ElectricityConsumerState.PowerOnActive) { return; } if (LandClaimShieldProtectionSystem.SharedIsUnderShieldProtection(objectTurret)) { return; } this.ServerRebuildFinalCacheIfNeeded(privateState, publicState); ServerUpdateAggroState(privateState, data.DeltaTime); this.ServerUpdateTurret(data, turretMode); // update weapon state (fires the weapon if needed) WeaponSystem.SharedUpdateCurrentWeapon( character, privateState.WeaponState, data.DeltaTime); }
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}."); }
private void UpdateCallback() { var areasGroup = LandClaimArea.GetPublicState(this.area).LandClaimAreasGroup; var status = LandClaimShieldProtectionSystem.SharedGetShieldPublicStatus(areasGroup); switch (status) { case ShieldProtectionStatus.Active: this.markControl.IsUnderShield = true; break; // ReSharper disable once CompareOfFloatsByEqualityOperator case ShieldProtectionStatus.Activating: // flicker the icon for half a second this.markControl.IsUnderShield = Math.Round(Api.Client.Core.ClientRealTime % 1.0) == 0.0; break; default: this.markControl.IsUnderShield = false; break; } }
public string Execute( double chargePercent = 100, [CurrentCharacterIfNull] ICharacter character = null) { if (!LandClaimShieldProtectionConstants.SharedIsEnabled) { return("S.H.I.E.L.D. protection is not available"); } var chargeFraction = MathHelper.Clamp(chargePercent / 100, min: 0, max: 1); 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 electricityCapacity); var privateState = LandClaimAreasGroup.GetPrivateState(areasGroup); privateState.ShieldProtectionCurrentChargeElectricity = electricityCapacity * chargeFraction; privateState.ShieldProtectionCooldownExpirationTime = 0; // reset the cooldown return($"Charge amount of the S.H.I.E.L.D. modified to {chargeFraction * 100}% and cooldown reset."); }
public static double ServerCalculateTotalDamage( WeaponFinalCache weaponCache, IWorldObject targetObject, FinalStatsCache targetFinalStatsCache, double damagePreMultiplier, bool clampDefenseTo1) { if (targetObject is IStaticWorldObject staticWorldObject && (!RaidingProtectionSystem.SharedCanRaid(staticWorldObject, showClientNotification: false) || !LandClaimShieldProtectionSystem.SharedCanRaid(staticWorldObject, showClientNotification: false) || !PveSystem.SharedIsAllowStaticObjectDamage(weaponCache.Character, staticWorldObject, showClientNotification: false) || !NewbieProtectionSystem.SharedIsAllowStructureDamage(weaponCache.Character, staticWorldObject, showClientNotification: false))) { return(0); } if (targetObject.ProtoGameObject is IProtoVehicle && !PveSystem.SharedIsAllowVehicleDamage(weaponCache, (IDynamicWorldObject)targetObject, showClientNotification: false)) { return(0); } if (weaponCache.ProtoExplosive is not null && targetObject is IStaticWorldObject targetStaticWorldObject) { // special case - apply the explosive damage to static object return(ServerCalculateTotalDamageByExplosive(weaponCache.Character, weaponCache.ProtoExplosive, targetStaticWorldObject, damagePreMultiplier)); } if (ServerIsRestrictedPvPDamage(weaponCache, targetObject, out var isPvPcase, out var isFriendlyFireCase)) { return(0); } var damageValue = damagePreMultiplier * weaponCache.DamageValue; var invertedArmorPiercingCoef = weaponCache.InvertedArmorPiercingCoef; var totalDamage = 0d; // calculate total damage by summing all the damage components foreach (var damageDistribution in weaponCache.DamageDistributions) { var defenseStatName = SharedGetDefenseStatName(damageDistribution.DamageType); var defenseFraction = targetFinalStatsCache[defenseStatName]; defenseFraction = MathHelper.Clamp(defenseFraction, 0, clampDefenseTo1 ? 1 : double.MaxValue); totalDamage += ServerCalculateDamageComponent( damageValue, invertedArmorPiercingCoef, damageDistribution, defenseFraction); } // multiply on final multiplier (usually used for expanding projectiles) totalDamage *= weaponCache.FinalDamageMultiplier; var damagingCharacter = weaponCache.Character; if (isPvPcase) { // apply PvP damage multiplier totalDamage *= WeaponConstants.DamagePvpMultiplier; } else if (damagingCharacter is not null && !damagingCharacter.IsNpc && targetObject.ProtoGameObject is IProtoCharacterMob protoCharacterMob && !protoCharacterMob.IsBoss) { // apply PvE damage multiplier totalDamage *= WeaponConstants.DamagePveMultiplier; }
public virtual bool SharedOnDamage( WeaponFinalCache weaponCache, IStaticWorldObject targetObject, double damagePreMultiplier, out double obstacleBlockDamageCoef, out double damageApplied) { var objectPublicState = GetPublicState(targetObject); var previousStructurePoints = objectPublicState.StructurePointsCurrent; if (previousStructurePoints <= 0f) { // already destroyed static world object obstacleBlockDamageCoef = 0; damageApplied = 0; return(false); } var serverDamage = this.SharedCalculateDamageByWeapon( weaponCache, damagePreMultiplier, targetObject, out obstacleBlockDamageCoef); if (serverDamage < 0) { Logger.Warning( $"Server damage less than 0 and this is suspicious. {this} calculated damage: {serverDamage:0.###}"); serverDamage = 0; } if (IsClient) { // simply call these methods to display a client notification only! // they are not used for anything else here // to calculate damage they're used in WeaponDamageSystem.ServerCalculateTotalDamage method. RaidingProtectionSystem.SharedCanRaid(targetObject, showClientNotification: true); LandClaimShieldProtectionSystem.SharedCanRaid(targetObject, showClientNotification: true); PveSystem.SharedIsAllowStaticObjectDamage(weaponCache.Character, targetObject, showClientNotification: true); NewbieProtectionSystem.SharedIsAllowStructureDamage(weaponCache.Character, targetObject, showClientNotification: true); damageApplied = 0; return(true); } if (serverDamage <= 0) { // no damage applied damageApplied = 0; return(true); } // apply damage damageApplied = serverDamage; var newStructurePoints = (float)(previousStructurePoints - serverDamage); if (newStructurePoints < 0) { newStructurePoints = 0; } Logger.Info( $"Damage applied to {targetObject} by {weaponCache.Character}:\n{serverDamage} dmg, current structure points {newStructurePoints}/{this.StructurePointsMax}, {weaponCache.Weapon}"); objectPublicState.StructurePointsCurrent = newStructurePoints; try { this.ServerOnStaticObjectDamageApplied( weaponCache, targetObject, previousStructurePoints, newStructurePoints); } catch (Exception ex) { Logger.Exception(ex, $"Problem on processing {nameof(this.ServerOnStaticObjectDamageApplied)}()"); } if (newStructurePoints <= 0f) { this.ServerOnStaticObjectZeroStructurePoints(weaponCache, weaponCache.Character, targetObject); } return(true); }
public static void ClientStartRelocation(IStaticWorldObject objectStructure) { var protoStructure = objectStructure.ProtoStaticWorldObject; var character = Client.Characters.CurrentPlayerCharacter; if (IsInObjectPlacementMode || ConstructionPlacementSystem.IsInObjectPlacementMode) { // already relocating/placing something return; } if (!SharedIsRelocatable(objectStructure)) { return; } if (!CreativeModeSystem.SharedIsInCreativeMode(character) && !LandClaimSystem.SharedIsOwnedLand(objectStructure.TilePosition, character, requireFactionPermission: true, out var hasNoFactionPermission, out _)) { // the building location or destination is in an area that is not owned by the player SharedShowCannotRelocateNotification( character, protoStructure, hasNoFactionPermission); return; } var isPvEorWithinInteractionArea = PveSystem.SharedIsPve(false) || protoStructure.SharedIsInsideCharacterInteractionArea( Api.Client.Characters.CurrentPlayerCharacter, objectStructure, writeToLog: false); if (!isPvEorWithinInteractionArea) { CannotInteractMessageDisplay.ClientOnCannotInteract( character, CoreStrings.Notification_TooFar, isOutOfRange: true); return; } if (LandClaimSystem.SharedIsUnderRaidBlock(character, objectStructure)) { // the building is in an area under the raid ConstructionSystem.SharedShowCannotBuildNotification( character, LandClaimSystem.ErrorRaidBlockActionRestricted_Message, protoStructure); return; } if (LandClaimShieldProtectionSystem.SharedIsUnderShieldProtection(objectStructure)) { // the building is in an area under shield protection LandClaimShieldProtectionSystem.SharedSendNotificationActionForbiddenUnderShieldProtection( character); return; } ClientDisableConstructionRelocation(); var sceneObject = Client.Scene.CreateSceneObject("StructureRelocationHelper"); componentObjectPlacementHelper = sceneObject.AddComponent <ClientComponentObjectPlacementHelper>(); componentRelocationHelper = sceneObject.AddComponent <ClientComponentObjectRelocationHelper>(); componentObjectPlacementHelper .Setup(protoStructure, isCancelable: true, isRepeatCallbackIfHeld: false, isDrawConstructionGrid: true, isBlockingInput: true, validateCanPlaceCallback: ClientValidateCanRelocate, placeSelectedCallback: ClientConstructionPlaceSelectedCallback, delayRemainsSeconds: 0.1); componentObjectPlacementHelper.HideBlueprintOnOverlapWithTheSameObject = false; componentRelocationHelper.Setup(objectStructure); void ClientValidateCanRelocate( Vector2Ushort tilePosition, bool logErrors, out string errorMessage, out bool canPlace, out bool isTooFar) { if (tilePosition == objectStructure.TilePosition) { canPlace = true; isTooFar = false; errorMessage = null; return; } if (!SharedCheckTileRequirementsForRelocation(character, objectStructure, tilePosition, out errorMessage, logErrors: logErrors)) { // time requirements are not valid canPlace = false; isTooFar = false; return; } if (!SharedValidateCanCharacterRelocateStructure(character, objectStructure, tilePosition, out errorMessage, logErrors: logErrors)) { canPlace = true; isTooFar = true; return; } if (SharedHasObstacle( character, objectStructure, tilePosition.ToVector2D() + protoStructure.Layout.Center)) { if (logErrors) { CannotInteractMessageDisplay.ClientOnCannotInteract( character, CoreStrings.Notification_ObstaclesOnTheWay, isOutOfRange: true); } errorMessage = CoreStrings.Notification_ObstaclesOnTheWay; canPlace = true; isTooFar = true; return; } canPlace = true; isTooFar = false; } void ClientConstructionPlaceSelectedCallback(Vector2Ushort tilePosition) { if (SharedHasObstacle( character, objectStructure, tilePosition.ToVector2D() + protoStructure.Layout.Center)) { CannotInteractMessageDisplay.ClientOnCannotInteract( character, CoreStrings.Notification_ObstaclesOnTheWay, isOutOfRange: true); return; } ClientTimersSystem.AddAction(0.1, ClientDisableConstructionRelocation); if (tilePosition != objectStructure.TilePosition) { Instance.CallServer(_ => _.ServerRemote_RelocateStructure(objectStructure, tilePosition)); } } }
public static bool SharedValidateCanCharacterRelocateStructure( ICharacter character, IStaticWorldObject objectStructure, Vector2Ushort toPosition, out string errorMessage, bool logErrors) { if (!SharedIsRelocatable(objectStructure)) { errorMessage = null; return(false); } if (!SharedCheckTileRequirementsForRelocation(character, objectStructure, toPosition, out errorMessage, logErrors)) { return(false); } if (!(objectStructure.ProtoGameObject is IProtoObjectStructure protoStructure)) { return(false); } var maxRelocationDistance = PveSystem.SharedIsPve(true) ? MaxRelocationDistancePvE : MaxRelocationDistancePvP; if (objectStructure.TilePosition.TileSqrDistanceTo(toPosition) > maxRelocationDistance * maxRelocationDistance) { if (logErrors) { ConstructionSystem.SharedShowCannotPlaceNotification( character, CoreStrings.Notification_TooFar, protoStructure); } errorMessage = CoreStrings.Notification_TooFar; return(false); } var itemInHands = character.SharedGetPlayerSelectedHotbarItem(); if (!(itemInHands.ProtoGameObject is IProtoItemToolToolbox)) { return(false); } if (CreativeModeSystem.SharedIsInCreativeMode(character)) { errorMessage = null; return(true); } if (!LandClaimSystem.SharedIsOwnedLand(objectStructure.TilePosition, character, requireFactionPermission: true, out var hasNoFactionPermission, ownedArea: out _) || !IsOwnedLand(toPosition, out hasNoFactionPermission)) { errorMessage = string.Format(CoreStrings.Faction_Permission_Required_Format, CoreStrings.Faction_Permission_LandClaimManagement_Title); // the building location or destination is in an area that is not owned by the player if (logErrors) { SharedShowCannotRelocateNotification( character, protoStructure, hasNoFactionPermission); } return(false); } if (LandClaimSystem.SharedIsUnderRaidBlock(character, objectStructure)) { // the building is in an area under the raid errorMessage = LandClaimSystem.ErrorRaidBlockActionRestricted_Message; if (logErrors) { ConstructionSystem.SharedShowCannotPlaceNotification( character, LandClaimSystem.ErrorRaidBlockActionRestricted_Message, protoStructure); } return(false); } if (LandClaimShieldProtectionSystem.SharedIsUnderShieldProtection(objectStructure)) { // the building is in an area under shield protection errorMessage = CoreStrings.ShieldProtection_ActionRestrictedBaseUnderShieldProtection; if (logErrors) { LandClaimShieldProtectionSystem.SharedSendNotificationActionForbiddenUnderShieldProtection( character); } return(false); } errorMessage = null; return(true); bool IsOwnedLand( Vector2Ushort startTilePosition, out bool hasNoFactionPermission) { var worldObjectLayoutTileOffsets = objectStructure.ProtoStaticWorldObject.Layout.TileOffsets; foreach (var tileOffset in worldObjectLayoutTileOffsets) { if (!LandClaimSystem.SharedIsOwnedLand(startTilePosition.AddAndClamp(tileOffset), character, requireFactionPermission: true, out hasNoFactionPermission, out _)) { return(false); } } hasNoFactionPermission = false; return(true); } }
public static bool CheckCanInteractForConstruction( ICharacter character, IStaticWorldObject worldObject, bool writeToLog, bool checkRaidblock) { var characterPosition = character.Position; var canInteract = false; var staticWorldObjectProto = ProtoObjectConstructionSite.SharedGetConstructionProto(worldObject) ?? worldObject.ProtoStaticWorldObject; var startTilePosition = worldObject.TilePosition; foreach (var tileOffset in staticWorldObjectProto.Layout.TileOffsets) { var tilePosition = startTilePosition + tileOffset; if (characterPosition.DistanceSquaredTo( new Vector2D(tilePosition.X + 0.5, tilePosition.Y + 0.5)) <= MaxDistanceForBuildRepairAction * MaxDistanceForBuildRepairAction) { canInteract = true; break; } } if (!canInteract) { canInteract = CreativeModeSystem.SharedIsInCreativeMode(character); } if (!canInteract) { if (writeToLog) { Logger.Warning( $"Character cannot interact with {worldObject} for (de)construction - too far.", character); if (IsClient) { CannotInteractMessageDisplay.ClientOnCannotInteract(worldObject, CoreStrings.Notification_TooFar, isOutOfRange: true); } } return(false); } if (checkRaidblock && LandClaimSystem.SharedIsUnderRaidBlock(character, worldObject)) { // the building is in an area under the raid if (writeToLog) { LandClaimSystem.SharedSendNotificationActionForbiddenUnderRaidblock(character); } return(false); } if (LandClaimShieldProtectionSystem.SharedIsUnderShieldProtection(worldObject)) { // the building is in an area under shield protection if (writeToLog) { LandClaimShieldProtectionSystem.SharedSendNotificationActionForbiddenUnderShieldProtection( character); } return(false); } return(true); }
public static bool SharedValidateCanCharacterRelocateStructure( ICharacter character, IStaticWorldObject objectStructure, Vector2Ushort toPosition, bool logErrors) { if (!SharedIsRelocatable(objectStructure)) { return(false); } if (!SharedCheckTileRequirementsForRelocation(character, objectStructure, toPosition, logErrors)) { return(false); } if (!(objectStructure.ProtoGameObject is IProtoObjectStructure protoStructure)) { return(false); } if (objectStructure.TilePosition.TileSqrDistanceTo(toPosition) > MaxRelocationDistance * MaxRelocationDistance) { if (logErrors) { ConstructionSystem.SharedShowCannotPlaceNotification( character, CoreStrings.Notification_TooFar, protoStructure); } return(false); } var itemInHands = character.SharedGetPlayerSelectedHotbarItem(); if (!(itemInHands.ProtoGameObject is IProtoItemToolToolbox)) { return(false); } if (CreativeModeSystem.SharedIsInCreativeMode(character)) { return(true); } if (!LandClaimSystem.SharedIsOwnedLand(objectStructure.TilePosition, character, out _) || !IsOwnedLand(toPosition)) { // the building location or destination is in an area that is not owned by the player if (logErrors) { ConstructionSystem.SharedShowCannotPlaceNotification( character, LandClaimSystem.ErrorNotLandOwner_Message, protoStructure); } return(false); } if (LandClaimSystem.SharedIsUnderRaidBlock(character, objectStructure)) { // the building is in an area under the raid if (logErrors) { ConstructionSystem.SharedShowCannotPlaceNotification( character, LandClaimSystem.ErrorRaidBlockActionRestricted_Message, protoStructure); } return(false); } if (LandClaimShieldProtectionSystem.SharedIsUnderShieldProtection(objectStructure)) { // the building is in an area under shield protection if (logErrors) { LandClaimShieldProtectionSystem.SharedSendNotificationActionForbiddenUnderShieldProtection( character); } return(false); } return(true); bool IsOwnedLand(Vector2Ushort startTilePosition) { var worldObjectLayoutTileOffsets = objectStructure.ProtoStaticWorldObject.Layout.TileOffsets; foreach (var tileOffset in worldObjectLayoutTileOffsets) { if (!LandClaimSystem.SharedIsOwnedLand(startTilePosition.AddAndClamp(tileOffset), character, out _)) { return(false); } } return(true); } }
public ObjectLandClaimCanUpgradeCheckResult SharedCanUpgrade( IStaticWorldObject worldObjectLandClaim, IProtoObjectLandClaim protoUpgradedLandClaim, ICharacter character, out IConstructionUpgradeEntryReadOnly upgradeEntry, bool writeErrors = true) { if (!this.SharedCanInteract(character, worldObjectLandClaim, writeToLog: writeErrors)) { upgradeEntry = null; return(ObjectLandClaimCanUpgradeCheckResult.ErrorUnknown); } upgradeEntry = null; foreach (var entry in this.ConfigUpgrade.Entries) { if (entry.ProtoStructure == protoUpgradedLandClaim) { upgradeEntry = entry; break; } } var currentLandClaimArea = GetPublicState(worldObjectLandClaim).LandClaimAreaObject; var founderName = LandClaimArea.GetPrivateState(currentLandClaimArea).LandClaimFounder; var result = ObjectLandClaimCanUpgradeCheckResult.Success; if (upgradeEntry == null) { result = ObjectLandClaimCanUpgradeCheckResult.ErrorUnknown; } if (result == ObjectLandClaimCanUpgradeCheckResult.Success) { if (character.Name != founderName && !CreativeModeSystem.SharedIsInCreativeMode(character)) { result = ObjectLandClaimCanUpgradeCheckResult.ErrorNotFounder; } } if (result == ObjectLandClaimCanUpgradeCheckResult.Success) { // validate player know the tech, have enough items, etc if (!upgradeEntry.CheckRequirementsSatisfied(character)) { upgradeEntry = null; result = ObjectLandClaimCanUpgradeCheckResult.ErrorRequirementsNotSatisfied; } } if (result == ObjectLandClaimCanUpgradeCheckResult.Success && LandClaimShieldProtectionSystem.SharedIsAreaUnderShieldProtection(currentLandClaimArea)) { // the building is in an area under shield protection result = ObjectLandClaimCanUpgradeCheckResult.ErrorUnderShieldProtection; } if (result == ObjectLandClaimCanUpgradeCheckResult.Success) { // check there will be no intersection with other areas var landClaimCenterTilePosition = LandClaimSystem.SharedCalculateLandClaimObjectCenterTilePosition(worldObjectLandClaim); if (!LandClaimSystem.SharedCheckCanPlaceOrUpgradeLandClaimThereConsideringShieldProtection( protoUpgradedLandClaim, landClaimCenterTilePosition, character)) { result = ObjectLandClaimCanUpgradeCheckResult.ErrorAreaIntersectionWithShieldProtectedArea; } if (!LandClaimSystem.SharedCheckCanPlaceOrUpgradeLandClaimThere( protoUpgradedLandClaim, landClaimCenterTilePosition, character)) { result = ObjectLandClaimCanUpgradeCheckResult.ErrorAreaIntersection; } if (!LandClaimSystem.SharedCheckNoLandClaimByDemoPlayers( protoUpgradedLandClaim, landClaimCenterTilePosition, character, exceptAreasGroup: LandClaimSystem.SharedGetLandClaimAreasGroup(currentLandClaimArea))) { result = ObjectLandClaimCanUpgradeCheckResult.ErrorAreaIntersectionDemoPlayer; } if (IsServer && !LandClaimSystem.ServerCheckFutureBaseWillExceedSafeStorageCapacity( protoUpgradedLandClaim, landClaimCenterTilePosition, character)) { result = ObjectLandClaimCanUpgradeCheckResult.ErrorExceededSafeStorageCapacity; } } if (result == ObjectLandClaimCanUpgradeCheckResult.Success) { if (!InteractionCheckerSystem.SharedHasInteraction(character, worldObjectLandClaim, requirePrivateScope: true)) { result = ObjectLandClaimCanUpgradeCheckResult.ErrorNoActiveInteraction; } } if (result == ObjectLandClaimCanUpgradeCheckResult.Success && LandClaimSystem.SharedIsUnderRaidBlock(character, worldObjectLandClaim)) { // the building is in an area under raid LandClaimSystem.SharedSendNotificationActionForbiddenUnderRaidblock(character); result = ObjectLandClaimCanUpgradeCheckResult.ErrorUnderRaid; } if (writeErrors && result != ObjectLandClaimCanUpgradeCheckResult.Success) { Logger.Warning( $"Can't upgrade: {worldObjectLandClaim} to {protoUpgradedLandClaim}: error code - {result}", character); } return(result); }