示例#1
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));
        }
示例#2
0
        protected override void ServerOnStaticObjectDamageApplied(
            WeaponFinalCache weaponCache,
            IStaticWorldObject targetObject,
            float previousStructurePoints,
            float currentStructurePoints)
        {
            var character = weaponCache.Character;

            if (character is not null &&
                !(weaponCache.ProtoWeapon is IProtoItemWeaponRanged) &&
                WorldObjectClaimSystem.SharedIsEnabled)
            {
                this.ServerTryClaimObject(targetObject, character);
            }

            base.ServerOnStaticObjectDamageApplied(weaponCache,
                                                   targetObject,
                                                   previousStructurePoints,
                                                   currentStructurePoints);
        }
示例#3
0
        protected override double SharedCalculateDamageByWeapon(
            WeaponFinalCache weaponCache,
            double damagePreMultiplier,
            IDynamicWorldObject targetObject,
            out double obstacleBlockDamageCoef)
        {
            var damage = base.SharedCalculateDamageByWeapon(weaponCache,
                                                            damagePreMultiplier,
                                                            targetObject,
                                                            out obstacleBlockDamageCoef);

            if (weaponCache.Character?.ProtoGameObject is IProtoCharacterMob protoCharacterMob &&
                protoCharacterMob.IsBoss)
            {
                // for balancing reasons we're increasing damage by boss
                damage *= 1.75;
            }

            return(damage);
        }
示例#4
0
        protected override double SharedCalculateDamageByWeapon(
            WeaponFinalCache weaponCache,
            double damagePreMultiplier,
            IStaticWorldObject targetObject,
            out double obstacleBlockDamageCoef)
        {
            if (IsServer)
            {
                damagePreMultiplier = LandClaimSystem.ServerAdjustDamageToUnprotectedStrongBuilding(weaponCache,
                                                                                                    targetObject,
                                                                                                    damagePreMultiplier);
            }

            var damage = base.SharedCalculateDamageByWeapon(weaponCache,
                                                            damagePreMultiplier,
                                                            targetObject,
                                                            out obstacleBlockDamageCoef);

            return(damage);
        }
        protected virtual double SharedCalculateDamageByWeapon(
            WeaponFinalCache weaponCache,
            double damagePreMultiplier,
            IDynamicWorldObject targetObject,
            out double obstacleBlockDamageCoef)
        {
            obstacleBlockDamageCoef = this.ObstacleBlockDamageCoef;
            if (IsClient)
            {
                // we don't apply any damage on the Client-side
                return(0);
            }

            return(WeaponDamageSystem.ServerCalculateTotalDamage(
                       weaponCache,
                       targetObject,
                       this.DefenseStats,
                       damagePreMultiplier,
                       clampDefenseTo1: false));
        }
示例#6
0
 public override void ServerExecuteExplosion(
     Vector2D positionEpicenter,
     IPhysicsSpace physicsSpace,
     WeaponFinalCache weaponFinalCache)
 {
     WeaponExplosionSystem.ServerProcessExplosionCircle(
         positionEpicenter: positionEpicenter,
         physicsSpace: physicsSpace,
         damageDistanceMax: this.DamageRadius,
         weaponFinalCache: weaponFinalCache,
         damageOnlyDynamicObjects: true,
         isDamageThroughObstacles: this.IsDamageThroughObstacles,
         callbackCalculateDamageCoefByDistanceForStaticObjects:
         this.ServerCalculateDamageCoefByDistanceForStaticObjects,
         callbackCalculateDamageCoefByDistanceForDynamicObjects: this
         .ServerCalculateDamageCoefByDistanceForDynamicObjects,
         // Missiles are falling from the sky and the explosion circles are clearly designated.
         // Players expecting that they will be not damaged when they stand outside the circles.
         collisionGroups: new[] { CollisionGroup.Default });
 }
        public override bool SharedOnDamage(
            WeaponFinalCache weaponCache,
            IStaticWorldObject targetObject,
            double damagePreMultiplier,
            out double obstacleBlockDamageCoef,
            out double damageApplied)
        {
            if (weaponCache.Character != null)
            {
                // damaged by character
                if (IsServer)
                {
                    // notify other characters
                    using (var tempList = Api.Shared.GetTempList <ICharacter>())
                    {
                        ServerWorld.GetScopedByPlayers(targetObject, tempList);
                        tempList.Remove(weaponCache.Character);
                        this.CallClient(tempList, _ => _.ClientRemote_OnHit());
                    }
                }
                else
                {
                    ClientOnHit();
                }
            }

            if (weaponCache.ProtoWeapon != null &&
                !(weaponCache.ProtoWeapon is IProtoItemWeaponMelee))
            {
                // hit but not damaged - only melee weapons (including pickaxes can damage this)
                obstacleBlockDamageCoef = this.ObstacleBlockDamageCoef;
                damageApplied           = 0;
                return(true);
            }

            return(base.SharedOnDamage(weaponCache,
                                       targetObject,
                                       damagePreMultiplier,
                                       out obstacleBlockDamageCoef,
                                       out damageApplied));
        }
示例#8
0
        protected override double SharedCalculateDamageByWeapon(
            WeaponFinalCache weaponCache,
            double damagePreMultiplier,
            IStaticWorldObject targetObject,
            out double obstacleBlockDamageCoef)
        {
            if (weaponCache.ProtoWeapon is IProtoItemToolMining protoItemToolMining)
            {
                // mining mineral with a mining device
                // block next damage completely - only one mineral could be mined at once
                obstacleBlockDamageCoef = 1;

                // get damage multiplier ("mining speed")
                var damageMultiplier = weaponCache.Character
                                       .SharedGetFinalStatMultiplier(StatName.MiningSpeed);

                return(protoItemToolMining.DamageToMinerals
                       * damageMultiplier
                       * ToolsConstants.ActionMiningSpeedMultiplier);
            }

            if (weaponCache.ProtoWeapon is ItemNoWeapon)
            {
                // no damage with hands
                obstacleBlockDamageCoef = 1;

                if (IsClient)
                {
                    NotificationSystem.ClientShowNotification(NotificationUsePickaxe,
                                                              icon: this.Icon);
                }

                return(0);
            }

            // not a mining tool - call default damage apply method
            return(base.SharedCalculateDamageByWeapon(weaponCache,
                                                      damagePreMultiplier,
                                                      targetObject,
                                                      out obstacleBlockDamageCoef));
        }
        protected override double SharedCalculateDamageByWeapon(
            WeaponFinalCache weaponCache,
            double damagePreMultiplier,
            IStaticWorldObject targetObject,
            out double obstacleBlockDamageCoef)
        {
            if (weaponCache.ProtoWeapon is ItemNoWeapon)
            {
                // no damage with hands
                obstacleBlockDamageCoef = 1;

                if (IsClient)
                {
                    NotificationSystem.ClientShowNotification(NotificationUseWeaponOrTool,
                                                              icon: this.Icon);
                }

                return(0);
            }

            if (!weaponCache.ProtoWeapon?.CanDamageStructures ?? false)
            {
                // probably a mob weapon
                obstacleBlockDamageCoef = 1;
                return(0);
            }

            if (IsServer &&
                !(this is ProtoObjectConstructionSite))
            {
                damagePreMultiplier = LandClaimSystem.ServerAdjustDamageToUnclaimedBuilding(weaponCache,
                                                                                            targetObject,
                                                                                            damagePreMultiplier);
            }

            return(base.SharedCalculateDamageByWeapon(weaponCache,
                                                      damagePreMultiplier,
                                                      targetObject,
                                                      out obstacleBlockDamageCoef));
        }
示例#10
0
        protected override void ServerOnStaticObjectZeroStructurePoints(
            WeaponFinalCache weaponCache,
            ICharacter byCharacter,
            IWorldObject targetObject)
        {
            // do not use default implementation because it will destroy the object automatically
            //base.ServerOnStaticObjectZeroStructurePoints(weaponCache, targetObject);

            var worldObject = (IStaticWorldObject)targetObject;
            var publicState = GetPublicState(worldObject);

            if (byCharacter != null &&
                (LandClaimSystem.ServerIsOwnedArea(publicState.LandClaimAreaObject, byCharacter) ||
                 CreativeModeSystem.SharedIsInCreativeMode(byCharacter)))
            {
                // this is the owner of the area or the player is in a creative mode
                if (byCharacter.SharedGetPlayerSelectedHotbarItemProto() is ProtoItemToolCrowbar)
                {
                    publicState.ServerTimeForDestruction = 0;
                    Logger.Important(
                        $"Land claim object {targetObject} destroyed by the owner with a crowbar - no destruction timer",
                        byCharacter);

                    this.ServerForceUpdate(worldObject, publicState);
                    return;
                }
            }

            if (publicState.ServerTimeForDestruction.HasValue)
            {
                // destruction timer is already set
                return;
            }

            // the land claim structure points is zero - it's broken now - set timer for destruction
            publicState.ServerTimeForDestruction = Server.Game.FrameTime
                                                   + this.DestructionTimeout.TotalSeconds;
            Logger.Important($"Timer for destruction set: {targetObject}. Timeout: {this.DestructionTimeout}");
            this.ServerForceUpdate(worldObject, publicState);
        }
示例#11
0
        public override void ServerOnObjectHitByExplosion(
            IWorldObject worldObject,
            double damage,
            WeaponFinalCache weaponCache)
        {
            base.ServerOnObjectHitByExplosion(worldObject, damage, weaponCache);

            if (worldObject is ICharacter character)
            {
                if (damage >= 5)
                {
                    character.ServerAddStatusEffect <StatusEffectDazed>(intensity: 0.5);
                }
            }
            else if (worldObject is IDynamicWorldObject dynamicWorldObject &&
                     dynamicWorldObject.ProtoGameObject is IProtoVehicle protoVehicle)
            {
                // apply additional vehicle damage
                var vehicleDamage = damage * VehicleAdditionalDamageMultiplier;
                protoVehicle.ServerApplyDamage(dynamicWorldObject, vehicleDamage);
            }
        }
示例#12
0
        public override bool SharedOnDamage(
            WeaponFinalCache weaponCache,
            IStaticWorldObject targetObject,
            double damagePreMultiplier,
            out double obstacleBlockDamageCoef,
            out double damageApplied)
        {
            if (weaponCache.ProtoObjectExplosive != null)
            {
                // accept explosive damage
                return(base.SharedOnDamage(weaponCache,
                                           targetObject,
                                           damagePreMultiplier,
                                           out obstacleBlockDamageCoef,
                                           out damageApplied));
            }

            // only damage from explosives is accepted
            obstacleBlockDamageCoef = 0;
            damageApplied           = 0; // no damage
            return(false);               // no hit
        }
        public override bool SharedOnDamage(
            WeaponFinalCache weaponCache,
            IStaticWorldObject targetObject,
            double damagePreMultiplier,
            out double obstacleBlockDamageCoef,
            out double damageApplied)
        {
            if (IsServer)
            {
                // an explosive object was damaged
                var privateState = GetPrivateState(targetObject);
                if (privateState.ExplosionDelaySecondsRemains > 0.1)
                {
                    // explode soon!
                    privateState.ExplosionDelaySecondsRemains = 0.1;
                }
            }

            obstacleBlockDamageCoef = 0;
            damageApplied           = 0; // no damage
            return(false);               // no hit
        }
        public override bool SharedOnDamage(
            WeaponFinalCache weaponCache,
            IWorldObject targetObject,
            double damagePreMultiplier,
            out double obstacleBlockDamageCoef,
            out double damageApplied)
        {
            if (IsServer &&
                (!weaponCache.Character?.IsNpc ?? false))
            {
                var mobPrivateState = GetPrivateState((ICharacter)targetObject);
                mobPrivateState.CurrentAgroCharacter = weaponCache.Character;
                //Logger.Dev(
                //    $"Mob damaged by player, let's agro: {targetObject} by {mobPrivateState.CurrentAgroCharacter}");
            }

            return(base.SharedOnDamage(weaponCache,
                                       targetObject,
                                       damagePreMultiplier,
                                       out obstacleBlockDamageCoef,
                                       out damageApplied));
        }
示例#15
0
        public override bool SharedOnDamage(
            WeaponFinalCache weaponCache,
            IStaticWorldObject targetObject,
            double damagePreMultiplier,
            out double obstacleBlockDamageCoef,
            out double damageApplied)
        {
            if (IsServer)
            {
                LandClaimSystem.ServerOnRaid(targetObject.Bounds,
                                             weaponCache.Character,
                                             isShort: this.IsShortRaidblockOnHit);
            }

            var publicState             = GetPublicState(targetObject);
            var previousStructurePoints = publicState.StructurePointsCurrent;

            if (previousStructurePoints <= 0f)
            {
                // already destroyed land claim object (waiting for the destroy timer)
                obstacleBlockDamageCoef = this.ObstacleBlockDamageCoef;
                damageApplied           = 0;

                if (IsServer &&
                    weaponCache.Character != null)
                {
                    var areaPrivateState = LandClaimArea.GetPrivateState(publicState.LandClaimAreaObject);
                    areaPrivateState.IsDestroyedByPlayers = true;
                }

                return(true);
            }

            return(base.SharedOnDamage(weaponCache,
                                       targetObject,
                                       damagePreMultiplier,
                                       out obstacleBlockDamageCoef,
                                       out damageApplied));
        }
示例#16
0
        protected override void ServerOnStaticObjectZeroStructurePoints(
            WeaponFinalCache weaponCache,
            ICharacter byCharacter,
            IWorldObject targetObject)
        {
            base.ServerOnStaticObjectZeroStructurePoints(weaponCache, byCharacter, targetObject);

            if (weaponCache == null ||
                (weaponCache.ProtoWeapon == null &&
                 weaponCache.ProtoObjectExplosive == null) ||
                PveSystem.ServerIsPvE)
            {
                return;
            }

            // the damage was dealt by a weapon or explosive - try to explode the deposit
            var worldObjectDeposit = this.SharedGetDepositWorldObject(
                Server.World.GetTile(targetObject.TilePosition));

            ((IProtoObjectDeposit)worldObjectDeposit?.ProtoStaticWorldObject)?
            .ServerOnExtractorDestroyedForDeposit(worldObjectDeposit);
        }
示例#17
0
        public override void SharedOnHit(
            WeaponFinalCache weaponCache,
            IWorldObject damagedObject,
            double damage,
            WeaponHitData hitData,
            out bool isDamageStop)
        {
            if (damagedObject is ICharacter)
            {
                base.SharedOnHit(weaponCache, damagedObject, damage, hitData, out isDamageStop);
            }

            // make arrows to always stop on the first hit and have a chance to drop on the ground
            isDamageStop = true;

            if (IsServer &&
                isDamageStop &&
                RandomHelper.NextDouble() <= 2 / 3.0)    // 2/3 chance to recover the arrow
            {
                this.ServerCreateDroppedArrow(weaponCache,
                                              hitData.FallbackTilePosition.ToVector2D() + hitData.HitPoint);
            }
        }
示例#18
0
        public override bool SharedOnDamage(
            WeaponFinalCache weaponCache,
            IWorldObject targetObject,
            double damagePreMultiplier,
            double damagePostMultiplier,
            out double obstacleBlockDamageCoef,
            out double damageApplied)
        {
            var result = base.SharedOnDamage(weaponCache, targetObject, damagePreMultiplier, damagePostMultiplier, out obstacleBlockDamageCoef, out damageApplied);

            if (!result)
            {
                return(false);
            }

            if (IsClient)
            {
                return(true);
            }

            ObjectMineralPragmiumSource.ServerTryClaimPragmiumClusterNearCharacter(weaponCache.Character);
            return(true);
        }
示例#19
0
        public override void SharedOnHit(
            WeaponFinalCache weaponCache,
            IWorldObject damagedObject,
            double damage,
            WeaponHitData hitData,
            out bool isDamageStop)
        {
            base.SharedOnHit(weaponCache,
                             damagedObject,
                             damage,
                             hitData,
                             out isDamageStop);

            if (IsServer &&
                damage > 0 &&
                damagedObject is ICharacter damagedCharacter)
            {
                // guaranteed small toxin effect per hit
                // (please note the addition formula inside the Toxins effect class is NOT linear
                //  so subsequent hits increasing it on less than 20%)
                damagedCharacter.ServerAddStatusEffect <StatusEffectToxins>(intensity: 0.2);
            }
        }
        protected virtual void ServerOnStaticObjectZeroStructurePoints(
            [CanBeNull] WeaponFinalCache weaponCache,
            [CanBeNull] ICharacter byCharacter,
            [NotNull] IWorldObject targetObject)
        {
            if (targetObject.IsDestroyed)
            {
                return;
            }

            Logger.Info($"Static object destroyed: {targetObject} by {byCharacter}");

            this.ServerSendObjectDestroyedEvent(targetObject);
            Server.World.DestroyObject(targetObject);

            if (weaponCache != null)
            {
                this.ServerOnStaticObjectDestroyedByCharacter(
                    byCharacter,
                    weaponCache.ProtoWeapon,
                    (IStaticWorldObject)targetObject);
            }
        }
示例#21
0
        protected override double SharedCalculateDamageByWeapon(
            WeaponFinalCache weaponCache,
            double damagePreMultiplier,
            IStaticWorldObject targetObject,
            out double obstacleBlockDamageCoef)
        {
            if (NewbieProtectionSystem.SharedIsNewbie(weaponCache.Character))
            {
                // don't allow mining a boss loot while under newbie protection
                if (IsClient)
                {
                    NewbieProtectionSystem.ClientNotifyNewbieCannotPerformAction(this);
                }

                obstacleBlockDamageCoef = 0;
                return(0);
            }

            return(base.SharedCalculateDamageByWeapon(weaponCache,
                                                      damagePreMultiplier,
                                                      targetObject,
                                                      out obstacleBlockDamageCoef));
        }
示例#22
0
        protected override double SharedCalculateDamageByWeapon(
            WeaponFinalCache weaponCache,
            double damagePreMultiplier,
            IStaticWorldObject targetObject,
            out double obstacleBlockDamageCoef)
        {
            if (weaponCache.ProtoWeapon is IProtoItemToolWoodcutting protoItemToolWoodCutting)
            {
                obstacleBlockDamageCoef = 1;

                // get damage multiplier ("woodcutting speed")
                var damageMultiplier = weaponCache.Character
                                       .SharedGetFinalStatMultiplier(StatName.WoodcuttingSpeed);

                return(protoItemToolWoodCutting.DamageToTree * damageMultiplier);
            }

            if (weaponCache.ProtoWeapon is ItemNoWeapon)
            {
                // no damage with hands
                obstacleBlockDamageCoef = 1;

                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));
        }
示例#23
0
        protected override void ServerOnStaticObjectZeroStructurePoints(
            WeaponFinalCache weaponCache,
            ICharacter byCharacter,
            IWorldObject targetObject)
        {
            base.ServerOnStaticObjectZeroStructurePoints(weaponCache, byCharacter, targetObject);

            if (weaponCache is null ||
                (weaponCache.ProtoWeapon is null &&
                 weaponCache.ProtoExplosive is null) ||
                PveSystem.ServerIsPvE)
            {
                return;
            }

            // explode
            var tilePosition = targetObject.TilePosition;

            Server.World.CreateStaticWorldObject <ObjectDepositExplosion>(tilePosition);

            // the damage was dealt by a weapon or explosive - try to explode the deposit
            var worldObjectDeposit = this.SharedGetDepositWorldObject(
                Server.World.GetTile(tilePosition));

            if (worldObjectDeposit is not null)
            {
                ((IProtoObjectDeposit)worldObjectDeposit.ProtoStaticWorldObject)
                .ServerOnExtractorDestroyedForDeposit(worldObjectDeposit);
            }
            else
            {
                // create charred ground at the center of the explosion
                Server.World.CreateStaticWorldObject(GetProtoEntity <ObjectCharredGround1>(),
                                                     (tilePosition + this.Layout.Center.ToVector2Int())
                                                     .ToVector2Ushort());
            }
        }
示例#24
0
        public override void ServerExecuteExplosion(
            Vector2D positionEpicenter,
            IPhysicsSpace physicsSpace,
            WeaponFinalCache weaponFinalCache)
        {
            WeaponExplosionSystem.ServerProcessExplosionCircle(
                positionEpicenter: positionEpicenter,
                physicsSpace: physicsSpace,
                damageDistanceMax: this.DamageRadius,
                weaponFinalCache: weaponFinalCache,
                damageOnlyDynamicObjects: true,
                isDamageThroughObstacles: this.IsDamageThroughObstacles,
                callbackCalculateDamageCoefByDistanceForStaticObjects:
                this.ServerCalculateDamageCoefByDistanceForStaticObjects,
                callbackCalculateDamageCoefByDistanceForDynamicObjects: this
                .ServerCalculateDamageCoefByDistanceForDynamicObjects,
                // Missiles are falling from the sky and the explosion circles are clearly designated.
                // Players are expecting that they will be not damaged when they stand outside the circles.
                collisionGroups: new[] { CollisionGroups.Default });

            // this is only for hoverboards as hoverboards on the ground have no physical collider
            WeaponExplosionSystem.ServerProcessExplosionCircle(
                positionEpicenter: positionEpicenter,
                physicsSpace: physicsSpace,
                damageDistanceMax: this.DamageRadius,
                weaponFinalCache: weaponFinalCache,
                damageOnlyDynamicObjects: true,
                isDamageThroughObstacles: this.IsDamageThroughObstacles,
                callbackCalculateDamageCoefByDistanceForStaticObjects:
                this.ServerCalculateDamageCoefByDistanceForStaticObjects,
                callbackCalculateDamageCoefByDistanceForDynamicObjects: this
                .ServerCalculateDamageCoefByDistanceForDynamicObjects,
                // this is only for hoverboards
                collisionGroups: new[] { CollisionGroups.HitboxMelee },
                // can damage only hoverboards
                filterCanDamage: worldObject => worldObject.ProtoGameObject is IProtoVehicleHoverboard);
        }
示例#25
0
        protected override void ServerOnDynamicObjectZeroStructurePoints(
            WeaponFinalCache weaponCache,
            ICharacter byCharacter,
            IWorldObject targetObject)
        {
            var vehicle = (IDynamicWorldObject)targetObject;

            // explode
            using var scopedBy = Api.Shared.GetTempList <ICharacter>();
            Server.World.GetCharactersInRadius(vehicle.TilePosition,
                                               scopedBy,
                                               radius: this.DestroyedExplosionRadius,
                                               onlyPlayers: true);

            this.CallClient(scopedBy.AsList(),
                            _ => _.ClientRemote_VehicleExploded(vehicle.Position));

            ExplosionHelper.ServerExplode(
                character:
                null, // yes, no damaging character here otherwise it will not receive the damage if staying close
                protoExplosive: null,
                protoWeapon: null,
                explosionPreset: this.DestroyedExplosionPreset,
                epicenterPosition: vehicle.Position
                + this.SharedGetObjectCenterWorldOffset(targetObject),
                damageDescriptionCharacters: this.DestroyedVehicleDamageDescriptionCharacters,
                physicsSpace: targetObject.PhysicsBody.PhysicsSpace,
                executeExplosionCallback: this.ServerExecuteVehicleExplosion);

            // destroy the vehicle completely after short explosion delay
            ServerTimersSystem.AddAction(
                this.DestroyedExplosionPreset.ServerDamageApplyDelay,
                () => base.ServerOnDynamicObjectZeroStructurePoints(weaponCache,
                                                                    byCharacter,
                                                                    targetObject));
        }
示例#26
0
        protected virtual void ServerExecuteExplosion(
            Vector2D positionEpicenter,
            IPhysicsSpace physicsSpace,
            WeaponFinalCache weaponFinalCache)
        {
            WeaponExplosionSystem.ServerProcessExplosionCircle(
                positionEpicenter: positionEpicenter,
                physicsSpace: physicsSpace,
                damageDistanceMax: this.DamageRadius,
                weaponFinalCache: weaponFinalCache,
                damageOnlyDynamicObjects: false,
                isDamageThroughObstacles: false,
                callbackCalculateDamageCoefByDistanceForStaticObjects: CalcDamageCoefByDistance,
                callbackCalculateDamageCoefByDistanceForDynamicObjects: CalcDamageCoefByDistance,
                collisionGroup: CollisionGroups.HitboxRanged);

            double CalcDamageCoefByDistance(double distance)
            {
                var distanceThreshold = 0.5;

                if (distance <= distanceThreshold)
                {
                    return(1);
                }

                distance -= distanceThreshold;
                distance  = Math.Max(0, distance);

                var maxDistance = this.DamageRadius;

                maxDistance -= distanceThreshold;
                maxDistance  = Math.Max(0, maxDistance);

                return(1 - Math.Min(distance / maxDistance, 1));
            }
        }
        public override void SharedOnHit(WeaponFinalCache weaponCache, IWorldObject damagedObject, double damage, WeaponHitData hitData, out bool isDamageStop)
        {
            weaponCache.AllowNpcToNpcDamage = true;

            base.SharedOnHit(weaponCache, damagedObject, damage, hitData, out isDamageStop);
        }
示例#28
0
        private void ServerOnMineralStageMined(
            WeaponFinalCache weaponCache,
            IStaticWorldObject mineralObject,
            int damageStage)
        {
            var byCharacter   = weaponCache.Character;
            var byWeaponProto = weaponCache.ProtoWeapon;

            Logger.Info(
                $"{mineralObject} current damage stage changed to {damageStage}. Dropping items for that stage",
                byCharacter);

            try
            {
                var dropItemsList   = this.DropItemsConfig.GetForStage(damageStage);
                var dropItemContext = new DropItemContext(byCharacter,
                                                          mineralObject,
                                                          byWeaponProto,
                                                          weaponCache.ProtoExplosive);
                var probabilityMultiplier = this.ServerGetDropListProbabilityMultiplier(mineralObject);

                var objectDrone = weaponCache.Drone;
                if (objectDrone is not null)
                {
                    // drop resources into the internal storage of the drone
                    var storageItemsContainer = ((IProtoDrone)objectDrone.ProtoGameObject)
                                                .ServerGetStorageItemsContainer(objectDrone);
                    dropItemsList.TryDropToContainer(storageItemsContainer,
                                                     dropItemContext,
                                                     probabilityMultiplier: probabilityMultiplier);
                }
                else if (byWeaponProto is IProtoItemWeaponMelee)
                {
                    var result = dropItemsList.TryDropToCharacterOrGround(
                        byCharacter,
                        (mineralObject.TilePosition.ToVector2D() + this.Layout.Center).ToVector2Ushort(),
                        dropItemContext,
                        probabilityMultiplier: probabilityMultiplier,
                        groundContainer: out _);
                    if (result.TotalCreatedCount > 0)
                    {
                        NotificationSystem.ServerSendItemsNotification(byCharacter, result);
                    }
                }
                else
                {
                    // not a melee weapon or cannot drop to the character inventory - drop on the ground only
                    dropItemsList.TryDropToGround(
                        (mineralObject.TilePosition.ToVector2D() + this.Layout.Center).ToVector2Ushort(),
                        dropItemContext,
                        out _,
                        probabilityMultiplier: probabilityMultiplier);
                }
            }
            finally
            {
                if (byWeaponProto is IProtoItemToolMining ||
                    weaponCache.ProtoExplosive is ObjectBombMining)
                {
                    // add experience proportional to the mineral structure points (effectively - for the time spent on mining)
                    var exp = SkillProspecting.ExperienceAddPerStructurePoint;
                    exp *= this.StructurePointsMax / this.DamageStagesCount;
                    byCharacter?.ServerAddSkillExperience <SkillProspecting>(exp);
                }

                this.ServerOnMineralStageMined(byCharacter, mineralObject);
            }
        }
示例#29
0
        public static void ServerExplode(
            [CanBeNull] ICharacter character,
            [CanBeNull] IProtoObjectExplosive protoObjectExplosive,
            ExplosionPreset explosionPreset,
            Vector2D epicenterPosition,
            DamageDescription damageDescriptionCharacters,
            IPhysicsSpace physicsSpace,
            ExecuteExplosionDelegate executeExplosionCallback)
        {
            ValidateIsServer();

            // schedule explosion charred ground spawning
            ServerTimersSystem.AddAction(
                delaySeconds: explosionPreset.SpriteAnimationDuration * 0.5,
                () =>
            {
                var tilePosition = (Vector2Ushort)epicenterPosition;

                // remove existing charred ground objects at the same tile
                foreach (var staticWorldObject in Shared.WrapInTempList(
                             Server.World.GetTile(tilePosition).StaticObjects))
                {
                    if (staticWorldObject.ProtoStaticWorldObject is ObjectCharredGround)
                    {
                        Server.World.DestroyObject(staticWorldObject);
                    }
                }

                // spawn charred ground
                var objectCharredGround = Server.World
                                          .CreateStaticWorldObject <ObjectCharredGround>(tilePosition);
                var objectCharredGroundOffset = epicenterPosition - tilePosition.ToVector2D();
                if (objectCharredGroundOffset != Vector2D.Zero)
                {
                    ObjectCharredGround.ServerSetWorldOffset(objectCharredGround,
                                                             (Vector2F)objectCharredGroundOffset);
                }
            });

            // schedule explosion damage
            ServerTimersSystem.AddAction(
                delaySeconds: explosionPreset.ServerDamageApplyDelay,
                () =>
            {
                // prepare weapon caches
                var characterFinalStatsCache = character?.SharedGetFinalStatsCache()
                                               ?? FinalStatsCache.Empty;

                var weaponFinalCache = new WeaponFinalCache(character,
                                                            characterFinalStatsCache,
                                                            weapon: null,
                                                            protoWeapon: null,
                                                            protoObjectExplosive: protoObjectExplosive,
                                                            damageDescription: damageDescriptionCharacters);

                // execute explosion
                executeExplosionCallback(
                    positionEpicenter: epicenterPosition,
                    physicsSpace: physicsSpace,
                    weaponFinalCache: weaponFinalCache);
            });
        }
示例#30
0
 public sealed override void ClientOnMiss(WeaponFinalCache weaponCache, Vector2D endPosition)
 {
     this.ClientExplodeAt(weaponCache, endPosition);
 }