コード例 #1
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
        }
コード例 #2
0
        /// <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
        }