Ejemplo n.º 1
0
        private static bool SharedHasObstacle(
            ICharacter character,
            IStaticWorldObject forStructureRelocation,
            Vector2D position)
        {
            if (PveSystem.SharedIsPve(false))
            {
                return(false);
            }

            var characterCenter = character.Position + character.PhysicsBody.CenterOffset;

            return(TestHasObstacle(position));

            // local method for testing if there is an obstacle from current to the specified position
            bool TestHasObstacle(Vector2D toPosition)
            {
                using var obstaclesInTheWay = character.PhysicsBody.PhysicsSpace.TestLine(
                          characterCenter,
                          toPosition,
                          CollisionGroup.Default,
                          sendDebugEvent: false);
                foreach (var test in obstaclesInTheWay.AsList())
                {
                    var testPhysicsBody = test.PhysicsBody;
                    if (testPhysicsBody.AssociatedProtoTile is not null)
                    {
                        // obstacle tile on the way
                        return(true);
                    }

                    var testWorldObject = testPhysicsBody.AssociatedWorldObject;
                    if (testWorldObject is null ||
                        ReferenceEquals(testWorldObject, character) ||
                        ReferenceEquals(testWorldObject, forStructureRelocation))
                    {
                        // not an obstacle - it's the character or world object itself
                        continue;
                    }

                    switch (testWorldObject.ProtoWorldObject)
                    {
                    case IProtoObjectDeposit:     // allow deposits
                    case ObjectWallDestroyed:     // allow destroyed walls
                        continue;
                    }

                    // obstacle object on the way
                    return(true);
                }

                // no obstacles
                return(false);
            }
        }
Ejemplo n.º 2
0
        protected override void PrepareTileRequirements(ConstructionTileRequirements tileRequirements)
        {
            base.PrepareTileRequirements(tileRequirements);

            // disallow placing mining bombs on the floor on the PvE servers
            tileRequirements.Add(
                new ConstructionTileRequirements.Validator(
                    ConstructionTileRequirements.ErrorNoFreeSpace,
                    c => !PveSystem.SharedIsPve(clientLogErrorIfDataIsNotYetAvailable: false) ||
                    c.Tile.StaticObjects.All(
                        o => o.ProtoStaticWorldObject.Kind != StaticObjectKind.Floor)));
        }
Ejemplo n.º 3
0
        public override bool SharedCanInteract(ICharacter character, IStaticWorldObject worldObject, bool writeToLog)
        {
            if (!base.SharedCanInteract(character, worldObject, writeToLog))
            {
                return(false);
            }

            var ownerName = GetPublicState(worldObject).OwnerName;

            if (ownerName == character.Name)
            {
                return(true);
            }

            if (PveSystem.SharedIsPve(false))
            {
                if (IsClient && PartySystem.ClientIsPartyMember(ownerName) ||
                    (IsServer &&
                     PartySystem.ServerIsSameParty(Server.Characters.GetPlayerCharacter(ownerName),
                                                   character)))
                {
                    // in PvE party members can pickup items of their party members
                }
                else
                {
                    // other players in PvE cannot pickup player's loot
                    if (writeToLog && IsClient)
                    {
                        PveSystem.ClientShowNotificationActionForbidden();
                    }

                    return(false);
                }
            }

            if (NewbieProtectionSystem.SharedIsNewbie(character))
            {
                // newbie cannot pickup other players' loot
                if (writeToLog)
                {
                    NewbieProtectionSystem.SharedShowNewbieCannotDamageOtherPlayersOrLootBags(character,
                                                                                              isLootBag: true);
                }

                return(false);
            }

            // non-newbie character can pickup players' loot
            // please note this validation has an override for derived ObjectPlayerLootContainerProtected
            return(true);
        }
Ejemplo n.º 4
0
        public double Get(TechTier tier, bool isSpecialized)
        {
            if (PveSystem.SharedIsPve(false))
            {
                return(0);
            }

            var tierIndex = (int)tier - (int)TechConstants.PvPTimeGateStartsFromTier;

            if (tierIndex < 0)
            {
                return(0);
            }

            var index = 2 * tierIndex + (isSpecialized ? 1 : 0);

            return(this.TimeGates[index]);
        }
Ejemplo n.º 5
0
        public virtual bool SharedCanInteract(ICharacter character, TWorldObject worldObject, bool writeToLog)
        {
            if (!this.IsInteractableObject)
            {
                return(false);
            }

            if (character.GetPublicState <ICharacterPublicState>().IsDead ||
                IsServer && !character.ServerIsOnline)
            {
                return(false);
            }

            if (worldObject is IStaticWorldObject staticWorldObject)
            {
                if (PveSystem.SharedIsPve(clientLogErrorIfDataIsNotYetAvailable: false))
                {
                    if (!PveSystem.SharedValidateInteractionIsNotForbidden(character,
                                                                           staticWorldObject,
                                                                           writeToLog))
                    {
                        // action forbidden by PvE system
                        return(false);
                    }
                }
                else // PvP servers have newbie protection system
                {
                    if (!NewbieProtectionSystem.SharedValidateInteractionIsNotForbidden(
                            character,
                            staticWorldObject,
                            writeToLog))
                    {
                        // action forbidden by newbie protection system
                        return(false);
                    }
                }
            }

            return(this.SharedIsInsideCharacterInteractionArea(character,
                                                               worldObject,
                                                               writeToLog));
        }
Ejemplo n.º 6
0
        protected override double SharedCalculateDamageByWeapon(
            WeaponFinalCache weaponCache,
            double damagePreMultiplier,
            IDynamicWorldObject targetObject,
            out double obstacleBlockDamageCoef)
        {
            if (PveSystem.SharedIsPve(false) &&
                (weaponCache.Character is null ||
                 !weaponCache.Character.IsNpc))
            {
                // no PvP damage in PvE (only creature damage is allowed)
                obstacleBlockDamageCoef = 0;
                return(0);
            }

            return(base.SharedCalculateDamageByWeapon(weaponCache,
                                                      damagePreMultiplier,
                                                      targetObject,
                                                      out obstacleBlockDamageCoef));
        }
Ejemplo n.º 7
0
        private static double SharedGetSpeedMultiplier(IStaticWorldObject objectDeposit)
        {
            return(GetDepositExtractionRateMultiplier()
                   * StructureConstants.DepositsExtractionSpeedMultiplier);

            double GetDepositExtractionRateMultiplier()
            {
                if (PveSystem.SharedIsPve(clientLogErrorIfDataIsNotYetAvailable: false))
                {
                    return(ExtractorPvE);
                }

                // extractor in PvP
                if (objectDeposit is null)
                {
                    return(ExtractorPvpWithoutDeposit);
                }

                var protoObjectDeposit = (IProtoObjectDeposit)objectDeposit.ProtoStaticWorldObject;

                return(ExtractorPvpWithDeposit);
            }
        }
        public static bool SharedIsAllowInteraction(
            ICharacter character,
            IStaticWorldObject worldObject,
            bool showClientNotification)
        {
            if (!SharedIsEnabled)
            {
                return(true);
            }

            if (character is null ||
                !PveSystem.SharedIsPve(clientLogErrorIfDataIsNotYetAvailable: false))
            {
                return(true);
            }

            var worldObjectPublicState = worldObject.AbstractPublicState as IWorldObjectPublicStateWithClaim;

            if (worldObjectPublicState?.WorldObjectClaim is null ||
                WorldObjectClaim.SharedIsClaimedForPlayer(worldObjectPublicState.WorldObjectClaim, character))
            {
                return(true);
            }

            if (IsClient && showClientNotification)
            {
                NotificationSystem.ClientShowNotification(
                    CoreStrings.WorldObjectClaim_Title,
                    CoreStrings.WorldObjectClaim_Description
                    + "[br]"
                    + CoreStrings.WorldObjectClaim_Description2,
                    NotificationColor.Bad,
                    icon: TextureResourceClaimedObject);
            }

            return(false);
        }
Ejemplo n.º 9
0
        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));
                }
            }
        }
Ejemplo n.º 10
0
        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);
            }
        }
Ejemplo n.º 11
0
        public virtual bool SharedCanInteract(ICharacter character, TWorldObject worldObject, bool writeToLog)
        {
            if (!this.IsInteractableObject)
            {
                return(false);
            }

            try
            {
                this.VerifyGameObject(worldObject);
            }
            catch (Exception ex)
            {
                Logger.Warning($"Interaction check failed: {ex.GetType().FullName}: {ex.Message}");
                return(false);
            }

            if (character.GetPublicState <ICharacterPublicState>().IsDead ||
                IsServer && !character.ServerIsOnline ||
                ((IsServer || character.IsCurrentClientCharacter) &&
                 PlayerCharacter.GetPrivateState(character).IsDespawned))
            {
                if (writeToLog)
                {
                    Logger.Warning(
                        $"Character cannot interact with {worldObject} - character is offline/despawned/dead.",
                        character);
                }

                return(false);
            }

            if (worldObject is IStaticWorldObject staticWorldObject)
            {
                if (PveSystem.SharedIsPve(clientLogErrorIfDataIsNotYetAvailable: false))
                {
                    if (!PveSystem.SharedValidateInteractionIsNotForbidden(character,
                                                                           staticWorldObject,
                                                                           writeToLog))
                    {
                        // action forbidden by PvE system
                        return(false);
                    }
                }
                else // PvP servers have newbie protection system
                {
                    if (!NewbieProtectionSystem.SharedValidateInteractionIsNotForbidden(
                            character,
                            staticWorldObject,
                            writeToLog))
                    {
                        // action forbidden by newbie protection system
                        return(false);
                    }
                }
            }

            return(this.SharedIsInsideCharacterInteractionArea(character,
                                                               worldObject,
                                                               writeToLog));
        }
Ejemplo n.º 12
0
        private static void SharedRebuildAllNodes()
        {
            if (Api.IsClient &&
                !PveSystem.ClientIsPveFlagReceived)
            {
                AvailableTechGroups = new TechGroup[0];
                return;
            }

            var isPvE = PveSystem.SharedIsPve(false);

            var allTechGroups = Api.FindProtoEntities <TechGroup>();

            foreach (var techGroup in allTechGroups)
            {
                SetupTimeGate(techGroup);

                techGroup.Nodes = techGroup.IsAvailable
                                      ? (IReadOnlyList <TechNode>)LazyAllNodesWithoutFiltering
                                  .Value
                                  .Where(n => n.Group == techGroup &&
                                         n.IsAvailable)
                                  .OrderBy(n => n.HierarchyLevel)
                                  .ThenBy(n => n.Order)
                                  .ThenBy(n => n.ShortId)
                                  .ToList()
                                      : new TechNode[0];

                var rootNodes = new List <TechNode>();
                foreach (var node in techGroup.Nodes)
                {
                    node.SharedResetCachedLearningPointsPrice();

                    if (node.IsRootNode)
                    {
                        rootNodes.Add(node);
                    }
                }

                techGroup.RootNodes = rootNodes;

                var requirements = new Requirements();
                techGroup.PrepareTechGroup(requirements);
                if (techGroup.LearningPointsPrice > 0)
                {
                    requirements.Insert(0, new TechGroupRequirementLearningPoints(techGroup.LearningPointsPrice));
                }

                if (!PveSystem.SharedIsPve(clientLogErrorIfDataIsNotYetAvailable: false) &&
                    techGroup.TimeGatePvP > 0)
                {
                    requirements.Add(new TechGroupRequirementTimeGate(techGroup.TimeGatePvP));
                }

                techGroup.GroupRequirements = requirements;

                Api.SafeInvoke(techGroup.NodesChanged);
            }

            AvailableTechGroups = allTechGroups.Where(t => t.IsAvailable).ToArray();
            Api.SafeInvoke(AvailableTechGroupsChanged);

            void SetupTimeGate(TechGroup techGroup)
            {
                if (isPvE)
                {
                    techGroup.TimeGatePvP = 0;
                    return;
                }

                if (techGroup.IsPrimary)
                {
                    techGroup.TimeGatePvP = techGroup.Tier switch
                    {
                        TechTier.Tier3 => TechConstants.PvpTechTimeGameTier3Basic,
                        TechTier.Tier4 => TechConstants.PvpTechTimeGameTier4Basic,
                        TechTier.Tier5 => TechConstants.PvpTechTimeGameTier5Basic,
                        _ => 0
                    };
                }
                else
                {
                    techGroup.TimeGatePvP = techGroup.Tier switch
                    {
                        TechTier.Tier3 => TechConstants.PvpTechTimeGameTier3Specialized,
                        TechTier.Tier4 => TechConstants.PvpTechTimeGameTier4Specialized,
                        TechTier.Tier5 => TechConstants.PvpTechTimeGameTier5Specialized,
                        _ => 0
                    };
                }
            }
        }