public override void Process(PDAEntryAdd packet)
        {
            using (packetSender.Suppress <PDAEntryAdd>())
                using (packetSender.Suppress <PDAEntryProgress>())
                {
                    TechType             techType  = packet.TechType.ToUnity();
                    PDAScanner.EntryData entryData = PDAScanner.GetEntryData(techType);

                    if (!PDAScanner.GetPartialEntryByKey(techType, out PDAScanner.Entry entry))
                    {
                        entry = PDAScanner.Add(techType, packet.Unlocked);
                    }

                    if (entry != null)
                    {
                        entry.unlocked++;

                        if (entry.unlocked >= entryData.totalFragments)
                        {
                            PDAScanner.partial.Remove(entry);
                            PDAScanner.complete.Add(entry.techType);
                        }
                        else
                        {
                            int totalFragments = entryData.totalFragments;
                            if (totalFragments > 1)
                            {
                                float num2 = (float)entry.unlocked / (float)totalFragments;
                                float arg  = (float)Mathf.RoundToInt(num2 * 100f);
                                ErrorMessage.AddError(Language.main.GetFormat <string, float, int, int>("ScannerInstanceScanned", Language.main.Get(entry.techType.AsString(false)), arg, entry.unlocked, totalFragments));
                            }
                        }
                    }
                }
        }
Example #2
0
        public override void Process(PDAEntryProgress packet)
        {
            using (packetSender.Suppress <PDAEntryAdd>())
                using (packetSender.Suppress <PDAEntryProgress>())
                {
                    TechType             techType  = packet.TechType.ToUnity();
                    PDAScanner.EntryData entryData = PDAScanner.GetEntryData(techType);

                    PDAScanner.Entry entry;
                    if (PDAScanner.GetPartialEntryByKey(techType, out entry))
                    {
                        if (packet.Unlocked > entry.unlocked)
                        {
                            Log.Info("PDAEntryProgress Upldate Old:" + entry.unlocked + " New" + packet.Unlocked);
                            entry.unlocked = packet.Unlocked;
                        }
                    }
                    else
                    {
                        Log.Info("PDAEntryProgress New TechType:" + techType + " Unlocked:" + packet.Unlocked);
                        MethodInfo methodAdd = typeof(PDAScanner).GetMethod("Add", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(TechType), typeof(int) }, null);
                        entry = (PDAScanner.Entry)methodAdd.Invoke(null, new object[] { techType, packet.Unlocked });
                    }
                }
        }
Example #3
0
        private void Process(ClientScanProgress msg)
        {
            var entryData = PDAScanner.GetEntryData(msg.tech);

            if (entryData == null)
            {
                return;
            }

            using (new MessageBlocker()) {
                PDAScanner.Entry entry;
                if (!PDAScanner.GetPartialEntryByKey(msg.tech, out entry))
                {
                    var methodAdd = typeof(PDAScanner).GetMethod("Add", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(TechType), typeof(int) }, null);
                    entry = (PDAScanner.Entry)methodAdd.Invoke(null, new object[] { msg.tech, 0 });
                }

                if (entry != null)
                {
                    entry.unlocked = msg.progress;
                    if (entry.unlocked >= entryData.totalFragments)
                    {
                        var partial  = (List <PDAScanner.Entry>)(typeof(PDAScanner).GetField("partial", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null));
                        var complete = (HashSet <TechType>)(typeof(PDAScanner).GetField("complete", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null));

                        partial.Remove(entry);
                        complete.Add(entry.techType);
                    }
                }
            }
        }
        public static bool Prefix(TechType techType, bool verbose)
        {
            if (Main.Config.Hardcore)
            {
                var entryData = PDAScanner.GetEntryData(techType);
                return(!verbose || entryData == null || (entryData != null && PDAScanner.ContainsCompleteEntry(techType)));
            }

            return(true);
        }
        public static void Postfix(ref StringBuilder sb, TechType techType)
        {
            PDAScanner.EntryData entryData = PDAScanner.GetEntryData(techType);
            if (entryData == null || PDAScanner.ContainsCompleteEntry(techType) || CrafterLogic.IsCraftRecipeUnlocked(techType))
            {
                return;
            }

            sb.Clear();
            TooltipFactory.WriteTitle(sb, Main.config.UnKnownTitle);
            TooltipFactory.WriteDescription(sb, Main.config.UnKnownDescription);
        }
Example #6
0
        public static void Prefix(PDAData data)
        {
            List <TechType> types = new List <TechType>(data.defaultTech);

            foreach (TechType techType in types)
            {
                PDAScanner.EntryData entryData = PDAScanner.GetEntryData(techType);
                if (entryData != null && entryData.locked)
                {
                    data.defaultTech.Remove(techType);
                }
            }
        }
        public static void Postfix()
        {
            if (PDAScanner.ContainsCompleteEntry(techType) || KnownTech.Contains(techType))
            {
                if (techType == TechType.ScrapMetal && !KnownTech.Contains(TechType.Titanium))
                {
                    PDAScanner.AddByUnlockable(TechType.Titanium, 1);
                    KnownTech.Add(TechType.Titanium);
                }

                if (!KnownTech.Contains(techType))
                {
                    KnownTech.Add(techType);
                }

                var entryData = PDAScanner.GetEntryData(techType);

                if (entryData != null && entryData.locked)
                {
                    PDAScanner.Unlock(entryData, true, true);

                    if (!KnownTech.Contains(entryData.blueprint))
                    {
                        KnownTech.Add(entryData.blueprint);
                    }
                }
#if SN1
                var techType2 = CraftData.GetHarvestOutputData(techType);
#elif BZ
                var techType2 = TechData.GetHarvestOutput(techType);
#endif
                if (techType2 != TechType.None)
                {
                    if (!KnownTech.Contains(techType2))
                    {
                        KnownTech.Add(techType2);
                    }

                    var entryData2 = PDAScanner.GetEntryData(techType2);
                    if (entryData2 != null && entryData2.locked)
                    {
                        PDAScanner.Unlock(entryData, true, true);

                        if (!KnownTech.Contains(entryData2.blueprint))
                        {
                            KnownTech.Add(entryData2.blueprint);
                        }
                    }
                }
            }
        }
Example #8
0
        public static void Callback()
        {
            // When a player scans a fragment, it will be deleted from the world. We want to send out a pickup event
            // before the object can be removed and corresponding scan data is invalidated.
            TechType techType = PDAScanner.scanTarget.techType;

            PDAScanner.EntryData entryData = PDAScanner.GetEntryData(techType);

            // Only do this for fragments and player scans or nearby fish
            if (entryData != null && entryData.destroyAfterScan && PDAScanner.scanTarget.gameObject && !PDAScanner.scanTarget.isPlayer)
            {
                // A lot of fragments are virtual entities (spawned by placeholders in the world).  Sometimes the server only knows the id
                // of the placeholder and not the virtual entity. TODO: we will need to propagate deterministic ids to children entities for
                // these virtual entities.
                NitroxServiceLocator.LocateService <Item>().PickedUp(PDAScanner.scanTarget.gameObject, techType);
            }
        }
        public static void Postfix()
        {
            PDAScanner.ScanTarget scanTarget = PDAScanner.scanTarget;
            PDAScanner.EntryData  entryData  = PDAScanner.GetEntryData(scanTarget.techType);
            TechType key       = entryData?.key ?? TechType.None;
            TechType blueprint = entryData?.blueprint ?? TechType.None;

            if (scanTarget.techType != TechType.None && CrafterLogic.IsCraftRecipeUnlocked(scanTarget.techType) || (entryData != null && ((blueprint != TechType.None && CrafterLogic.IsCraftRecipeUnlocked(entryData.blueprint)) || (key != TechType.None && CrafterLogic.IsCraftRecipeUnlocked(entryData.key)))) || !scanTarget.isValid || !GameModeUtils.RequiresBlueprints())
            {
                return;
            }
#if SN1
            HandReticle.main.SetInteractText(Main.config.UnKnownLabel, false, HandReticle.Hand.None);
#elif BZ
            HandReticle.main.SetText(HandReticle.TextType.Hand, Main.config.UnKnownLabel, true, GameInput.Button.None);
#endif
        }
Example #10
0
        public static void Postfix(Pickupable pickupable)
        {
            if (newgame && Main.config.Hardcore && !Utils.GetContinueMode() && pickupable.GetTechType() != TechType.FireExtinguisher)
            {
                CoroutineHost.StartCoroutine(GiveHardcoreScanner());
                newgame = false;
                SMLHelper.V2.Handlers.IngameMenuHandler.RegisterOnQuitEvent(() => newgame = true);
            }

            TechType techType = pickupable.GetTechType();

            PDAScanner.EntryData entryData  = PDAScanner.GetEntryData(techType);
            GameObject           gameObject = pickupable.gameObject;

            if (Main.config.ScanOnPickup && Inventory.main.container.Contains(TechType.Scanner) && entryData != null)
            {
                if (!PDAScanner.GetPartialEntryByKey(techType, out PDAScanner.Entry entry))
                {
                    entry = PDAScanner.Add(techType, 1);
                }
                if (entry != null)
                {
                    PDAScanner.partial.Remove(entry);
                    PDAScanner.complete.Add(entry.techType);
                    PDAScanner.NotifyRemove(entry);
                    PDAScanner.Unlock(entryData, true, true, true);
                    KnownTech.Add(techType, false);
                    if (gameObject != null)
                    {
                        gameObject.SendMessage("OnScanned", null, SendMessageOptions.DontRequireReceiver);
                    }
#if SN1
                    ResourceTracker.UpdateFragments();
#endif
                }
            }

            if (!Main.config.Hardcore && entryData == null)
            {
                KnownTech.Add(techType, true);
            }
        }
        public static void Postfix(ScannerTool __instance)
        {
            PDAScanner.ScanTarget scanTarget = PDAScanner.scanTarget;
#if SN1
            PDAScanner.Result result = PDAScanner.CanScan();
#elif BZ
            PDAScanner.Result result = PDAScanner.CanScan(scanTarget);
#endif
            PDAScanner.EntryData entryData = PDAScanner.GetEntryData(PDAScanner.scanTarget.techType);

            if ((entryData != null && (CrafterLogic.IsCraftRecipeUnlocked(entryData.blueprint) || CrafterLogic.IsCraftRecipeUnlocked(entryData.key))) || PDAScanner.ContainsCompleteEntry(scanTarget.techType) || __instance.energyMixin.charge <= 0f || !scanTarget.isValid || result != PDAScanner.Result.Scan || !GameModeUtils.RequiresBlueprints())
            {
                return;
            }
#if SN1
            HandReticle.main.SetInteractText(Main.config.UnKnownLabel, false, HandReticle.Hand.None);
#elif BZ
            HandReticle.main.SetText(HandReticle.TextType.Hand, Main.config.UnKnownLabel, true, GameInput.Button.None);
#endif
        }
        static void unlockPopupsUpdate()
        {
            KnownTech.AnalysisTech _getEntry(TechType techType) =>
            KnownTech.analysisTech.FirstOrDefault(tech => tech.techType == techType);

            foreach (var popup in unlockPopups)
            {
                var tech   = _getEntry(popup.Key);
                var sprite = _getEntry(popup.Value)?.unlockPopup;

                if (sprite == null && PDAScanner.GetEntryData(popup.Value) is PDAScanner.EntryData fragData)
                {
                    sprite = _getEntry(fragData.blueprint)?.unlockPopup;                     // try popup.Value as fragment tech type
                }
                if (sprite != null)
                {
                    tech.unlockPopup = sprite;
                }
            }
        }
Example #13
0
        public override void Process(PDAEntryAdd packet)
        {
            using (packetSender.Suppress <PDAEntryAdd>())
                using (packetSender.Suppress <PDAEntryProgress>())
                {
                    TechType             techType  = packet.TechType.Enum();
                    PDAScanner.EntryData entryData = PDAScanner.GetEntryData(techType);

                    PDAScanner.Entry entry;
                    if (!PDAScanner.GetPartialEntryByKey(techType, out entry))
                    {
                        MethodInfo methodAdd = typeof(PDAScanner).GetMethod("Add", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(TechType), typeof(int) }, null);
                        entry = (PDAScanner.Entry)methodAdd.Invoke(null, new object[] { techType, packet.Unlocked });
                    }

                    if (entry != null)
                    {
                        entry.unlocked++;

                        if (entry.unlocked >= entryData.totalFragments)
                        {
                            List <PDAScanner.Entry> partial  = (List <PDAScanner.Entry>)(typeof(PDAScanner).GetField("partial", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null));
                            HashSet <TechType>      complete = (HashSet <TechType>)(typeof(PDAScanner).GetField("complete", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null));
                            partial.Remove(entry);
                            complete.Add(entry.techType);
                        }
                        else
                        {
                            int totalFragments = entryData.totalFragments;
                            if (totalFragments > 1)
                            {
                                float num2 = (float)entry.unlocked / (float)totalFragments;
                                float arg  = (float)Mathf.RoundToInt(num2 * 100f);
                                ErrorMessage.AddError(Language.main.GetFormat <string, float, int, int>("ScannerInstanceScanned", Language.main.Get(entry.techType.AsString(false)), arg, entry.unlocked, totalFragments));
                            }
                        }
                    }
                }
        }
Example #14
0
        private static bool Prefix(TechType techType, int num = 1, bool noMessage = false, bool spawnIfCantAdd = true)
        {
            if (techType == TechType.Titanium && num == 2 && !noMessage && spawnIfCantAdd)
            {
                TechType scannedFragment = PDAScanner.scanTarget.techType;
#if !RELEASE
                Logger.Log(Logger.Level.Debug, $"Intercepting scan of fragment {scannedFragment.ToString()}");
#endif

                TechData recipe; // "Variable declaration can be inlined" says Visual Studio, but I'm not sure if it would remain in-scope further down the function if it is.
                if (IngredientsFromScanning.Main.config.TryOverrideRecipe(scannedFragment, out recipe))
                {
#if !RELEASE
                    Logger.Log(Logger.Level.Debug, $"Using OverrideRecipe: {JsonConvert.SerializeObject(recipe, Oculus.Newtonsoft.Json.Formatting.Indented)}");
#endif
                }
                else if ((int)scannedFragment > 1112 && (int)scannedFragment < 1117)
                {
                    // TechTypes 1113 to 1116 are Cyclops fragments, which have no blueprint associated, so we need to process them specially.
                    recipe = new TechData();

                    /*CyclopsHullFragment = 1113,
                     * CyclopsBridgeFragment = 1114,
                     * CyclopsEngineFragment = 1115,
                     * CyclopsDockingBayFragment = 1116,*/

                    switch ((int)scannedFragment)
                    {
                    case 1113:
                        recipe.Ingredients.Add(new Ingredient(TechType.PlasteelIngot, 2));
                        recipe.Ingredients.Add(new Ingredient(TechType.Lead, 1));
                        break;

                    case 1114:
                        recipe.Ingredients.Add(new Ingredient(TechType.EnameledGlass, 3));
                        break;

                    case 1115:
                        recipe.Ingredients.Add(new Ingredient(TechType.Lubricant, 1));
                        recipe.Ingredients.Add(new Ingredient(TechType.AdvancedWiringKit, 1));
                        recipe.Ingredients.Add(new Ingredient(TechType.Lead, 1));
                        break;

                    case 1116:
                        recipe.Ingredients.Add(new Ingredient(TechType.PlasteelIngot, 2));
                        break;
                    }
                    recipe.Ingredients.Add(new Ingredient(TechType.Lead, 1));
                    recipe.Ingredients.Add(new Ingredient(TechType.PlasteelIngot, 1));
#if !RELEASE
                    Logger.Log(Logger.Level.Debug, $"Using recipe from manual override: {JsonConvert.SerializeObject(recipe, Oculus.Newtonsoft.Json.Formatting.Indented)}");
#endif
                }
                else
                {
                    PDAScanner.EntryData entryData = PDAScanner.GetEntryData(scannedFragment);
                    if (entryData == null) // Sanity check; this should always be true
                    {
#if !RELEASE
                        Logger.Log(Logger.Level.Debug, $"Failed to find EntryData for fragment");
#endif

                        /*CraftData.AddToInventory(TechType.Titanium);
                         * CraftData.AddToInventory(TechType.Titanium); // Adding them one-by-one so as to prevent it being caught by this very routine.*/
                        return(true);
                    }
                    //Logger.Log(Logger.Level.Debug, $"Found entryData {entryData.ToString()}");
#if !RELEASE
                    Logger.Log(Logger.Level.Debug, $"Found entryData {JsonConvert.SerializeObject(entryData, Oculus.Newtonsoft.Json.Formatting.Indented)}");
#endif


                    //CraftData.AddToInventory(TechType.Titanium);
                    //CraftData.AddToInventory(TechType.Copper);
                    recipe = CraftDataHandler.GetTechData(entryData.blueprint);
                    if (recipe == null)
                    {
#if !RELEASE
                        Logger.Log(Logger.Level.Debug, $"Failed to find blueprint for EntryData");
#endif

                        /*CraftData.AddToInventory(TechType.Titanium);
                         * CraftData.AddToInventory(TechType.Titanium); // One-by-one again, as above.*/
                        return(true);
                    }
                    //Logger.Log(Logger.Level.Debug, $"Found recipe {recipe.ToString()}");
#if !RELEASE
                    Logger.Log(Logger.Level.Debug, $"Using recipe from EntryData: {JsonConvert.SerializeObject(recipe, Oculus.Newtonsoft.Json.Formatting.Indented)}");
#endif
                }

                for (int i = 0; i < recipe.Ingredients.Count; i++)
                {
                    if (IngredientsFromScanning.Main.config.TrySubstituteIngredient(recipe.Ingredients[i].techType, out List <Ingredient> Substitutes))
                    {
                        foreach (Ingredient sub in Substitutes)
                        {
                            recipe.Ingredients.Add(sub);
                        }
                        recipe.Ingredients.RemoveAt(i); // Remove the current ingredient...
                        i--;                            // ...and make sure the loop continues at the item after this, not the one after that.
                    }
                }

                // I believe the easiest way to get a random item from the blueprint would be to make a list of techTypes; if an ingredient is used twice in the recipe, it will appear in the list twice.
                // That way, we can generate a random number where 0<=rnd<list.count, and select that item.
                List <TechType> bp = new List <TechType> {
                };
                for (int i = 0; i < recipe.Ingredients.Count; i++)
                {
                    for (int j = 0; j < recipe.Ingredients[i].amount; j++)
                    {
                        bp.Add(recipe.Ingredients[i].techType);
                    }
                }

                // Now build up weights
                List <WeightedItem> BlueprintPairs = new List <WeightedItem>();
                float TotalWeight = 0f;
                //Logger.Log(Logger.Level.Error, "Unidentified Vehicle Type!");
                for (int i = 0; i < bp.Count; i++)
                {
                    float thisWeight = IngredientsFromScanning.Main.config.GetWeightForTechType(bp[i]);
                    TotalWeight += thisWeight;
                    WeightedItem thisWeightedItem = new WeightedItem(TotalWeight, bp[i]);
#if !RELEASE
                    Logger.Log(Logger.Level.Debug, $"Adding item to drop list, TechType = {thisWeightedItem.tech.ToString()},   this weight = {thisWeight}, cumulative weight = {thisWeightedItem.Weight}");
#endif
                    BlueprintPairs.Add(thisWeightedItem);
                }

                // Now we should be able to pick a few random numbers between 0 and the list's total weight, and add those. We want to remove that entry afterwards, but that's not a big ask.
                System.Random rng            = new System.Random();
                int           numIngredients = Math.Min(IngredientsFromScanning.Main.config.GenerateGiftValue(), BlueprintPairs.Count);
#if !RELEASE
                Logger.Log(Logger.Level.Debug, $"Generated a value for this scan of {numIngredients} components.");
#endif

                int    awards = 0;
                double r;
                for (int i = 0; i < numIngredients && BlueprintPairs.Count > 0; i++)
                {
                    r = rng.NextDouble() * TotalWeight;
                    for (int j = 0; j < BlueprintPairs.Count; j++)
                    {
                        //                                               This part is for sanity checking
                        //                                   ___________________________|______________________________
                        //                                  /                                                          \
                        if (r < BlueprintPairs[j].Weight || ((j + 1) == BlueprintPairs.Count && awards < numIngredients))
                        {
#if !RELEASE
                            Logger.Log(Logger.Level.Debug, $"With randomised weight of {r}, adding tech {BlueprintPairs[j].tech} to player inventory");
#endif
                            AddInventory(BlueprintPairs[j].tech, 1, false, true);
                            //CraftData.AddToInventory(BlueprintPairs[j].tech, 1, false, true);
                            awards++;
                            TotalWeight -= IngredientsFromScanning.Main.config.GetWeightForTechType(BlueprintPairs[j].tech);
                            BlueprintPairs.RemoveAt(j);
                            break;
                        }
                    }
                }
                return(false);
            }
            return(true);
        }