Beispiel #1
0
        /*
         * Future proofed method to allow for string custom contract type names
         * instead of relying only on the enum values
         */
        public void SetContractType(ContractTypeValue contractTypeValue)
        {
            if (AllowMissionControl())
            {
                List <Type> encounters = null;

                string type = contractTypeValue.Name;
                CurrentContractType = type;

                if (AvailableEncounters.ContainsKey(type))
                {
                    encounters = AvailableEncounters[type];

                    int  index             = UnityEngine.Random.Range(0, encounters.Count);
                    Type selectedEncounter = encounters[index];
                    Main.Logger.Log($"[MissionControl] Setting contract type to '{type}' and using Encounter Rule of '{selectedEncounter.Name}'");
                    SetEncounterRule(selectedEncounter);
                }
                else
                {
                    Main.Logger.Log($"[MissionControl] Unknown contract / encounter type of '{type}'. Using fallback ruleset.");
                    SetEncounterRule(typeof(FallbackEncounterRules));
                }

                IsContractValid = true;
            }
            else
            {
                Main.Logger.Log($"[MissionControl] Mission Control is not allowed to run. Possibly a story mission or flashpoint contract.");
                EncounterRules     = null;
                EncounterRulesName = null;
            }
        }
        /*
         * Future proofed method to allow for string custom contract type names
         * instead of relying only on the enum values
         */
        public bool SetContractType(ContractTypeValue contractTypeValue)
        {
            List <Type> encounters = null;

            string type = contractTypeValue.Name;

            CurrentContractType = type;

            if (AvailableEncounters.ContainsKey(type))
            {
                encounters = AvailableEncounters[type];
            }
            else
            {
                Main.Logger.LogError($"[MissionControl] Unknown contract / encounter type of '{type}'");
                EncounterRules = null;
                return(false);
            }

            int  index             = UnityEngine.Random.Range(0, encounters.Count);
            Type selectedEncounter = encounters[index];

            Main.Logger.Log($"[MissionControl] Setting contract type to '{type}' and using Encounter Rule of '{selectedEncounter.Name}'");
            SetEncounterRule(selectedEncounter);

            IsContractValid = true;
            return(true);
        }
Beispiel #3
0
        private void AddContractType(MetadataDatabase mdd, ContractType_MDD contractTypeMDD)
        {
            ContractTypeValue contractTypeValue = ContractTypeEnumeration.Instance.CreateEnumValueFromDatabase(mdd, contractTypeMDD.EnumValueRow);

            if (!AvailableCustomContractTypes.ContainsKey(contractTypeValue.Name))
            {
                AvailableCustomContractTypes.Add(contractTypeValue.Name, new List <ContractTypeValue>());
            }
            Main.LogDebug($"[DataManager.AddContractType] Adding custom contract type: {contractTypeValue.Name}");
            AvailableCustomContractTypes[contractTypeValue.Name].Add(contractTypeValue);
        }
Beispiel #4
0
        public static Contract CreateTravelContract(
            string mapName,
            string mapPath,
            string encounterGuid,
            ContractTypeValue contractTypeValue,
            ContractOverride ovr,
            GameContext context,
            FactionValue employer,
            FactionValue target,
            FactionValue targetsAlly,
            FactionValue employersAlly,
            FactionValue neutralToAll,
            FactionValue hostileToAll,
            bool isGlobal,
            int difficulty)
        {
            LogDebug("CreateTravelContract");
            var starSystem = context.GetObject(GameContextObjectTagEnum.TargetStarSystem) as StarSystem;
            var seed       = Globals.Rng.Next(0, int.MaxValue);

            ovr.FullRehydrate();
            var contractOverride = new ContractOverride();

            contractOverride.CopyContractTypeData(ovr);
            contractOverride.contractName           = ovr.contractName;
            contractOverride.difficulty             = ovr.difficulty;
            contractOverride.longDescription        = ovr.longDescription;
            contractOverride.shortDescription       = ovr.shortDescription;
            contractOverride.travelOnly             = true;
            contractOverride.useTravelCostPenalty   = !isGlobal;
            contractOverride.disableNegotations     = ovr.disableNegotations;
            contractOverride.disableAfterAction     = ovr.disableAfterAction;
            contractOverride.salvagePotential       = ovr.salvagePotential;
            contractOverride.contractRewardOverride = ovr.contractRewardOverride;
            contractOverride.travelSeed             = seed;
            contractOverride.difficultyUIModifier   = ovr.difficultyUIModifier;
            var       simGameEventResult = new SimGameEventResult();
            var       gameResultAction   = new SimGameResultAction();
            const int length             = 14;

            gameResultAction.Type                 = SimGameResultAction.ActionType.System_StartNonProceduralContract;
            gameResultAction.value                = mapName;
            gameResultAction.additionalValues     = new string[length];
            gameResultAction.additionalValues[0]  = starSystem.ID;
            gameResultAction.additionalValues[1]  = mapPath;
            gameResultAction.additionalValues[2]  = encounterGuid;
            gameResultAction.additionalValues[3]  = ovr.ID;
            gameResultAction.additionalValues[4]  = isGlobal.ToString();
            gameResultAction.additionalValues[5]  = employer.Name;
            gameResultAction.additionalValues[6]  = target.Name;
            gameResultAction.additionalValues[7]  = difficulty.ToString();
            gameResultAction.additionalValues[8]  = "true";
            gameResultAction.additionalValues[9]  = targetsAlly.Name;
            gameResultAction.additionalValues[10] = seed.ToString();
            gameResultAction.additionalValues[11] = employersAlly.Name;
            gameResultAction.additionalValues[12] = neutralToAll.Name;
            gameResultAction.additionalValues[13] = hostileToAll.Name;
            simGameEventResult.Actions            = new SimGameResultAction[1];
            simGameEventResult.Actions[0]         = gameResultAction;
            contractOverride.OnContractSuccessResults.Add(simGameEventResult);
            return(new Contract(mapName, mapPath, encounterGuid, contractTypeValue, Globals.Sim.BattleTechGame, contractOverride, context, true, actualDifficulty)
            {
                Override =
                {
                    travelSeed = seed
                }
            });
        }
Beispiel #5
0
        public static bool Prefix(ref bool __result, SimGameResultAction action, object additionalObject)
        {
            try
            {
                SimGameState simulation = UnityGameInstance.BattleTechGame.Simulation;

                if (simulation == null || action.Type != SimGameResultAction.ActionType.System_AddContract)
                {
                    return(true);
                }

                // In vanilla the SimGameResultAction.ActionType.System_AddContract is only used for travel-contracts (breadcrumbs)
                // I use it to add custom contracts by custom events which need to have negotiations disabled as they are "self-employed opportunity contracts"
                SimGameState.AddContractData addContractData   = simulation.ParseContractActionData(action.value, action.additionalValues);
                ContractOverride             contractOverride  = simulation.DataManager.ContractOverrides.Get(addContractData.ContractName).Copy();
                ContractTypeValue            contractTypeValue = contractOverride.ContractTypeValue;

                // Call original method if contract is a breadcrumb (used by campaign a lot)
                if (contractTypeValue.IsTravelOnly)
                {
                    return(true);
                }
                // Custom handling
                else
                {
                    // Validate target system and enrich contractData
                    StarSystem targetSystem;
                    Logger.Debug($"[SimGameState_ApplyEventAction_PREFIX] addContractData.TargetSystem: {addContractData.TargetSystem}");
                    if (!string.IsNullOrEmpty(addContractData.TargetSystem))
                    {
                        string validatedSystemString = simulation.GetValidatedSystemString(addContractData.TargetSystem);
                        addContractData.IsGlobal = validatedSystemString != simulation.CurSystem.ID;

                        if (simulation.GetSystemById(validatedSystemString) != null)
                        {
                            targetSystem = simulation.GetSystemById(validatedSystemString);
                        }
                        else
                        {
                            throw new Exception("Couldn't find StarSystem for: " + validatedSystemString);
                        }
                    }
                    else
                    {
                        targetSystem = simulation.CurSystem;
                    }
                    Logger.Debug($"[SimGameState_ApplyEventAction_PREFIX] targetSystem.ID: {targetSystem.ID}");



                    // Internal helper method
                    IEnumerator InjectAdditionalContractRoutine()
                    {
                        while (!targetSystem.InitialContractsFetched)
                        {
                            yield return(new WaitForSeconds(0.2f));
                        }

                        InjectAdditionalContract();

                        yield break;
                    }

                    // Internal helper method
                    void InjectAdditionalContract(bool refresh = true)
                    {
                        // Get the contract
                        Contract contract = simulation.GetValidContractForContractDataAndSystem(addContractData, targetSystem);

                        targetSystem.SystemContracts.Add(contract);

                        if (refresh)
                        {
                            SGContractsWidget    ___contractsWidget           = (SGContractsWidget)AccessTools.Field(typeof(SGRoomController_CmdCenter), "contractsWidget").GetValue(simulation.RoomManager.CmdCenterRoom);
                            List <Contract>      allContracts                 = simulation.GetAllCurrentlySelectableContracts(true);
                            ContractDisplayStyle?___contractDisplayAutoSelect = Traverse.Create(___contractsWidget).Field("contractDisplayAutoSelect").GetValue <ContractDisplayStyle?>();
                            ___contractsWidget.ListContracts(allContracts, ___contractDisplayAutoSelect);
                        }
                    }



                    if (simulation.TimeMoving)
                    {
                        simulation.PauseTimer();
                        simulation.StopPlayMode();
                    }



                    // Need to check this as the initial contract fetching routine clears all existing contracts
                    Logger.Debug($"[SimGameState_ApplyEventAction_PREFIX] targetSystem.InitialContractsFetched: {targetSystem.InitialContractsFetched}");
                    if (!targetSystem.InitialContractsFetched)
                    {
                        SceneSingletonBehavior <UnityGameInstance> .Instance.StartCoroutine(InjectAdditionalContractRoutine());

                        return(false);
                    }
                    else
                    {
                        InjectAdditionalContract(false);

                        // Skip original method
                        return(false);
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Error(e);
                return(true);
            }
        }
        public static Contract GetValidContractForContractDataAndSystem(this SimGameState simGameState, SimGameState.AddContractData addContractData, StarSystem starSystem)
        {
            Logger.Debug($"[SimGameStateExtensions_GetValidContractForContractDataAndSystem] (addContractData) ContractName: {addContractData.ContractName}, Target: {addContractData.Target}, Employer: {addContractData.Employer}, TargetSystem: {addContractData.TargetSystem}, TargetAlly: {addContractData.TargetAlly}");
            Logger.Debug($"[SimGameStateExtensions_GetValidContractForContractDataAndSystem] starSystem: {starSystem.Name}");
            Logger.Debug($"[SimGameStateExtensions_GetValidContractForContractDataAndSystem] starSystem.Def.SupportedBiomes: {String.Join(", ", starSystem.Def.SupportedBiomes.Select(sb => sb.ToString()))}");

            if (starSystem == null)
            {
                throw new Exception("starSystem is null");
            }

            GameInstance gameInstance = simGameState.BattleTechGame;
            DataManager  dataManager  = simGameState.BattleTechGame.DataManager;
            GameContext  gameContext  = new GameContext(simGameState.Context);

            gameContext.SetObject(GameContextObjectTagEnum.TargetStarSystem, starSystem);

            ContractOverride  contractOverride  = dataManager.ContractOverrides.Get(addContractData.ContractName).Copy();
            ContractTypeValue contractTypeValue = contractOverride.ContractTypeValue;

            FactionValue employer      = string.IsNullOrEmpty(addContractData.Employer) ? FactionEnumeration.GetInvalidUnsetFactionValue() : FactionEnumeration.GetFactionByName(addContractData.Employer);
            FactionValue employersAlly = string.IsNullOrEmpty(addContractData.EmployerAlly) ? FactionEnumeration.GetInvalidUnsetFactionValue() : FactionEnumeration.GetFactionByName(addContractData.EmployerAlly);
            FactionValue target        = string.IsNullOrEmpty(addContractData.Target) ? FactionEnumeration.GetInvalidUnsetFactionValue() : FactionEnumeration.GetFactionByName(addContractData.Target);
            FactionValue targetsAlly   = string.IsNullOrEmpty(addContractData.TargetAlly) ? FactionEnumeration.GetInvalidUnsetFactionValue() : FactionEnumeration.GetFactionByName(addContractData.TargetAlly);
            FactionValue neutralToAll  = string.IsNullOrEmpty(addContractData.NeutralToAll) ? FactionEnumeration.GetInvalidUnsetFactionValue() : FactionEnumeration.GetFactionByName(addContractData.NeutralToAll);
            FactionValue hostileToAll  = string.IsNullOrEmpty(addContractData.HostileToAll) ? FactionEnumeration.GetInvalidUnsetFactionValue() : FactionEnumeration.GetFactionByName(addContractData.HostileToAll);

            if (employer.IsInvalidUnset || target.IsInvalidUnset)
            {
                throw new Exception("ContractData didn't have a valid employerValue and/or targetValue");
            }


            // Get all valid encounters (all contract types) for the requested system
            List <MapAndEncounters> allValidMapAndEncountersForCurrentSystem = MetadataDatabase.Instance.GetReleasedMapsAndEncountersBySinglePlayerProceduralContractTypeAndTags(starSystem.Def.MapRequiredTags, starSystem.Def.MapExcludedTags, starSystem.Def.SupportedBiomes, true);

            // Remove all items that dont have an encounter layer for the requested contract type
            allValidMapAndEncountersForCurrentSystem.RemoveAll(MapAndEncounters => MapAndEncounters.Encounters.All(el => el.ContractTypeValue != contractTypeValue));



            // Debug
            foreach (MapAndEncounters mae in allValidMapAndEncountersForCurrentSystem)
            {
                Logger.Info($"allValidMapAndEncountersForCurrentSystem (Map): {mae.Map.FriendlyName}");
                Logger.Info($"allValidMapAndEncountersForCurrentSystem (Encounters): {String.Join(", ", Array.ConvertAll(mae.Encounters, item => item.FriendlyName))}");
                Logger.Info($"-");
            }

            // @ToDo: Remove Map "mapGeneral_taigaRiver_iTnd" for ContractTypeValue "Rescue" (Broken in Vanilla, no buildings at target zones)
            //if (contractTypeValue.FriendlyName == "Rescue")
            //{
            //    allValidMapAndEncountersForCurrentSystem.RemoveAll(MapAndEncounters => MapAndEncounters.Map.MapID == "mapGeneral_taigaRiver_iTnd");
            //}



            // Get a random item
            Random           random           = new Random();
            MapAndEncounters mapAndEncounters = allValidMapAndEncountersForCurrentSystem.OrderBy(MapAndEncounters => random.NextDouble()).First();



            // Debug
            Logger.Info($"chosenMapAndEncounters (Map): {mapAndEncounters.Map.FriendlyName}");
            Logger.Info($"chosenMapAndEncounters: {String.Join(", ", Array.ConvertAll(mapAndEncounters.Encounters, item => item.FriendlyName))}");



            // Get the matching encounter layers
            List <EncounterLayer_MDD> encounterLayers = new List <EncounterLayer_MDD>();

            foreach (EncounterLayer_MDD encounterLayer in mapAndEncounters.Encounters)
            {
                if (encounterLayer.ContractTypeRow.ContractTypeID == (long)contractTypeValue.ID)
                {
                    encounterLayers.Add(encounterLayer);
                }
            }
            if (encounterLayers.Count <= 0)
            {
                throw new Exception("Map does not contain any encounters of type: " + contractTypeValue.Name);
            }



            // Debug
            foreach (EncounterLayer_MDD elMdd in encounterLayers)
            {
                Logger.Info($"chosenEncounter (Name): {elMdd.FriendlyName}");
                Logger.Info($"chosenEncounter (ContractTypeValue): {elMdd.ContractTypeValue}");
            }



            // Get GUID of a random valid encounter layer
            string encounterLayerGUID = encounterLayers[simGameState.NetworkRandom.Int(0, encounterLayers.Count)].EncounterLayerGUID;


            // Check if we need to travel
            if (addContractData.IsGlobal)
            {
                Logger.Debug($"[SimGameStateExtensions_GetValidContractForContractDataAndSystem] Custom handling of travel contracts isn't implemented. Falling back to default handling");

                // Fallback to relevant part of default vanilla method
                simGameState.AddContract(addContractData);

                //Contract travelContract = simGameState.CreateTravelContract(mapAndEncounters.Map.MapName, mapAndEncounters.Map.MapPath, encounterLayerGUID, contractTypeValue, contractOverride, gameContext, employer, employersAlly, target, targetsAlly, neutralToAll, hostileToAll, addContractData.IsGlobal);
                //simGameState.PrepContract(travelContract, employer, employersAlly, target, targetsAlly, neutralToAll, hostileToAll, mapAndEncounters.Map.BiomeSkinEntry.BiomeSkin, travelContract.Override.travelSeed, starSystem);
                //simGameState.GlobalContracts.Add(travelContract);

                //return travelContract;
            }

            Contract contract = new Contract(mapAndEncounters.Map.MapName, mapAndEncounters.Map.MapPath, encounterLayerGUID, contractTypeValue, gameInstance, contractOverride, gameContext, true, contractOverride.difficulty, 0, null);

            Logger.Debug($"[SimGameStateExtensions_GetValidContractForContractDataAndSystem] Contract: {contract.Override.ID}({contractTypeValue}), Difficulty: {contract.Difficulty}, CanNegotiate: {contract.CanNegotiate}, Biome: {mapAndEncounters.Map.BiomeSkinEntry.Name}, Map: {mapAndEncounters.Map.MapName}");

            simGameState.PrepContract(contract, employer, employersAlly, target, targetsAlly, neutralToAll, hostileToAll, mapAndEncounters.Map.BiomeSkinEntry.BiomeSkin, 0, starSystem);
            // Set negotiations
            if (!contract.CanNegotiate)
            {
                contract.SetNegotiatedValues(contract.Override.negotiatedSalary, contract.Override.negotiatedSalvage);
            }



            return(contract);
        }