protected virtual void Explode()
        {
            ExplosionCE explosion = GenSpawn.Spawn(CE_ThingDefOf.ExplosionCE, ExactPosition.ToIntVec3(), Map) as ExplosionCE;

            explosion.height     = ExactPosition.y;
            explosion.radius     = def.projectile.explosionRadius;
            explosion.damType    = def.projectile.damageDef;
            explosion.instigator = launcher;
            explosion.damAmount  = def.projectile.GetDamageAmount(1);
            explosion.weapon     = equipmentDef;
            explosion.projectile = def;
            explosion.preExplosionSpawnThingDef            = def.projectile.preExplosionSpawnThingDef;
            explosion.preExplosionSpawnChance              = def.projectile.preExplosionSpawnChance;
            explosion.preExplosionSpawnThingCount          = def.projectile.preExplosionSpawnThingCount;
            explosion.postExplosionSpawnThingDef           = def.projectile.postExplosionSpawnThingDef;
            explosion.postExplosionSpawnChance             = def.projectile.postExplosionSpawnChance;
            explosion.postExplosionSpawnThingCount         = def.projectile.postExplosionSpawnThingCount;
            explosion.applyDamageToExplosionCellsNeighbors = def.projectile.applyDamageToExplosionCellsNeighbors;
            explosion.chanceToStartFire = def.projectile.explosionChanceToStartFire;
            explosion.damageFalloff     = def.projectile.explosionDamageFalloff;
            explosion.StartExplosion(def.projectile.soundExplode);
            explosion.armorPenetration = explosion.damAmount * 0.1f;

            //This code was disabled because it didn't run under previous circumstances. Could be enabled if necessary

            /*
             * if (map != null && base.ExactPosition.ToIntVec3().IsValid)
             * {
             *  ThrowBigExplode(base.ExactPosition + Gen.RandomHorizontalVector(def.projectile.explosionRadius * 0.5f), base.Map, def.projectile.explosionRadius * 0.4f);
             * }
             */

            base.Impact(null); // base.Impact() handles this.Destroy() and comp.Explode()
        }
Exemplo n.º 2
0
        /// <summary>
        /// Produces a secondary explosion on impact using the explosion values from the projectile's projectile def. Requires the projectile's launcher to be passed on due to protection level.
        /// Intended use is for HEAT and similar weapons that spawn secondary explosions while also penetrating, NOT explosive ammo of anti-materiel rifles as the explosion just spawns
        /// on top of the pawn, not inside the hit body part.
        ///
        /// Additionally handles fragmentation effects if defined.
        /// </summary>
        /// <param name="instigator">Launcher of the projectile calling the method</param>
        public virtual void Explode(Thing instigator, Vector3 pos, Map map, float scaleFactor = 1)
        {
            var posIV = pos.ToIntVec3();

            if (map == null)
            {
                Log.Warning("Tried to do explodeCE in a null map.");
                return;
            }
            if (!posIV.InBounds(map))
            {
                Log.Warning("Tried to explodeCE out of bounds");
                return;
            }

            if (!Props.fragments.NullOrEmpty())
            {
                var projCE        = parent as ProjectileCE;
                var edifice       = posIV.GetEdifice(map);
                var edificeHeight = edifice == null ? 0 : new CollisionVertical(edifice).Max;
                var height        = projCE != null?Mathf.Max(edificeHeight, pos.y) : edificeHeight;

                foreach (var fragment in Props.fragments)
                {
                    _monoDummy.GetComponent <MonoDummy>().StartCoroutine(FragRoutine(pos, map, height, instigator, fragment, Props.fragSpeedFactor));
                }
            }

            // Regular explosion stuff
            if (Props.explosionRadius > 0 && Props.explosionDamage > 0 && parent.def != null && GenGrid.InBounds(posIV, map))
            {
                // Copy-paste from GenExplosion
                ExplosionCE explosion = GenSpawn.Spawn(CE_ThingDefOf.ExplosionCE, posIV, map) as ExplosionCE;
                explosion.height     = pos.y;
                explosion.radius     = Props.explosionRadius * scaleFactor;
                explosion.damType    = Props.explosionDamageDef;
                explosion.instigator = instigator;
                explosion.damAmount  = GenMath.RoundRandom(Props.explosionDamage * scaleFactor);
                explosion.weapon     = null;
                explosion.projectile = parent.def;
                explosion.preExplosionSpawnThingDef            = Props.preExplosionSpawnThingDef;
                explosion.preExplosionSpawnChance              = Props.preExplosionSpawnChance;
                explosion.preExplosionSpawnThingCount          = Props.preExplosionSpawnThingCount;
                explosion.postExplosionSpawnThingDef           = Props.postExplosionSpawnThingDef;
                explosion.postExplosionSpawnChance             = Props.postExplosionSpawnChance;
                explosion.postExplosionSpawnThingCount         = Props.postExplosionSpawnThingCount;
                explosion.applyDamageToExplosionCellsNeighbors = Props.applyDamageToExplosionCellsNeighbors;
                explosion.armorPenetration  = explosion.damAmount * 0.1f;
                explosion.damageFalloff     = Props.damageFalloff;
                explosion.chanceToStartFire = Props.chanceToStartFire;
                explosion.StartExplosion(Props.soundExplode ?? Props.explosionDamageDef.soundExplosion);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Produces a secondary explosion on impact using the explosion values from the projectile's projectile def. Requires the projectile's launcher to be passed on due to protection level.
        /// Intended use is for HEAT and similar weapons that spawn secondary explosions while also penetrating, NOT explosive ammo of anti-materiel rifles as the explosion just spawns
        /// on top of the pawn, not inside the hit body part.
        ///
        /// Additionally handles fragmentation effects if defined.
        /// </summary>
        /// <param name="instigator">Launcher of the projectile calling the method</param>
        public virtual void Explode(Thing instigator, Vector3 pos, Map map, float scaleFactor = 1)
        {
            var posIV = pos.ToIntVec3();

            if (map == null)
            {
                Log.Warning("Tried to do explodeCE in a null map.");
                return;
            }
            if (!posIV.InBounds(map))
            {
                Log.Warning("Tried to explodeCE out of bounds");
                return;
            }

            var projCE = parent as ProjectileCE;

            #region Fragmentation
            if (!Props.fragments.NullOrEmpty())
            {
                float   edificeHeight = (new CollisionVertical(posIV.GetEdifice(map))).Max;
                Vector2 exactOrigin   = new Vector2(pos.x, pos.z);
                float   height;

                //Fragments fly from a 0 to 45 degree angle away from the explosion
                var range = new FloatRange(0, Mathf.PI / 8f);

                if (projCE != null)
                {
                    height = Mathf.Max(edificeHeight, pos.y);
                    if (edificeHeight < height)
                    {
                        //If the projectile exploded above the ground, they can fly 45 degree away at the bottom as well
                        range.min = -Mathf.PI / 8f;
                    }
                    // TODO : Check for hitting the bottom or top of a roof
                }
                else
                {
                    //Height is not tracked on non-CE projectiles, so we assume this one's on top of the edifice
                    height = edificeHeight;
                }

                foreach (ThingCountClass fragment in Props.fragments)
                {
                    for (int i = 0; i < fragment.count; i++)
                    {
                        ProjectileCE projectile = (ProjectileCE)ThingMaker.MakeThing(fragment.thingDef, null);
                        GenSpawn.Spawn(projectile, posIV, map);

                        projectile.canTargetSelf   = true;
                        projectile.minCollisionSqr = 1f;
                        //TODO : Don't hardcode at FragmentShadowChance, make XML-modifiable
                        projectile.castShadow = (UnityEngine.Random.value < FragmentShadowChance);
                        projectile.logMisses  = false;
                        projectile.Launch(
                            instigator,
                            exactOrigin,
                            range.RandomInRange,
                            UnityEngine.Random.Range(0, 360),
                            height,
                            Props.fragSpeedFactor * projectile.def.projectile.speed,
                            projCE
                            );
                    }
                }
            }
            #endregion

            // Regular explosion stuff
            if (Props.explosionRadius > 0 && Props.explosionDamage > 0 && parent.def != null && GenGrid.InBounds(posIV, map))
            {
                // Copy-paste from GenExplosion
                ExplosionCE explosion = GenSpawn.Spawn(CE_ThingDefOf.ExplosionCE, posIV, map) as ExplosionCE;
                explosion.height     = pos.y;
                explosion.radius     = Props.explosionRadius * scaleFactor;
                explosion.damType    = Props.explosionDamageDef;
                explosion.instigator = instigator;
                explosion.damAmount  = GenMath.RoundRandom(Props.explosionDamage * scaleFactor);
                explosion.weapon     = null;
                explosion.projectile = parent.def;
                explosion.preExplosionSpawnThingDef            = Props.preExplosionSpawnThingDef;
                explosion.preExplosionSpawnChance              = Props.preExplosionSpawnChance;
                explosion.preExplosionSpawnThingCount          = Props.preExplosionSpawnThingCount;
                explosion.postExplosionSpawnThingDef           = Props.postExplosionSpawnThingDef;
                explosion.postExplosionSpawnChance             = Props.postExplosionSpawnChance;
                explosion.postExplosionSpawnThingCount         = Props.postExplosionSpawnThingCount;
                explosion.applyDamageToExplosionCellsNeighbors = Props.applyDamageToExplosionCellsNeighbors;

                // TODO: for some reason projectile goes to null
                if (parent.def.projectile != null)
                {
                    explosion.chanceToStartFire      = parent.def.projectile.explosionChanceToStartFire;
                    explosion.dealMoreDamageAtCenter = parent.def.projectile.explosionDealMoreDamageAtCenter;
                }
                explosion.StartExplosion(Props.explosionDamageDef.soundExplosion);
            }
        }