コード例 #1
0
        protected override double SharedCalculateDamageByWeapon(
            WeaponFinalCache weaponCache,
            double damagePreMultiplier,
            IStaticWorldObject targetObject,
            out double obstacleBlockDamageCoef)
        {
            obstacleBlockDamageCoef = 1;
            if (!PveSystem.SharedIsAllowStructureDamage(weaponCache.Character,
                                                        targetObject,
                                                        showClientNotification: false))
            {
                return(0);
            }

            if (weaponCache.ProtoWeapon is IProtoItemToolWoodcutting protoItemToolWoodCutting)
            {
                // get damage multiplier ("woodcutting speed")
                var damageMultiplier = weaponCache.Character
                                       .SharedGetFinalStatMultiplier(StatName.WoodcuttingSpeed);

                return(protoItemToolWoodCutting.DamageToTree
                       * damageMultiplier
                       * ToolsConstants.ActionWoodcuttingSpeedMultiplier);
            }

            if (weaponCache.ProtoWeapon is ItemNoWeapon)
            {
                // no damage with hands
                if (IsClient)
                {
                    NotificationSystem.ClientShowNotification(NotificationUseAxe,
                                                              icon: this.Icon);
                }

                return(0);
            }

            // not a wood-cutting tool - call default damage apply method
            return(base.SharedCalculateDamageByWeapon(weaponCache,
                                                      damagePreMultiplier,
                                                      targetObject,
                                                      out obstacleBlockDamageCoef));
        }
コード例 #2
0
        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);
                PveSystem.SharedIsAllowStructureDamage(weaponCache.Character,
                                                       targetObject,
                                                       showClientNotification: true);

                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);
        }
コード例 #3
0
        public static double ServerCalculateTotalDamage(
            WeaponFinalCache weaponCache,
            IWorldObject targetObject,
            FinalStatsCache targetFinalStatsCache,
            double damagePreMultiplier,
            bool clampDefenseTo1)
        {
            if (targetObject is IStaticWorldObject staticWorldObject &&
                (!RaidingProtectionSystem.SharedCanRaid(staticWorldObject,
                                                        showClientNotification: false) ||
                 !PveSystem.SharedIsAllowStructureDamage(weaponCache.Character,
                                                         staticWorldObject,
                                                         showClientNotification: false)))
            {
                return(0);
            }

            if (weaponCache.ProtoObjectExplosive != null &&
                targetObject.ProtoWorldObject is IProtoStaticWorldObject targetStaticWorldObjectProto)
            {
                // special case - apply the explosive damage
                return(ServerCalculateTotalDamageByExplosive(weaponCache.ProtoObjectExplosive,
                                                             targetStaticWorldObjectProto,
                                                             damagePreMultiplier));
            }

            // these two cases apply only if damage dealt not by a bomb
            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 != null &&
                     !damagingCharacter.IsNpc)
            {
                // apply PvE damage multiplier
                totalDamage *= WeaponConstants.DamagePveMultiplier;
            }
            else if (damagingCharacter != null &&
                     damagingCharacter.IsNpc)
            {
                // apply creature damage multiplier
                totalDamage *= WeaponConstants.DamageCreaturesMultiplier;

                if (targetObject is ICharacter victim &&
                    !victim.ServerIsOnline &&
                    !victim.IsNpc)
                {
                    // don't deal creature damage to offline players
                    totalDamage = 0;
                }
            }

            if (isFriendlyFireCase)
            {
                totalDamage *= WeaponConstants.DamageFriendlyFireMultiplier;
            }

            return(totalDamage);
        }