Exemple #1
0
        protected virtual void Explode()
        {
            Map map = base.Map;

            this.Destroy(DestroyMode.Vanish);
            ProjectilePropertiesCE propsCE     = def.projectile as ProjectilePropertiesCE;
            ThingDef preExplosionSpawnThingDef = this.def.projectile.preExplosionSpawnThingDef;
            float    explosionSpawnChance      = this.def.projectile.explosionSpawnChance;

            GenExplosion.DoExplosion(base.Position,
                                     map,
                                     this.def.projectile.explosionRadius,
                                     this.def.projectile.damageDef,
                                     this.launcher,
                                     this.def.projectile.soundExplode,
                                     this.def,
                                     this.equipmentDef,
                                     this.def.projectile.postExplosionSpawnThingDef,
                                     this.def.projectile.explosionSpawnChance,
                                     1,
                                     false, // propsCE == null ? false : propsCE.damageAdjacentTiles,
                                     preExplosionSpawnThingDef,
                                     this.def.projectile.explosionSpawnChance,
                                     1);
            ThrowBigExplode(base.Position.ToVector3Shifted() + Gen.RandomHorizontalVector(def.projectile.explosionRadius * 0.5f), map, def.projectile.explosionRadius * 0.4f);
            CompExplosiveCE comp = this.TryGetComp <CompExplosiveCE>();

            if (comp != null)
            {
                comp.Explode(launcher, this.Position, Find.VisibleMap);
            }
        }
        protected virtual void Explode()
        {
            this.Destroy(DestroyMode.Vanish);
            ProjectilePropertiesCE propsCE     = def.projectile as ProjectilePropertiesCE;
            ThingDef preExplosionSpawnThingDef = this.def.projectile.preExplosionSpawnThingDef;
            float    explosionSpawnChance      = this.def.projectile.explosionSpawnChance;

            GenExplosion.DoExplosion(base.Position,
                                     base.Map,
                                     this.def.projectile.explosionRadius,
                                     this.def.projectile.damageDef,
                                     this.launcher,
                                     this.def.projectile.soundExplode,
                                     this.def,
                                     this.equipmentDef,
                                     this.def.projectile.postExplosionSpawnThingDef,
                                     this.def.projectile.explosionSpawnChance,
                                     1,
                                     propsCE == null ? false : propsCE.damageAdjacentTiles,
                                     preExplosionSpawnThingDef,
                                     this.def.projectile.explosionSpawnChance,
                                     1);
            CompExplosiveCE comp = this.TryGetComp <CompExplosiveCE>();

            if (comp != null)
            {
                comp.Explode(launcher, this.Position, Find.VisibleMap);
            }
        }
        private void ApplySuppression(Pawn pawn)
        {
            ShieldBelt shield = null;

            if (pawn.RaceProps.Humanlike)
            {
                // check for shield user

                List <Apparel> wornApparel = pawn.apparel.WornApparel;
                for (int i = 0; i < wornApparel.Count; i++)
                {
                    var personalShield = wornApparel[i] as ShieldBelt;
                    if (personalShield != null)
                    {
                        shield = personalShield;
                        break;
                    }
                }
            }
            //Add suppression
            CompSuppressable compSuppressable = pawn.TryGetComp <CompSuppressable>();

            if (compSuppressable != null &&
                pawn.Faction != launcher?.Faction &&
                (shield == null || shield?.ShieldState == ShieldState.Resetting))
            {
                suppressionAmount = def.projectile.damageAmountBase;
                ProjectilePropertiesCE propsCE = def.projectile as ProjectilePropertiesCE;
                float penetrationAmount        = propsCE == null ? 0f : propsCE.armorPenetration;
                suppressionAmount *= 1 - Mathf.Clamp(compSuppressable.ParentArmor - penetrationAmount, 0, 1);
                compSuppressable.AddSuppression(suppressionAmount, OriginIV3);
            }
        }
        protected virtual void Explode()
        {
            Map map = base.Map;
            //this.Destroy(DestroyMode.Vanish);
            ProjectilePropertiesCE propsCE = def.projectile as ProjectilePropertiesCE;

            GenExplosion.DoExplosion(ExactPosition.ToIntVec3(),
                                     map,
                                     this.def.projectile.explosionRadius,
                                     this.def.projectile.damageDef,
                                     this.launcher,
                                     this.def.projectile.soundExplode,
                                     this.def,
                                     this.equipmentDef,
                                     this.def.projectile.postExplosionSpawnThingDef,
                                     this.def.projectile.explosionSpawnChance,
                                     1,
                                     propsCE != null && propsCE.damageAdjacentTiles,
                                     this.def.projectile.preExplosionSpawnThingDef,
                                     this.def.projectile.explosionSpawnChance,
                                     1);

            //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()
        }
Exemple #5
0
        protected virtual void Explode()
        {
            Map map = base.Map;
            //this.Destroy(DestroyMode.Vanish);
            ProjectilePropertiesCE propsCE = def.projectile as ProjectilePropertiesCE;

            GenExplosion.DoExplosion(ExactPosition.ToIntVec3(),
                                     map,
                                     def.projectile.explosionRadius,
                                     def.projectile.damageDef,
                                     launcher,
                                     def.projectile.damageAmountBase,
                                     def.projectile.soundExplode,
                                     equipmentDef,
                                     def,
                                     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.explosionDealMoreDamageAtCenter);

            //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()
        }
Exemple #6
0
        /// <summary>
        /// Determines the armor penetration value of a given dinfo. Checks WeaponGear to see if it is a projectile, melee weapon or pawn and tries to retrieve the penetration value accordingly.
        /// </summary>
        /// <param name="dinfo">DamageInfo to determine penetration for</param>
        /// <returns>Armor penetration value for attack used, 0 if it can't be determined</returns>
        private static float GetPenetrationValue(DamageInfo dinfo)
        {
            if (dinfo.Def.isExplosive)
            {
                return(dinfo.Amount * 0.1f); // Explosions have 10% of their damage as penetration
            }

            if (dinfo.WeaponGear != null)
            {
                // Case 1: projectile attack
                ProjectilePropertiesCE projectileProps = dinfo.WeaponGear.projectile as ProjectilePropertiesCE;
                if (projectileProps != null)
                {
                    return(projectileProps.armorPenetration);
                }

                // Case 2: melee attack
                Pawn instigatorPawn = dinfo.Instigator as Pawn;
                if (instigatorPawn != null)
                {
                    // Pawn is using melee weapon
                    if (dinfo.WeaponGear.IsMeleeWeapon)
                    {
                        if (instigatorPawn.equipment == null ||
                            instigatorPawn.equipment.Primary == null ||
                            instigatorPawn.equipment.Primary.def != dinfo.WeaponGear)
                        {
                            Log.Error("CE tried getting armor penetration from melee weapon " + dinfo.WeaponGear.defName + " but instigator " + dinfo.Instigator.ToString() + " equipment does not match");
                            return(0);
                        }
                        return(instigatorPawn.equipment.Primary.GetStatValue(CE_StatDefOf.MeleeWeapon_Penetration));
                    }

                    // Pawn is using body parts
                    if (instigatorPawn.def == dinfo.WeaponGear)
                    {
                        // Pawn is augmented
                        if (dinfo.WeaponLinkedHediff != null)
                        {
                            HediffCompProperties_VerbGiver compProps = dinfo.WeaponLinkedHediff.CompPropsFor(typeof(HediffComp_VerbGiver)) as HediffCompProperties_VerbGiver;
                            if (compProps != null)
                            {
                                VerbPropertiesCE verbProps = compProps.verbs.FirstOrDefault(v => v as VerbPropertiesCE != null) as VerbPropertiesCE;
                                if (verbProps != null)
                                {
                                    return(verbProps.meleeArmorPenetration);
                                }
                            }
                            return(0);
                        }

                        // Regular pawn melee
                        if (dinfo.WeaponBodyPartGroup != null &&
                            instigatorPawn.verbTracker != null &&
                            !instigatorPawn.verbTracker.AllVerbs.NullOrEmpty())
                        {
                            Verb verb = instigatorPawn.verbTracker.AllVerbs.FirstOrDefault(v => v.verbProps.linkedBodyPartsGroup == dinfo.WeaponBodyPartGroup);
                            if (verb == null)
                            {
                                Log.Error("CE could not find matching verb on Pawn " + instigatorPawn.ToString() + " for BodyPartGroup " + dinfo.WeaponBodyPartGroup.ToString());
                                return(0);
                            }
                            VerbPropertiesCE verbProps = verb.verbProps as VerbPropertiesCE;
                            if (verbProps != null)
                            {
                                return(verbProps.meleeArmorPenetration);
                            }
                        }
                    }
                }
            }
#if DEBUG
            Log.Warning("CE could not determine armor penetration, defaulting");
#endif
            return(9999);    // Really high default value so vanilla damage sources such as GiveInjuriesToKill always penetrate
        }
        /// <summary>
        /// Determines the armor penetration value of a given dinfo. Checks WeaponGear to see if it is a projectile, melee weapon or pawn and tries to retrieve the penetration value accordingly.
        /// </summary>
        /// <param name="dinfo">DamageInfo to determine penetration for</param>
        /// <returns>Armor penetration value for attack used, 0 if it can't be determined</returns>
        private static float GetPenetrationValue(DamageInfo dinfo)
        {
            if (dinfo.Def.isExplosive)
            {
                return(dinfo.Amount * 0.1f); // Explosions have 10% of their damage as penetration
            }

            if (dinfo.Weapon != null)
            {
                // Case 1: projectile attack
                ProjectilePropertiesCE projectileProps = dinfo.Weapon.projectile as ProjectilePropertiesCE;
                if (projectileProps != null)
                {
                    return(projectileProps.armorPenetration);
                }

                // Case 2: melee attack
                Pawn instigatorPawn = dinfo.Instigator as Pawn;
                if (instigatorPawn != null)
                {
                    // Pawn is using melee weapon
                    if (dinfo.Weapon.IsWeapon)
                    {
                        var equipment = instigatorPawn.equipment?.Primary;
                        if (equipment == null || equipment.def != dinfo.Weapon)
                        {
                            Log.Error("CE tried getting armor penetration from melee weapon " + dinfo.Weapon.defName + " but instigator " + dinfo.Instigator.ToString() + " equipment does not match");
                            return(0);
                        }
                        var penetrationMult = equipment.GetStatValue(CE_StatDefOf.MeleePenetrationFactor);
                        var tool            = equipment.def.tools.FirstOrDefault(t => t.linkedBodyPartsGroup == dinfo.WeaponBodyPartGroup) as ToolCE;
                        return(tool.armorPenetration * penetrationMult);
                    }

                    // Get penetration from tool
                    if (instigatorPawn.verbTracker != null &&
                        !instigatorPawn.verbTracker.AllVerbs.NullOrEmpty())
                    {
                        Verb verb = instigatorPawn.verbTracker.AllVerbs.FirstOrDefault(v => v.tool.linkedBodyPartsGroup == dinfo.WeaponBodyPartGroup);
                        if (verb == null)
                        {
                            Log.Error("CE could not find matching verb on Pawn " + instigatorPawn.ToString() + " for BodyPartGroup " + dinfo.WeaponBodyPartGroup.ToString());
                            return(0);
                        }
                        var tool = verb.tool as ToolCE;
                        if (tool != null)
                        {
                            return(tool.armorPenetration);
                        }
                    }

                    /*
                     * // Pawn is using body parts
                     * if (instigatorPawn.def == dinfo.Weapon)
                     * {
                     *  // Pawn is augmented
                     *  if (dinfo.WeaponLinkedHediff != null)
                     *  {
                     *      HediffCompProperties_VerbGiver compProps = dinfo.WeaponLinkedHediff.CompPropsFor(typeof(HediffComp_VerbGiver)) as HediffCompProperties_VerbGiver;
                     *      if (compProps != null)
                     *      {
                     *          VerbPropertiesCE verbProps = compProps.verbs.FirstOrDefault(v => v as VerbPropertiesCE != null) as VerbPropertiesCE;
                     *          if (verbProps != null) return verbProps.meleeArmorPenetration;
                     *      }
                     *      return 0;
                     *  }
                     *
                     *  // Regular pawn melee
                     *  if (dinfo.WeaponBodyPartGroup != null
                     *  && instigatorPawn.verbTracker != null
                     *  && !instigatorPawn.verbTracker.AllVerbs.NullOrEmpty())
                     *  {
                     *      Verb verb = instigatorPawn.verbTracker.AllVerbs.FirstOrDefault(v => v.verbProps.linkedBodyPartsGroup == dinfo.WeaponBodyPartGroup);
                     *      if (verb == null)
                     *      {
                     *          Log.Error("CE could not find matching verb on Pawn " + instigatorPawn.ToString() + " for BodyPartGroup " + dinfo.WeaponBodyPartGroup.ToString());
                     *          return 0;
                     *      }
                     *      var tool = verb.tool as ToolCE;
                     *      if (tool != null) return tool.armorPenetration;
                     *  }
                     * }
                     */
                }
            }
#if DEBUG
            Log.Warning("CE could not determine armor penetration, defaulting");
#endif
            return(9999);    // Really high default value so vanilla damage sources such as GiveInjuriesToKill always penetrate
        }
        /// <summary>
        /// Determines the armor penetration value of a given dinfo. Attempts to extract the tool/verb from the damage info.
        /// </summary>
        /// <param name="dinfo">DamageInfo to determine penetration for</param>
        /// <returns>Armor penetration value for attack used, 0 if it can't be determined</returns>
        private static float GetPenetrationValue(DamageInfo dinfo)
        {
            if (dinfo.Def.isExplosive)
            {
                return(dinfo.Amount * 0.1f); // Explosions have 10% of their damage as penetration
            }

            if (dinfo.Weapon != null)
            {
                // Case 1: projectile attack
                ProjectilePropertiesCE projectileProps = dinfo.Weapon.projectile as ProjectilePropertiesCE;
                if (projectileProps != null)
                {
                    return(projectileProps.armorPenetration);
                }

                // Case 2: melee attack
                Pawn instigatorPawn = dinfo.Instigator as Pawn;
                if (instigatorPawn != null)
                {
                    // Case 2.1: .. of an equiped melee weapon
                    if (dinfo.Weapon.IsMeleeWeapon)
                    {
                        ThingWithComps equipment = instigatorPawn.equipment?.Primary;

                        if (equipment == null || equipment.def != dinfo.Weapon)
                        {
                            Log.Error("CE tried getting armor penetration from melee weapon " + dinfo.Weapon.defName + " but instigator " + dinfo.Instigator.ToString() + " equipment does not match");
                            return(0);
                        }
                        var penetrationMult = equipment.GetStatValue(CE_StatDefOf.MeleePenetrationFactor);
                        var tool            = equipment.def.tools.OfType <ToolCE>().GetUsedTool(dinfo);

                        return(tool.armorPenetration * penetrationMult);
                    }

                    // Case 2.2: .. of a ranged weapon
                    if (dinfo.Weapon.IsRangedWeapon)
                    {
                        var tool = dinfo.Weapon.tools.OfType <ToolCE>().GetUsedTool(dinfo);
                        return(tool.armorPenetration);
                    }

                    // Case 2.3: .. of the pawn
                    if (instigatorPawn.def == dinfo.Weapon)
                    {
                        Verb availableVerb = instigatorPawn.meleeVerbs.TryGetMeleeVerb();

                        // Case 2.3.1: .. of a weaponized hediff (power claw, scyther blade)
                        HediffCompProperties_VerbGiver compProps = dinfo.WeaponLinkedHediff?.CompPropsFor(typeof(HediffComp_VerbGiver)) as HediffCompProperties_VerbGiver;
                        if (compProps != null)
                        {
                            var tool = compProps.tools.OfType <ToolCE>().GetUsedTool(dinfo);

                            if (tool != null)
                            {
                                return(tool.armorPenetration);
                            }

                            VerbPropertiesCE verbProps = compProps.verbs?.FirstOrDefault(v => v is VerbPropertiesCE) as VerbPropertiesCE;

                            var verbs = compProps.verbs;

                            if (verbs.Count() > 1)
                            {
                                Log.ErrorOnce("CE :: HediffCompProperties_VerbGiver for " + dinfo.WeaponLinkedHediff + " has multiple VerbPropertiesCE. [While evaluating DamageInfo " + dinfo.ToString() + "]", dinfo.WeaponLinkedHediff.GetHashCode() + 128937921);
                            }

                            if (verbProps != null)
                            {
                                Log.ErrorOnce("CE :: HediffCompProperties_VerbGiver from DamageInfo " + dinfo.ToString() + " has VerbPropertiesCE, but these should be moved to <tools> for B18", dinfo.WeaponLinkedHediff.GetHashCode() + 128937921);

                                return(verbProps.meleeArmorPenetration);
                            }
                        }

                        // AllVerbs: bodyparts of the pawn
                        // meleeVerbs: all verbs considered "melee worthy"

                        // Case 2.4: .. of a tool naturally on the body (hands/fist, head)
                        if (instigatorPawn.verbTracker != null &&
                            !instigatorPawn.verbTracker.AllVerbs.NullOrEmpty())
                        {
                            var verbs = instigatorPawn.verbTracker.AllVerbs.Where(v => v.tool is ToolCE && v.tool.linkedBodyPartsGroup == dinfo.WeaponBodyPartGroup);

                            if (verbs.Count() > 1)
                            {
                                Log.ErrorOnce("CE :: Race " + instigatorPawn.def + " has multiple ToolCE with linkedBodyPartsGroup=" + dinfo.WeaponBodyPartGroup.ToString() + " which can not be distunguished between. Consider using different linkedBodyPartsGroups. [While evaluating DamageInfo " + dinfo.ToString() + "]", instigatorPawn.def.GetHashCode() + 128937921);
                            }

                            if (!verbs.Any())
                            {
                                Log.ErrorOnce("CE :: Pawn " + instigatorPawn.ToString() + " for BodyPartGroup " + dinfo.WeaponBodyPartGroup.ToString() + " could not find matching verb (in AllVerbs: " + String.Join(",", instigatorPawn.verbTracker.AllVerbs.Select(x => x.ToString()).ToArray()) + ") [While evaluating DamageInfo " + dinfo.ToString() + "]", instigatorPawn.def.GetHashCode() + 128937921);
                                return(0);
                            }

                            return((verbs.First().tool as ToolCE).armorPenetration);
                        }
                    }
                }
            }
#if DEBUG
            Log.Warning("CE could not determine armor penetration, defaulting");
#endif
            return(9999);    // Really high default value so vanilla damage sources such as GiveInjuriesToKill always penetrate
        }
Exemple #9
0
        protected override void Impact(Thing hitThing)
        {
            Map map = base.Map;

            base.Impact(hitThing);
            if (hitThing != null)
            {
                int          damageAmountBase = def.projectile.damageAmountBase;
                ThingDef     equipmentDef     = this.equipmentDef;
                DamageDef_CE damDefCE         = def.projectile.damageDef as DamageDef_CE;

                DamageInfo dinfo = new DamageInfo(
                    def.projectile.damageDef,
                    damageAmountBase,
                    ExactRotation.eulerAngles.y,
                    launcher,
                    null,
                    equipmentDef);

                //  if (damDefCE != null && damDefCE.harmOnlyOutsideLayers) dinfo.ForceHitPart.depth = BodyPartDepth.Outside;

                ProjectilePropertiesCE propsCE = def.projectile as ProjectilePropertiesCE;
                if (propsCE != null && !propsCE.secondaryDamage.NullOrEmpty())
                {
                    // Log.Message("propsCE: " + propsCE.ToString());
                    // Get the correct body part
                    Pawn pawn = hitThing as Pawn;
                    if (pawn != null && def.projectile.damageDef.workerClass == typeof(DamageWorker_AddInjuryCE))
                    {
                        BodyPartRecord exactPartFromDamageInfo = DamageWorker_AddInjuryCE.GetExactPartFromDamageInfo(dinfo, pawn);
                        dinfo = new DamageInfo(
                            dinfo.Def,
                            dinfo.Amount,
                            dinfo.Angle,
                            dinfo.Instigator,
                            exactPartFromDamageInfo = (DamageWorker_AddInjuryCE.GetExactPartFromDamageInfo(dinfo, pawn)),
                            dinfo.WeaponGear);
                    }
                    List <DamageInfo> dinfoList = new List <DamageInfo>()
                    {
                        dinfo
                    };
                    foreach (SecondaryDamage secDamage in propsCE.secondaryDamage)
                    {
                        dinfoList.Add(new DamageInfo(
                                          secDamage.def,
                                          secDamage.amount,
                                          dinfo.Angle,
                                          dinfo.Instigator,
                                          dinfo.ForceHitPart,
                                          dinfo.WeaponGear));
                    }
                    foreach (DamageInfo curDinfo in dinfoList)
                    {
                        hitThing.TakeDamage(curDinfo);
                    }
                }
                else
                {
                    hitThing.TakeDamage(dinfo);
                }
            }
            else
            {
                SoundDefOf.BulletImpactGround.PlayOneShot(new TargetInfo(base.Position, map, false));
                MoteMaker.MakeStaticMote(ExactPosition, map, ThingDefOf.Mote_ShotHit_Dirt, 1f);
            }
        }
Exemple #10
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)
        {
            // Append ammo stats
            ProjectilePropertiesCE props = projectileDef?.projectile as ProjectilePropertiesCE;

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

            StringBuilder stringBuilder = new StringBuilder();

            // Damage type/amount
            string 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.damageAmountBase, ToStringStyle.Integer) + " (" + props.damageDef.LabelCap + ")");
                foreach (SecondaryDamage sec in props.secondaryDamage)
                {
                    stringBuilder.AppendLine("   " + GenText.ToStringByStyle(sec.amount, ToStringStyle.Integer) + " (" + sec.def.LabelCap + ")");
                }
            }
            else
            {
                stringBuilder.AppendLine(dmgList + GenText.ToStringByStyle(props.damageAmountBase, ToStringStyle.Integer) + " (" + props.damageDef.LabelCap + ")");
            }
            // Explosion radius
            if (props.explosionRadius > 0)
            {
                stringBuilder.AppendLine("   " + "CE_DescExplosionRadius".Translate() + ": " + GenText.ToStringByStyle(props.explosionRadius, ToStringStyle.FloatOne));
            }

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

            if (secExpProps != null)
            {
                if (secExpProps.explosionRadius > 0)
                {
                    stringBuilder.AppendLine("   " + "CE_DescSecondaryExplosion".Translate() + ":");
                    stringBuilder.AppendLine("   " + "   " + "CE_DescExplosionRadius".Translate() + ": " + GenText.ToStringByStyle(secExpProps.explosionRadius, ToStringStyle.FloatOne));
                    stringBuilder.AppendLine("   " + "   " + "CE_DescDamage".Translate() + ": " +
                                             GenText.ToStringByStyle(secExpProps.explosionDamage, ToStringStyle.Integer) + " (" + secExpProps.explosionDamageDef.LabelCap + ")");
                }
                if (secExpProps.fragRange > 0)
                {
                    stringBuilder.AppendLine("   " + "CE_DescFragRange".Translate() + ": " + GenText.ToStringByStyle(secExpProps.fragRange, ToStringStyle.FloatTwo));
                }
            }

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

            return(stringBuilder.ToString());
        }
Exemple #11
0
        public override string GetDescription()
        {
            if (ammoDef != null && ammoDef.ammoClass != null && ammoDef.linkedProjectile != null)
            {
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.AppendLine(base.GetDescription());

                // Append ammo class description
                if (!string.IsNullOrEmpty(ammoDef.ammoClass.description))
                {
                    stringBuilder.AppendLine("\n" +
                                             (string.IsNullOrEmpty(ammoDef.ammoClass.LabelCap) ? "" : ammoDef.ammoClass.LabelCap + ":\n") +
                                             ammoDef.ammoClass.description);
                }

                // Append ammo stats
                ProjectilePropertiesCE props = ammoDef.linkedProjectile.projectile as ProjectilePropertiesCE;
                if (props != null)
                {
                    // Damage type/amount
                    stringBuilder.AppendLine("\n" + "CE_DescDamage".Translate() + ": ");
                    stringBuilder.AppendLine("   " + GenText.ToStringByStyle(props.damageAmountBase, ToStringStyle.Integer) + " (" + props.damageDef.LabelCap + ")");
                    if (!props.secondaryDamage.NullOrEmpty())
                    {
                        foreach (SecondaryDamage sec in props.secondaryDamage)
                        {
                            stringBuilder.AppendLine("   " + GenText.ToStringByStyle(sec.amount, ToStringStyle.Integer) + " (" + sec.def.LabelCap + ")");
                        }
                    }
                    // Explosion radius
                    if (props.explosionRadius > 0)
                    {
                        stringBuilder.AppendLine("CE_DescExplosionRadius".Translate() + ": " + GenText.ToStringByStyle(props.explosionRadius, ToStringStyle.FloatOne));
                    }

                    // Secondary explosion
                    CompProperties_ExplosiveCE secExpProps = ammoDef.linkedProjectile.GetCompProperties <CompProperties_ExplosiveCE>();
                    if (secExpProps != null)
                    {
                        if (secExpProps.explosionRadius > 0)
                        {
                            stringBuilder.AppendLine("CE_DescSecondaryExplosion".Translate() + ":");
                            stringBuilder.AppendLine("   " + "CE_DescExplosionRadius".Translate() + ": " + GenText.ToStringByStyle(secExpProps.explosionRadius, ToStringStyle.FloatOne));
                            stringBuilder.AppendLine("   " + "CE_DescDamage".Translate() + ": " +
                                                     GenText.ToStringByStyle(secExpProps.explosionDamage, ToStringStyle.Integer) + " (" + secExpProps.explosionDamageDef.LabelCap + ")");
                        }
                        if (secExpProps.fragRange > 0)
                        {
                            stringBuilder.AppendLine("CE_DescFragRange".Translate() + ": " + GenText.ToStringByStyle(secExpProps.fragRange, ToStringStyle.FloatTwo));
                        }
                    }

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

                return(stringBuilder.ToString());
            }
            return(base.GetDescription());
        }
Exemple #12
0
        public virtual void RayCast(Thing launcher, VerbProperties verbProps, Vector2 origin, float shotAngle, float shotRotation, float shotHeight = 0f, float shotSpeed = -1f, float spreadDegrees = 0f, float aperatureSize = 0.03f, Thing equipment = null)
        {
            float magicSpreadFactor        = Mathf.Sin(0.06f / 2 * Mathf.Deg2Rad) + aperatureSize;
            float magicLaserDamageConstant = 1 / (magicSpreadFactor * magicSpreadFactor * 3.14159f);

            ProjectilePropertiesCE pprops = def.projectile as ProjectilePropertiesCE;

            shotRotation = Mathf.Deg2Rad * shotRotation + (float)(3.14159 / 2.0f);
            Vector3 direction   = new Vector3(Mathf.Cos(shotRotation) * Mathf.Cos(shotAngle), Mathf.Sin(shotAngle), Mathf.Sin(shotRotation) * Mathf.Cos(shotAngle));
            Vector3 origin3     = new Vector3(origin.x, shotHeight, origin.y);
            Map     map         = launcher.Map;
            Vector3 destination = direction * verbProps.range + origin3;

            this.shotAngle    = shotAngle;
            this.shotHeight   = shotHeight;
            this.shotRotation = shotRotation;
            this.launcher     = launcher;
            this.origin       = origin;
            equipmentDef      = equipment?.def ?? null;
            Ray   ray          = new Ray(origin3, direction);
            var   lbce         = this as LaserBeamCE;
            float spreadRadius = Mathf.Sin(spreadDegrees / 2.0f * Mathf.Deg2Rad);

            LaserGunDef defWeapon = equipmentDef as LaserGunDef;
            Vector3     muzzle    = ray.GetPoint((defWeapon == null ? 0.9f : defWeapon.barrelLength));
            var         it_bounds = CE_Utility.GetBoundsFor(intendedTarget);

            for (int i = 1; i < verbProps.range; i++)
            {
                float spreadArea = (i * spreadRadius + aperatureSize) * (i * spreadRadius + aperatureSize) * 3.14159f;
                if (pprops.damageFalloff)
                {
                    lbce.DamageModifier = 1 / (magicLaserDamageConstant * spreadArea);
                }

                Vector3 tp = ray.GetPoint(i);
                if (tp.y > CollisionVertical.WallCollisionHeight)
                {
                    break;
                }
                if (tp.y < 0)
                {
                    destination   = tp;
                    landed        = true;
                    ExactPosition = tp;
                    Position      = ExactPosition.ToIntVec3();
                    break;
                }
                foreach (Thing thing in Map.thingGrid.ThingsListAtFast(tp.ToIntVec3()))
                {
                    if (this == thing)
                    {
                        continue;
                    }
                    var bounds = CE_Utility.GetBoundsFor(thing);
                    if (!bounds.IntersectRay(ray, out var dist))
                    {
                        continue;
                    }
                    if (i < 2 && thing != intendedTarget)
                    {
                        continue;
                    }

                    if (thing is Plant plant)
                    {
                        if (!Rand.Chance(thing.def.fillPercent * plant.Growth))
                        {
                            continue;
                        }
                    }
                    else if (thing is Building)
                    {
                        if (!Rand.Chance(thing.def.fillPercent))
                        {
                            continue;
                        }
                    }
                    ExactPosition = tp;
                    destination   = tp;
                    landed        = true;
                    LastPos       = destination;
                    ExactPosition = destination;
                    Position      = ExactPosition.ToIntVec3();

                    lbce.SpawnBeam(muzzle, destination);

                    lbce.Impact(thing, muzzle);

                    return;
                }
            }
            if (lbce != null)
            {
                lbce.SpawnBeam(muzzle, destination);
                Destroy(DestroyMode.Vanish);
                return;
            }
        }
        /// <summary>
        ///     Takes into account the target being downed and the projectile having been fired while the target was downed, and
        ///     the target's bodySize
        /// </summary>
        private bool ImpactThroughBodySize(Thing thing, float height)
        {
            Pawn pawn = thing as Pawn;

            if (pawn != null)
            {
                PersonalShield shield = null;
                if (pawn.RaceProps.Humanlike)
                {
                    // check for shield user

                    List <Apparel> wornApparel = pawn.apparel.WornApparel;
                    for (int i = 0; i < wornApparel.Count; i++)
                    {
                        if (wornApparel[i] is PersonalShield)
                        {
                            shield = (PersonalShield)wornApparel[i];
                            break;
                        }
                    }
                }
                //Add suppression
                CompSuppressable compSuppressable = pawn.TryGetComp <CompSuppressable>();
                if (compSuppressable != null)
                {
                    if (shield == null || (shield != null && shield?.ShieldState == ShieldState.Resetting))
                    {
                        /*
                         * if (pawn.skills.GetSkill(SkillDefOf.Shooting).level >= 1)
                         * {
                         *  suppressionAmount = (def.projectile.damageAmountBase * (1f - ((pawn.skills.GetSkill(SkillDefOf.Shooting).level) / 100) * 3));
                         * }
                         * else suppressionAmount = def.projectile.damageAmountBase;
                         */
                        suppressionAmount = def.projectile.damageAmountBase;
                        ProjectilePropertiesCE propsCE = def.projectile as ProjectilePropertiesCE;
                        float penetrationAmount        = propsCE == null ? 0f : propsCE.armorPenetration;
                        suppressionAmount *= 1 - Mathf.Clamp(compSuppressable.parentArmor - penetrationAmount, 0, 1);
                        compSuppressable.AddSuppression(suppressionAmount, origin.ToIntVec3());
                    }
                }

                //Check horizontal distance
                Vector3 dest              = destination;
                Vector3 orig              = origin;
                Vector3 pawnPos           = pawn.DrawPos;
                float   closestDistToPawn = Math.Abs((dest.z - orig.z) * pawnPos.x - (dest.x - orig.x) * pawnPos.z +
                                                     dest.x * orig.z - dest.z * orig.x)
                                            /
                                            (float)
                                            Math.Sqrt((dest.z - orig.z) * (dest.z - orig.z) +
                                                      (dest.x - orig.x) * (dest.x - orig.x));
                if (closestDistToPawn <= CE_Utility.GetCollisionWidth(pawn))
                {
                    //Check vertical distance
                    float pawnHeight = CE_Utility.GetCollisionHeight(pawn);
                    if (height < pawnHeight)
                    {
                        Impact(thing);
                        return(true);
                    }
                }
            }
            if (thing.def.fillPercent > 0 || thing.def.Fillage == FillCategory.Full)
            {
                if (height < CE_Utility.GetCollisionHeight(thing) || thing.def.Fillage == FillCategory.Full)
                {
                    Impact(thing);
                    return(true);
                }
            }
            return(false);
        }
Exemple #14
0
        public static readonly DamageDef absorbDamageDef = DamageDefOf.Blunt;   //The damage def to convert absorbed shots into

        /// <summary>
        /// Calculates deflection chance and damage through armor
        /// </summary>
        public static int GetAfterArmorDamage(Pawn pawn, int damAmountInt, BodyPartRecord part, DamageInfo dinfo, bool damageArmor, ref bool deflected)
        {
            DamageDef damageDef = dinfo.Def;

            if (damageDef.armorCategory == DamageArmorCategory.IgnoreArmor)
            {
                return(damAmountInt);
            }
            float   damageAmount   = (float)damAmountInt;
            StatDef deflectionStat = damageDef.armorCategory.DeflectionStat();
            // Get armor penetration value
            float pierceAmount = 0f;

            if (dinfo.WeaponGear != null)
            {
                Pawn instigatorPawn = dinfo.Instigator as Pawn;
                if (dinfo.WeaponGear.Verbs.Find(s => s.projectileDef != null) != null)
                {
                    ProjectilePropertiesCE projectileProps = dinfo.WeaponGear.Verbs.Find(s => s.projectileDef != null).projectileDef.projectile as ProjectilePropertiesCE;
                    //     ProjectilePropertiesCE projectileProps = dinfo.WeaponGear.projectile as ProjectilePropertiesCE;
                    if (projectileProps != null)
                    {
                        pierceAmount = projectileProps.armorPenetration;
                    }
                }
                else if (dinfo.Instigator != null)
                {
                    if (instigatorPawn != null)
                    {
                        if (instigatorPawn.equipment != null && instigatorPawn.equipment.Primary != null)
                        {
                            pierceAmount = instigatorPawn.equipment.Primary.GetStatValue(StatDef.Named("ArmorPenetration"));
                        }
                        else
                        {
                            pierceAmount = instigatorPawn.GetStatValue(StatDef.Named("ArmorPenetration"));
                        }
                    }
                }
            }


            // Run armor calculations on all apparel
            if (pawn.apparel != null)
            {
                List <Apparel> wornApparel = new List <Apparel>(pawn.apparel.WornApparel);
                for (int i = wornApparel.Count - 1; i >= 0; i--)
                {
                    if (wornApparel[i].def.apparel.CoversBodyPart(part))
                    {
                        Thing armorThing = damageArmor ? wornApparel[i] : null;
                        //Check for deflection
                        if (ApplyArmor(ref damageAmount, ref pierceAmount, wornApparel[i].GetStatValue(deflectionStat, true), armorThing, damageDef))
                        {
                            deflected = true;
                            if (damageDef != absorbDamageDef)
                            {
                                damageDef      = absorbDamageDef;
                                deflectionStat = damageDef.armorCategory.DeflectionStat();
                                i++;
                            }
                        }
                        if (damageAmount < 0.001)
                        {
                            return(0);
                        }
                    }
                }
            }

            float pawnArmorAmount = 0f;

            BodyPartRecord outerPart = part;

            while (outerPart.parent != null && outerPart.depth != BodyPartDepth.Outside)
            {
                outerPart = outerPart.parent;
            }

            if (outerPart.IsInGroup(DefDatabase <BodyPartGroupDef> .GetNamed("CoveredByNaturalArmor")))
            {
                pawnArmorAmount = pawn.GetStatValue(deflectionStat);
            }

            if (pawnArmorAmount > 0 && ApplyArmor(ref damageAmount, ref pierceAmount, pawnArmorAmount, null, damageDef))
            {
                deflected = true;
                if (damageAmount < 0.001)
                {
                    return(0);
                }
                damageDef      = absorbDamageDef;
                deflectionStat = damageDef.armorCategory.DeflectionStat();
                ApplyArmor(ref damageAmount, ref pierceAmount, pawn.GetStatValue(deflectionStat, true), pawn, damageDef);
            }
            return(Mathf.RoundToInt(damageAmount));
        }