예제 #1
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(
                // the delay is quite small and just needed to ensure
                // that the charred ground spawned some time after this object is destroyed
                delaySeconds: explosionPreset.SpriteAnimationDuration * 0.5,
                () =>
            {
                var tilePosition = (Vector2Ushort)epicenterPosition;
                if (!Server.World.GetTile(tilePosition)
                    .StaticObjects
                    .Any(so => so.ProtoStaticWorldObject is ObjectCharredGround))
                {
                    // spawn charred ground
                    var objectCharredGround =
                        Server.World.CreateStaticWorldObject <ObjectCharredGround>(tilePosition);
                    var objectCharredGroundOffset = epicenterPosition - tilePosition.ToVector2D();
                    if (objectCharredGroundOffset != Vector2D.Zero)
                    {
                        ObjectCharredGround.ServerSetWorldOffset(objectCharredGround,
                                                                 objectCharredGroundOffset.ToVector2F());
                    }
                }
            });

            // schedule explosion damage
            ServerTimersSystem.AddAction(
                delaySeconds: explosionPreset.ServerDamageApplyDelay,
                () =>
            {
                // prepare weapon caches
                var characterFinalStatsCache = character != null
                                                       ? 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);
            });
        }
예제 #2
0
        private static double ServerCalculateTotalDamageByExplosive(
            IProtoObjectExplosive protoObjectExplosive,
            IProtoStaticWorldObject targetStaticWorldObjectProto,
            double damagePreMultiplier)
        {
            var damage = protoObjectExplosive.ServerCalculateTotalDamageByExplosive(targetStaticWorldObjectProto);

            damage *= damagePreMultiplier;
            return(damage);
        }
예제 #3
0
        private void ClientRemote_NoDamageToDepositUnderClaimDelay(IProtoGameObject protoObjectExplosive)
        {
            var icon = protoObjectExplosive switch
            {
                IProtoObjectExplosive objectExplosive => objectExplosive.Icon,
                IProtoItem item => item.Icon,
                _ => null
            };

            NotificationSystem.ClientShowNotification(
                string.Format(NotificationNoDamageToDepositUnderCooldown_TitleFormat, this.Name),
                NotificationNoDamageToDepositUnderCooldown_Description,
                color: NotificationColor.Bad,
                icon);
        }
    }
예제 #4
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);
            });
        }
예제 #5
0
 protected abstract void PrepareProtoItemExplosive(
     out IProtoObjectExplosive objectExplosiveProto);
예제 #6
0
        public WeaponFinalCache(
            ICharacter character,
            FinalStatsCache characterFinalStatsCache,
            [CanBeNull] IItem weapon,
            [CanBeNull] IProtoItemWeapon protoWeapon,
            DamageDescription damageDescription,
            IProtoObjectExplosive protoObjectExplosive = null)
        {
            this.Character            = character;
            this.Weapon               = weapon;
            this.ProtoWeapon          = (IProtoItemWeapon)weapon?.ProtoItem ?? protoWeapon;
            this.ProtoObjectExplosive = protoObjectExplosive;

            if (damageDescription == null)
            {
                // TODO: it looks like not implemented yet and we should throw an exception here
                // fallback in case weapon don't provide damage description (such as no-ammo weapon)
                damageDescription = new DamageDescription(
                    damageValue: 0,
                    armorPiercingCoef: 0,
                    finalDamageMultiplier: 1,
                    rangeMax: 0,
                    damageDistribution: new DamageDistribution());
            }

            var descriptionDamages        = damageDescription.DamageProportions;
            var damageDistributionsCount  = descriptionDamages.Count;
            var resultDamageDistributions = new List <DamageProportion>(damageDistributionsCount);

            var totalPercents = 0d;

            for (var index = 0; index < damageDistributionsCount; index++)
            {
                var source   = descriptionDamages[index];
                var statName = this.GetProportionStatName(source.DamageType);
                var resultDamageProportion = source.Proportion + characterFinalStatsCache[statName];
                if (resultDamageProportion <= 0)
                {
                    continue;
                }

                resultDamageDistributions.Add(new DamageProportion(source.DamageType, resultDamageProportion));
                totalPercents += resultDamageProportion;
            }

            if (damageDistributionsCount > 0 &&
                Math.Abs(totalPercents - 1) > 0.001d)
            {
                throw new Exception(
                          "Sum of all damage proportions must be exactly 1. Calculated value: "
                          + totalPercents.ToString("F3"));
            }

            this.DamageDistributions = resultDamageDistributions;

            this.DamageValue = damageDescription.DamageValue * (protoWeapon?.DamageMultiplier ?? 1.0)
                               + characterFinalStatsCache[StatName.DamageAdd];

            if (protoWeapon?.WeaponSkillProto != null)
            {
                var statName = protoWeapon.WeaponSkillProto.StatNameDamageBonusMultiplier;
                this.DamageValue *= characterFinalStatsCache.GetMultiplier(statName);
            }

            this.RangeMax = damageDescription.RangeMax * (protoWeapon?.RangeMultipier ?? 1.0)
                            + characterFinalStatsCache[StatName.AttackRangeMax];

            var armorPiercingCoef = (1 + characterFinalStatsCache[StatName.AttackArmorPiercingMultiplier])
                                    * (damageDescription.ArmorPiercingCoef
                                       * (protoWeapon?.ArmorPiercingMultiplier ?? 1.0)
                                       + characterFinalStatsCache[StatName.AttackArmorPiercingValue]);

            this.InvertedArmorPiercingCoef = 1 - armorPiercingCoef;

            this.FinalDamageMultiplier = damageDescription.FinalDamageMultiplier
                                         + characterFinalStatsCache[StatName.AttackFinalDamageMultiplier];
        }
예제 #7
0
        0;     // no heavy weapon experience, since it is not even a weapon

        protected override void PrepareProtoItemExplosive(
            out IProtoObjectExplosive objectExplosiveProto)
        {
            objectExplosiveProto = GetProtoEntity <ObjectBombMining>();
        }