示例#1
0
        private void ServerTimerTick()
        {
            const double experienceToAdd = ExperienceAddWhenOnlinePerSecond
                                           * TimerIntervalSeconds;

            foreach (var character in Server.Characters.EnumerateAllPlayerCharacters(onlyOnline: true))
            {
                if (character.ProtoCharacter.GetType() != typeof(PlayerCharacter))
                {
                    // only characters of specific type (PlayerCharacter) are processed
                    continue;
                }

                var publicState = PlayerCharacter.GetPublicState(character);
                if (publicState.IsDead)
                {
                    // dead characters are not processed
                    continue;
                }

                if (CharacterIdleSystem.ServerIsIdlePlayer(character))
                {
                    // idle character
                    continue;
                }

                character.ServerAddSkillExperience(this, experienceToAdd);
            }
        }
示例#2
0
        protected override void ServerUpdate(StatusEffectData data)
        {
            var character = data.Character;

            if (!character.ServerIsOnline)
            {
                // only online characters are affected by thirst
                return;
            }

            if (!IsLowWater(character))
            {
                // not thirsty anymore
                character.ServerRemoveStatusEffect(this);
                return;
            }

            if (CharacterIdleSystem.ServerIsIdlePlayer(character))
            {
                return;
            }

            // reduce character health
            var stats = data.CharacterCurrentStats;

            stats.ServerReduceHealth(DamagePerSecond * data.DeltaTime, data.StatusEffect);
        }
        protected sealed override void ServerUpdate(ServerUpdateData data)
        {
            base.ServerUpdate(data);

            if (this.durabilityDecreasePerServerUpdate <= 0)
            {
                // non-degradeable
                return;
            }

            if (data.DeltaTime <= 0)
            {
                // not processed
                return;
            }

            // try to degrade durability over time and give experience for cybernetic affinity skill
            var item  = data.GameObject;
            var owner = item.Container?.OwnerAsCharacter;

            if (owner is null ||
                !owner.ServerIsOnline ||
                owner.SharedGetPlayerContainerEquipment() != item.Container)
            {
                // player offline or not an equipped item
                return;
            }

            if (CharacterIdleSystem.ServerIsIdlePlayer(owner))
            {
                return;
            }

            var durabilityDecrease = this.durabilityDecreasePerServerUpdate;

            durabilityDecrease *= owner.SharedGetFinalStatMultiplier(StatName.ImplantDegradationSpeedMultiplier);
            ItemDurabilitySystem.ServerModifyDurability(item, -durabilityDecrease, roundUp: false);

            owner.ServerAddSkillExperience <SkillCyberneticAffinity>(
                data.DeltaTime * SkillCyberneticAffinity.ExperienceAddedPerImplantPerSecond);

            if (!item.IsDestroyed)
            {
                this.ServerUpdateInstalledImplant(data);
            }
        }
示例#4
0
        public void ServerOnSkillExperienceAdded(
            ICharacter character,
            double experienceAdded,
            byte currentLevel)
        {
            var multiplier = this.ExperienceToLearningPointsConversionMultiplier
                             * TechConstants.ServerSkillExperienceToLearningPointsConversionMultiplier;

            // apply reversed experience gain multiplier so faster/slower skill exp gain speed will not affect LP gain speed
            multiplier /= TechConstants.ServerSkillExperienceGainMultiplier;

            if (multiplier <= 0 ||
                double.IsNaN(multiplier))
            {
                return;
            }

            // reduce LP gain proportionally to the skill level
            var lpRateMultiplier = MathHelper.Lerp(1,
                                                   TechConstants.SkillLearningPointMultiplierAtMaximumLevel,
                                                   currentLevel / (double)this.MaxLevel);

            multiplier *= lpRateMultiplier;

            if (multiplier <= 0)
            {
                return;
            }

            var learningPointsToAdd = experienceAdded * multiplier;

            var partyMembersNames = this.IsSharingLearningPointsWithPartyMembers
                                        ? PartySystem.ServerGetPartyMembersReadOnly(character)
                                        : Array.Empty <string>();

            if (partyMembersNames.Count <= 1)
            {
                // no experience share, no party or a single member party - add all LP to the current character
                character.SharedGetTechnologies()
                .ServerAddLearningPoints(learningPointsToAdd);
                return;
            }

            using var onlinePartyMembers = Api.Shared.GetTempList <ICharacter>();
            foreach (var partyMemberName in partyMembersNames)
            {
                var partyMember = Server.Characters.GetPlayerCharacter(partyMemberName);
                if (partyMember is null)
                {
                    continue;
                }

                if (ReferenceEquals(partyMember, character) ||
                    (partyMember.ServerIsOnline &&
                     !CharacterIdleSystem.ServerIsIdlePlayer(partyMember)))
                {
                    onlinePartyMembers.Add(partyMember);
                }
            }

            if (onlinePartyMembers.Count <= 1 ||
                PartyConstants.PartyLearningPointsSharePercent == 0)
            {
                // no party, or a single member party, or no party share %
                // - add all LP to the current character
                character.SharedGetTechnologies()
                .ServerAddLearningPoints(learningPointsToAdd);
                return;
            }

            // player has a party
            // add only a share of LP to current character
            var currentCharacterLearningPointsShare = learningPointsToAdd * (1 - PartyConstants.PartyLearningPointsSharePercent);

            character.SharedGetTechnologies()
            .ServerAddLearningPoints(currentCharacterLearningPointsShare);

            // distribute the rest equally to the other party members
            var learningPointsShare = learningPointsToAdd
                                      * PartyConstants.PartyLearningPointsSharePercent
                                      / (onlinePartyMembers.Count - 1);

            foreach (var partyMember in onlinePartyMembers.AsList())
            {
                if (!ReferenceEquals(partyMember, character))
                {
                    partyMember.SharedGetTechnologies()
                    .ServerAddLearningPoints(learningPointsShare);
                }
            }
        }
示例#5
0
        private bool ServerCheckIsDoorShouldBeOpened(
            IStaticWorldObject worldObject,
            TPrivateState privateState)
        {
            if (privateState.IsBlockedByShield)
            {
                return(false);
            }

            var mode = privateState.AccessMode;

            if (mode == WorldObjectAccessMode.Closed)
            {
                return(false);
            }

            Server.World.GetInViewScopeByPlayers(worldObject, StaticTempCharactersNearby);
            if (StaticTempCharactersNearby.Count == 0)
            {
                // no characters nearby
                return(false);
            }

            var objectOpeningBounds = this.SharedGetDoorOpeningBounds(worldObject);

            foreach (var character in StaticTempCharactersNearby)
            {
                if (!character.ServerIsOnline ||
                    CharacterIdleSystem.ServerIsIdlePlayer(character) ||
                    character.ProtoCharacter is PlayerCharacterSpectator)
                {
                    continue;
                }

                if (!objectOpeningBounds.Contains(character.Position))
                {
                    // too far from this door
                    continue;
                }

                if (!WorldObjectAccessModeSystem.ServerHasAccess(worldObject,
                                                                 character,
                                                                 mode,
                                                                 writeToLog: false))
                {
                    continue;
                }

                // we don't do this check because it requires character to be the door owner
                //if (!this.SharedCanInteract(character, gameObject, writeToLog: false))
                //{
                //    return false;
                //}

                // we do this check instead:
                // ensure the character is alive and there is a direct line of sight between the character and the door
                var characterPublicState = character.GetPublicState <ICharacterPublicState>();
                if (characterPublicState.IsDead)
                {
                    // dead
                    continue;
                }

                if (!this.IsHeavyVehicleCanPass &&
                    characterPublicState is PlayerCharacterPublicState playerCharacterPublicState &&
                    playerCharacterPublicState.CurrentVehicle?.ProtoGameObject is IProtoVehicle protoVehicle &&
                    protoVehicle.IsHeavyVehicle)
                {
                    // in a heavy vehicle and cannot pass
                    continue;
                }

                var characterPhysicsBody = character.PhysicsBody;
                var characterCenter      = character.Position + characterPhysicsBody.CenterOffset;
                if (!ObstacleTestHelper.SharedHasObstaclesOnTheWay(characterCenter,
                                                                   characterPhysicsBody.PhysicsSpace,
                                                                   worldObject,
                                                                   sendDebugEvents: true))
                {
                    return(true);
                }
            }

            // the door should be closed
            return(false);
        }