Пример #1
0
        public virtual void Explode(Thing instigator, Vector3 pos, Map map, float scaleFactor = 1, float?direction = null, List <Thing> ignoredThings = null)
        {
            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;
            }

            //Try to throw fragments -- increase count by scaleFactor
            parent.TryGetComp <CompFragments>()?.Throw(pos, map, instigator);//scaleFactor);

            if (Props.explosiveRadius > 0 && //&& Props.damageAmountBase > 0 Disabled to allow flame explosions etc
                parent.def != null)
            {
                //Call GenExplosionCE for main explosion
                GenExplosionCE.DoExplosion(posIV, map, Props.explosiveRadius, Props.explosiveDamageType, instigator,
                                           GenMath.RoundRandom(Props.damageAmountBase), Props.damageAmountBase * 0.1f,
                                           Props.explosionSound, null, parent.def, null,
                                           Props.postExplosionSpawnThingDef, Props.postExplosionSpawnChance, Props.postExplosionSpawnThingCount,
                                           Props.applyDamageToExplosionCellsNeighbors, Props.preExplosionSpawnThingDef, Props.preExplosionSpawnChance,
                                           Props.preExplosionSpawnThingCount, Props.chanceToStartFire, Props.damageFalloff, direction, ignoredThings,
                                           pos.y, scaleFactor);
            }
        }
Пример #2
0
        private bool TryDetonate(float stackCountScale = 1)
        {
            if (Find.Maps.IndexOf(Map) < 0)
            {
                return(false);
            }

            CompExplosiveCE comp     = this.TryGetComp <CompExplosiveCE>();
            var             detProps = AmmoDef?.detonateProjectile?.projectile;

            if (comp != null || detProps != null)
            {
                if (Rand.Chance(Mathf.Clamp01(0.75f - Mathf.Pow(HitPoints / MaxHitPoints, 2))))
                {
                    if (comp != null)
                    {
                        comp.Explode(this, Position.ToVector3Shifted(), Map, Mathf.Pow(stackCountScale, 0.333f), null, new List <Thing>()
                        {
                            this
                        });
                    }
                    else
                    {
                        this.TryGetComp <CompFragments>()?.Throw(Position.ToVector3Shifted(), Map, this); //Mathf.Pow(scale, 0.333f));
                    }
                    if (detProps != null)
                    {
                        GenExplosionCE.DoExplosion(Position, Map, detProps.explosionRadius, detProps.damageDef,
                                                   this, detProps.GetDamageAmount(1), GenExplosionCE.GetExplosionAP(detProps),
                                                   detProps.soundExplode,
                                                   null, def, null, detProps.postExplosionSpawnThingDef, detProps.postExplosionSpawnChance,
                                                   detProps.postExplosionSpawnThingCount, detProps.applyDamageToExplosionCellsNeighbors,
                                                   detProps.preExplosionSpawnThingDef, detProps.preExplosionSpawnChance, detProps.preExplosionSpawnThingCount,
                                                   detProps.explosionChanceToStartFire, detProps.explosionDamageFalloff, null, new List <Thing>()
                        {
                            this
                        }, 0f, Mathf.Pow(stackCountScale, 0.333f));
                    }
                }

                return(true);
            }
            return(false);
        }
Пример #3
0
        protected virtual void Impact(Thing hitThing)
        {
            var ignoredThings = new List <Thing>();

            //Spawn things from preExplosionSpawnThingDef != null
            if (Position.IsValid &&
                def.projectile.preExplosionSpawnChance > 0 &&
                def.projectile.preExplosionSpawnThingDef != null &&
                (Controller.settings.EnableAmmoSystem || !(def.projectile.preExplosionSpawnThingDef is AmmoDef)) &&
                Rand.Value < def.projectile.preExplosionSpawnChance)
            {
                var thingDef = def.projectile.preExplosionSpawnThingDef;

                if (thingDef.IsFilth && Position.Walkable(Map))
                {
                    FilthMaker.TryMakeFilth(Position, Map, thingDef);
                }
                else if (Controller.settings.ReuseNeolithicProjectiles)
                {
                    var reusableAmmo = ThingMaker.MakeThing(thingDef);
                    reusableAmmo.stackCount = 1;
                    reusableAmmo.SetForbidden(true, false);
                    GenPlace.TryPlaceThing(reusableAmmo, Position, Map, ThingPlaceMode.Near);
                    LessonAutoActivator.TeachOpportunity(CE_ConceptDefOf.CE_ReusableNeolithicProjectiles, reusableAmmo, OpportunityType.GoodToKnow);
                    ignoredThings.Add(reusableAmmo);
                }
            }

            var explodePos = hitThing?.DrawPos ?? ExactPosition;

            if (!explodePos.ToIntVec3().IsValid)
            {
                Destroy();
                return;
            }

            var explodingComp = this.TryGetComp <CompExplosiveCE>();

            if (explodingComp == null)
            {
                this.TryGetComp <CompFragments>()?.Throw(explodePos, Map, launcher);
            }

            //If the comp exists, it'll already call CompFragments
            if (explodingComp != null || def.projectile.explosionRadius > 0)
            {
                //Handle anything explosive

                if (hitThing is Pawn && (hitThing as Pawn).Dead)
                {
                    ignoredThings.Add((hitThing as Pawn).Corpse);
                }

                var suppressThings = new List <Pawn>();
                var dir            = new float?(origin.AngleTo(Vec2Position()));

                // Opt-out for things without explosionRadius
                if (def.projectile.explosionRadius > 0)
                {
                    GenExplosionCE.DoExplosion(explodePos.ToIntVec3(), Map, def.projectile.explosionRadius,
                                               def.projectile.damageDef, launcher, def.projectile.GetDamageAmount(1), def.projectile.GetDamageAmount(1) * 0.1f,
                                               def.projectile.soundExplode, equipmentDef,
                                               def, null, def.projectile.postExplosionSpawnThingDef, def.projectile.postExplosionSpawnChance, def.projectile.postExplosionSpawnThingCount,
                                               def.projectile.applyDamageToExplosionCellsNeighbors, def.projectile.preExplosionSpawnThingDef, def.projectile.preExplosionSpawnChance,
                                               def.projectile.preExplosionSpawnThingCount, def.projectile.explosionChanceToStartFire, def.projectile.explosionDamageFalloff,
                                               dir, ignoredThings, explodePos.y);

                    // Apply suppression around impact area
                    if (explodePos.y < SuppressionRadius)
                    {
                        suppressThings.AddRange(GenRadial.RadialDistinctThingsAround(explodePos.ToIntVec3(), Map, SuppressionRadius + def.projectile.explosionRadius, true)
                                                .Where(x => x is Pawn).Select(x => x as Pawn));
                    }
                }

                if (explodingComp != null)
                {
                    explodingComp.Explode(this, explodePos, Map, 1f, dir, ignoredThings);

                    if (explodePos.y < SuppressionRadius)
                    {
                        suppressThings.AddRange(GenRadial.RadialDistinctThingsAround(explodePos.ToIntVec3(), Map, SuppressionRadius + (explodingComp.props as CompProperties_ExplosiveCE).explosiveRadius, true)
                                                .Where(x => x is Pawn).Select(x => x as Pawn));
                    }
                }

                foreach (var thing in suppressThings)
                {
                    ApplySuppression(thing as Pawn);
                }
            }

            Destroy();
        }
Пример #4
0
        /// <summary>
        ///     Generates a readout text for a projectile with the damage amount, type, secondary explosion and other CE stats for
        ///     display in info-box
        /// </summary>
        /// <param name="projectileDef">The projectile's ThingDef</param>
        /// <returns>Formatted string listing projectile stats</returns>
        public static string GetProjectileReadout(this ThingDef projectileDef, Thing weapon)
        {
            // Append ammo stats
            var props = projectileDef?.projectile as ProjectilePropertiesCE;

            if (props == null)
            {
                Log.Error("CE tried getting projectile readout with null props");
                return("");
            }

            var stringBuilder = new StringBuilder();

            // Damage type/amount
            var dmgList = "   " + "CE_DescDamage".Translate() + ": ";

            if (!props.secondaryDamage.NullOrEmpty())
            {
                // If we have multiple damage types, put every one in its own line
                stringBuilder.AppendLine(dmgList);
                stringBuilder.AppendLine("   " + GenText.ToStringByStyle(props.GetDamageAmount(weapon), ToStringStyle.Integer) + " (" + props.damageDef.LabelCap + ")");
                foreach (var sec in props.secondaryDamage)
                {
                    var secondaryChance = sec.chance >= 1.0f ? "" : $"({GenText.ToStringByStyle(sec.chance, ToStringStyle.PercentZero)} {"CE_Chance".Translate()})";
                    stringBuilder.AppendLine($"   {GenText.ToStringByStyle(sec.amount, ToStringStyle.Integer)} ({sec.def.LabelCap}) {secondaryChance}");
                }
            }
            else
            {
                stringBuilder.AppendLine(dmgList + GenText.ToStringByStyle(props.GetDamageAmount(weapon), ToStringStyle.Integer) + " (" + props.damageDef.LabelCap + ")");
            }
            // Explosion radius
            if (props.explosionRadius > 0)
            {
                stringBuilder.AppendLine("   " + "CE_DescExplosionRadius".Translate() + ": " + props.explosionRadius.ToStringByStyle(ToStringStyle.FloatOne));
            }

            // Sharp / blunt AP
            if (props.explosionRadius > 0)
            {
                if (props.damageDef.armorCategory != CE_DamageArmorCategoryDefOf.Heat &&
                    props.damageDef.armorCategory != CE_DamageArmorCategoryDefOf.Electric &&
                    props.damageDef != DamageDefOf.Stun &&
                    props.damageDef != DamageDefOf.Extinguish &&
                    props.damageDef != DamageDefOf.Smoke)
                {
                    stringBuilder.AppendLine("   " + "CE_DescBluntPenetration".Translate() + ": " + GenExplosionCE.GetExplosionAP(props) + " " + "CE_MPa".Translate());
                }
            }
            else
            {
                stringBuilder.AppendLine("   " + "CE_DescSharpPenetration".Translate() + ": " + props.armorPenetrationSharp.ToStringByStyle(ToStringStyle.FloatTwo) + " " + "CE_mmRHA".Translate());
                stringBuilder.AppendLine("   " + "CE_DescBluntPenetration".Translate() + ": " + props.armorPenetrationBlunt.ToStringByStyle(ToStringStyle.FloatTwo) + " " + "CE_MPa".Translate());
            }

            // Secondary explosion
            var secExpProps = projectileDef.GetCompProperties <CompProperties_ExplosiveCE>();

            if (secExpProps != null)
            {
                if (secExpProps.explosiveRadius > 0)
                {
                    stringBuilder.AppendLine("   " + "CE_DescSecondaryExplosion".Translate() + ":");
                    stringBuilder.AppendLine("   " + "   " + "CE_DescDamage".Translate() + ": " + secExpProps.damageAmountBase.ToStringByStyle(ToStringStyle.Integer) + " (" + secExpProps.explosiveDamageType.LabelCap + ")");
                    stringBuilder.AppendLine("   " + "   " + "CE_DescExplosionRadius".Translate() + ": " + secExpProps.explosiveRadius.ToStringByStyle(ToStringStyle.FloatOne));
                }
            }

            // Pellets
            if (props.pelletCount > 1)
            {
                stringBuilder.AppendLine("   " + "CE_DescPelletCount".Translate() + ": " + GenText.ToStringByStyle(props.pelletCount, ToStringStyle.Integer));
            }
            if (props.spreadMult != 1)
            {
                stringBuilder.AppendLine("   " + "CE_DescSpreadMult".Translate() + ": " + props.spreadMult.ToStringByStyle(ToStringStyle.PercentZero));
            }

            // Fragments
            var fragmentComp = projectileDef.GetCompProperties <CompProperties_Fragments>();

            if (fragmentComp != null)
            {
                stringBuilder.AppendLine("   " + "CE_DescFragments".Translate() + ":");
                foreach (var fragmentDef in fragmentComp.fragments)
                {
                    var fragmentProps = fragmentDef?.thingDef?.projectile as ProjectilePropertiesCE;
                    stringBuilder.AppendLine("   " + "   " + fragmentDef.LabelCap);
                    stringBuilder.AppendLine("   " + "   " + "   " + "CE_DescSharpPenetration".Translate() + ": " + fragmentProps?.armorPenetrationSharp.ToStringByStyle(ToStringStyle.FloatTwo) + " " + "CE_mmRHA".Translate());
                    stringBuilder.AppendLine("   " + "   " + "   " + "CE_DescBluntPenetration".Translate() + ": " + fragmentProps?.armorPenetrationBlunt.ToStringByStyle(ToStringStyle.FloatTwo) + " " + "CE_MPa".Translate());
                }
            }

            return(stringBuilder.ToString());
        }