Ejemplo n.º 1
0
        static void Postfix(ToHit __instance, ref string __result, AbstractActor attacker, Weapon weapon, ICombatant target,
                            Vector3 attackPosition, Vector3 targetPosition, LineOfFireLevel lofLevel, bool isCalledShot)
        {
            Mod.Log.Trace?.Write("TH:GAMD entered");

            if (attacker.HasMovedThisRound && attacker.JumpedLastRound ||
                (SharedState.CombatHUD?.SelectionHandler?.ActiveState != null &&
                 SharedState.CombatHUD?.SelectionHandler?.ActiveState is SelectionStateJump))
            {
                string localText = new Text(Mod.LocalizedText.Labels[ModText.LT_Label_Attacker_Jumped]).ToString();
                __result = string.Format("{0}{1} {2:+#;-#}; ", __result, localText, Mod.Config.ToHitSelfJumped);
            }

            // Check melee patches
            MeleeAttack selectedAttack = ModState.GetSelectedAttack(attacker);

            if (selectedAttack != null && weapon.Type == WeaponType.Melee)
            {
                foreach (KeyValuePair <string, int> kvp in selectedAttack.AttackModifiers)
                {
                    string localText = new Text(Mod.LocalizedText.Labels[kvp.Key]).ToString();
                    Mod.Log.Info?.Write($" - Found attack modifier for desc: {localText} = {kvp.Value}");

                    __result = string.Format("{0}{1} {2:+#;-#}; ", __result, localText, kvp.Value);
                }
            }
        }
        static void Postfix(CombatHUDWeaponSlot __instance, Weapon ___displayedWeapon, CombatHUD ___HUD)
        {
            if (__instance == null || ___displayedWeapon == null || ___HUD.SelectedActor == null ||
                !Mod.Config.Melee.FilterCanUseInMeleeWeaponsByAttack)
            {
                return;
            }

            MeleeAttack selectedAttack = ModState.GetSelectedAttack(___HUD.SelectedActor);

            if (selectedAttack != null)
            {
                Mod.UILog.Debug?.Write($"Checking ranged weapons attacker: {___HUD.SelectedActor.DistinctId()} using selectedAttack: {selectedAttack.Label}");

                // Check if the weapon can fire according to the select melee type
                bool isAllowed = selectedAttack.IsRangedWeaponAllowed(___displayedWeapon);
                Mod.UILog.Debug?.Write($"Ranged weapon '{___displayedWeapon.UIName}' can fire in melee by type? {isAllowed}");

                if (!isAllowed)
                {
                    Mod.UILog.Debug?.Write($"Disabling weapon from selection");
                    __instance.ToggleButton.isChecked = false;
                    Traverse showDisabledHexT = Traverse.Create(__instance).Method("ShowDisabledHex");
                    showDisabledHexT.GetValue();
                }
            }
            //else
            //{
            //    // No selected attack, so revert the weapon to the state it should have
            //    __instance.ToggleButton.isChecked = ___displayedWeapon.IsEnabled && !___displayedWeapon.IsDisabled;
            //}
        }
Ejemplo n.º 3
0
        static void Postfix(ToHit __instance, ref float __result, Mech attacker, ICombatant target, Vector3 targetPosition, MeleeAttackType meleeAttackType)
        {
            Mod.Log.Trace?.Write("TH:GAMM entered");

            if (__instance == null)
            {
                return;
            }

            MeleeAttack selectedAttack = ModState.GetSelectedAttack(attacker);

            if (selectedAttack == null)
            {
                return;
            }

            Mod.Log.Debug?.Write("Adding CBTBE modifiers to ToHit");
            int sumMod = 0;

            foreach (KeyValuePair <string, int> kvp in selectedAttack.AttackModifiers)
            {
                string localText = new Text(Mod.LocalizedText.Labels[kvp.Key]).ToString();
                Mod.Log.Debug?.Write($" - Found attack modifier: {localText} = {kvp.Value}, adding to sum modifier");
                sumMod += kvp.Value;
            }

            __result += (float)sumMod;
        }
Ejemplo n.º 4
0
        static void Postfix(Mech attacker, ICombatant target, ref MeleeAttackType __result)
        {
            MeleeAttack selectedAttack = ModState.GetSelectedAttack(attacker);

            if (selectedAttack != null)
            {
                Mod.Log.Info?.Write($"Forcing melee animation to {selectedAttack.AttackAnimation} for " +
                                    $"attacker: {attacker.DistinctId()} vs. target: {target.DistinctId()}");
                __result = selectedAttack.AttackAnimation;
            }
        }
Ejemplo n.º 5
0
        static void Postfix(SelectionStateJump __instance, ref float __result)
        {
            Mod.Log.Trace?.Write("SSJ:PSFS - entered.");

            MeleeAttack selectedAttack = ModState.GetSelectedAttack(__instance.SelectedActor);

            if (__instance.SelectedActor is Mech selectedMech && selectedAttack != null && __instance.PotentialMeleeTarget != null)
            {
                float newStability = selectedMech.CurrentStability + selectedAttack.AttackerInstability;
                float minStability = selectedMech.GetMinStability(StabilityChangeSource.DFA, newStability);
                Mod.Log.Debug?.Write($"Stability change for {CombatantUtils.Label(selectedMech)} => " +
                                     $"current: {selectedMech.CurrentStability}  projectedNew: {selectedAttack.AttackerInstability}  " +
                                     $"totalChange: {newStability}  afterDump: {minStability}");
                __result = minStability;
            }
        }
Ejemplo n.º 6
0
        static void Postfix(MechMeleeSequence __instance, Mech mech, ICombatant meleeTarget,
                            List <Weapon> requestedWeapons, Vector3 desiredMeleePosition)
        {
            try
            {
                // Find the selectedAttack we should use for this sequence
                MeleeAttack selectedAttack = ModState.GetSelectedAttack(mech);
                if (selectedAttack == null)
                {
                    Mod.MeleeLog.Warn?.Write($"Melee sequence {__instance.SequenceGUID} has no pre-selected attack state, will have to autoselected. Let Frost know as this should not happen!");
                    MeleeState meleeState = ModState.AddorUpdateMeleeState(mech, desiredMeleePosition, meleeTarget as AbstractActor);
                    if (meleeState == null)
                    {
                        Mod.Log.Error?.Write($"Could not build melee state for selected melee attack - this should NEVER happen!");
                        return;
                    }
                    selectedAttack = meleeState.GetHighestDamageAttackForUI();
                }

                if (selectedAttack == null || !selectedAttack.IsValid)
                {
                    Mod.Log.Error?.Write($"Could not select a valid attack for the selected sequence - this should NEVER happen!");
                    return;
                }

                // Check to see if we have an imaginary weapon to use; if not create it
                (Weapon meleeWeapon, Weapon dfaWeapon)weapons = ModState.GetFakedWeapons(mech);

                // Create the weapon + representation
                ModState.AddOrUpdateMeleeSequenceState(__instance.SequenceGUID, selectedAttack, weapons.meleeWeapon);

                StringBuilder sb = new StringBuilder();
                foreach (Weapon weapon in requestedWeapons)
                {
                    sb.Append(weapon.UIName);
                    sb.Append(",");
                }
                Mod.MeleeLog.Info?.Write($"  -- Initial requested weapons: {sb}");

                isValid = true;
            }
            catch (Exception e)
            {
                Mod.Log.Error?.Write(e, $"Failed to initialize Melee sequence {__instance.SequenceGUID}!");
            }
        }
        static void Postfix(CombatHUDWeaponSlot __instance, Weapon ___displayedWeapon, CombatHUD ___HUD, int ___displayedHeat)
        {
            if (__instance == null || ___displayedWeapon == null || ___HUD.SelectedActor == null)
            {
                return;
            }

            Mod.UILog.Trace?.Write("CHUDWS:GTTS entered");

            // Check melee patches
            MeleeAttack selectedAttack = ModState.GetSelectedAttack(___HUD.SelectedActor);

            if (selectedAttack != null && ___displayedWeapon.Type == WeaponType.Melee)
            {
                if (___displayedWeapon.WeaponSubType == WeaponSubType.Melee)
                {
                    float targetDamage = selectedAttack.TargetDamageClusters.Sum();
                    Mod.UILog.Trace?.Write($" - Extra Strings for type: {___displayedWeapon.Type} && {___displayedWeapon.WeaponSubType} " +
                                           $"=> Damage: {targetDamage}  instability: {selectedAttack.TargetInstability}  " +
                                           $"heat: {___displayedHeat}");
                    __instance.ToolTipHoverElement.ExtraStrings = new List <Text>
                    {
                        new Text(Mod.LocalizedText.Labels[ModText.LT_Label_Weapon_Hover_Damage], targetDamage),
                        new Text(Mod.LocalizedText.Labels[ModText.LT_Label_Weapon_Hover_Instability], selectedAttack.TargetInstability),
                        new Text(Mod.LocalizedText.Labels[ModText.LT_Label_Weapon_Hover_Heat], ___displayedHeat)
                    };
                }
                else if (___displayedWeapon.WeaponSubType == WeaponSubType.DFA)
                {
                    float targetDamage = selectedAttack.TargetDamageClusters.Sum();
                    Mod.UILog.Trace?.Write($" - Extra Strings for type: {___displayedWeapon.Type} && {___displayedWeapon.WeaponSubType} " +
                                           $"=> Damage: {targetDamage}  instability: {selectedAttack.TargetInstability}  " +
                                           $"heat: {___displayedHeat}");
                    __instance.ToolTipHoverElement.ExtraStrings = new List <Text>
                    {
                        new Text(Mod.LocalizedText.Labels[ModText.LT_Label_Weapon_Hover_Damage], targetDamage),
                        new Text(Mod.LocalizedText.Labels[ModText.LT_Label_Weapon_Hover_Instability], selectedAttack.TargetInstability),
                        new Text(Mod.LocalizedText.Labels[ModText.LT_Label_Weapon_Hover_Heat], ___displayedHeat)
                    };
                }
            }
        }
        static void Postfix(CombatHUDWeaponSlot __instance, ICombatant target, Weapon ___displayedWeapon, CombatHUD ___HUD)
        {
            if (__instance == null || ___displayedWeapon == null || ___HUD.SelectedActor == null || target == null)
            {
                return;
            }

            Mod.UILog.Trace?.Write("CHUDWS:SHC entered");

            Traverse addToolTipDetailT = Traverse.Create(__instance)
                                         .Method("AddToolTipDetail", new Type[] { typeof(string), typeof(int) });

            AbstractActor actor = __instance.DisplayedWeapon.parent;

            if (actor.HasMovedThisRound && actor.JumpedLastRound ||
                (SharedState.CombatHUD?.SelectionHandler?.ActiveState != null &&
                 SharedState.CombatHUD?.SelectionHandler?.ActiveState is SelectionStateJump))
            {
                string localText = new Text(Mod.LocalizedText.Labels[ModText.LT_Label_Attacker_Jumped]).ToString();
                Mod.UILog.Debug?.Write($" Adding Attacker Jump modifier of: {Mod.Config.ToHitSelfJumped}");
                addToolTipDetailT.GetValue(new object[] { localText, Mod.Config.ToHitSelfJumped });
            }

            // Check melee patches
            MeleeAttack selectedAttack = ModState.GetSelectedAttack(___HUD.SelectedActor);

            if (selectedAttack != null && ___displayedWeapon.Type == WeaponType.Melee)
            {
                if (___displayedWeapon.WeaponSubType == WeaponSubType.Melee ||
                    ___displayedWeapon.WeaponSubType == WeaponSubType.DFA)
                {
                    foreach (KeyValuePair <string, int> kvp in selectedAttack.AttackModifiers)
                    {
                        string localText = new Text(Mod.LocalizedText.Labels[kvp.Key]).ToString();
                        Mod.UILog.Debug?.Write($" - SetHitChance found attack modifier: {localText} = {kvp.Value}");
                        addToolTipDetailT.GetValue(new object[] { localText, kvp.Value });
                    }
                }
            }
        }
Ejemplo n.º 9
0
        static void Postfix(SelectionStateMove __instance, ref float __result)
        {
            Mod.Log.Trace?.Write("SSM:PSFS - entered.");

            MeleeAttack selectedAttack = ModState.GetSelectedAttack(__instance.SelectedActor);

            if (__instance.SelectedActor is Mech selectedMech && selectedAttack != null && __instance.PotentialMeleeTarget != null)
            {
                float newStability = selectedMech.CurrentStability + selectedAttack.AttackerInstability;

                List <WayPoint>       waypoints    = ActorMovementSequence.ExtractWaypointsFromPath(selectedMech, selectedMech.Pathing.CurrentPath, selectedMech.Pathing.ResultDestination, selectedMech.Pathing.CurrentMeleeTarget, selectedMech.Pathing.MoveType);
                StabilityChangeSource changeSource = StabilityChangeSource.Moving;
                if (WayPoint.GetDistFromWaypointList(selectedMech.CurrentPosition, waypoints) < 1f)
                {
                    changeSource = StabilityChangeSource.RemainingStationary;
                }
                float minStability = selectedMech.GetMinStability(changeSource, newStability);
                Mod.Log.Debug?.Write($"Stability change for {CombatantUtils.Label(selectedMech)} => " +
                                     $"current: {selectedMech.CurrentStability}  projectedNew: {selectedAttack.AttackerInstability}  " +
                                     $"totalChange: {newStability}  afterDump: {minStability}");
                __result = minStability;
            }
        }
        static void Postfix(CombatHUDWeaponSlot __instance, Weapon ___displayedWeapon, CombatHUD ___HUD)
        {
            if (__instance == null || ___displayedWeapon == null || ___HUD.SelectedActor == null)
            {
                return;
            }
            Mod.UILog.Trace?.Write("CHUDWS:UDFAW entered");

            MeleeAttack selectedAttack = ModState.GetSelectedAttack(___HUD.SelectedActor);

            if (selectedAttack == null || !(selectedAttack is DFAAttack))
            {
                Mod.UILog.Debug?.Write("Defaulting DFA damage.");

                Mech  parentMech   = ___displayedWeapon.parent as Mech;
                float targetDamage = parentMech.DFATargetDamage();
                __instance.DamageText.SetText($"{targetDamage}");
            }
            else if (selectedAttack is DFAAttack)
            {
                Mod.UILog.Debug?.Write("Updating labels for DFA state.");

                float totalDamage = selectedAttack.TargetDamageClusters.Sum();
                if (selectedAttack.TargetDamageClusters.Length > 1)
                {
                    int    avgDamage = (int)Math.Floor(totalDamage / selectedAttack.TargetDamageClusters.Length);
                    string damageS   = $"{avgDamage} <size=80%>(x{selectedAttack.TargetDamageClusters.Length})";
                    Mod.UILog.Debug?.Write($"  - damageS is: {damageS}");
                    __instance.DamageText.SetText(damageS);
                }
                else
                {
                    __instance.DamageText.SetText($"{totalDamage}");
                    Mod.UILog.Debug?.Write($"  - damageS is: {totalDamage}");
                }
            }
        }
        static void Postfix(CombatHUDWeaponSlot __instance, Weapon ___displayedWeapon, CombatHUD ___HUD)
        {
            if (__instance == null || ___displayedWeapon == null || ___HUD.SelectedActor == null)
            {
                return;
            }
            Mod.UILog.Trace?.Write("CHUDWS:UMW entered");

            MeleeAttack selectedAttack = ModState.GetSelectedAttack(___HUD.SelectedActor);

            if (selectedAttack == null || selectedAttack is DFAAttack)
            {
                string weaponLabel = new Text(Mod.LocalizedText.Labels[ModText.LT_Label_Weapon_Panel_Melee_Weapon],
                                              new object[] { Mod.LocalizedText.Labels[ModText.LT_Label_Weapon_Panel_Melee_No_Attack_Type] }
                                              ).ToString();
                __instance.WeaponText.SetText(weaponLabel);

                Mech parentMech = ___displayedWeapon.parent as Mech;

                float  kickDam    = parentMech.KickDamage();
                float  punchDam   = parentMech.PunchDamage();
                float  weapDam    = parentMech.PhysicalWeaponDamage();
                string damageText = new Text(Mod.LocalizedText.Labels[ModText.LT_Label_Weapon_Panel_Melee_No_Attack_Type_Damage],
                                             new object[] { weapDam, punchDam, kickDam }
                                             ).ToString();
                __instance.DamageText.SetText(damageText);
            }
            else if (selectedAttack is ChargeAttack || selectedAttack is KickAttack || selectedAttack is PunchAttack || selectedAttack is WeaponAttack)
            {
                string attackName = "UNKNOWN";
                if (selectedAttack is ChargeAttack)
                {
                    attackName = Mod.LocalizedText.Labels[ModText.LT_Label_Melee_Type_Charge];
                }
                else if (selectedAttack is KickAttack)
                {
                    attackName = Mod.LocalizedText.Labels[ModText.LT_Label_Melee_Type_Kick];
                }
                else if (selectedAttack is WeaponAttack)
                {
                    attackName = Mod.LocalizedText.Labels[ModText.LT_Label_Melee_Type_Physical_Weapon];
                }
                else if (selectedAttack is PunchAttack)
                {
                    attackName = Mod.LocalizedText.Labels[ModText.LT_Label_Melee_Type_Punch];
                }

                string weaponLabel = new Text(Mod.LocalizedText.Labels[ModText.LT_Label_Weapon_Panel_Melee_Weapon],
                                              new object[] { attackName }
                                              ).ToString();
                __instance.WeaponText.SetText(weaponLabel);

                float totalDamage = selectedAttack.TargetDamageClusters.Sum();
                if (selectedAttack.TargetDamageClusters.Length > 1)
                {
                    int avgDamage = (int)Math.Floor(totalDamage / selectedAttack.TargetDamageClusters.Length);
                    __instance.DamageText.SetText($"{avgDamage} <size=80%>(x{selectedAttack.TargetDamageClusters.Length})");
                }
                else
                {
                    __instance.DamageText.SetText($"{totalDamage}");
                }

                ___displayedWeapon.StatCollection.Set <float>(ModStats.HBS_Weapon_DamagePerShot, totalDamage);
                ___displayedWeapon.StatCollection.Set <float>(ModStats.HBS_Weapon_Instability, selectedAttack.TargetInstability);
                CustAmmoCategories.DamageModifiersCache.ClearDamageCache(___displayedWeapon);
            }
        }
        static bool Prefix(CombatHUDFireButton __instance)
        {
            if (__instance == null || __instance.gameObject == null)
            {
                return(true);
            }

            Mod.UILog.Info?.Write($"CHUDFB - OnClick FIRED for FireMode: {__instance.CurrentFireMode}");

            bool shouldReturn = true;
            CombatHUDAttackModeSelector selector = SharedState.CombatHUD.AttackModeSelector;

            if (__instance.gameObject.name == ModConsts.ChargeFB_GO_ID)
            {
                MeleeState meleeState = ModState.GetMeleeState(
                    SharedState.CombatHUD.SelectionHandler.ActiveState.SelectedActor,
                    SharedState.CombatHUD.SelectionHandler.ActiveState.PreviewPos);
                ModState.AddOrUpdateSelectedAttack(
                    SharedState.CombatHUD.SelectionHandler.ActiveState.SelectedActor,
                    meleeState.Charge
                    );
                Mod.UILog.Info?.Write("User selected Charge button");
                shouldReturn = false;
            }
            else if (__instance.gameObject.name == ModConsts.KickFB_GO_ID)
            {
                MeleeState meleeState = ModState.GetMeleeState(
                    SharedState.CombatHUD.SelectionHandler.ActiveState.SelectedActor,
                    SharedState.CombatHUD.SelectionHandler.ActiveState.PreviewPos);
                ModState.AddOrUpdateSelectedAttack(
                    SharedState.CombatHUD.SelectionHandler.ActiveState.SelectedActor,
                    meleeState.Kick
                    );
                Mod.UILog.Info?.Write("User selected Kick button");
                shouldReturn = false;
            }
            else if (__instance.gameObject.name == ModConsts.PhysicalWeaponFB_GO_ID)
            {
                MeleeState meleeState = ModState.GetMeleeState(
                    SharedState.CombatHUD.SelectionHandler.ActiveState.SelectedActor,
                    SharedState.CombatHUD.SelectionHandler.ActiveState.PreviewPos);
                ModState.AddOrUpdateSelectedAttack(
                    SharedState.CombatHUD.SelectionHandler.ActiveState.SelectedActor,
                    meleeState.PhysicalWeapon
                    );
                Mod.UILog.Info?.Write("User selected PhysWeap button");
                shouldReturn = false;
            }
            else if (__instance.gameObject.name == ModConsts.PunchFB_GO_ID)
            {
                MeleeState meleeState = ModState.GetMeleeState(
                    SharedState.CombatHUD.SelectionHandler.ActiveState.SelectedActor,
                    SharedState.CombatHUD.SelectionHandler.ActiveState.PreviewPos);
                ModState.AddOrUpdateSelectedAttack(
                    SharedState.CombatHUD.SelectionHandler.ActiveState.SelectedActor,
                    meleeState.Punch
                    );
                Mod.UILog.Info?.Write("User selected Punch button");
                shouldReturn = false;
            }
            else
            {
                MeleeAttack selectedAttack2 = ModState.GetSelectedAttack(SharedState.CombatHUD?.SelectionHandler?.ActiveState?.SelectedActor);
                if (selectedAttack2 != null)
                {
                    Mod.UILog.Info?.Write("OnClick from generic CHUDFB with selected type, short-cutting to action.");

                    // Disable the buttons to prevent accidental clicks?
                    if (selectedAttack2 is ChargeAttack)
                    {
                        ModState.ChargeFB.CurrentFireMode = CombatHUDFireButton.FireMode.None;
                    }
                    if (selectedAttack2 is KickAttack)
                    {
                        ModState.KickFB.CurrentFireMode = CombatHUDFireButton.FireMode.None;
                    }
                    if (selectedAttack2 is WeaponAttack)
                    {
                        ModState.PhysicalWeaponFB.CurrentFireMode = CombatHUDFireButton.FireMode.None;
                    }
                    if (selectedAttack2 is PunchAttack)
                    {
                        ModState.PunchFB.CurrentFireMode = CombatHUDFireButton.FireMode.None;
                    }

                    return(true);
                }
            }

            MeleeAttack selectedAttack = ModState.GetSelectedAttack(SharedState.CombatHUD?.SelectionHandler?.ActiveState?.SelectedActor);

            if (selectedAttack != null)
            {
                Mod.UILog.Debug?.Write("Enabling description container for melee attack");
                selector.DescriptionContainer.SetActive(true);
                selector.DescriptionContainer.gameObject.SetActive(true);

                HashSet <string> descriptonNotes = selectedAttack.DescriptionNotes;
                string           description     = String.Join(", ", descriptonNotes);
                Mod.UILog.Debug?.Write($"Aggregate description is: {description}");

                selector.DescriptionText.SetText(description);
                selector.DescriptionText.ForceMeshUpdate(true);

                // TODO: Update weapon damage instead?

                // Update the weapon strings
                SharedState.CombatHUD.WeaponPanel.RefreshDisplayedWeapons();
            }

            return(shouldReturn);
        }