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); } }
//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); } } } } }
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); } }
// 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); }
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); }
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); }
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); }
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) { } }
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)); } } } }
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" }); } }