Пример #1
0
        public static void ConCmdAICScramble(ConCommandArgs args)
        {
            var rng = new Xoroshiro128Plus(0);

            AutoItemConfig.instances.ForEach(x => {
                /*if(x.configEntry.Description.AcceptableValues is AcceptableValueList) {
                 *
                 * } else if(x.configEntry.Description.AcceptableValues is AcceptableValueRange)*/
                var av = x.configEntry.Description.AcceptableValues;
                if (x.propType == typeof(bool))
                {
                    x.UpdateProperty(rng.nextBool);
                }
                else if (x.propType == typeof(int))
                {
                    if (av != null && av is AcceptableValueRange <int> )
                    {
                        x.UpdateProperty((int)Mathf.Lerp(((AcceptableValueRange <int>)av).MinValue, ((AcceptableValueRange <int>)av).MaxValue, rng.nextNormalizedFloat));
                    }
                    else if (av != null && av is AcceptableValueList <int> )
                    {
                        x.UpdateProperty(rng.NextElementUniform(((AcceptableValueList <int>)av).AcceptableValues));
                    }
                    else
                    {
                        x.UpdateProperty(rng.nextInt);
                    }
                }
                else if (x.propType == typeof(float))
                {
                    if (av != null && av is AcceptableValueRange <float> )
                    {
                        x.UpdateProperty(Mathf.Lerp(((AcceptableValueRange <float>)av).MinValue, ((AcceptableValueRange <float>)av).MaxValue, rng.nextNormalizedFloat));
                    }
                    else if (av != null && av is AcceptableValueList <float> )
                    {
                        x.UpdateProperty(rng.NextElementUniform(((AcceptableValueList <float>)av).AcceptableValues));
                    }
                    else
                    {
                        x.UpdateProperty((rng.nextNormalizedFloat - 0.5f) * float.MaxValue);
                    }
                }
            });
        }
        // Token: 0x060003CC RID: 972 RVA: 0x0000EA98 File Offset: 0x0000CC98
        public override PickupIndex GenerateDrop(Xoroshiro128Plus rng)
        {
            List <PickupIndex> list = this.selector.Evaluate(rng.nextNormalizedFloat);

            if (list.Count <= 0)
            {
                return(PickupIndex.none);
            }
            return(rng.NextElementUniform <PickupIndex>(list));
        }
            public void AddShrineStack(Interactor interactor)
            {
                waitingForRefresh = true;
                CharacterBody component = interactor.GetComponent <CharacterBody>();

                int addReds = 0;

                int[] itemStacks = component.inventory.itemStacks;
                for (int i = 0; i < itemStacks.Length; i++)
                {
                    ItemIndex itemIndex = (ItemIndex)i;
                    if (itemStacks[i] > 0)
                    {
                        switch (ItemCatalog.GetItemDef(itemIndex).tier)
                        {
                        case ItemTier.Tier1:
                        case ItemTier.Tier2:
                        case ItemTier.Lunar:
                        case ItemTier.Boss:
                            addReds += itemStacks[i];
                            component.inventory.itemAcquisitionOrder.Remove(itemIndex);
                            component.inventory.ResetItem(itemIndex);
                            break;
                        }
                    }
                }
                for (var i = 0; i < addReds; i++)
                {
                    var rolledRed = rng.NextElementUniform <ItemIndex>(availableItems);
                    component.inventory.GiveItem(rolledRed);
                }
                component.inventory.SetDirtyBit(8U);

                Chat.SendBroadcastChat(new Chat.SubjectFormatChatMessage
                {
                    subjectAsCharacterBody = component,
                    baseToken = "MYSTICSITEMS_SHRINE_LEGENDARY_USE_MESSAGE"
                });
                EffectManager.SpawnEffect(LegacyResourcesAPI.Load <GameObject>("Prefabs/Effects/ShrineUseEffect"), new EffectData
                {
                    origin   = transform.position,
                    rotation = Quaternion.identity,
                    scale    = 1f,
                    color    = new Color32(255, 97, 84, 255)
                }, true);
                purchaseCount++;
                refreshTimer = refreshDuration;
                if (purchaseCount >= maxPurchaseCount)
                {
                    symbolTransform.gameObject.SetActive(false);
                }
            }
Пример #4
0
        //Chance Shrine
        private static void ShrineChanceBehavior_AddShrineStack(On.RoR2.ShrineChanceBehavior.orig_AddShrineStack orig, ShrineChanceBehavior self, Interactor activator)
        {
            orig(self, activator);
            var characterBody = activator.GetComponent <CharacterBody>();

            if (characterBody)
            {
                var inv = characterBody.inventory;
                if (inv)
                {
                    if (inv.GetItemCount(ExtraShrineRollItemIndex) > 0 && Util.CheckRoll(ItemProcChance * inv.GetItemCount(ExtraShrineRollItemIndex), characterBody.master))
                    {
                        Xoroshiro128Plus rng    = new Xoroshiro128Plus(Run.instance.treasureRng.nextUlong);
                        PickupIndex      none   = PickupIndex.none;
                        PickupIndex      value  = rng.NextElementUniform <PickupIndex>(Run.instance.availableTier1DropList);
                        PickupIndex      value2 = rng.NextElementUniform <PickupIndex>(Run.instance.availableTier2DropList);
                        PickupIndex      value3 = rng.NextElementUniform <PickupIndex>(Run.instance.availableTier3DropList);
                        PickupIndex      value4 = rng.NextElementUniform <PickupIndex>(Run.instance.availableEquipmentDropList);
                        WeightedSelection <PickupIndex> weightedSelection = new WeightedSelection <PickupIndex>(8);
                        weightedSelection.AddChoice(none, self.failureWeight);
                        weightedSelection.AddChoice(value, self.tier1Weight);
                        weightedSelection.AddChoice(value2, self.tier2Weight);
                        weightedSelection.AddChoice(value3, self.tier3Weight);
                        weightedSelection.AddChoice(value4, self.equipmentWeight);
                        PickupIndex pickupIndex = weightedSelection.Evaluate(rng.nextNormalizedFloat);
                        bool        flag        = pickupIndex == PickupIndex.none;
                        if (flag)
                        {
                            Chat.AddMessage("<color=\"green\">Lucky Default Sphere <style=cShrine>has rolled the shrine an additional time for:</style><color=\"white\"> Nothing.");
                        }
                        else
                        {
                            Chat.AddMessage($"<color=\"green\">Lucky Default Sphere <style=cShrine>has rolled the shrine an additional time for:</style><color=\"white\"> {Language.GetString(PickupCatalog.GetPickupDef(pickupIndex).nameToken)}");
                            PickupDropletController.CreatePickupDroplet(pickupIndex, self.dropletOrigin.position, self.dropletOrigin.forward * 20f);
                        }
                    }
                }
            }
        }
Пример #5
0
        public static void RepopulateTerminals(MultiShopController multiShopController, ItemTierShopConfig itemTierConfig)
        {
            GameObject[] terminalGameObjects = multiShopController.GetFieldValue <GameObject[]>("terminalGameObjects");
            for (int i = 0; i < multiShopController.terminalPositions.Length; i++)
            {
                List <PickupIndex> otherItemsList = new List <PickupIndex>();
                PickupIndex        newPickupIndex = PickupIndex.none;
                Xoroshiro128Plus   treasureRng    = Run.instance.treasureRng;
                switch (itemTierConfig.itemTier)
                {
                case ItemTier.Tier1:
                    newPickupIndex = treasureRng.NextElementUniform <PickupIndex>(Run.instance.availableTier1DropList);
                    break;

                case ItemTier.Tier2:
                    newPickupIndex = treasureRng.NextElementUniform <PickupIndex>(Run.instance.availableTier2DropList);
                    break;

                case ItemTier.Tier3:
                    newPickupIndex = treasureRng.NextElementUniform <PickupIndex>(Run.instance.availableTier3DropList);
                    break;

                case ItemTier.Lunar:
                    newPickupIndex = treasureRng.NextElementUniform <PickupIndex>(Run.instance.availableLunarDropList);
                    break;

                case ItemTier.Boss:
                    otherItemsList = new List <PickupIndex>();
                    var bossItemIndexList = R2API.ItemDropAPI.GetDefaultDropList(ItemTier.Boss);
                    foreach (var itemIndex in bossItemIndexList)
                    {
                        otherItemsList.Add(new PickupIndex(itemIndex));
                    }
                    newPickupIndex = treasureRng.NextElementUniform <PickupIndex>(otherItemsList);
                    break;

                case ItemTier.NoTier:
                    if (itemTierConfig.isEquipment)
                    {
                        otherItemsList = new List <PickupIndex>();
                        var equipmentIndexList = R2API.ItemDropAPI.GetDefaultEquipmentDropList();
                        foreach (var itemIndex in equipmentIndexList)
                        {
                            otherItemsList.Add(new PickupIndex(itemIndex));
                        }
                        newPickupIndex = treasureRng.NextElementUniform <PickupIndex>(otherItemsList);
                        //self.itemTier = ItemTier.Tier1;
                    }
                    break;
                }
                bool newHidden = Run.instance.treasureRng.nextNormalizedFloat < 0.2f;
                terminalGameObjects[i].GetComponent <ShopTerminalBehavior>().SetPickupIndex(newPickupIndex, newHidden);
            }
        }
Пример #6
0
        // Token: 0x060013BE RID: 5054 RVA: 0x00054754 File Offset: 0x00052954
        public unsafe static void AddSpawnPoint(NodeGraph nodeGraph, NodeGraph.NodeIndex nodeIndex, Xoroshiro128Plus rng)
        {
            Vector3 vector;

            nodeGraph.GetNodePosition(nodeIndex, out vector);
            NodeGraph.LinkIndex[] activeNodeLinks = nodeGraph.GetActiveNodeLinks(nodeIndex);
            Quaternion            rotation;

            if (activeNodeLinks.Length != 0)
            {
                NodeGraph.LinkIndex linkIndex = *rng.NextElementUniform <NodeGraph.LinkIndex>(activeNodeLinks);
                Vector3             a;
                nodeGraph.GetNodePosition(nodeGraph.GetLinkEndNode(linkIndex), out a);
                rotation = Util.QuaternionSafeLookRotation(a - vector);
            }
            else
            {
                rotation = Quaternion.Euler(0f, rng.nextNormalizedFloat * 360f, 0f);
            }
            SpawnPoint.AddSpawnPoint(vector, rotation);
        }
Пример #7
0
        public static void CreateTerminals(On.RoR2.MultiShopController.orig_CreateTerminals orig, MultiShopController self, ItemTierShopConfig itemTierConfig)
        {
            // Boss Items and Equipment can not be part of multi shops by default, so needs a special case
            List <PickupIndex> otherItemsList = new List <PickupIndex>();

            if (itemTierConfig.itemTier == ItemTier.Boss)
            {
                var itemIndexList = R2API.ItemDropAPI.GetDefaultDropList(ItemTier.Boss);
                foreach (var itemIndex in itemIndexList)
                {
                    otherItemsList.Add(new PickupIndex(itemIndex));
                }
            }
            else if (itemTierConfig.itemTier == ItemTier.NoTier && itemTierConfig.isEquipment)
            {
                var itemIndexList = R2API.ItemDropAPI.GetDefaultEquipmentDropList();
                foreach (var itemIndex in itemIndexList)
                {
                    otherItemsList.Add(new PickupIndex(itemIndex));
                }
            }
            if (otherItemsList.Count > 0)
            {
                self.SetFieldValue("terminalGameObjects", new GameObject[self.terminalPositions.Length]);
                for (int i = 0; i < self.terminalPositions.Length; i++)
                {
                    PickupIndex      newPickupIndex = PickupIndex.none;
                    Xoroshiro128Plus treasureRng    = Run.instance.treasureRng;
                    newPickupIndex = treasureRng.NextElementUniform <PickupIndex>(otherItemsList);
                    bool       newHidden  = Run.instance.treasureRng.nextNormalizedFloat < 0.2f;
                    GameObject gameObject = UnityEngine.Object.Instantiate <GameObject>(self.terminalPrefab, self.terminalPositions[i].position, self.terminalPositions[i].rotation);
                    self.GetFieldValue <GameObject[]>("terminalGameObjects")[i] = gameObject;
                    gameObject.GetComponent <ShopTerminalBehavior>().SetPickupIndex(newPickupIndex, newHidden);
                    NetworkServer.Spawn(gameObject);
                }
                return;
            }

            orig(self);
        }
Пример #8
0
        private static ItemIndex SelectItemFromTier(List <ItemIndex> itemIndexs, ItemTier itemTier)
        {
            List <ItemIndex> tieredItems = new List <ItemIndex>();
            var itemIndex = ItemIndex.None;

            foreach (var item in itemIndexs)
            {
                var itemDef = ItemCatalog.GetItemDef(item);
                if (itemDef.tier == itemTier)
                {
                    tieredItems.Add(item);
                }
            }
            if (tieredItems.Count > 0)
            {
                Xoroshiro128Plus rng = new Xoroshiro128Plus(Run.instance.treasureRng.nextUlong);

                itemIndex = rng.NextElementUniform(tieredItems);
            }


            return(itemIndex);
        }
Пример #9
0
        public void Awake()
        {
            noRefresh       = Config.Wrap("Shrine of Chance", "NoCooldown", "When enabled, this gets rid of the 2 second cooldown between purchases. Default = false", false);
            maximumPurchase = Config.Wrap("Shrine of Chance", "MaxPurchase", "The maximum number of purchases you can make before the shrine is disabled. Default = 2", 2);
            chatMessages    = Config.Wrap("Chat", "ChatMessages", "When enabled, you will get a message in the chat letting you know you have increased odds. Default = true", true);

            //init failure count
            int failureCount = 0;

            On.RoR2.ShrineChanceBehavior.AddShrineStack += (orig, self, activator) =>
            {
                //set maximum purchase count
                self.maxPurchaseCount = maximumPurchase.Value;

                /*
                 * everything is default the first 2 tries.
                 * if you fail 2 times in a row, on the third try, the weights change to be more favorable for a tier 2 item or equipment
                 * if you fail 5 times in a row, on the sixth try, the weights change to be more favorable for a tier 3 item
                 * if you fail 8 times in a row, on the ninth try, you are guaranteed a tier 3 item
                 */

                if (failureCount >= 0 && failureCount < 2)
                {
                    self.tier1Weight     = 8;
                    self.tier2Weight     = 2;
                    self.tier3Weight     = 0.2f;
                    self.equipmentWeight = 2;
                    self.failureWeight   = 10.1f;
                }
                else if (failureCount >= 2 && failureCount < 5)
                {
                    if (chatMessages.Value)
                    {
                        Chat.AddMessage("Increased chances for tier 2 item or equipment");
                    }
                    self.tier1Weight     = -100;
                    self.tier2Weight     = 4;
                    self.tier3Weight     = 0.2f;
                    self.equipmentWeight = 2;
                    self.failureWeight   = 10.1f;
                }
                else if (failureCount >= 5 && failureCount < 8)
                {
                    if (chatMessages.Value)
                    {
                        Chat.AddMessage("Increased chances for tier 3 item");
                    }
                    self.tier1Weight     = -100;
                    self.tier2Weight     = 2;
                    self.tier3Weight     = 4;
                    self.equipmentWeight = -100;
                    self.failureWeight   = 10.1f;
                }
                else if (failureCount >= 8)
                {
                    if (chatMessages.Value)
                    {
                        Chat.AddMessage("Guaranteed Legendary. You've earned it.");
                    }
                    self.tier1Weight     = -100;
                    self.tier2Weight     = -100;
                    self.tier3Weight     = 1000;
                    self.equipmentWeight = -100;
                    self.failureWeight   = -100;
                }

                if (!NetworkServer.active)
                {
                    Debug.LogWarning("[Server] function 'System.Void RoR2.ShrineChanceBehavior::AddShrineStack(RoR2.Interactor)' called on client");
                    return;
                }
                Xoroshiro128Plus rng    = self.GetFieldValue <Xoroshiro128Plus>("rng");
                PickupIndex      none   = PickupIndex.none;
                PickupIndex      value  = rng.NextElementUniform <PickupIndex>(Run.instance.availableTier1DropList);
                PickupIndex      value2 = rng.NextElementUniform <PickupIndex>(Run.instance.availableTier2DropList);
                PickupIndex      value3 = rng.NextElementUniform <PickupIndex>(Run.instance.availableTier3DropList);
                PickupIndex      value4 = rng.NextElementUniform <PickupIndex>(Run.instance.availableEquipmentDropList);
                WeightedSelection <PickupIndex> weightedSelection = new WeightedSelection <PickupIndex>(8);
                weightedSelection.AddChoice(none, self.failureWeight);
                weightedSelection.AddChoice(value, self.tier1Weight);
                weightedSelection.AddChoice(value2, self.tier2Weight);
                weightedSelection.AddChoice(value3, self.tier3Weight);
                weightedSelection.AddChoice(value4, self.equipmentWeight);
                PickupIndex pickupIndex = weightedSelection.Evaluate(rng.nextNormalizedFloat);
                bool        flag        = pickupIndex == PickupIndex.none;
                if (flag)
                {
                    Chat.SubjectFormatChatMessage formatChatMessage = new Chat.SubjectFormatChatMessage();
                    formatChatMessage.subjectAsCharacterBody = activator.GetComponent <CharacterBody>();
                    formatChatMessage.baseToken = "SHRINE_CHANCE_FAIL_MESSAGE";
                    Chat.SendBroadcastChat((Chat.ChatMessageBase)formatChatMessage);
                    //on failure, increment failure count
                    failureCount++;
                }
                else
                {
                    self.SetFieldValue <int>("successfulPurchaseCount", self.GetFieldValue <int>("successfulPurchaseCount") + 1);
                    //this.successfulPurchaseCount++;
                    PickupDropletController.CreatePickupDroplet(pickupIndex, self.dropletOrigin.position, self.dropletOrigin.forward * 20f);
                    Chat.SubjectFormatChatMessage formatChatMessage = new Chat.SubjectFormatChatMessage();
                    formatChatMessage.subjectAsCharacterBody = activator.GetComponent <CharacterBody>();
                    formatChatMessage.baseToken = "SHRINE_CHANCE_SUCCESS_MESSAGE";
                    Chat.SendBroadcastChat((Chat.ChatMessageBase)formatChatMessage);
                    //on success, reset failure count to 0
                    failureCount = 0;
                }
                //Action<bool, Interactor> action = ShrineChanceBehavior.onShrineChancePurchaseGlobal;
                Action <bool, Interactor> action = typeof(ShrineChanceBehavior).GetFieldValue <Action <bool, Interactor> >("onShrineChancePurchaseGlobal");
                if (action != null)
                {
                    action(flag, activator);
                }
                self.SetFieldValue <bool>("waitingForRefresh", true);
                //this.waitingForRefresh = true;
                if (noRefresh.Value)
                {
                    self.SetFieldValue <float>("refreshTimer", 0f);
                }
                else
                {
                    self.SetFieldValue <float>("refreshTimer", 2f);
                }
                //this.refreshTimer = 2f;
                EffectManager.instance.SpawnEffect(Resources.Load <GameObject>("Prefabs/Effects/ShrineUseEffect"), new EffectData
                {
                    origin   = base.transform.position,
                    rotation = Quaternion.identity,
                    scale    = 1f,
                    color    = self.shrineColor
                }, true);
                if (self.GetFieldValue <int>("successfulPurchaseCount") >= self.maxPurchaseCount)
                {
                    self.symbolTransform.gameObject.SetActive(false);
                }
            };
        }
        public void ShrineRestackInventory([NotNull] Xoroshiro128Plus rng)
        {
            if (!NetworkServer.active)
            {
                Debug.LogWarning("[Server] function 'System.Void RoR2.Inventory::ShrineRestackInventory(Xoroshiro128Plus)' called on client");
                return;
            }
            List <ItemIndex> list  = new List <ItemIndex>();
            List <ItemIndex> list2 = new List <ItemIndex>();
            List <ItemIndex> list3 = new List <ItemIndex>();
            List <ItemIndex> list4 = new List <ItemIndex>();
            List <ItemIndex> list5 = new List <ItemIndex>();
            int num  = 0;
            int num2 = 0;
            int num3 = 0;
            int num4 = 0;
            int num5 = 0;

            for (int i = 0; i < this.itemStacks.Length; i++)
            {
                ItemIndex itemIndex = (ItemIndex)i;
                if (this.itemStacks[i] > 0)
                {
                    switch (ItemCatalog.GetItemDef(itemIndex).tier)
                    {
                    case ItemTier.Tier1:
                        num += this.itemStacks[i];
                        list.Add(itemIndex);
                        break;

                    case ItemTier.Tier2:
                        num2 += this.itemStacks[i];
                        list2.Add(itemIndex);
                        break;

                    case ItemTier.Tier3:
                        num3 += this.itemStacks[i];
                        list3.Add(itemIndex);
                        break;

                    case ItemTier.Lunar:
                        num4 += this.itemStacks[i];
                        list4.Add(itemIndex);
                        break;

                    case ItemTier.Boss:
                        num5 += this.itemStacks[i];
                        list5.Add(itemIndex);
                        break;

                    default:
                        goto IL_12C;
                    }
                    this.itemAcquisitionOrder.Remove(itemIndex);
                    this.ResetItem(itemIndex);
                }
                IL_12C :;
            }
            ItemIndex itemIndex2 = (list.Count == 0) ? ItemIndex.None : rng.NextElementUniform <ItemIndex>(list);
            ItemIndex itemIndex3 = (list2.Count == 0) ? ItemIndex.None : rng.NextElementUniform <ItemIndex>(list2);
            ItemIndex itemIndex4 = (list3.Count == 0) ? ItemIndex.None : rng.NextElementUniform <ItemIndex>(list3);
            ItemIndex itemIndex5 = (list4.Count == 0) ? ItemIndex.None : rng.NextElementUniform <ItemIndex>(list4);
            ItemIndex itemIndex6 = (list5.Count == 0) ? ItemIndex.None : rng.NextElementUniform <ItemIndex>(list5);

            this.GiveItem(itemIndex2, num);
            this.GiveItem(itemIndex3, num2);
            this.GiveItem(itemIndex4, num3);
            this.GiveItem(itemIndex5, num4);
            this.GiveItem(itemIndex6, num5);
            base.SetDirtyBit(8U);
        }
Пример #11
0
        private void MultiShopController_on_CreateTerminals1(On.RoR2.MultiShopController.orig_CreateTerminals orig, RoR2.MultiShopController self)
        {
            orig(self);

            int questionCount          = 0;
            int sameCount              = 0;
            List <PickupIndex> pickups = new List <PickupIndex>();

            Xoroshiro128Plus rng = self.GetFieldValue <Xoroshiro128Plus>("rng");

            GameObject[]           terminals = self.GetFieldValue <GameObject[]>("terminalGameObjects");
            ShopTerminalBehavior[] behaviors = new ShopTerminalBehavior[3];
            for (int i = 0; i < 3; i++)
            {
                GameObject           terminal = terminals[i];
                ShopTerminalBehavior stb      = terminal.GetComponent <ShopTerminalBehavior>();

                behaviors[i] = stb;
                if (stb)
                {
                    bool shopDirty = false;
                    bool hidden    = stb.pickupIndexIsHidden;
                    if (hidden)
                    {
                        questionCount++;
                        if (questionCount > maxQuestions.Value)
                        {
                            hidden     = false;
                            shopDirty |= true;
                        }
                    }
                    PickupIndex pickupIndex = stb.CurrentPickupIndex();
                    if (pickups.Contains(pickupIndex))
                    {
                        sameCount++;
                        if (sameCount > maxSame.Value)
                        {
                            shopDirty |= true;
                            switch (self.itemTier)
                            {
                            case ItemTier.Tier1:
                                pickupIndex = rng.NextElementUniform(Run.instance.availableTier1DropList);
                                break;

                            case ItemTier.Tier2:
                                pickupIndex = rng.NextElementUniform(Run.instance.availableTier2DropList);
                                break;

                            case ItemTier.Tier3:
                                pickupIndex = rng.NextElementUniform(Run.instance.availableTier3DropList);
                                break;

                            case ItemTier.Lunar:
                                pickupIndex = rng.NextElementUniform(Run.instance.availableLunarDropList);
                                break;
                            }
                        }
                    }
                    pickups.Add(pickupIndex);

                    if (shopDirty)
                    {
                        stb.SetPickupIndex(pickupIndex, hidden);
                    }
                }
                else
                {
                    TweakLogger.LogWarning("MultiShopImprovements", "Something was wrong with a terminal, aborting.");
                    return;
                }
            }
            while (questionCount > maxQuestions.Value)
            {
                questionCount--;
                behaviors[questionCount].SetPickupIndex(pickups[questionCount], false);
            }
            if (sameCount > maxSame.Value)
            {
            }
        }
Пример #12
0
        private void BossGroupDropRewards(On.RoR2.BossGroup.orig_DropRewards orig, BossGroup self)
        {
            //NOTE: We're overwriting the behavior entirely here, so no need to call back to orig

            //If no players, nothing to do
            int participatingPlayerCount = R2API.ItemDropAPI.BossDropParticipatingPlayerCount ?? Run.instance.participatingPlayerCount;

            if (participatingPlayerCount == 0)
            {
                return;
            }

            //More items for more players and for more mountain shrines
            int itemCount = (1 + self.bonusRewardCount);

            if (self.scaleRewardsByPlayerCount)
            {
                itemCount *= participatingPlayerCount;
            }

            for (int i = 0; i < itemCount; i++)
            {
                var rng = new Xoroshiro128Plus(Run.instance.stageRng.nextUlong);

                //Create spawn card for a free green-item shop
                var spawnCard  = Resources.Load <InteractableSpawnCard>("SpawnCards/InteractableSpawnCard/iscTripleShopLarge");
                var controller = spawnCard.prefab.GetComponent <MultiShopController>();

                //Slowly increasing chance of red items, capping at 20%
                var maxChance      = RaincoatConfig.BossDropRedsMaxChance.Value;
                var chancePerStage = RaincoatConfig.BossDropRedsChancePerStage.Value;
                var minStage       = RaincoatConfig.BossDropRedsMinStage.Value;
                var redChance      = Mathf.Min(maxChance, chancePerStage * (Run.instance.stageClearCount - minStage - 1));
                controller.itemTier = rng.nextNormalizedFloat < redChance || self.forceTier3Reward ? ItemTier.Tier3 : ItemTier.Tier2;

                //Determine where to place the shop (randomly relative to the drop position)
                var placementRule = new DirectorPlacementRule();
                placementRule.maxDistance   = 60f;
                placementRule.minDistance   = 10f;
                placementRule.placementMode = DirectorPlacementRule.PlacementMode.Approximate;
                placementRule.position      = self.dropPosition.position;
                placementRule.spawnOnTarget = self.dropPosition;

                var spawnRequest = new DirectorSpawnRequest(spawnCard, placementRule, rng);

                var oldBaseCost = controller.baseCost;
                controller.baseCost = 0;
                var spawnedObj = DirectorCore.instance.TrySpawnObject(spawnRequest);
                controller.baseCost = oldBaseCost;
                if (spawnedObj != null)
                {
                    //Replace first terminal with special boss item, if applicable
                    var bossDrops = self.GetFieldValue <List <PickupIndex> >("bossDrops");
                    if (bossDrops?.Count > 0 && rng.nextNormalizedFloat <= self.bossDropChance)
                    {
                        controller = spawnedObj.GetComponent <MultiShopController>();
                        var terminal = controller.GetFieldValue <GameObject[]>("terminalGameObjects")[0];
                        var behavior = terminal.GetComponent <ShopTerminalBehavior>();
                        behavior.SetPickupIndex(rng.NextElementUniform(bossDrops));
                    }
                }
            }
        }
Пример #13
0
        private IEnumerator RunDice(CharacterBody body)
        {
            AkSoundEngine.PostEvent(SoundEvents.PlayJestersDice, body.gameObject);

            //Allow the dice rolling sound to run before actually swapping items
            yield return(new WaitForSecondsRealtime(1.2f));

            int collideCount      = Physics.OverlapSphereNonAlloc(body.corePosition, 25, _colliders, (int)LayerIndex.fakeActor.mask);
            var pickupControllers = Enumerable.Range(0, collideCount)
                                    .Select(i => _colliders[i].GetComponent <GenericPickupController>())
                                    .Where(c => c != null).ToList();

            int rerollCount = 0;

            foreach (var controller in pickupControllers)
            {
                var newIndex = controller.pickupIndex;

                var pickupDef = PickupCatalog.GetPickupDef(controller.pickupIndex);
                if (pickupDef.itemIndex != ItemIndex.None)
                {
                    var tier = ItemCatalog.GetItemDef(pickupDef.itemIndex).tier;
                    if (tier != ItemTier.NoTier)
                    {
                        newIndex = _rng.NextElementUniform(GetDropList(tier));
                    }
                }
                else if (pickupDef.equipmentIndex != EquipmentIndex.None)
                {
                    if (pickupDef.isLunar)
                    {
                        newIndex = _rng.NextElementUniform(Run.instance.availableLunarDropList);
                    }
                    else
                    {
                        newIndex = _rng.NextElementUniform(Run.instance.availableEquipmentDropList);
                    }
                }

                Debug.Log($"Replacing {controller.pickupIndex} on ground with {newIndex}");
                if (newIndex != controller.pickupIndex)
                {
                    var pos = controller.transform.position;
                    NetworkServer.Destroy(controller.gameObject);
                    PickupDropletController.CreatePickupDroplet(newIndex, pos, Vector3.zero);
                    rerollCount++;
                }
            }

            //Even if no item was rerolled on the ground, still reroll a random item in inventory
            if (rerollCount == 0)
            {
                rerollCount = 1;
            }

            var inv = body.master.inventory;

            for (int i = 0; i < rerollCount; i++)
            {
                //Accumulate list of all items in inventory so we can choose one randomly to reroll
                var allItems = new List <ItemIndex>();
                for (var item = ItemIndex.Syringe; item < (ItemIndex)ItemCatalog.itemCount; item++)
                {
                    for (int k = 0; k < inv.GetItemCount(item); k++)
                    {
                        //Vvoid rerolling 'hidden' (no tier) items and boss items
                        var def = ItemCatalog.GetItemDef(item);
                        if (def.tier != ItemTier.NoTier && def.tier != ItemTier.Boss)
                        {
                            //Will also avoid rerolling the last Gesture
                            //This is primarily so that if using with Gesture, will create a 'shuffle' run
                            if (item != ItemIndex.AutoCastEquipment || inv.GetItemCount(ItemIndex.AutoCastEquipment) > 1)
                            {
                                allItems.Add(item);
                            }
                        }
                    }
                }

                //If no items to reroll, we're done
                if (allItems.Count == 0)
                {
                    break;
                }

                //Replace item with a random item in the same tier
                var rerollItem   = _rng.NextElementUniform(allItems);
                var tier         = ItemCatalog.GetItemDef(rerollItem).tier;
                var newPickup    = _rng.NextElementUniform(GetDropList(tier));
                var newPickupDef = PickupCatalog.GetPickupDef(newPickup);
                inv.RemoveItem(rerollItem, 1);
                inv.GiveItem(newPickupDef.itemIndex, 1);

                //Display message
                var lostPickup    = PickupCatalog.FindPickupIndex(rerollItem);
                var lostPickupDef = PickupCatalog.GetPickupDef(lostPickup);
                var lostText      = Util.GenerateColoredString(Language.GetString(lostPickupDef.nameToken), lostPickupDef.baseColor);
                var newText       = Util.GenerateColoredString(Language.GetString(newPickupDef.nameToken), newPickupDef.baseColor);
                Chat.SendBroadcastChat(new Chat.SimpleChatMessage
                {
                    baseToken = $"The die has been cast: {lostText} has been lost and {newText} has been gained"
                });
            }
        }