public static void SoundHitBuildingPrefix(ref SoundDef __result, Verb_MeleeAttack __instance) { if (__instance.caster is Pawn pawn) { var pawn_EquipmentTracker = pawn.equipment; if (pawn_EquipmentTracker != null) { //Log.Message("2"); var thingWithComps = pawn_EquipmentTracker .Primary; // (ThingWithComps)AccessTools.Field(typeof(Pawn_EquipmentTracker), "primaryInt").GetValue(pawn_EquipmentTracker); if (thingWithComps != null) { //Log.Message("3"); var CompExtraSounds = thingWithComps.GetComp <CompExtraSounds>(); if (CompExtraSounds != null) { if (CompExtraSounds.Props.soundHitBuilding != null) { __result = CompExtraSounds.Props.soundHitBuilding; } } } } } }
public static void Postfix(Verb_MeleeAttack __instance, ref float __result) { if (__instance.caster is Thing caster && caster.TryGetComp <CompTargetingMode>() is CompTargetingMode targetingComp && __result == caster.GetStatValue(StatDefOf.MeleeHitChance)) { __result *= __result * targetingComp.GetTargetingMode().HitChanceFactor; } }
public static void SoundHitPawnPrefix(ref SoundDef __result, Verb_MeleeAttack __instance) { if (__instance.caster is Pawn pawn) { var pawn_EquipmentTracker = pawn.equipment; if (pawn_EquipmentTracker != null) { //Log.Message("2"); var thingWithComps = pawn_EquipmentTracker .Primary; // (ThingWithComps)AccessTools.Field(typeof(Pawn_EquipmentTracker), "primaryInt").GetValue(pawn_EquipmentTracker); if (thingWithComps?.def?.defName == "RE_StunGun") { if (thingWithComps.TryGetComp <CompStunCharge>() is CompStunCharge charge) { if (charge.StoredEnergy == charge.StoredEnergyMax) { charge.DrainEnergy(); SoundDef.Named("RE_StunGun").PlayOneShot(pawn); if (pawn.LastAttackedTarget.HasThing) { if (pawn.LastAttackedTarget.Thing is Pawn targetPawn) { HealthUtility.AdjustSeverity(targetPawn, HediffDef.Named("RE_ShockBuildup"), 1.0f); MoteMaker.ThrowLightningGlow(targetPawn.DrawPos, pawn.Map, 5); } } } } } } } }
private static void ApplyNormalDamageToTarget(Verb_MeleeAttack vMA, Pawn attacker, LocalTargetInfo target) { MRpawntoken token = MainController.GetPawnToken(attacker); Pawn tpawn = target.Thing as Pawn; // Immobile targets receive full damage on normal hits (The only possible result against them) with independence of the Attack Mode selected bool immobile = (target.Thing.def.category != ThingCategory.Pawn) || tpawn.Downed || (tpawn.GetPosture() != PawnPosture.Standing); if (token.amode.solver == 3 && !immobile) { return; // On Disarm Mode we do no damage at all } var DamageInfosToApply = Traverse.Create(vMA).Method("DamageInfosToApply", new Type[] { typeof(LocalTargetInfo) }); foreach (DamageInfo current in (DamageInfosToApply.GetValue <IEnumerable <DamageInfo> >(target))) { if (target.ThingDestroyed) { break; } if (!immobile && (token.amode.solver == 1 || token.amode.solver == 2)) { // On Capture & Stun we do half the damage on normal hits current.SetAmount(Mathf.Max(1, Mathf.RoundToInt(current.Amount * 0.5f))); } target.Thing.TakeDamage(current); } }
private static void ApplyParryDamageToTarget(Verb_MeleeAttack vMA, Pawn attacker, LocalTargetInfo target) { // The main differences between a regular hit and a parried one regarding damage are the following: // - If the target has an active shield with energy it will absorb the FULL damage of the attack // - If the target is wielding a melee weapon it will absorb all the damage of the attack suffering // Original Damage * ParryReduction * (1-Melee Skill) (minimum of 1) of damage // - If the target is unarmed, the damage received will be reduced by ParryReduction MRpawntoken token = MainController.GetPawnToken(attacker); if (token.amode.solver == 3) { return; // On Disarm Mode we do no damage at all on parried hits } bool rollback = false; Pawn tpawn = target.Thing as Pawn; var DamageInfosToApply = Traverse.Create(vMA).Method("DamageInfosToApply", new Type[] { typeof(LocalTargetInfo) }); foreach (DamageInfo current in (DamageInfosToApply.GetValue <IEnumerable <DamageInfo> >(target))) { if (target.ThingDestroyed) { break; } if (token.amode.solver == 1 || token.amode.solver == 2) { // On Capture & Stun we do half the damage on parry hits current.SetAmount(Mathf.Max(1, Mathf.RoundToInt(current.Amount * 0.5f))); } rollback = current.Def.isExplosive; // We briefly active isExplosive to make Vanilla Personal Shields able to intercept melee damage current.Def.isExplosive = true; if (PawnHasActiveAbsorber(current, tpawn)) // We have to do a double check so Apparel absorbers take precedence over wield weapon damage { target.Thing.TakeDamage(current); } else if (tpawn.equipment != null && tpawn.equipment.Primary != null && tpawn.equipment.Primary.def.IsMeleeWeapon) { // The target has an equiped melee weapon after a parry, it will deny any damage to the target but the weapon will suffer some damage itself current.SetAmount(Mathf.Max(1, Mathf.RoundToInt(current.Amount * Constants.ParryReduction * (1f - tpawn.GetStatValue(StatDefOf.MeleeHitChance, true))))); // If the current damage is enough to destroy the weapon we try to drop it instead. If there is not enough room nearby, it will be destroyed if (tpawn.equipment.Primary.HitPoints <= current.Amount) { ThingWithComps thingwithcomps = new ThingWithComps(); if (tpawn.equipment.TryDropEquipment(tpawn.equipment.Primary, out thingwithcomps, tpawn.Position)) { current.Def.isExplosive = rollback; break; } } tpawn.equipment.Primary.TakeDamage(current); } else { // Unarmed defender, it just takes reduced damage current.SetAmount(Mathf.Max(1, Mathf.RoundToInt(current.Amount * Constants.ParryReduction))); target.Thing.TakeDamage(current); } current.Def.isExplosive = rollback; } }
public static void SoundHitBuildingPostfix(ref SoundDef __result, Verb_MeleeAttack __instance) { if (__instance.caster is Pawn pawn) { if (pawn.equipment?.Primary?.GetCompExtraSounds()?.Props.soundHitBuilding is SoundDef soundHitBuilding) { __result = soundHitBuilding; } } }
static void Postfix(Verb_MeleeAttack __instance) { LocalTargetInfo currentTarget = Traverse.Create(__instance).Field("currentTarget").GetValue <LocalTargetInfo>(); if (currentTarget != null && currentTarget.HasThing) { Thing t = currentTarget.Thing; MoteMaker.ThrowText(t.DrawPos, t.Map, "DM_MISS".Translate(), 3.65f); } }
public static void SoundHitPawnPrefix(ref SoundDef __result, Verb_MeleeAttack __instance) { if (__instance.caster is Pawn pawn && pawn.GetComp <CompHulk>() is CompHulk w && w.IsTransformed) { if (w.CurrentHulkForm.def.attackSound is SoundDef soundToPlay) { if (Rand.Value < 0.5f) { soundToPlay.PlayOneShot(new TargetInfo(pawn)); } } } }
private static void ApplyCriticalDamageToTarget(Verb_MeleeAttack vMA, Pawn attacker, LocalTargetInfo target) { Pawn tpawn = target.Thing as Pawn; var DamageInfosToApply = Traverse.Create(vMA).Method("DamageInfosToApply", new Type[] { typeof(LocalTargetInfo) }); MRpawntoken token = MainController.GetPawnToken(attacker); switch (token.amode.solver) { case 0: // Kill // Double damage on all applied damage foreach (DamageInfo current in (DamageInfosToApply.GetValue <IEnumerable <DamageInfo> >(target))) { if (target.ThingDestroyed) { break; } current.SetAmount(Mathf.Max(1, Mathf.RoundToInt(current.Amount * 2f))); target.Thing.TakeDamage(current); } break; case 1: // Capture // We replace all damage by an anesthesize effect if (target.Thing.def.category == ThingCategory.Pawn) { HealthUtility.TryAnesthesize(tpawn); } break; case 2: // Stun // We replace ALL damage by a short stun effect instead target.Thing.TakeDamage(new DamageInfo(DamageDefOf.Stun, 20)); break; case 3: // Disarm // We replace ALL damage by removing currently equiped weapon if (tpawn.equipment != null && tpawn.equipment.Primary != null) { ThingWithComps thingwithcomps = new ThingWithComps(); tpawn.equipment.TryDropEquipment(tpawn.equipment.Primary, out thingwithcomps, tpawn.Position); } break; default: Log.Warning(string.Concat(new object[] { "Melee Rebalance: Critical Special effect not registered for ", attacker })); break; } }
public static void GetNonMissChance_PostFix(Verb_MeleeAttack __instance, LocalTargetInfo target, ref float __result) { //if (target.Thing != null && target.Thing is Pawn) //{ Pawn attacker = __instance.CasterPawn; if (attacker != null) { Pawn_EquipmentTracker pawn_EquipmentTracker = attacker.equipment; if (pawn_EquipmentTracker != null) { foreach (ThingWithComps thingWithComps in pawn_EquipmentTracker.AllEquipmentListForReading) { if (thingWithComps != null) { if (thingWithComps.def.IsMeleeWeapon) { if (thingWithComps.def.defName.Contains("SWSaber_")) { CompForceUser compForce = attacker.TryGetComp <CompForceUser>(); if (compForce == null) { __result = 0.5f; } else if (!compForce.IsForceUser) { __result = 0.5f; } else { float newAccuracy = (float)(__result / 2); int accuracyPoints = compForce.ForceSkillLevel("PJ_LightsaberAccuracy"); if (accuracyPoints > 0) { for (int i = 0; i < accuracyPoints; i++) { newAccuracy += 0.2f; } } __result = newAccuracy; } } } } } } } //} }
public static void TryCastShot_Melee_PostFix(Verb_MeleeAttack __instance, bool __result) { if (!SettingsHelper.LatestVersion.npcdegrade) { if (!__instance.CasterPawn.IsColonistPlayerControlled) { return; } } if (SettingsHelper.LatestVersion.degradeMelee && Utility.Eligable(__instance)) { Utility.Fire(__instance); } }
public static void SoundHitPawnPostfix(ref SoundDef __result, Verb_MeleeAttack __instance) { if (__instance.caster is Pawn pawn) { if (pawn.kindDef?.GetModExtensionExtraSounds()?.soundHitPawn is SoundDef modExtSoundHitPawn) { __result = modExtSoundHitPawn; } if (pawn.equipment?.Primary?.GetCompExtraSounds()?.Props.soundHitPawn is SoundDef soundHitPawn) { __result = soundHitPawn; } } }
public static void TryCastShot(Verb_MeleeAttack __instance) { BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; FieldInfo field = (__instance.GetType()).GetField("currentTarget", bindFlags); object fieldValue = field.GetValue(__instance); if (fieldValue != null && fieldValue is LocalTargetInfo) { Thing targetThing = ((LocalTargetInfo)fieldValue).Thing; if (__instance.CasterPawn != null && targetThing != null && targetThing is Pawn && !(targetThing as Pawn).Dead && (targetThing as Pawn).RaceProps.Humanlike && (targetThing as Pawn).equipment != null) { WeaponAssingment.doCQC(targetThing as Pawn, __instance.CasterPawn); } } }
public static void Postfix(Verb_MeleeAttack __instance, ref float __result) { if (typeof(Thing).Equals(__instance.caster)) { Thing caster = __instance.caster; if (caster != null) { if (typeof(CompTargetingMode).Equals(caster.TryGetComp <CompTargetingMode>())) { CompTargetingMode targetingComp = caster.TryGetComp <CompTargetingMode>(); if (targetingComp != null && __result == caster.GetStatValue(StatDefOf.MeleeHitChance)) { __result *= __result * targetingComp.GetTargetingMode().HitChanceFactor; } } } } }
//=================================== COMPEXTRASOUNDS public static void SoundHitPawnPrefix(ref SoundDef __result, Verb_MeleeAttack __instance) { if (__instance.caster is Pawn pawn) { var pawn_PawnKindDef = pawn.kindDef; if (pawn_PawnKindDef != null) { var extraSoundsExtension = pawn_PawnKindDef.GetModExtension <DefModExtension_ExtraSounds>(); if (extraSoundsExtension != null) { if (extraSoundsExtension != null) { if (extraSoundsExtension.soundHitPawn != null) { __result = extraSoundsExtension.soundHitPawn; } } } } var pawn_EquipmentTracker = pawn.equipment; if (pawn_EquipmentTracker != null) { //Log.Message("2"); var thingWithComps = pawn_EquipmentTracker .Primary; // (ThingWithComps)AccessTools.Field(typeof(Pawn_EquipmentTracker), "primaryInt").GetValue(pawn_EquipmentTracker); if (thingWithComps != null) { //Log.Message("3"); var CompExtraSounds = thingWithComps.GetComp <CompExtraSounds>(); if (CompExtraSounds != null) { if (CompExtraSounds.Props.soundHitPawn != null) { __result = CompExtraSounds.Props.soundHitPawn; } } } } } }
public static void GetNonMissChance_PostFix(Verb_MeleeAttack __instance, ref float __result) { if (__instance.Caster is not Pawn attacker) { return; } var weapon = __instance.EquipmentSource; if (weapon == null || !IsSWSaber(weapon.def)) { return; } var compForce = attacker.GetForceCompIfForceUser(); if (compForce == null) { __result = 0.5f; } else { var newAccuracy = __result / 2; var accuracyPoints = compForce.ForceSkillLevel("PJ_LightsaberAccuracy"); if (accuracyPoints > 0) { for (var i = 0; i < accuracyPoints; i++) { newAccuracy += 0.2f; } } __result = newAccuracy; } }
// RimWorld.Verb_MeleeAttack public static void DamageInfosToApply_PostFix(Verb_MeleeAttack __instance, ref IEnumerable <DamageInfo> __result, LocalTargetInfo target) { var newList = new List <DamageInfo>(); //__result = null; var EquipmentSource = __instance.EquipmentSource; if (EquipmentSource != null) { //Log.Message("1"); var comp = EquipmentSource.AllComps.FirstOrDefault(x => x is OgsCompSlotLoadable.CompSlotLoadable); if (comp != null) { //Log.Message("2"); var compSlotLoadable = comp as OgsCompSlotLoadable.CompSlotLoadable; if (compSlotLoadable.Slots != null && compSlotLoadable.Slots.Count > 0) { //Log.Message("3"); var statSlots = compSlotLoadable.Slots.FindAll(z => !z.IsEmpty() && ((OgsCompSlotLoadable.SlotLoadableDef)z.def).doesChangeStats); if (statSlots != null && statSlots.Count > 0) { foreach (var slot in statSlots) { //Log.Message("5"); var slotBonus = slot.SlotOccupant.def.GetModExtension <SlottedBonusExtension>(); if (slotBonus != null) { //Log.Message("6"); var superClass = __instance.GetType().BaseType; if (slotBonus.damageDef != null) { //Log.Message("7"); var num = __instance.verbProps.AdjustedMeleeDamageAmount(__instance, __instance.CasterPawn); var def = __instance.verbProps.meleeDamageDef; BodyPartGroupDef weaponBodyPartGroup = null; HediffDef weaponHediff = null; if (__instance.CasterIsPawn) { if (num >= 1f) { weaponBodyPartGroup = __instance.verbProps.linkedBodyPartsGroup; if (__instance.HediffCompSource != null) { weaponHediff = __instance.HediffCompSource.Def; } } else { num = 1f; def = DamageDefOf.Blunt; } } //Log.Message("9"); ThingDef def2; if (__instance.EquipmentSource != null) { def2 = __instance.EquipmentSource.def; } else { def2 = __instance.CasterPawn.def; } //Log.Message("10"); var angle = (target.Thing.Position - __instance.CasterPawn.Position) .ToVector3(); //Log.Message("11"); var caster = __instance.caster; //Log.Message("12"); var newdamage = GenMath.RoundRandom(num); // Log.Message("applying damage "+newdamage+" out of "+num); var damageInfo = new DamageInfo(slotBonus.damageDef, newdamage, slotBonus.armorPenetration, -1f, caster, null, def2); damageInfo.SetBodyRegion(BodyPartHeight.Undefined, BodyPartDepth.Outside); damageInfo.SetWeaponBodyPartGroup(weaponBodyPartGroup); damageInfo.SetWeaponHediff(weaponHediff); damageInfo.SetAngle(angle); //Log.Message("13"); newList.Add(damageInfo); __result = newList.AsEnumerable(); } var vampiricEffect = slotBonus.vampiricHealChance; if (vampiricEffect != null) { //Log.Message("vampiricHealingCalled"); var randValue = Rand.Value; //Log.Message("randValue = " + randValue.ToString()); if (randValue <= vampiricEffect.chance) { MoteMaker.ThrowText(__instance.CasterPawn.DrawPos, __instance.CasterPawn.Map, "Vampiric Effect: Success", 6f); //MoteMaker.ThrowText(__instance.CasterPawn.DrawPos, __instance.CasterPawn.Map, "Success".Translate(), 6f); ApplyHealing(__instance.caster, vampiricEffect.woundLimit, target.Thing); } } } } } } } } }
public static bool TryCastShot(Verb_MeleeAttack __instance, ref bool __result) { Pawn casterPawn = __instance.CasterPawn; if (!casterPawn.Spawned) { return(false); } if (casterPawn.stances.FullBodyBusy) { return(false); } Thing thing = currentTargetFieldRef(__instance).Thing; if (!__instance.CanHitTarget(thing)) { Log.Warning(string.Concat(casterPawn, " meleed ", thing, " from out of melee position.")); } casterPawn.rotationTracker.Face(thing.DrawPos); if (!funcIsTargetImmobile(__instance, currentTargetFieldRef(__instance)) && casterPawn.skills != null) { casterPawn.skills.Learn(SkillDefOf.Melee, 200f * __instance.verbProps.AdjustedFullCycleTime(__instance, casterPawn)); } Pawn pawn = thing as Pawn; if (pawn != null && !pawn.Dead && (casterPawn.MentalStateDef != MentalStateDefOf.SocialFighting || pawn.MentalStateDef != MentalStateDefOf.SocialFighting)) { pawn.mindState.meleeThreat = casterPawn; pawn.mindState.lastMeleeThreatHarmTick = Find.TickManager.TicksGame; } Map map = thing.Map; Vector3 drawPos = thing.DrawPos; SoundDef soundDef; bool result; if (Rand.Chance(funcGetNonMissChance(__instance, thing))) { if (!Rand.Chance(funcGetDodgeChance(__instance, thing))) { soundDef = ((thing.def.category != ThingCategory.Building) ? funcSoundHitPawn(__instance) : funcSoundHitBuilding(__instance)); if (__instance.verbProps.impactMote != null) { MoteMaker.MakeStaticMote(drawPos, map, __instance.verbProps.impactMote); } BattleLogEntry_MeleeCombat battleLogEntry_MeleeCombat = __instance.CreateCombatLog((ManeuverDef maneuver) => maneuver.combatLogRulesHit, alwaysShow: true); result = true; DamageWorker.DamageResult damageResult = funcApplyMeleeDamageToTarget(__instance, currentTargetFieldRef(__instance)); if (damageResult.stunned && damageResult.parts.NullOrEmpty()) { Find.BattleLog.RemoveEntry(battleLogEntry_MeleeCombat); } else { damageResult.AssociateWithLog(battleLogEntry_MeleeCombat); if (damageResult.deflected) { battleLogEntry_MeleeCombat.RuleDef = __instance.maneuver.combatLogRulesDeflect; battleLogEntry_MeleeCombat.alwaysShowInCompact = false; } } } else { result = false; soundDef = funcSoundDodge(__instance, thing); MoteMaker.ThrowText(drawPos, map, "TextMote_Dodge".Translate(), 1.9f); __instance.CreateCombatLog((ManeuverDef maneuver) => maneuver.combatLogRulesDodge, alwaysShow: false); } } else { result = false; soundDef = funcSoundMiss(__instance); __instance.CreateCombatLog((ManeuverDef maneuver) => maneuver.combatLogRulesMiss, alwaysShow: false); } soundDef.PlayOneShot(new TargetInfo(thing.Position, map)); if (casterPawn.Spawned) { casterPawn.Drawer.Notify_MeleeAttackOn(thing); } if (pawn != null && !pawn.Dead && pawn.Spawned) { pawn.stances.StaggerFor(95); } if (casterPawn.Spawned) { casterPawn.rotationTracker.FaceCell(thing.Position); } if (casterPawn.caller != null) { casterPawn.caller.Notify_DidMeleeAttack(); } return(result); }
public static bool Prefix(Verb_MeleeAttack __instance, ref bool __result) { var verbMA = Traverse.Create(__instance); if (__instance.CasterPawn.stances.FullBodyBusy) { __result = false; return(false); } LocalTargetInfo target = verbMA.Field("currentTarget").GetValue <LocalTargetInfo>(); Thing thing = target.Thing; if (!__instance.CanHitTarget(thing)) { Log.Warning(string.Concat(new object[] { __instance.CasterPawn, " meleed ", thing, " from out of melee position." })); } __instance.CasterPawn.Drawer.rotator.Face(thing.DrawPos); if (!verbMA.Method("IsTargetImmobile", target).GetValue <bool>() && __instance.CasterPawn.skills != null) { __instance.CasterPawn.skills.Learn(SkillDefOf.Melee, 250f, false); } SoundDef soundDef; // We register the attacker and reset its ParryCounters MainController.ResetParryCounter(__instance.CasterPawn); switch (ResolveMeleeAttack(__instance.CasterPawn, thing, verbMA.Field("surpriseAttack").GetValue <bool>())) // 0 Miss, 1 Hit, 2 Parry, 3 Critical { case 1: // Hit __result = true; ApplyNormalDamageToTarget(__instance, __instance.CasterPawn, target); if (thing.def.category == ThingCategory.Building) { soundDef = verbMA.Method("SoundHitBuilding").GetValue <SoundDef>(); } else { soundDef = verbMA.Method("SoundHitPawn").GetValue <SoundDef>(); } break; case 2: // Parry ApplyParryDamageToTarget(__instance, __instance.CasterPawn, target); __result = false; soundDef = SoundDefOf.MetalHitImportant; break; case 3: // Critical ApplyCriticalDamageToTarget(__instance, __instance.CasterPawn, target); __result = true; soundDef = SoundDefOf.Thunder_OnMap; break; default: // Miss __result = false; soundDef = verbMA.Method("SoundMiss").GetValue <SoundDef>(); break; } soundDef.PlayOneShot(new TargetInfo(thing.Position, __instance.CasterPawn.Map, false)); __instance.CasterPawn.Drawer.Notify_MeleeAttackOn(thing); Pawn pawntemp = thing as Pawn; if (pawntemp != null && !pawntemp.Dead) { pawntemp.stances.StaggerFor(95); if (__instance.CasterPawn.MentalStateDef != MentalStateDefOf.SocialFighting || pawntemp.MentalStateDef != MentalStateDefOf.SocialFighting) { pawntemp.mindState.meleeThreat = __instance.CasterPawn; pawntemp.mindState.lastMeleeThreatHarmTick = Find.TickManager.TicksGame; } } __instance.CasterPawn.Drawer.rotator.FaceCell(thing.Position); if (__instance.CasterPawn.caller != null) { __instance.CasterPawn.caller.Notify_DidMeleeAttack(); } return(false); }
// RimWorld.Verb_MeleeAttack public static void DamageInfosToApply_PostFix(Verb_MeleeAttack __instance, ref IEnumerable <DamageInfo> __result, LocalTargetInfo target) { List <DamageInfo> newList = new List <DamageInfo>(); //__result = null; ThingWithComps ownerEquipment = __instance.ownerEquipment; if (ownerEquipment != null) { //Log.Message("1"); ThingComp comp = ownerEquipment.AllComps.FirstOrDefault((ThingComp x) => x is CompSlotLoadable); if (comp != null) { //Log.Message("2"); CompSlotLoadable compSlotLoadable = comp as CompSlotLoadable; if (compSlotLoadable.Slots != null && compSlotLoadable.Slots.Count > 0) { //Log.Message("3"); List <SlotLoadable> statSlots = compSlotLoadable.Slots.FindAll((SlotLoadable z) => !z.IsEmpty() && ((SlotLoadableDef)z.def).doesChangeStats == true); if (statSlots != null && statSlots.Count > 0) { //Log.Message("4"); foreach (SlotLoadable slot in statSlots) { //Log.Message("5"); CompSlottedBonus slotBonus = slot.SlotOccupant.TryGetComp <CompSlottedBonus>(); if (slotBonus != null) { //Log.Message("6"); Type superClass = __instance.GetType().BaseType; if (slotBonus.Props.damageDef != null) { //Log.Message("7"); float num = __instance.verbProps.AdjustedMeleeDamageAmount(__instance, __instance.CasterPawn, __instance.ownerEquipment); DamageDef def = __instance.verbProps.meleeDamageDef; BodyPartGroupDef weaponBodyPartGroup = null; HediffDef weaponHediff = null; if (__instance.CasterIsPawn) { //Log.Message("8"); if (num >= 1f) { weaponBodyPartGroup = __instance.verbProps.linkedBodyPartsGroup; if (__instance.ownerHediffComp != null) { weaponHediff = __instance.ownerHediffComp.Def; } } else { num = 1f; def = DamageDefOf.Blunt; } } //Log.Message("9"); ThingDef def2; if (__instance.ownerEquipment != null) { def2 = __instance.ownerEquipment.def; } else { def2 = __instance.CasterPawn.def; } //Log.Message("10"); Vector3 angle = (target.Thing.Position - __instance.CasterPawn.Position).ToVector3(); //Log.Message("11"); Thing caster = __instance.caster; //Log.Message("12"); int newdamage = GenMath.RoundRandom(num); // Log.Message("applying damage "+newdamage+" out of "+num); DamageInfo damageInfo = new DamageInfo(slotBonus.Props.damageDef, newdamage, -1f, caster, null, def2); damageInfo.SetBodyRegion(BodyPartHeight.Undefined, BodyPartDepth.Outside); damageInfo.SetWeaponBodyPartGroup(weaponBodyPartGroup); damageInfo.SetWeaponHediff(weaponHediff); damageInfo.SetAngle(angle); //Log.Message("13"); newList.Add(damageInfo); __result = newList.AsEnumerable <DamageInfo>(); } SlotBonusProps_VampiricEffect vampiricEffect = slotBonus.Props.vampiricHealChance; if (vampiricEffect != null) { //Log.Message("vampiricHealingCalled"); float randValue = Rand.Value; //Log.Message("randValue = " + randValue.ToString()); if (randValue <= vampiricEffect.chance) { MoteMaker.ThrowText(__instance.CasterPawn.DrawPos, __instance.CasterPawn.Map, "Vampiric Effect: Success", 6f); //MoteMaker.ThrowText(__instance.CasterPawn.DrawPos, __instance.CasterPawn.Map, "Success".Translate(), 6f); ApplyHealing(__instance.caster, vampiricEffect.woundLimit, target.Thing); } } } } } } } } }
public static void DamageInfosToApply_PostFix(Verb_MeleeAttack __instance, ref IEnumerable <DamageInfo> __result, LocalTargetInfo target) { var equipmentSource = __instance.EquipmentSource; if (equipmentSource == null) { return; } var casterPawn = __instance.CasterPawn; if (casterPawn == null) { return; } var slots = equipmentSource.GetSlots(); if (slots != null) { Vector3?damageAngle = null; var hediffCompSource = __instance.HediffCompSource; var verbProps = __instance.verbProps; List <DamageInfo> newList = null; foreach (var slot in slots) { // Skip slot if doesChangeStats (defaults to false) is false. if (!(slot.Def?.doesChangeStats ?? false)) { continue; } var slotBonus = slot.SlotOccupant?.TryGetCompSlottedBonus(); if (slotBonus != null) { var slotBonusProps = slotBonus.Props; var damageDef = slotBonusProps.damageDef; if (damageDef != null) { // This logic should be same as the first Verb_MeleeAttackDamage.DamageInfosToApply DamageInfo, // except using damageDef (and CasterPawn always being non-null as established above). var damageAmount = verbProps.AdjustedMeleeDamageAmount(__instance, casterPawn); var weaponBodyPartGroup = verbProps.AdjustedLinkedBodyPartsGroup(__instance.tool); HediffDef weaponHediff = null; damageAmount = Rand.Range(damageAmount * MeleeDamageRandomFactorMin, damageAmount * MeleeDamageRandomFactorMax); if (damageAmount >= 1f) { if (hediffCompSource != null) { weaponHediff = hediffCompSource.Def; } } else { damageAmount = 1f; damageDef = DamageDefOf.Blunt; } damageAngle ??= (target.Thing.Position - casterPawn.Position).ToVector3(); // TODO: armorPenetration should somehow be calculated via VerbProperties.AdjustedArmorPenetration. var damageInfo = new DamageInfo(damageDef, damageAmount, slotBonusProps.armorPenetration, -1f, casterPawn, weapon: equipmentSource.def); damageInfo.SetBodyRegion(BodyPartHeight.Undefined, BodyPartDepth.Outside); damageInfo.SetWeaponBodyPartGroup(weaponBodyPartGroup); damageInfo.SetWeaponHediff(weaponHediff); damageInfo.SetAngle(damageAngle.Value); if (newList == null) { newList = new List <DamageInfo>(); __result = newList; } newList.Add(damageInfo); } var vampiricEffect = slotBonusProps.vampiricHealChance; if (vampiricEffect != null) { var randValue = Rand.Value; //Log.Message("vampiricHealingCalled: randValue = " + randValue); if (randValue <= vampiricEffect.chance) { MoteMaker.ThrowText(casterPawn.DrawPos, casterPawn.Map, "Vampiric Effect: Success", 6f); // TODO: Translate()? damageAngle ??= (target.Thing.Position - casterPawn.Position).ToVector3(); ApplyHealing(casterPawn, vampiricEffect.woundLimit, vampiricEffect.amountRange, target.Pawn, vampiricEffect.damageDef, vampiricEffect.armorPenetration, damageAngle); } } } } } }