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);
        }
Пример #2
0
        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);
        }