예제 #1
0
        private static DialogueContent BuildContent(CastDef castDef, List <string> quips)
        {
            string quip          = quips[Mod.Random.Next(0, quips.Count)];
            string localizedQuip = new Localize.Text(quip).ToString();

            return(Coordinator.BuildDialogueContent(castDef, localizedQuip, Color.white));
        }
예제 #2
0
        // Generates a random quip and publishes it
        public static void PlayQuip(AbstractActor source, List <string> quips, float showDuration = 3)
        {
            CastDef         castDef = Coordinator.CreateCast(source);
            DialogueContent content = BuildContent(castDef, quips);

            source.Combat.MessageCenter.PublishMessage(new CustomDialogMessage(source, content, showDuration));
        }
예제 #3
0
        public static DialogueContent BuildDialogueContent(CastDef castDef, string dialogue, Color dialogueColor)
        {
            if (castDef == null || String.IsNullOrEmpty(castDef.id) || castDef.defaultEmotePortrait == null || String.IsNullOrEmpty(castDef.defaultEmotePortrait.portraitAssetPath))
            {
                Mod.Log.Warn?.Write("Was passed a castDef with an empty ID - we can't handle this!");
                return(null);
            }

            Mod.Log.Info?.Write($"Creating dialogueContent for castDef: {castDef.id}");

            DialogueContent content = new DialogueContent(dialogue, dialogueColor, castDef.id, null, null,
                                                          DialogCameraDistance.Medium, DialogCameraHeight.Default, 0);

            // ContractInitialize normally sets the castDef on the content... no need, since we have the actual ref
            Traverse castDefT = Traverse.Create(content).Field("castDef");

            castDefT.SetValue(castDef);

            // Initialize the active contract's team settings
            ApplyCastDef(content);

            // Load the default emote portrait
            Traverse dialogueSpriteCacheT = Traverse.Create(content).Field("dialogueSpriteCache");
            Dictionary <string, Sprite> dialogueSpriteCache = dialogueSpriteCacheT.GetValue <Dictionary <string, Sprite> >();

            Mod.Log.Debug?.Write($"Populating dialogueContent with sprite from path: {castDef.defaultEmotePortrait.portraitAssetPath}");
            dialogueSpriteCache[castDef.defaultEmotePortrait.portraitAssetPath] = ModState.Portraits[castDef.defaultEmotePortrait.portraitAssetPath];

            return(content);
        }
예제 #4
0
        public static CastDef CreateCast(CombatGameState combat, string sourceGUID, Team team, string employerFactionName = "Support")
        {
            string castDefId = $"castDef_{sourceGUID}";

            if (combat.DataManager.CastDefs.Exists(castDefId))
            {
                return(combat.DataManager.CastDefs.Get(castDefId));
            }

            FactionValue actorFaction  = team?.FactionValue;
            bool         factionExists = actorFaction.Name != "INVALID_UNSET" && actorFaction.Name != "NoFaction" &&
                                         actorFaction.FactionDefID != null && actorFaction.FactionDefID.Length != 0 ? true : false;

            if (factionExists)
            {
                Mod.Log.Debug?.Write($"Found factionDef for id:{actorFaction}");
                string     factionId          = actorFaction?.FactionDefID;
                FactionDef employerFactionDef = UnityGameInstance.Instance.Game.DataManager.Factions.Get(factionId);
                if (employerFactionDef == null)
                {
                    Mod.Log.Error?.Write($"Error finding FactionDef for faction with id '{factionId}'");
                }
                else
                {
                    employerFactionName = employerFactionDef.Name.ToUpper();
                }
            }
            else
            {
                Mod.Log.Debug?.Write($"FactionDefID does not exist for faction: {actorFaction}");
            }

            CastDef newCastDef = new CastDef
            {
                // Temp test data
                FactionValue  = actorFaction,
                firstName     = $"{employerFactionName} -",
                showRank      = false,
                showCallsign  = true,
                showFirstName = true,
                showLastName  = false
            };

            // DisplayName order is first, callsign, lastname

            newCastDef.id = castDefId;
            string portraitPath = GetRandomPortraitPath();

            newCastDef.callsign = GetRandomCallsign();
            Mod.Log.Debug?.Write($" Generated cast with callsign: {newCastDef.callsign} and DisplayName: {newCastDef.DisplayName()} using portrait: '{portraitPath}'");

            // Load the associated portrait
            newCastDef.defaultEmotePortrait.portraitAssetPath = portraitPath;
            Mod.Log.Debug?.Write($"Generated random portrait: {portraitPath}.");

            ((DictionaryStore <CastDef>)UnityGameInstance.BattleTechGame.DataManager.CastDefs).Add(newCastDef.id, newCastDef);

            return(newCastDef);
        }
예제 #5
0
        public static void PlayQuip(CombatGameState combat, string sourceGUID, Team team,
                                    string employerFactionName, List <string> quips, float showDuration = 3)
        {
            CastDef         castDef = Coordinator.CreateCast(combat, sourceGUID, team, employerFactionName);
            DialogueContent content = BuildContent(castDef, quips);

            combat.MessageCenter.PublishMessage(new CustomDialogMessage(sourceGUID, content, showDuration));
        }
예제 #6
0
        public static CastDef CreateCast()
        {
            Contract     contract            = MissionControl.Instance.CurrentContract;
            FactionValue employerFaction     = contract.GetTeamFaction(EncounterRules.EMPLOYER_TEAM_ID);
            string       factionId           = employerFaction.FactionDefID;
            string       employerFactionName = "Military Support";

            if (employerFaction.Name != "INVALID_UNSET" && employerFaction.Name != "NoFaction")
            {
                FactionDef employerFactionDef = UnityGameInstance.Instance.Game.DataManager.Factions.Get(factionId);
                if (employerFactionDef == null)
                {
                    Main.Logger.LogError($"[RuntimeCastFactory] Error finding FactionDef for faction with id '{factionId}'");
                }
                employerFactionName = employerFactionDef.Name.ToUpper();
            }

            string employerFactionKey = (employerFaction.Name != "INVALID_UNSET" && employerFaction.Name != "NoFaction") ? "All" : employerFaction.ToString();

            string gender       = DataManager.Instance.GetRandomGender();
            string firstName    = DataManager.Instance.GetRandomFirstName(gender, employerFactionKey);
            string lastName     = DataManager.Instance.GetRandomLastName(employerFactionKey);
            string rank         = DataManager.Instance.GetRandomRank(employerFactionKey);
            string portraitPath = DataManager.Instance.GetRandomPortraitPath(gender);
            Gender btGender     = Gender.Male;

            if (gender == "Female")
            {
                btGender = Gender.Female;
            }
            if (gender == "Unspecified")
            {
                btGender = Gender.NonBinary;
            }

            CastDef runtimeCastDef = new CastDef();

            // Temp test data
            runtimeCastDef.id            = $"castDef_{rank}{firstName}{lastName}";
            runtimeCastDef.internalName  = $"{rank}{firstName}{lastName}";
            runtimeCastDef.firstName     = $"{rank} {firstName}";
            runtimeCastDef.lastName      = lastName;
            runtimeCastDef.callsign      = rank;
            runtimeCastDef.rank          = employerFactionName;
            runtimeCastDef.gender        = btGender;
            runtimeCastDef.FactionValue  = employerFaction;
            runtimeCastDef.showRank      = true;
            runtimeCastDef.showFirstName = true;
            runtimeCastDef.showCallsign  = false;
            runtimeCastDef.showLastName  = true;
            runtimeCastDef.defaultEmotePortrait.portraitAssetPath = portraitPath;

            ((DictionaryStore <CastDef>)UnityGameInstance.BattleTechGame.DataManager.CastDefs).Add(runtimeCastDef.id, runtimeCastDef);

            return(runtimeCastDef);
        }
        // Generates a random quip and publishes it
        public static void PublishQuip(AbstractActor source, List <string> quips)
        {
            string quip          = quips[Mod.Random.Next(0, quips.Count)];
            string localizedQuip = new Localize.Text(quip).ToString();

            CastDef         castDef = Coordinator.CreateCast(source);
            DialogueContent content = Coordinator.BuildDialogueContent(castDef, localizedQuip, Color.white);

            Mod.Log.Info?.Write($"Publishing quip: {localizedQuip} with portrait: {castDef.defaultEmotePortrait.portraitAssetPath}");
            source.Combat.MessageCenter.PublishMessage(new CustomDialogMessage(source, content, 3));
        }
예제 #8
0
 public AddDialogueChunk(string dialogueGuid, string dialogChunkName, string debugDescription, string cameraTargetGuid, bool usePresetDialog = true, string presetDialog = null, CastDef castDef = null)
 {
     this.dialogueGuid     = dialogueGuid;
     this.dialogChunkName  = dialogChunkName;
     this.debugDescription = debugDescription;
     this.cameraTargetGuid = cameraTargetGuid;
     if (usePresetDialog)
     {
         this.presetDialog = presetDialog;
     }
     this.castDef = castDef;
 }
예제 #9
0
        // Generates a random quip and publishes it
        public static void PublishQuip(AbstractActor source, List <string> quips)
        {
            string quip          = quips[Mod.Random.Next(0, quips.Count)];
            string localizedQuip = new Localize.Text(quip).ToString();

            CastDef         castDef = Coordinator.CreateCast(source);
            DialogueContent content = new DialogueContent(
                localizedQuip, Color.white, castDef.id, null, null, DialogCameraDistance.Medium, DialogCameraHeight.Default, 0
                );

            content.ContractInitialize(source.Combat);
            source.Combat.MessageCenter.PublishMessage(new CustomDialogMessage(source, content, 3));
        }
예제 #10
0
        public static ConversationContent CreateConversationContent(string presetDialogue, string cameraTargetGuid, CastDef cast = null)
        {
            CastDef castDef = (cast == null) ? RuntimeCastFactory.CreateCast() : cast;

            if (MissionControl.Instance.IsSkirmish())
            {
                presetDialogue = Regex.Replace(presetDialogue, "{COMMANDER\\..+}", "Commander");
            }

            DialogueContent dialogueContent1 = new DialogueContent(
                presetDialogue, Color.white, castDef.id, "",
                cameraTargetGuid, BattleTech.DialogCameraDistance.Medium, BattleTech.DialogCameraHeight.Default, -1
                );

            ConversationContent conversation = new ConversationContent("Conversation MC Test 1", new DialogueContent[] { dialogueContent1 });

            return(conversation);
        }
        public static bool Prefix(TeamOverride __instance, Contract contract, DataManager dataManager,
                                  ref Contract ___contract, ref DataManager ___dataManager, ref string ___teamLeaderCastDefId, ref List <LanceOverride> ___lanceOverrideList, ref Faction ___faction)
        {
            ___contract    = contract;
            ___dataManager = dataManager;

            if (___teamLeaderCastDefId == CastDef.castDef_TeamLeader_Current)
            {
                ___teamLeaderCastDefId = CastDef.GetCombatCastDefIdFromFaction(___faction, contract.BattleTechGame.DataManager);
            }

            for (int i = 0; i < ___lanceOverrideList.Count; ++i)
            {
                LanceOverride lanceOverride = ___lanceOverrideList[i];
                lanceOverrides[lanceOverride.GetHashCode()] = __instance;
                IRBT14MadlibsFix.Logger.Log($"TO:RML setting teamOverride:[{__instance.GetHashCode()}] for lanceOverride:[{lanceOverride.GetHashCode()}]");
                lanceOverride.RunMadLibs(contract);
            }

            return(false);
        }
예제 #12
0
        public static DialogueGameLogic CreateDialogLogic(GameObject parent, string name, string cameraTargetGuid, string presetDialogue = null, CastDef castDef = null)
        {
            GameObject dialogueGameLogicGo = CreateDialogLogicGameObject(parent, name);

            DialogueGameLogic dialogueGameLogic = dialogueGameLogicGo.AddComponent <DialogueGameLogic>();

            if (presetDialogue == null)
            {
                presetDialogue = DataManager.Instance.GetRandomDialogue("AllyDrop",
                                                                        MissionControl.Instance.CurrentContractType, MissionControl.Instance.EncounterRulesName);
            }
            dialogueGameLogic.conversationContent = CreateConversationContent(presetDialogue, cameraTargetGuid, castDef);

            return(dialogueGameLogic);
        }
예제 #13
0
        public static void Prefix(AttackStackSequence __instance, MessageCenterMessage message)
        {
            stopwatch.Restart();
            if (ShouldSkipProcessing(__instance, message))
            {
                return;
            }

            if (!(message is AttackCompleteMessage attackCompleteMessage))
            {
                return;
            }

            var director = __instance.directorSequences;

            if (director == null)
            {
                return;
            }

            LogReport(new string('═', 46));
            LogReport($"{director[0].attacker.DisplayName} attacks {director[0].chosenTarget.DisplayName}");

            // get the attacker in case they have mech quirks
            AbstractActor defender = null;

            switch (director[0]?.chosenTarget)
            {
            case Vehicle _:
                defender = (Vehicle)director[0]?.chosenTarget;
                break;

            case Mech _:
                defender = (Mech)director[0]?.chosenTarget;
                break;
            }

            // a building or turret?
            if (defender == null)
            {
                LogDebug("Not a mech or vehicle");
                return;
            }

            if (defender.IsDead || defender.IsFlaggedForDeath)
            {
                return;
            }

            var attacker = director[0].attacker;
            var index    = GetActorIndex(defender);

            if (modSettings.OneChangePerTurn &&
                TrackedActors[index].PanicWorsenedRecently)
            {
                LogDebug($"OneChangePerTurn {defender.Nickname} - abort");
                return;
            }

            if (!modSettings.AlwaysPanic &&
                !ShouldPanic(defender, attackCompleteMessage.attackSequence))
            {
                return;
            }

            // automatically eject a klutzy pilot on knockdown with an additional roll failing on 13
            if (defender.IsFlaggedForKnockdown)
            {
                var defendingMech = (Mech)defender;
                if (defendingMech.pilot.pilotDef.PilotTags.Contains("pilot_klutz"))
                {
                    if (Random.Range(1, 100) == 13)
                    {
                        defender.Combat.MessageCenter.PublishMessage(new AddSequenceToStackMessage
                                                                         (new ShowActorInfoSequence(defender, "WOOPS!", FloatieMessage.MessageNature.Debuff, false)));
                        LogReport("Very klutzy!");
                        return;
                    }
                }
            }

            // store saving throw
            // check it against panic
            // check it again ejection
            var savingThrow = SavingThrows.GetSavingThrow(defender, attacker);

            Mech_AddExternalHeat_Patch.heatDamage = 0;
            // panic saving throw
            if (SavingThrows.SavedVsPanic(defender, savingThrow))
            {
                return;
            }

            // stop if pilot isn't Panicked
            if (TrackedActors[index].PanicStatus != PanicStatus.Panicked)
            {
                return;
            }

            // eject saving throw
            if (!modSettings.AlwaysPanic &&
                SavingThrows.SavedVsEject(defender, savingThrow))
            {
                return;
            }

            // ejecting
            // random phrase
            if (modSettings.EnableEjectPhrases &&
                defender is Mech &&
                Random.Range(1, 100) <= modSettings.EjectPhraseChance)
            {
                var ejectMessage = ejectPhraseList[Random.Range(0, ejectPhraseList.Count)];
                // thank you IRBTModUtils
                //LogDebug($"defender {defender}");
                var castDef = Coordinator.CreateCast(defender);
                var content = new DialogueContent(
                    ejectMessage, Color.white, castDef.id, null, null, DialogCameraDistance.Medium, DialogCameraHeight.Default, 0
                    );
                content.ContractInitialize(defender.Combat);
                defender.Combat.MessageCenter.PublishMessage(new PanicSystemDialogMessage(defender, content, 6));
            }

            // remove effects, to prevent exceptions that occur for unknown reasons
            var combat           = UnityGameInstance.BattleTechGame.Combat;
            var effectsTargeting = combat.EffectManager.GetAllEffectsTargeting(defender);

            foreach (var effect in effectsTargeting)
            {
                // some effects removal throw, so silently drop them
                try
                {
                    defender.CancelEffect(effect);
                }
                catch
                {
                    // ignored
                }
            }

            if (modSettings.VehiclesCanPanic &&
                defender is Vehicle)
            {
                // make the regular Pilot Ejected floatie not appear, for this ejection
                var original = AccessTools.Method(typeof(BattleTech.VehicleRepresentation), "PlayDeathFloatie");
                var prefix   = AccessTools.Method(typeof(VehicleRepresentation), nameof(VehicleRepresentation.PrefixDeathFloatie));
                harmony.Patch(original, new HarmonyMethod(prefix));
                defender.EjectPilot(defender.GUID, attackCompleteMessage.stackItemUID, DeathMethod.PilotEjection, true);
                harmony.Unpatch(original, HarmonyPatchType.Prefix);
                CastDef         castDef = Coordinator.CreateCast(defender);
                DialogueContent content = new DialogueContent(
                    "Destroy the tech, let's get outta here!", Color.white, castDef.id, null, null, DialogCameraDistance.Medium, DialogCameraHeight.Default, 0
                    );
                content.ContractInitialize(defender.Combat);
                defender.Combat.MessageCenter.PublishMessage(new PanicSystemDialogMessage(defender, content, 5));
            }
            else
            {
                defender.EjectPilot(defender.GUID, attackCompleteMessage.stackItemUID, DeathMethod.PilotEjection, false);
            }

            LogReport("Ejected");
            //LogDebug($"Runtime {stopwatch.Elapsed}");

            if (!modSettings.CountAsKills)
            {
                return;
            }

            try
            {
                // this seems pretty convoluted
                var attackerPilot = combat.AllMechs.Where(mech => mech.pilot.Team.IsLocalPlayer)
                                    .Where(x => x.PilotableActorDef == attacker.PilotableActorDef).Select(y => y.pilot).FirstOrDefault();

                var statCollection = attackerPilot?.StatCollection;
                if (statCollection == null)
                {
                    return;
                }

                if (defender is Mech)
                {
                    // add UI icons.. and pilot history?   ... MechsKilled already incremented??
                    // TODO count kills recorded on pilot history so it's not applied twice
                    statCollection.Set("MechsKilled", attackerPilot.MechsKilled + 1);
                    var stat = statCollection.GetStatistic("MechsEjected");
                    if (stat == null)
                    {
                        statCollection.AddStatistic("MechsEjected", 1);
                        return;
                    }

                    var value = stat.Value <int>();
                    statCollection.Set("MechsEjected", value + 1);
                }

                // add achievement kill (more complicated)
                var combatProcessors = Traverse.Create(UnityGameInstance.BattleTechGame.Achievements).Field("combatProcessors").GetValue <AchievementProcessor[]>();
                var combatProcessor  = combatProcessors.FirstOrDefault(x => x.GetType() == AccessTools.TypeByName("BattleTech.Achievements.CombatProcessor"));

                // field is of type Dictionary<string, CombatProcessor.MechCombatStats>
                var playerMechStats = Traverse.Create(combatProcessor).Field("playerMechStats").GetValue <IDictionary>();
                if (playerMechStats != null)
                {
                    foreach (DictionaryEntry kvp in playerMechStats)
                    {
                        if ((string)kvp.Key == attackerPilot.GUID)
                        {
                            Traverse.Create(kvp.Value).Method("IncrementKillCount").GetValue();
                        }
                    }
                }

                else if (modSettings.VehiclesCanPanic &&
                         defender is Vehicle)
                {
                    var stat = statCollection.GetStatistic("VehiclesEjected");
                    if (stat == null)
                    {
                        statCollection.AddStatistic("VehiclesEjected", 1);
                        return;
                    }

                    var value = stat.Value <int>();
                    statCollection.Set("VehiclesEjected", value + 1);
                }
            }
            catch (Exception ex)
            {
                LogDebug(ex);
            }
        }
예제 #14
0
        public static void ProcessBatchedTurnDamage(AbstractActor actor)
        {
            int heatdamage = 0;

            if (ShouldSkipProcessing(actor))
            {
                return;
            }

            AbstractActor attacker = TurnDamageTracker.attackActor();

            LogReport($"\n{new string('═', 46)}");
            LogReport($"Damage to {actor.DisplayName}/{actor.Nickname}/{actor.GUID}");
            LogReport($"Damage by {attacker.DisplayName}/{attacker.Nickname}/{attacker.GUID}");

            // get the attacker in case they have mech quirks
            AbstractActor defender = null;

            switch (actor)
            {
            case Vehicle _:
                defender = (Vehicle)actor;
                break;

            case Mech _:
                defender = (Mech)actor;
                break;
            }

            // a building or turret?
            if (defender == null)
            {
                LogDebug("Not a mech or vehicle");
                return;
            }

            if (defender.IsDead || defender.IsFlaggedForDeath)
            {
                LogDebug("He's dead Jim.....");
                return;
            }

            var index = GetActorIndex(defender);

            if (modSettings.OneChangePerTurn &&
                TrackedActors[index].PanicWorsenedRecently)
            {
                LogDebug($"OneChangePerTurn {defender.Nickname} - abort");
                return;
            }

            float damageIncludingHeatDamage = 0;

            if (!modSettings.AlwaysPanic &&
                !ShouldPanic(defender, attacker, out heatdamage, out damageIncludingHeatDamage))
            {
                return;
            }

            // automatically eject a klutzy pilot on knockdown with an additional roll failing on 13
            if (defender.IsFlaggedForKnockdown)
            {
                var defendingMech = (Mech)defender;
                if (defendingMech.pilot.pilotDef.PilotTags.Contains("pilot_klutz"))
                {
                    if (Random.Range(1, 100) == 13)
                    {
                        defender.Combat.MessageCenter.PublishMessage(new AddSequenceToStackMessage
                                                                         (new ShowActorInfoSequence(defender, "WOOPS!", FloatieMessage.MessageNature.Debuff, false)));
                        LogReport("Very klutzy!");
                        return;
                    }
                }
            }

            // store saving throw
            // check it against panic
            // check it again ejection
            var savingThrow = SavingThrows.GetSavingThrow(defender, attacker, heatdamage, damageIncludingHeatDamage);

            // panic saving throw
            if (SavingThrows.SavedVsPanic(defender, savingThrow))
            {
                return;
            }

            if (!modSettings.OneChangePerTurn)
            {
                TurnDamageTracker.resetDamageTrackerFor(defender);
            }

            // stop if pilot isn't Panicked
            if (TrackedActors[index].PanicStatus != PanicStatus.Panicked)
            {
                return;
            }

            // eject saving throw
            if (!modSettings.AlwaysPanic &&
                SavingThrows.SavedVsEject(defender, savingThrow))
            {
                return;
            }

            // ejecting
            // random phrase
            if (modSettings.EnableEjectPhrases &&
                defender is Mech &&
                Random.Range(1, 100) <= modSettings.EjectPhraseChance)
            {
                var ejectMessage = ejectPhraseList[Random.Range(0, ejectPhraseList.Count)];
                var castDef      = Coordinator.CreateCast(defender);
                var content      = Coordinator.BuildDialogueContent(castDef, ejectMessage, Color.white);
                defender.Combat.MessageCenter.PublishMessage(new PanicSystemDialogMessage(defender, content, 6));
            }

            // remove effects, to prevent exceptions that occur for unknown reasons
            var combat           = UnityGameInstance.BattleTechGame.Combat;
            var effectsTargeting = combat.EffectManager.GetAllEffectsTargeting(defender);

            foreach (var effect in effectsTargeting)
            {
                // some effects removal throw, so silently drop them
                try
                {
                    defender.CancelEffect(effect);
                }
                catch
                {
                    // ignored
                }
            }

            if (modSettings.VehiclesCanPanic &&
                defender is Vehicle v)
            {
                // make the regular Pilot Ejected floatie not appear, for this ejection
                Patches.VehicleRepresentation.supressDeathFloatieOnce();
                defender.EjectPilot(defender.GUID, -1, DeathMethod.PilotEjection, true);
                CastDef castDef = Coordinator.CreateCast(defender);
                var     content = Coordinator.BuildDialogueContent(castDef, "Destroy the tech, let's get outta here!", Color.white);
                defender.Combat.MessageCenter.PublishMessage(new PanicSystemDialogMessage(defender, content, 5));
            }
            else
            {
                defender.EjectPilot(defender.GUID, -1, DeathMethod.PilotEjection, false);
            }

            LogReport("Ejected");
            //LogDebug($"Runtime {stopwatch.Elapsed}");

            if (!modSettings.CountAsKills)
            {
                return;
            }

            //handle weird cases due to damage from all sources
            if (attacker.GUID == defender.GUID)
            {
                //killed himself - possibly mines or made a building land on his own head ;)
                LogReport("Self Kill not counting");
                return;
            }

            if (attacker.team.GUID == defender.team.GUID)
            {
                //killed a friendly
                LogReport("Friendly Fire, Same Team Kill, not counting");
                return;
            }

            if (TurnDamageTracker.EjectionAlreadyCounted(defender))
            {
                return;
            }

            try
            {
                // this seems pretty convoluted
                var attackerPilot = combat.AllMechs.Where(mech => mech.pilot.Team.IsLocalPlayer)
                                    .Where(x => x.PilotableActorDef == attacker.PilotableActorDef).Select(y => y.pilot).FirstOrDefault();

                var statCollection = attackerPilot?.StatCollection;
                if (statCollection == null)
                {
                    return;
                }

                if (defender is Mech)
                {
                    // add UI icons.. and pilot history?   ... MechsKilled already incremented??
                    // TODO count kills recorded on pilot history so it's not applied twice -added a check above should work unless other mods are directly modifying stats
                    statCollection.Set("MechsKilled", attackerPilot.MechsKilled + 1);
                    var stat = statCollection.GetStatistic("MechsEjected");
                    if (stat == null)
                    {
                        statCollection.AddStatistic("MechsEjected", 1);
                    }
                    else
                    {
                        var value = stat.Value <int>();
                        statCollection.Set("MechsEjected", value + 1);
                    }
                }
                else if (modSettings.VehiclesCanPanic &&
                         defender is Vehicle)
                {
                    statCollection.Set("OthersKilled", attackerPilot.OthersKilled + 1);
                    var stat = statCollection.GetStatistic("VehiclesEjected");
                    if (stat == null)
                    {
                        statCollection.AddStatistic("VehiclesEjected", 1);
                        //return;
                    }
                    else
                    {
                        var value = stat.Value <int>();
                        statCollection.Set("VehiclesEjected", value + 1);
                    }
                }

                try
                {
                    object PlayerMechStats = playerMechStatsField.GetValue(CombatProcessor);
                    bool   result          = (bool)tryGetValue.Invoke(PlayerMechStats, new[] { attackerPilot.GUID, mechCombatStats });

                    if (result)
                    {
                        incrementKillCount.Invoke(mechCombatStats, null);
                    }
                }
                catch (Exception e)
                {
                    LogError(e);
                    // add achievement kill (more complicated)
                    var combatProcessors = Traverse.Create(UnityGameInstance.BattleTechGame.Achievements).Field("combatProcessors").GetValue <AchievementProcessor[]>();
                    var combatProcessor  = combatProcessors.FirstOrDefault(x => x.GetType() == AccessTools.TypeByName("BattleTech.Achievements.CombatProcessor"));

                    // field is of type Dictionary<string, CombatProcessor.MechCombatStats>
                    var playerMechStats = Traverse.Create(combatProcessor).Field("playerMechStats").GetValue <IDictionary>();
                    if (playerMechStats != null)
                    {
                        foreach (DictionaryEntry kvp in playerMechStats)
                        {
                            if ((string)kvp.Key == attackerPilot.GUID)
                            {
                                Traverse.Create(kvp.Value).Method("IncrementKillCount").GetValue();
                            }
                        }
                    }
                }


                var r = attackerPilot.StatCollection.GetStatistic("MechsEjected") == null
                        ? 0
                        : attackerPilot.StatCollection.GetStatistic("MechsEjected").Value <int>();
                LogDebug($"{attackerPilot.Callsign} SetMechEjectionCount {r}");

                r = attackerPilot.StatCollection.GetStatistic("VehiclesEjected") == null
                    ? 0
                    : attackerPilot.StatCollection.GetStatistic("VehiclesEjected").Value <int>();
                LogDebug($"{attackerPilot.Callsign} SetVehicleEjectionCount {r}");
            }
            catch (Exception ex)
            {
                LogDebug(ex);
            }
        }
예제 #15
0
        public static CastDef CreateCast(AbstractActor actor)
        {
            string castDefId = $"castDef_{actor.GUID}";

            if (actor.Combat.DataManager.CastDefs.Exists(castDefId))
            {
                return(actor.Combat.DataManager.CastDefs.Get(castDefId));
            }

            FactionValue actorFaction  = actor?.team?.FactionValue;
            bool         factionExists = actorFaction.Name != "INVALID_UNSET" && actorFaction.Name != "NoFaction" &&
                                         actorFaction.FactionDefID != null && actorFaction.FactionDefID.Length != 0 ? true : false;

            string employerFactionName = "Military Support";

            if (factionExists)
            {
                Mod.Log.Debug($"Found factionDef for id:{actorFaction}");
                string     factionId          = actorFaction?.FactionDefID;
                FactionDef employerFactionDef = UnityGameInstance.Instance.Game.DataManager.Factions.Get(factionId);
                if (employerFactionDef == null)
                {
                    Mod.Log.Error($"Error finding FactionDef for faction with id '{factionId}'");
                }
                else
                {
                    employerFactionName = employerFactionDef.Name.ToUpper();
                }
            }
            else
            {
                Mod.Log.Debug($"FactionDefID does not exist for faction: {actorFaction}");
            }

            CastDef newCastDef = new CastDef {
                // Temp test data
                FactionValue  = actorFaction,
                firstName     = $"{employerFactionName} -",
                showRank      = false,
                showCallsign  = true,
                showFirstName = true,
                showLastName  = false
            };

            // DisplayName order is first, callsign, lastname

            newCastDef.id = castDefId;
            string portraitPath = GetRandomPortraitPath();

            newCastDef.defaultEmotePortrait.portraitAssetPath = portraitPath;
            if (actor.GetPilot() != null)
            {
                Mod.Log.Debug("Actor has a pilot, using pilot values.");
                Pilot pilot = actor.GetPilot();
                newCastDef.callsign = pilot.Callsign;

                // Hide the faction name if it's the player's mech
                if (actor.team.IsLocalPlayer)
                {
                    newCastDef.showFirstName = false;
                }
            }
            else
            {
                Mod.Log.Debug("Actor is not piloted, generating castDef.");
                newCastDef.callsign = GetRandomCallsign();
            }
            Mod.Log.Debug($" Generated cast with callsign: {newCastDef.callsign} and DisplayName: {newCastDef.DisplayName()} using portrait: '{portraitPath}'");

            ((DictionaryStore <CastDef>)UnityGameInstance.BattleTechGame.DataManager.CastDefs).Add(newCastDef.id, newCastDef);

            return(newCastDef);
        }