internal static void Hook() { On.RoR2.SceneDirector.PlaceTeleporter += ResetClassValues; On.RoR2.HealthComponent.TakeDamage += BrittleCrownDamageHook; On.RoR2.GlobalEventManager.OnHitEnemy += BrittleCrownOnHitHook; On.RoR2.DeathRewards.OnKilledServer += ShareKillMoney; On.RoR2.BarrelInteraction.OnInteractionBegin += ShareBarrelMoney; On.RoR2.MoneyPickup.OnTriggerStay += ShareTomeMoney; On.RoR2.SceneExitController.Begin += SplitExitMoney; On.RoR2.PurchaseInteraction.OnInteractionBegin += OnShopPurchase; On.EntityStates.GoldGat.GoldGatFire.FireBullet += GoldGatFireHook; On.RoR2.Networking.GameNetworkManager.OnClientConnect += GoldGatConnect; On.RoR2.Networking.GameNetworkManager.OnClientDisconnect += GoldGatDisconnect; if (ShareSuite.MoneyIsShared.Value && GeneralHooks.IsMultiplayer()) { IL.EntityStates.GoldGat.GoldGatFire.FireBullet += RemoveGoldGatMoneyLine; } }
private static void OnPurchaseDrop(On.RoR2.ShopTerminalBehavior.orig_DropPickup orig, ShopTerminalBehavior self) { if (!NetworkServer.active) { orig(self); return; } var costType = self.GetComponent <PurchaseInteraction>().costType; if (!GeneralHooks.IsMultiplayer() || // is not multiplayer !IsValidItemPickup(self.CurrentPickupIndex()) || // item is not shared !ShareSuite.PrinterCauldronFixEnabled.Value || // dupe fix isn't enabled self.itemTier == ItemTier.Lunar || costType == CostTypeIndex.Money) { orig(self); } }
private static void SplitExitMoney(On.RoR2.SceneExitController.orig_Begin orig, SceneExitController self) { MapTransitionActive = true; if (!ShareSuite.MoneyIsShared.Value || !GeneralHooks.IsMultiplayer()) { orig(self); return; } var players = PlayerCharacterMasterController.instances.Count; foreach (var player in PlayerCharacterMasterController.instances) { player.master.money = (uint) // ReSharper disable once PossibleLossOfFraction Mathf.FloorToInt(player.master.money / players); } orig(self); }
private void ReloadHooks(object _ = null, EventArgs __ = null) { if (_previouslyEnabled && !ModIsEnabled.Value) { GeneralHooks.UnHook(); MoneySharingHooks.UnHook(); ItemSharingHooks.UnHook(); EquipmentSharingHooks.UnHook(); _previouslyEnabled = false; } if (!_previouslyEnabled && ModIsEnabled.Value) { _previouslyEnabled = true; GeneralHooks.Hook(); MoneySharingHooks.Hook(); ItemSharingHooks.Hook(); EquipmentSharingHooks.Hook(); } }
public static void OnGrantEquipment() { On.RoR2.GenericPickupController.GrantEquipment += (orig, self, body, inventory) => { if (!ShareSuite.ModIsEnabled.Value) { orig(self, body, inventory); return; } #region Sharedequipment var equip = PickupCatalog.GetPickupDef(self.pickupIndex).equipmentIndex; if (!ShareSuite.GetEquipmentBlackList().Contains((int)equip) && NetworkServer.active && IsValidEquipmentPickup(self.pickupIndex) && GeneralHooks.IsMultiplayer()) { foreach (var player in PlayerCharacterMasterController.instances.Select(p => p.master) .Where(p => p.alive || ShareSuite.DeadPlayersGetItems.Value)) { SyncToolbotEquip(player, ref equip); // Sync Mul-T Equipment, but perform primary equipment pickup only for clients if (player.inventory == inventory) { continue; } player.inventory.SetEquipmentIndex(equip); self.NetworkpickupIndex = PickupCatalog.FindPickupIndex(equip); } } orig(self, body, inventory); #endregion }; }
public static void OnGrantItem() { On.RoR2.GenericPickupController.GrantItem += (orig, self, body, inventory) => { if (!ShareSuite.ModIsEnabled.Value) { orig(self, body, inventory); return; } // Item to share var item = PickupCatalog.GetPickupDef(self.pickupIndex).itemIndex; if (!ShareSuite.GetItemBlackList().Contains((int)item) && NetworkServer.active && IsValidItemPickup(self.pickupIndex) && GeneralHooks.IsMultiplayer()) { foreach (var player in PlayerCharacterMasterController.instances.Select(p => p.master)) { // Ensure character is not original player that picked up item if (player.inventory == inventory) { continue; } // Do not reward dead players if not required if (!player.alive && !ShareSuite.DeadPlayersGetItems.Value) { continue; } player.inventory.GiveItem(item); } } orig(self, body, inventory); }; }
public static void SendRichPickupMessage(CharacterMaster player, PickupDef pickupDef) { var body = player.hasBody ? player.GetBody() : null; if (!GeneralHooks.IsMultiplayer() || body == null || !ShareSuite.RichMessagesEnabled.Value) { SendPickupMessage(player, pickupDef.pickupIndex); return; } var pickupColor = pickupDef.baseColor; var pickupName = Language.GetString(pickupDef.nameToken); var playerColor = GetPlayerColor(player.playerCharacterMasterController); if (Blacklist.HasItem(pickupDef.itemIndex) || !ItemSharingHooks.IsValidItemPickup(pickupDef.pickupIndex)) { var singlePickupMessage = $"<color=#{playerColor}>{body.GetUserName()}</color> <color=#{GrayColor}>picked up</color> " + $"<color=#{ColorUtility.ToHtmlStringRGB(pickupColor)}>" + $"{pickupName ?? "???"}</color> <color=#{GrayColor}>for themself. </color>" + $"<color=#{NotSharingColor}>(Item Set to NOT be Shared)</color>"; Chat.SendBroadcastChat(new Chat.SimpleChatMessage { baseToken = singlePickupMessage }); return; } var pickupMessage = $"<color=#{playerColor}>{body.GetUserName()}</color> <color=#{GrayColor}>picked up</color> " + $"<color=#{ColorUtility.ToHtmlStringRGB(pickupColor)}>" + $"{pickupName ?? "???"}</color> <color=#{GrayColor}>for themself</color>" + $"{ItemPickupFormatter(body)}<color=#{GrayColor}>.</color>"; Chat.SendBroadcastChat(new Chat.SimpleChatMessage { baseToken = pickupMessage }); }
private static void OnShopPurchase(On.RoR2.PurchaseInteraction.orig_OnInteractionBegin orig, PurchaseInteraction self, Interactor activator) { if (!self.CanBeAffordedByInteractor(activator)) { return; } var characterBody = activator.GetComponent <CharacterBody>(); var inventory = characterBody.inventory; #region Cauldronfix // If this is not a multi-player server or the fix is disabled, do the normal drop action if (!GeneralHooks.IsMultiplayer() || !ShareSuite.PrinterCauldronFixEnabled.Value) { orig(self, activator); return; } var shop = self.GetComponent <ShopTerminalBehavior>(); // If the cost type is an item, give the user the item directly and send the pickup message if (self.costType == CostTypeIndex.WhiteItem || self.costType == CostTypeIndex.GreenItem || self.costType == CostTypeIndex.RedItem || self.costType == CostTypeIndex.BossItem || self.costType == CostTypeIndex.LunarItemOrEquipment) { var item = PickupCatalog.GetPickupDef(shop.CurrentPickupIndex()).itemIndex; inventory.GiveItem(item); SendPickupMessage(inventory.GetComponent <CharacterMaster>(), shop.CurrentPickupIndex()); } #endregion Cauldronfix orig(self, activator); }
private static void OnPurchaseDrop(On.RoR2.ShopTerminalBehavior.orig_DropPickup orig, ShopTerminalBehavior self) { if (!NetworkServer.active) { orig(self); return; } var costType = self.GetComponent <PurchaseInteraction>().costType; //If is valid drop and dupe fix not enabled, true -> we want the item to pop //if is valid drop and dupe fix is enabled, false -> item IS shared, we don't want the item to pop, PrinterCauldronFix should deal with this //if is not valid drop and dupe fix is not enabled, true -> item ISN'T shared, and dupe fix isn't enabled, we want to pop //if is not valid drop and dupe fix is enabled, false -> item ISN'T shared, dupe fix should catch, we don't want to pop if (!GeneralHooks.IsMultiplayer() || // is not multiplayer (!IsValidItemPickup(self.CurrentPickupIndex()) && !ShareSuite.PrinterCauldronFixEnabled.Value) || //if it's not a valid drop AND the dupe fix isn't enabled self.itemTier == ItemTier.Lunar || costType == CostTypeIndex.Money) { orig(self); } }
public void Update() { if (!NetworkServer.active || !ModIsEnabled.Value || !MoneyIsShared.Value || MoneySharingHooks.MapTransitionActive || !GeneralHooks.IsMultiplayer()) { return; } foreach (var playerCharacterMasterController in PlayerCharacterMasterController.instances) { if (playerCharacterMasterController.master.IsDeadAndOutOfLivesServer()) { continue; } if (playerCharacterMasterController.master.money == MoneySharingHooks.SharedMoneyValue) { continue; } playerCharacterMasterController.master.money = (uint)MoneySharingHooks.SharedMoneyValue; } }
private static void BrittleCrownOnHitHook(On.RoR2.GlobalEventManager.orig_OnHitEnemy orig, GlobalEventManager self, DamageInfo info, GameObject victim) { if (!ShareSuite.MoneyIsShared.Value || !GeneralHooks.IsMultiplayer() || !(bool)info.attacker || !(bool)info.attacker.GetComponent <CharacterBody>() || !(bool)info.attacker.GetComponent <CharacterBody>().master ) { orig(self, info, victim); return; } #region Sharedmoney // The idea here is that we track amount of money pre and post function evaluation. // We can subsequently apply the difference to the shared pool. var body = info.attacker.GetComponent <CharacterBody>(); var preDamageMoney = body.master.money; orig(self, info, victim); var postDamageMoney = body.master.money; // Ignore all of this if we do not actually have the item if (!body.inventory || body.inventory.GetItemCount(ItemCatalog.FindItemIndex("GoldOnHit")) <= 0) { return; } // Apply the calculation to the shared money pool SharedMoneyValue += (int)postDamageMoney - (int)preDamageMoney; #endregion }
private static void OnShopPurchase(On.RoR2.PurchaseInteraction.orig_OnInteractionBegin orig, PurchaseInteraction self, Interactor activator) { if (!self.CanBeAffordedByInteractor(activator)) { return; } if (!GeneralHooks.IsMultiplayer()) { orig(self, activator); return; } if (self.costType == CostTypeIndex.None) { orig(self, activator); return; } var shop = self.GetComponent <ShopTerminalBehavior>(); #region Cauldronfix if (printerCosts.Contains(self.costType)) { if (ShareSuite.PrinterCauldronFixEnabled.Value) { var characterBody = activator.GetComponent <CharacterBody>(); var inventory = characterBody.inventory; var item = PickupCatalog.GetPickupDef(shop.CurrentPickupIndex())?.itemIndex; if (item == null) { RoR2.Console.print("ShareSuite: PickupCatalog is null."); } else { inventory.GiveItem(item.Value); } orig(self, activator); ChatHandler.SendRichCauldronMessage(inventory.GetComponent <CharacterMaster>(), shop.CurrentPickupIndex()); return; } } #endregion Cauldronfix #region EquipDronefix if (ShareSuite.EquipmentShared.Value) { if (self.costType == CostTypeIndex.Equipment) { var rng = self.GetComponent <Xoroshiro128Plus>(); var itemIndex = ItemIndex.None; var costTypeDef = CostTypeCatalog.GetCostTypeDef(self.costType); if (shop) { itemIndex = PickupCatalog.GetPickupDef(shop.CurrentPickupIndex()).itemIndex; } var payCostResults = costTypeDef.PayCost(self.cost, activator, self.gameObject, rng, itemIndex); if (payCostResults.equipmentTaken.Count >= 1) { orig(self, activator); EquipmentSharingHooks.RemoveAllUnBlacklistedEquipment(); return; } } } #endregion orig(self, activator); }
private static void OnGrantItem(On.RoR2.GenericPickupController.orig_GrantItem orig, GenericPickupController self, CharacterBody body, Inventory inventory) { var item = PickupCatalog.GetPickupDef(self.pickupIndex); var itemDef = ItemCatalog.GetItemDef(item.itemIndex); var randomizedPlayerDict = new Dictionary <CharacterMaster, PickupDef>(); if ((ShareSuite.RandomizeSharedPickups.Value || !BlackList.HasItem(item.itemIndex)) && NetworkServer.active && IsValidItemPickup(self.pickupIndex) && GeneralHooks.IsMultiplayer()) { if (ShareSuite.RandomizeSharedPickups.Value) { randomizedPlayerDict.Add(body.master, item); } foreach (var player in PlayerCharacterMasterController.instances.Select(p => p.master)) { // Ensure character is not original player that picked up item if (player.inventory == inventory) { continue; } // Do not reward dead players if not required if (!ShareSuite.DeadPlayersGetItems.Value && player.IsDeadAndOutOfLivesServer()) { continue; } if (ShareSuite.RandomizeSharedPickups.Value) { var pickupIndex = GetRandomItemOfTier(itemDef.tier, item.pickupIndex); if (pickupIndex == null) { // Could not find any not blacklisted item in that tier. You get nothing! Good day, sir! continue; } var giveItem = PickupCatalog.GetPickupDef(pickupIndex.Value); player.inventory.GiveItem(giveItem.itemIndex); // Alternative: Only show pickup text for yourself // var givePickupDef = PickupCatalog.GetPickupDef(givePickupIndex); // Chat.AddPickupMessage(body, givePickupDef.nameToken, givePickupDef.baseColor, 1); // Legacy -- old normal pickup message handler //SendPickupMessage(player, giveItem); randomizedPlayerDict.Add(player, giveItem); } // Otherwise give everyone the same item else { player.inventory.GiveItem(item.itemIndex); } } ChatHandler.SendRichRandomizedPickupMessage(body.master, item, randomizedPlayerDict); orig(self, body, inventory); return; } ChatHandler.SendRichPickupMessage(body.master, item); orig(self, body, inventory); }
private static void OnShopPurchase(On.RoR2.PurchaseInteraction.orig_OnInteractionBegin orig, PurchaseInteraction self, Interactor activator) { if (!self.CanBeAffordedByInteractor(activator)) { return; } if (!GeneralHooks.IsMultiplayer()) { orig(self, activator); return; } var shop = self.GetComponent <ShopTerminalBehavior>(); #region Cauldronfix if (ShareSuite.PrinterCauldronFixEnabled.Value) { var characterBody = activator.GetComponent <CharacterBody>(); var inventory = characterBody.inventory; if (self.costType == CostTypeIndex.WhiteItem || self.costType == CostTypeIndex.GreenItem || self.costType == CostTypeIndex.RedItem || self.costType == CostTypeIndex.BossItem || self.costType == CostTypeIndex.LunarItemOrEquipment) { var item = PickupCatalog.GetPickupDef(shop.CurrentPickupIndex()).itemIndex; inventory.GiveItem(item); ChatHandler.SendRichCauldronMessage(inventory.GetComponent <CharacterMaster>(), shop.CurrentPickupIndex()); orig(self, activator); return; } } #endregion Cauldronfix #region EquipDronefix if (ShareSuite.EquipmentShared.Value) { var rng = self.GetComponent <Xoroshiro128Plus>(); var itemIndex = ItemIndex.None; var costTypeDef = CostTypeCatalog.GetCostTypeDef(self.costType); if (shop) { itemIndex = PickupCatalog.GetPickupDef(shop.CurrentPickupIndex()).itemIndex; } var payCostResults = costTypeDef.PayCost(self.cost, activator, self.gameObject, rng, itemIndex); foreach (var equipmentIndex in payCostResults.equipmentTaken) { //TODO fix equipment drones here } } #endregion EquipDronefix orig(self, activator); }
private static void OnGrantEquipment(On.RoR2.GenericPickupController.orig_GrantEquipment orig, GenericPickupController self, CharacterBody body, Inventory inventory) { #region Sharedequipment if (!ShareSuite.EquipmentShared.Value || !GeneralHooks.IsMultiplayer() || !NetworkServer.active) { orig(self, body, inventory); return; } // Get the old and new equipment's index var oldEquip = body.inventory.currentEquipmentIndex; var oldEquipPickupIndex = GetPickupIndex(oldEquip); var newEquip = PickupCatalog.GetPickupDef(self.pickupIndex).equipmentIndex; // Send the pickup message ChatHandler.SendPickupMessage(body.master, self.pickupIndex); // Give the equipment to the picker inventory.SetEquipmentIndex(newEquip); // Destroy the object Object.Destroy(self.gameObject); // If the old equipment was not shared and the new one is, drop the blacklisted equipment and any other // shared equipment that the other players have if (!EquipmentShared(oldEquip) && EquipmentShared(newEquip)) { CreateDropletIfExists(oldEquipPickupIndex, self.transform.position); DropAllOtherSharedEquipment(self, body, oldEquip); } // If the old equipment was shared and the new one isn't, but the picker is the only one alive with the // shared equipment, drop it on the ground and return else if (EquipmentShared(oldEquip) && !EquipmentShared(newEquip) && GetLivingPlayersWithEquipment(oldEquip) < 1 || !EquipmentShared(oldEquip) && !EquipmentShared(newEquip)) { CreateDropletIfExists(oldEquipPickupIndex, self.transform.position); return; } // If the new equip is shared, create a droplet of the old one. else if (EquipmentShared(newEquip)) { CreateDropletIfExists(oldEquipPickupIndex, self.transform.position); } // If the equipment they're picking up is not shared and someone else is alive with the shared equipment, // return else { return; } // Loop over everyone who has an inventory and isn't the picker foreach (var player in PlayerCharacterMasterController.instances.Select(p => p.master) .Where(p => p.inventory && p != body.master)) { var playerInventory = player.inventory; var playerOrigEquipment = playerInventory.currentEquipmentIndex; // If the player currently has an equipment that's blacklisted if (!EquipmentShared(playerOrigEquipment)) { // And the config option is set so that they will drop the item when shared if (!ShareSuite.DropBlacklistedEquipmentOnShare.Value) { continue; } // Create a droplet of their current blacklisted equipment on the ground var transform = player.GetBodyObject().transform; var pickupIndex = PickupCatalog.FindPickupIndex(playerOrigEquipment); PickupDropletController.CreatePickupDroplet(pickupIndex, transform.position, transform.forward * 20f); } // Give the player the new equipment playerInventory.SetEquipmentIndex(newEquip); self.NetworkpickupIndex = PickupCatalog.FindPickupIndex(newEquip); // Sync the equipment if they're playing MUL-T SyncToolbotEquip(player, ref newEquip); } #endregion }
private static void ScrappingToIdle_OnEnter(On.EntityStates.Scrapper.ScrappingToIdle.orig_OnEnter orig, ScrappingToIdle self) { if (!(ShareSuite.PrinterCauldronFixEnabled.Value && NetworkServer.active && GeneralHooks.IsMultiplayer())) { orig(self); return; } _itemLock = true; orig(self); ScrapperController scrapperController = GetInstanceField(typeof(ScrapperBaseState), self, "scrapperController") as ScrapperController; Debug.Log(scrapperController); Debug.Log(_itemLock); if (scrapperController) { PickupIndex pickupIndex = PickupIndex.none; ItemDef itemDef = ItemCatalog.GetItemDef(scrapperController.lastScrappedItemIndex); if (itemDef != null) { switch (itemDef.tier) { case ItemTier.Tier1: pickupIndex = PickupCatalog.FindPickupIndex("ItemIndex.ScrapWhite"); break; case ItemTier.Tier2: pickupIndex = PickupCatalog.FindPickupIndex("ItemIndex.ScrapGreen"); break; case ItemTier.Tier3: pickupIndex = PickupCatalog.FindPickupIndex("ItemIndex.ScrapRed"); break; case ItemTier.Boss: pickupIndex = PickupCatalog.FindPickupIndex("ItemIndex.ScrapYellow"); break; } } if (pickupIndex == PickupIndex.none) { return; } var interactor = GetInstanceField(typeof(ScrapperController), scrapperController, "interactor") as Interactor; Debug.Log("Interactor Established"); PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex); if (!interactor) { return; } SetInstanceField(typeof(ScrappingToIdle), self, "foundValidScrap", true); CharacterBody component = interactor.GetComponent <CharacterBody>(); component.inventory.GiveItem(pickupDef.itemIndex); ChatHandler.SendRichCauldronMessage(component.inventory.GetComponent <CharacterMaster>(), pickupIndex); scrapperController.itemsEaten -= 1; } }
public static void OnShopPurchase() { On.RoR2.PurchaseInteraction.OnInteractionBegin += (orig, self, activator) => { if (!ShareSuite.ModIsEnabled.Value) { orig(self, activator); return; } // Return if you can't afford the item if (!self.CanBeAffordedByInteractor(activator)) { return; } var characterBody = activator.GetComponent <CharacterBody>(); var inventory = characterBody.inventory; #region Sharedmoney if (ShareSuite.MoneyIsShared.Value) { switch (self.costType) { case CostTypeIndex.Money: { // Remove money from shared money pool orig(self, activator); MoneySharingHooks.SharedMoneyValue -= self.cost; return; } case CostTypeIndex.PercentHealth: { // Share the damage taken from a sacrifice // as it generates shared money orig(self, activator); var teamMaxHealth = 0; foreach (var playerCharacterMasterController in PlayerCharacterMasterController.instances) { var charMaxHealth = playerCharacterMasterController.master.GetBody().maxHealth; if (charMaxHealth > teamMaxHealth) { teamMaxHealth = (int)charMaxHealth; } } var purchaseInteraction = self.GetComponent <PurchaseInteraction>(); var shrineBloodBehavior = self.GetComponent <ShrineBloodBehavior>(); var amount = (uint)(teamMaxHealth * purchaseInteraction.cost / 100.0 * shrineBloodBehavior.goldToPaidHpRatio); if (ShareSuite.MoneyScalarEnabled.Value) { amount *= (uint)ShareSuite.MoneyScalar.Value; } MoneySharingHooks.SharedMoneyValue += (int)amount; return; } } } #endregion #region Cauldronfix // If this is not a multi-player server or the fix is disabled, do the normal drop action if (!GeneralHooks.IsMultiplayer() || !ShareSuite.PrinterCauldronFixEnabled.Value) { orig(self, activator); return; } var shop = self.GetComponent <ShopTerminalBehavior>(); // If the cost type is an item, give the user the item directly and send the pickup message if (self.costType == CostTypeIndex.WhiteItem || self.costType == CostTypeIndex.GreenItem || self.costType == CostTypeIndex.RedItem || self.costType == CostTypeIndex.BossItem || self.costType == CostTypeIndex.LunarItemOrEquipment) { var item = PickupCatalog.GetPickupDef(shop.CurrentPickupIndex()).itemIndex; inventory.GiveItem(item); SendPickupMessage.Invoke(null, new object[] { inventory.GetComponent <CharacterMaster>(), shop.CurrentPickupIndex() }); } #endregion Cauldronfix orig(self, activator); }; }