using System.Linq; namespace Supercell.Laser.Logic.Home { using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Supercell.Laser.Logic.Command.Home; using Supercell.Laser.Logic.Data; using Supercell.Laser.Logic.Data.Helper; using Supercell.Laser.Logic.Helper; using Supercell.Laser.Logic.Home.Gatcha; using Supercell.Laser.Logic.Home.Items; using Supercell.Laser.Logic.Home.Quest; using Supercell.Laser.Logic.Home.Structures; using Supercell.Laser.Logic.Message.Home; using Supercell.Laser.Titan.DataStream; [JsonObject(MemberSerialization.OptIn)] public class ClientHome { public const int DAILYOFFERS_COUNT = 6; public const int MAX_BATTLE_TOKENS = 500; public const int BATTLE_TOKENS_REGEN_AMOUNT = 20; public const int BATTLE_TOKENS_REGEN_MINUTES = 20; public static readonly int[] GoldPacksPrice = new int[] { 20, 50, 140, 280 }; public static readonly int[] GoldPacksAmount = new int[] { 150, 400, 1200, 2600 }; [JsonProperty] public long HomeId; [JsonProperty] public int ThumbnailId; [JsonProperty] public int CharacterId; [JsonProperty] public int SkinId; [JsonProperty] public List OfferBundles; [JsonProperty] public int TrophiesReward; [JsonProperty] public int TokenReward; [JsonProperty] public int StarTokenReward; [JsonProperty] public int StarPointsGained; [JsonProperty] public int CoinsGained; [JsonProperty] public int GemsGained; [JsonProperty] public int PowerPlayTrophiesReward; [JsonProperty] public int TokenDoublers; [JsonProperty] public int BrawlPassProgress; [JsonProperty] public int PremiumPassProgress; [JsonProperty] public int BrawlPassTokens; [JsonProperty] public bool HasPremiumPass; [JsonProperty] public List UnlockedEmotes; [JsonProperty] public List UnlockedSkins; [JsonProperty] public int BattleTokens; [JsonProperty] public DateTime BattleTokensRefreshStart; [JsonProperty] public int TrophyRoadProgress; [JsonProperty] public int Namecolor; [JsonProperty] public int Exp; [JsonProperty] public Quests Quests; [JsonProperty] public int[] SelectedSkins; [JsonProperty] public List OffersClaimed; [JsonProperty] public string Day; [JsonProperty] public DateTime CreatorEndTime; [JsonProperty] public DateTime PremiumEndTime; [JsonProperty] public DateTime PremiumWelcomeNotifDate; [JsonProperty] public bool BlockFriendRequests; [JsonProperty] public bool CreatorCodeActivated; [JsonProperty] public NotificationFactory NotificationFactory; [JsonProperty] public bool TelegramLinked; [JsonProperty] public List TelegramLinkedChats; [JsonProperty] public bool HasIP; [JsonProperty] public string FirstIpAddress; [JsonProperty] public string IpAddress; [JsonProperty] public string Device; [JsonProperty] public string AndroidId; [JsonProperty] public string CountryCode; [JsonProperty] public bool IsDev; [JsonIgnore] public EventData[] Events; public PlayerThumbnailData Thumbnail => DataTables.Get(DataType.PlayerThumbnail).GetDataByGlobalId(ThumbnailId); public CharacterData Character => DataTables.Get(DataType.Character).GetDataByGlobalId(CharacterId); public HomeMode HomeMode; [JsonProperty] public DateTime LastVisitHomeTime; public void GenerateNotification( DateTime offerStart, DateTime offerEnd, int id, string messageEntry, int count, int brawlerId, int skin, string claim) { if (TimerMath(offerStart, offerEnd) <= -1 || OffersClaimed.Contains(claim)) { return; } OffersClaimed.Add(claim); HomeMode.Home.NotificationFactory.Add(new Notification { Id = id, MessageEntry = messageEntry, DonationCount = count, brawlerId = brawlerId, skin = skin, }); } public ClientHome() { ThumbnailId = GlobalId.CreateGlobalId(28, 0); CharacterId = GlobalId.CreateGlobalId(16, 0); SelectedSkins = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; OfferBundles = new List(); LastVisitHomeTime = DateTime.UnixEpoch; OffersClaimed = new List(); TrophyRoadProgress = 1; BrawlPassProgress = 1; PremiumPassProgress = 1; UnlockedEmotes = new List(); BattleTokens = MAX_BATTLE_TOKENS; BattleTokensRefreshStart = new(); UnlockedSkins = new List(); if (NotificationFactory == null) { NotificationFactory = new NotificationFactory(); } TelegramLinked = false; TelegramLinkedChats = new List(); } public void LogicConfData(ByteStream stream, DateTime utcNow) { stream.WriteVInt(utcNow.Year * 1000 + utcNow.DayOfYear); stream.WriteVInt(utcNow.Hour * 3600 + utcNow.Minute * 60 + utcNow.Second); stream.WriteString(Day ?? utcNow.ToString("yyyy-MM-dd")); } public int TimerMath(DateTime timer_start, DateTime timer_end) { { DateTime timer_now = DateTime.Now; if (timer_now > timer_start) { if (timer_now < timer_end) { int time_sec = (int)(timer_end - timer_now).TotalSeconds; return time_sec; } else { return -1; } } else { return -1; } } } public void HomeVisited() { NotificationFactory n = new(); /*encoder.WriteVInt(1); { encoder.WriteVInt(83); encoder.WriteInt(0); encoder.WriteBoolean(false); encoder.WriteInt(0); encoder.WriteString(null); encoder.WriteInt(0); encoder.WriteStringReference("Добро пожаловать в Name Server"); encoder.WriteInt(0); encoder.WriteStringReference("Также рекомендуем зайти в наш тг канал и чат нажав кнопку ниже!(t.me/link)"); encoder.WriteInt(0); encoder.WriteStringReference("Перейти"); encoder.WriteStringReference("pop_up_1920x1235_welcome.png"); encoder.WriteStringReference("6bb3b752a80107a14671c7bdebe0a1b662448d0c"); encoder.WriteStringReference("brawlstars://extlink?page=https%3A%2F%2Ft.me%Сюда тег канала%2F"); encoder.WriteVInt(0); }*/ NormalizeUnlockedEmotes(); RotateShopContent(DateTime.UtcNow, OfferBundles.Count == 0); LastVisitHomeTime = DateTime.UtcNow; UpdateOfferBundles(); // Системные уведомления GenerateNotification( new DateTime(2020, 7, 31, 0, 0, 0), new DateTime(2034, 7, 27, 0, 0, 0), 81, "Привет! Не забудьте привязать свой аккаунт =0", 1, 0, 0, "notif_privyazka"); GenerateNotification( new DateTime(2020, 7, 31, 0, 0, 0), new DateTime(2034, 7, 27, 0, 0, 0), 81, "А также, подпишитесь на Telegram: @shiny_brawl", 1, 0, 0, "notif_tg"); NotificationFactory.Add(new Notification { Id = 83, PrimaryMessageEntry = "Добро пожаловать в Flane Brawl", SecondaryMessageEntry = "Также рекомендуем зайти в наш телеграм канал(t.me/flanebrawl)", ButtonMessageEntry = "Перейти", FileLocation = "pop_up_1920x1235_welcome.png", FileSha = "6bb3b752a80107a14671c7bdebe0a1b662448d0c", ExtLint = "brawlstars://extlink?page=https%3A%2F%2Ft.me%flanebrawl", }); /* string json = JsonConvert.SerializeObject(NotificationFactory, Formatting.Indented); System.Console.WriteLine(json); */ // Premium: уведомление об истечении через 3 дня if (HomeMode.Avatar.IsPremium && PremiumEndTime > DateTime.UtcNow) { double daysLeft = (PremiumEndTime - DateTime.UtcNow).TotalDays; if (daysLeft <= 3) { string claimKey = $"notif_prem_expire_{PremiumEndTime:yyyyMMdd}"; GenerateNotification( DateTime.UtcNow.AddDays(-1), PremiumEndTime, 81, $"Внимание! Ваш Premium истекает {PremiumEndTime:dd.MM.yyyy}!\nОбратитесь к администрации для продления.", 1, 0, 0, claimKey); } // Ежедневный нотиф о статусе Premium (раз в сутки) if (PremiumWelcomeNotifDate.Date < DateTime.UtcNow.Date) { PremiumWelcomeNotifDate = DateTime.UtcNow; int daysLeftInt = (int)Math.Ceiling(daysLeft); NotificationFactory.Add(new Notification { Id = 81, MessageEntry = $"Premium активен! Бонусы: x2 кубки в боях + ежедневные ящики.\nОстаток: {daysLeftInt} дн. (до {PremiumEndTime:dd.MM.yyyy})" }); } } if (Quests == null && TrophyRoadProgress >= 11) { Quests = new Quests(); Quests.AddRandomQuests(HomeMode.Avatar.Heroes, 12); } else if (Quests != null) { if (Quests.QuestList.Count < 12) // New quests adds at 07:00 AM UTC { Quests.AddRandomQuests(HomeMode.Avatar.Heroes, 12 - Quests.QuestList.Count); } } } private void NormalizeUnlockedEmotes() { if (UnlockedEmotes == null) { UnlockedEmotes = new List(); return; } List normalizedEmotes = new List(); foreach (int emote in UnlockedEmotes) { if (emote <= 0) { continue; } int normalizedEmote = emote < 52000000 ? 52000000 + emote : emote; if (!normalizedEmotes.Contains(normalizedEmote)) { normalizedEmotes.Add(normalizedEmote); } } UnlockedEmotes = normalizedEmotes; } public void Tick() { LastVisitHomeTime = DateTime.UtcNow; if (PremiumEndTime < DateTime.Now && HomeMode.Avatar.IsPremium) // vip OGO HomeMode.Avatar.IsPremium = false; // vip OGO if (BattleTokens == 0 && BattleTokensRefreshStart == new DateTime())// GOVNOCOD BattleTokens = MAX_BATTLE_TOKENS;// GOVNOCOD // GOVNOCOD int maxIterations = MAX_BATTLE_TOKENS / BATTLE_TOKENS_REGEN_AMOUNT + 1;// GOVNOCOD int iterations = 0;// GOVNOCOD while (ShouldAddTokens() && iterations++ < maxIterations)// GOVNOCOD {// GOVNOCOD BattleTokensRefreshStart = BattleTokensRefreshStart.AddMinutes(BATTLE_TOKENS_REGEN_MINUTES);// GOVNOCOD BattleTokens = Math.Min(MAX_BATTLE_TOKENS, BattleTokens + BATTLE_TOKENS_REGEN_AMOUNT);// GOVNOCOD // GOVNOCOD if (BattleTokens >= MAX_BATTLE_TOKENS)// GOVNOCOD {// GOVNOCOD BattleTokens = MAX_BATTLE_TOKENS;// GOVNOCOD BattleTokensRefreshStart = new DateTime();// GOVNOCOD break;// GOVNOCOD }// GOVNOCOD }// GOVNOCOD TokenReward = 0; TrophiesReward = 0; StarTokenReward = 0; } public int GetbattleTokensRefreshSeconds() { if (BattleTokensRefreshStart == new DateTime()) { return -1; } return (int)BattleTokensRefreshStart.AddMinutes(BATTLE_TOKENS_REGEN_MINUTES).Subtract(DateTime.UtcNow).TotalSeconds; } public bool ShouldAddTokens() { if (BattleTokensRefreshStart == new DateTime()) { return false; } return GetbattleTokensRefreshSeconds() < 1; } public void PurchaseOffer(int index, int brawler_reference) { if (index < 0 || index >= OfferBundles.Count) return; OfferBundle bundle = OfferBundles[index]; if (bundle.Purchased) return; if (bundle.Currency == 0) { if (!HomeMode.Avatar.UseDiamonds(bundle.Cost)) return; } else if (bundle.Currency == 1) { if (!HomeMode.Avatar.UseGold(bundle.Cost)) return; } else if (bundle.Currency == 3) { if (!HomeMode.Avatar.UseStarPoints(bundle.Cost)) return; } if (bundle.Claim == "debug") { ; } else { OffersClaimed.Add(bundle.Claim); } bundle.Purchased = true; LogicGiveDeliveryItemsCommand command = new LogicGiveDeliveryItemsCommand(); Random rand = new Random(); foreach (Offer offer in bundle.Items) { if (offer.Type == ShopItem.BrawlBox || offer.Type == ShopItem.FreeBox) { for (int x = 0; x < offer.Count; x++) { DeliveryUnit unit = new DeliveryUnit(10); HomeMode.SimulateGatcha(unit); if (x + 1 != offer.Count) { command.Execute(HomeMode); } command.DeliveryUnits.Add(unit); } } else if (offer.Type == ShopItem.HeroPower) { DeliveryUnit unit = new DeliveryUnit(100); GatchaDrop reward = new GatchaDrop(6); reward.DataGlobalId = offer.ItemDataId; reward.Count = offer.Count; unit.AddDrop(reward); command.DeliveryUnits.Add(unit); } else if (offer.Type == ShopItem.BigBox) { for (int x = 0; x < offer.Count; x++) { DeliveryUnit unit = new DeliveryUnit(12); HomeMode.SimulateGatcha(unit); if (x + 1 != offer.Count) { command.Execute(HomeMode); } command.DeliveryUnits.Add(unit); } } else if (offer.Type == ShopItem.MegaBox) { for (int x = 0; x < offer.Count; x++) { DeliveryUnit unit = new DeliveryUnit(11); HomeMode.SimulateGatcha(unit); if (x + 1 != offer.Count) { command.Execute(HomeMode); } command.DeliveryUnits.Add(unit); } } else if (offer.Type == ShopItem.Skin) { DeliveryUnit unit = new DeliveryUnit(100); GatchaDrop reward = new GatchaDrop(9); reward.SkinGlobalId = GlobalId.CreateGlobalId(29, offer.SkinDataId); unit.AddDrop(reward); command.DeliveryUnits.Add(unit); } else if (offer.Type == ShopItem.Gems) { DeliveryUnit unit = new DeliveryUnit(100); GatchaDrop reward = new GatchaDrop(8); reward.Count = offer.Count; unit.AddDrop(reward); command.DeliveryUnits.Add(unit); } else if (offer.Type == ShopItem.Coin) { DeliveryUnit unit = new DeliveryUnit(100); GatchaDrop reward = new GatchaDrop(7); reward.Count = offer.Count; unit.AddDrop(reward); command.DeliveryUnits.Add(unit); } else if (offer.Type == ShopItem.GuaranteedHero) { DeliveryUnit unit = new DeliveryUnit(100); GatchaDrop reward = new GatchaDrop(1); reward.DataGlobalId = offer.ItemDataId; reward.Count = 1; unit.AddDrop(reward); command.DeliveryUnits.Add(unit); } else if (offer.Type == ShopItem.CoinDoubler) { DeliveryUnit unit = new DeliveryUnit(100); GatchaDrop reward = new GatchaDrop(2); reward.Count = offer.Count; unit.AddDrop(reward); command.DeliveryUnits.Add(unit); } else if (offer.Type == ShopItem.EmoteBundle) { DeliveryUnit unit = new DeliveryUnit(100); List Emotes_All = new List { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300 }; List unlockedEmoteInstances = UnlockedEmotes.Select(GlobalId.GetInstanceId).ToList(); List Emotes_Locked = Emotes_All.Except(unlockedEmoteInstances).OrderBy(x => Guid.NewGuid()).Take(3).ToList(); foreach (int x in Emotes_Locked) { GatchaDrop reward = new GatchaDrop(11); reward.Count = 1; reward.DataGlobalId = 52000000 + x; reward.PinGlobalId = 52000000 + x; unit.AddDrop(reward); } command.DeliveryUnits.Add(unit); } else if (offer.Type == ShopItem.RandomEmotes) { DeliveryUnit unit = new DeliveryUnit(100); List Emotes_All = new List { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300 }; List unlockedEmoteInstances = UnlockedEmotes.Select(GlobalId.GetInstanceId).ToList(); List Emotes_Locked = Emotes_All.Except(unlockedEmoteInstances).OrderBy(x => Guid.NewGuid()).Take(3).ToList(); foreach (int x in Emotes_Locked) { GatchaDrop reward = new GatchaDrop(11); reward.Count = 1; reward.DataGlobalId = 52000000 + x; reward.PinGlobalId = 52000000 + x; unit.AddDrop(reward); } command.DeliveryUnits.Add(unit); } else if (offer.Type == ShopItem.Emote) { DeliveryUnit unit = new DeliveryUnit(100); GatchaDrop reward = new GatchaDrop(11); reward.Count = 1; reward.DataGlobalId = 52000155; reward.PinGlobalId = 52000155; unit.AddDrop(reward); command.DeliveryUnits.Add(unit); } else if (offer.Type == ShopItem.GuaranteedBox) { var baseRarityPools = new Dictionary>() { { 0, new List { 1, 2, 3, 7, 8, 9, 14, 22, 30, 27 } }, // Common { 1, new List { 10, 6, 13, 24 } }, // Rare { 2, new List { 4, 18, 19, 34, 25 } }, // Super Rare { 3, new List { 16, 20, 26, 29, 43, 15, 36 } }, // Epic { 4, new List { 37, 11, 17, 21, 32, 31 } }, // Mega Epic { 5, new List { 12, 5, 28, 23 } }, // Legendary { 6, new List { 35 } } // Chromatic }; if (baseRarityPools.TryGetValue(offer.SkinDataId, out var pool)) { var availableHeroes = pool.Where(heroId => !HomeMode.HasHeroUnlocked(16000000 + heroId)).ToList(); if (availableHeroes.Count > 0) { int randomItemId = availableHeroes[new Random().Next(availableHeroes.Count)]; var unit = new DeliveryUnit(100); var reward = new GatchaDrop(1) { DataGlobalId = 16000000 + randomItemId, Count = 1 }; unit.AddDrop(reward); command.DeliveryUnits.Add(unit); } else { // если бойца нет то можно что то дать чтобы не крашнулось к хуям если автоматическая защита не сработает } } } else { // todo... } UpdateOfferBundles(); } command.Execute(HomeMode); AvailableServerCommandMessage message = new AvailableServerCommandMessage(); message.Command = command; HomeMode.GameListener.SendMessage(message); } private void RotateShopContent(DateTime time, bool isNewAcc) { OfferBundles.RemoveAll(offer => offer.EndTime != DateTime.MinValue && offer.EndTime <= time); bool hasDailyDeals = OfferBundles.Any(bundle => bundle.IsDailyDeals); bool hasSpecialOffers = OfferBundles.Any(bundle => !bundle.IsDailyDeals && !bundle.IsTrue); // Генерируем только если акций нет совсем (новый аккаунт) // или пришло время плановой ротации (после 8:00 UTC нового дня) bool isScheduledRotation = DateTime.UtcNow >= DateTime.UtcNow.Date.AddHours(8) && LastVisitHomeTime < DateTime.UtcNow.Date.AddHours(8); bool shouldRefreshShop = (!hasDailyDeals && !hasSpecialOffers) || isScheduledRotation; if (shouldRefreshShop) { UpdateDailyOfferBundles(); UpdateDailySkins(); } } public void DevColorCmd(string color) { if (color == "12") { Namecolor = 12; } if (color == "13") { Namecolor = 13; } if (color == "14") { Namecolor = 14; } } private void UpdateDailyOfferBundles() { OfferBundles = new List(); OfferBundles.Add(GenerateDailyGift()); // Premium: ежедневный бесплатный ящик (2 больших или 1 мега — рандомно) if (HomeMode.Avatar.IsPremium && HomeMode.Home.PremiumEndTime > DateTime.UtcNow) { OfferBundles.Add(GeneratePremiumDailyBox()); } List dailyOffers = GenerateAllDailyOffers(); if (dailyOffers != null) { OfferBundles.AddRange(dailyOffers); } List unlockedHeroes = HomeMode.Avatar.Heroes; List possibleHeroes = new(); foreach (Hero hero in unlockedHeroes) { if (hero.PowerLevel == 8) continue; if (hero.PowerPoints >= 1410) continue; possibleHeroes.Add(hero); } Random random = new Random(); bool shouldPowerPoints = true; bool hasMegaBox = false; int offerCount = 0; // Ежедневных акций теперь максимум DAILYOFFERS_COUNT (6) for (int i = 1; i < DAILYOFFERS_COUNT; i++) { if (possibleHeroes.Count == 0) break; offerCount++; if (!hasMegaBox && random.Next(0, 100) > 33) { i++; offerCount++; hasMegaBox = true; OfferBundle megaBoxOffer = GenerateDailyOffer(false, null); if (megaBoxOffer != null) { OfferBundles.Add(megaBoxOffer); } } int heroIndex = random.Next(0, possibleHeroes.Count); Hero brawler = possibleHeroes[heroIndex]; possibleHeroes.RemoveAt(heroIndex); OfferBundle dailyOffer = GenerateDailyOffer(shouldPowerPoints, brawler); if (dailyOffer != null) { if (!shouldPowerPoints) { shouldPowerPoints = dailyOffer.Items[0].Type != ShopItem.HeroPower; } OfferBundles.Add(dailyOffer); } } if (offerCount < 3 && !hasMegaBox) { OfferBundle fallbackMegaBoxOffer = GenerateDailyOffer(false, null); if (fallbackMegaBoxOffer != null) { OfferBundles.Add(fallbackMegaBoxOffer); } } } private void UpdateDailySkins() { List skins = new() { "Witch", "Rockstar", "Beach", "Pink", "Panda", "White", "Hair", "Gold", "Rudo", "Bandita", "Rey", "Knight", "Caveman", "Dragon", "Summer", "Summertime", "Pheonix", "Greaser", "GirlPrereg", "Box", "Santa", "Chef", "Boombox", "Wizard", "Reindeer", "GalElf", "Hat", "Footbull", "Popcorn", "Hanbok", "Cny", "Valentine", "WarsBox", "Nightwitch", "Cart", "Shiba", "GalBunny", "Ms", "GirlHotrod", "Maple", "RR", "Mecha", "MechaWhite", "MechaNight", "FootbullBlue", "Outlaw", "Hogrider", "BoosterDefault", "Shark", "HoleBlue", "BoxMoonFestival", "WizardRed", "Pirate", "GirlWitch", "KnightDark", "DragonDark", "DJ", "Wolf", "Brown", "Total", "Sally", "Leonard", "SantaRope", "Gift", "GT", "SniperDefaultAddonBee", "SniperLadyBug", "SniperLadyBugAddonBee", "Virus", "BoosterVirus", "HoleStreetNinja", "Gamer", "Valentines", "Koala", "BearKoala", "TurretDefault", "AgentP", "Football", "Arena", "Tanuki", "Horus", "ArenaPSG", "DarkBunny", "College", "TurretTanuki", "TotemDefault", "Bazaar", "RedDragon", "Constructor", "Hawaii", "Barbking", "Trader", "StationSummer", "Silver", "SniperMonster", "BombMonster", "SniperMonsterAddonBee", "Bank", "Retro", "Ranger", "Tracksuit" }; List gemSkins = new(); List starPointSkins = new(); foreach (Hero hero in HomeMode.Avatar.Heroes) { CharacterData character = DataTables.Get(DataType.Character).GetDataByGlobalId(hero.CharacterId); string characterName = character.Name; foreach (string name in skins) { SkinData skin = DataTables.Get(DataType.Skin).GetData(characterName + name); if (skin == null) continue; if (UnlockedSkins.Contains(skin.GetGlobalId())) continue; if (skin.Name == "RocketGirlRanger") continue; if (skin.Name == "PowerLevelerKnight") continue; if (skin.Name == "BlowerTrader") continue; if (skin.CostLegendaryTrophies > 1) { starPointSkins.Add(skin.GetGlobalId()); continue; } if (!skin.Name.EndsWith("Gold")) { gemSkins.Add(skin.GetGlobalId()); } else { string silverSkinName = skin.Name.Replace("Gold", "Silver"); SkinData silverSkin = DataTables.Get(DataType.Skin).GetData(silverSkinName); if (silverSkin == null) { gemSkins.Add(skin.GetGlobalId()); continue; } if (UnlockedSkins.Contains(silverSkin.GetGlobalId())) { gemSkins.Add(silverSkin.GetGlobalId()); } } } } Random random = new Random(); int[] selectedGemSkinIds = new int[Math.Min(gemSkins.Count, 8)]; for (int i = 0; i < Math.Min(gemSkins.Count, 8); i++) { int randomIndex; do { randomIndex = random.Next(0, gemSkins.Count); } while (selectedGemSkinIds.Contains(gemSkins[randomIndex])); selectedGemSkinIds[i] = gemSkins[randomIndex]; } foreach (int skinId in selectedGemSkinIds) { SkinData skin = DataTables.Get(DataType.Skin).GetDataByGlobalId(skinId); OfferBundle bundle = new OfferBundle(); bundle.IsDailyDeals = false; bundle.EndTime = DateTime.UtcNow.Date.AddDays(1).AddHours(8); if (skin.CostGems > 0) { int discountedCost = (int)Math.Floor(skin.CostGems * 0.85); int roundedCost = (discountedCost / 10) * 10 - 1; bundle.Currency = 0; bundle.Cost = roundedCost; bundle.OldCost = skin.CostGems - 1; } else { continue; } Offer offer = new Offer(ShopItem.Skin, 1); offer.SkinDataId = GlobalId.GetInstanceId(skinId); bundle.Items.Add(offer); OfferBundles.Add(bundle); } int[] selectedStarSkinIds = new int[Math.Min(starPointSkins.Count, 3)]; for (int i = 0; i < Math.Min(starPointSkins.Count, 3); i++) { int randomIndex; do { randomIndex = random.Next(0, starPointSkins.Count); } while (selectedStarSkinIds.Contains(starPointSkins[randomIndex])); selectedStarSkinIds[i] = starPointSkins[randomIndex]; } foreach (int skinId in selectedStarSkinIds) { SkinData skin = DataTables.Get(DataType.Skin).GetDataByGlobalId(skinId); OfferBundle bundle = new OfferBundle(); bundle.Currency = 3; bundle.IsDailyDeals = false; bundle.EndTime = DateTime.UtcNow.Date.AddDays(1).AddHours(8); bundle.Cost = skin.CostLegendaryTrophies; Offer offer = new Offer(ShopItem.Skin, 1); offer.SkinDataId = GlobalId.GetInstanceId(skinId); bundle.Items.Add(offer); OfferBundles.Add(bundle); } } public void UpdateOfferBundles() { OfferBundles.RemoveAll(bundle => bundle.IsTrue); } public void GenerateOffer( DateTime OfferStart, DateTime OfferEnd, int Count, int BrawlerID, int Extra, ShopItem Item, int Cost, int OldCost, int Currency, string Claim, string Title, string BGR ) { OfferBundle bundle = new OfferBundle(); bundle.IsDailyDeals = false; bundle.IsTrue = true; bundle.EndTime = OfferEnd; bundle.Cost = Cost; bundle.OldCost = OldCost; bundle.Currency = Currency; bundle.Claim = Claim; bundle.Title = Title; bundle.BackgroundExportName = BGR; if (OffersClaimed.Contains(bundle.Claim)) { bundle.Purchased = true; } if (TimerMath(OfferStart, OfferEnd) == -1) { bundle.Purchased = true; } if (HomeMode.HasHeroUnlocked(16000000 + BrawlerID)) { bundle.Purchased = true; } Offer offer = new Offer(Item, Count, (16000000 + BrawlerID), Extra); bundle.Items.Add(offer); OfferBundles.Add(bundle); } public void GenerateOffer2( DateTime OfferStart, DateTime OfferEnd, int Count, int BrawlerID, int Extra, ShopItem Item, int Count2, int BrawlerID2, int Extra2, ShopItem Item2, int Cost, int OldCost, int Currency, string Claim, string Title, string BGR ) { OfferBundle bundle = new OfferBundle(); bundle.IsDailyDeals = false; bundle.IsTrue = true; bundle.EndTime = OfferEnd; bundle.Cost = Cost; bundle.OldCost = OldCost; bundle.Currency = Currency; bundle.Claim = Claim; bundle.Title = Title; bundle.BackgroundExportName = BGR; if (OffersClaimed.Contains(bundle.Claim)) { bundle.Purchased = true; } if (TimerMath(OfferStart, OfferEnd) == -1) { bundle.Purchased = true; } if (HomeMode.HasHeroUnlocked(16000000 + BrawlerID)) { bundle.Purchased = true; } Offer offer = new Offer(Item, Count, (16000000 + BrawlerID), Extra); bundle.Items.Add(offer); Offer offer2 = new Offer(Item2, Count2, (16000000 + BrawlerID2), Extra2); bundle.Items.Add(offer2); OfferBundles.Add(bundle); } public void GenerateOffer3( DateTime OfferStart, DateTime OfferEnd, int Count, int BrawlerID, int Extra, ShopItem Item, int Count2, int BrawlerID2, int Extra2, ShopItem Item2, int Count3, int BrawlerID3, int Extra3, ShopItem Item3, int Cost, int OldCost, int Currency, string Claim, string Title, string BGR ) { OfferBundle bundle = new OfferBundle(); bundle.IsDailyDeals = false; bundle.IsTrue = true; bundle.EndTime = OfferEnd; bundle.Cost = Cost; bundle.OldCost = OldCost; bundle.Currency = Currency; bundle.Claim = Claim; bundle.Title = Title; bundle.BackgroundExportName = BGR; if (OffersClaimed.Contains(bundle.Claim)) { bundle.Purchased = true; } if (TimerMath(OfferStart, OfferEnd) == -1) { bundle.Purchased = true; } if (HomeMode.HasHeroUnlocked(16000000 + BrawlerID)) { bundle.Purchased = true; } Offer offer = new Offer(Item, Count, (16000000 + BrawlerID), Extra); bundle.Items.Add(offer); Offer offer2 = new Offer(Item2, Count2, (16000000 + BrawlerID2), Extra2); bundle.Items.Add(offer2); Offer offer3 = new Offer(Item3, Count3, (16000000 + BrawlerID3), Extra3); bundle.Items.Add(offer3); OfferBundles.Add(bundle); } /// /// Ежедневный бесплатный ящик для Premium-игроков: /// 50% — 1 Мега-ящик, 50% — 2 Больших ящика. /// private OfferBundle GeneratePremiumDailyBox() { OfferBundle bundle = new OfferBundle(); bundle.IsDailyDeals = true; bundle.EndTime = DateTime.UtcNow.Date.AddDays(1).AddHours(8); bundle.Cost = 0; bundle.Title = "🌟 Premium"; Random random = new Random(); if (random.Next(0, 2) == 0) { // 1 Мега-ящик bundle.Items.Add(new Offer(ShopItem.MegaBox, 1)); } else { // 2 Больших ящика bundle.Items.Add(new Offer(ShopItem.BigBox, 2)); } return bundle; } private OfferBundle GenerateDailyGift() { OfferBundle bundle = new OfferBundle(); bundle.IsDailyDeals = true; bundle.EndTime = DateTime.UtcNow.Date.AddDays(1).AddHours(8); Random random = new Random(); int type = random.Next(0, 3); switch (type) { case 0: bundle.Items.Add(new Offer(ShopItem.FreeBox, 1)); bundle.Cost = 0; break; case 1: int coinAmount = random.Next(50, 201); bundle.Items.Add(new Offer(ShopItem.Coin, coinAmount)); bundle.Cost = 0; break; case 2: List upgradableHeroes = HomeMode.Avatar.Heroes .Where(h => h.PowerLevel < 8 && h.PowerPoints < 1410) .ToList(); if (upgradableHeroes.Count > 0) { Hero randomHero = upgradableHeroes[random.Next(upgradableHeroes.Count)]; int ppAmount = random.Next(10, 76); bundle.Items.Add(new Offer(ShopItem.HeroPower, ppAmount, randomHero.CharacterId)); bundle.Cost = 0; bundle.Currency = 1; } else { int fallbackCoins = random.Next(70, 150); bundle.Items.Add(new Offer(ShopItem.Coin, fallbackCoins)); bundle.Cost = 0; } break; } return bundle; } private OfferBundle GenerateGift() { OfferBundle bundle = new OfferBundle(); bundle.IsDailyDeals = false; bundle.EndTime = DateTime.UtcNow.Date.AddDays(1).AddHours(8); // tomorrow at 8:00 utc (11:00 MSK) bundle.Cost = 0; bundle.Title = "Thanks for 600 subscribers"; Offer offer = new Offer(ShopItem.Gems, 80); bundle.Items.Add(offer); return bundle; } private OfferBundle GenerateGift1() { OfferBundle bundle = new OfferBundle(); bundle.IsDailyDeals = false; bundle.EndTime = DateTime.UtcNow.Date.AddDays(1).AddHours(8); // tomorrow at 8:00 utc (11:00 MSK) bundle.Cost = 0; bundle.Title = "Gift Day 2"; Offer offer = new Offer(ShopItem.Skin, 1, 29000000, 52); bundle.Items.Add(offer); return bundle; } private OfferBundle GenerateGift2() { OfferBundle bundle = new OfferBundle(); bundle.IsDailyDeals = false; bundle.EndTime = DateTime.UtcNow.Date.AddDays(1).AddHours(8); // tomorrow at 8:00 utc (11:00 MSK) bundle.Cost = 0; bundle.Title = "Gift Day 3"; Offer offer = new Offer(ShopItem.Gems, 30); bundle.Items.Add(offer); return bundle; } private OfferBundle GenerateDailyOffer(bool shouldPowerPoints, Hero brawler) { OfferBundle bundle = new OfferBundle(); bundle.IsDailyDeals = true; bundle.EndTime = DateTime.UtcNow.Date.AddDays(1).AddHours(8); Random random = new Random(); int type = shouldPowerPoints ? 0 : 1; switch (type) { case 0: if (brawler == null) return null; int count = random.Next(15, 100) + 1; bundle.Items.Add(new Offer(ShopItem.HeroPower, count, brawler.CharacterId)); bundle.Cost = count * 2; bundle.Currency = 1; break; case 1: bundle.Items.Add(new Offer(ShopItem.MegaBox, 1)); bundle.Cost = 40; bundle.OldCost = 80; bundle.Currency = 0; break; } return bundle; } private int RoundToNearestEndingWith9(int price) { int tens = price / 10; int remainder = price % 10; if (remainder < 9) { return tens * 10 - 1; } return (tens + 1) * 10 - 1; } private List GenerateAllDailyOffers() { var random = new Random(); var endTime = DateTime.UtcNow.Date.AddDays(1).AddHours(8); List allBundles = new List(); // Фон для особых акций const string SpecialBg = "offer_special"; // ── 1. Монеты + очки силы ────────────────────────────────────────────── { OfferBundle cp = new OfferBundle { IsDailyDeals = false, EndTime = endTime, Currency = 0, Title = "ОСОБАЯ АКЦИЯ", BackgroundExportName = SpecialBg }; int[] coinOptions = { 300, 400, 500, 600, 750, 900, 1000, 1500, 2000 }; int[] powerOptions = { 100, 150, 200, 250, 300, 400, 500, 750, 1000 }; int offerType = random.Next(4); bool addCoins = offerType <= 1 || offerType == 3; bool addPower = offerType <= 2; int selectedCoin = addCoins ? coinOptions[random.Next(coinOptions.Length)] : 0; int selectedPower = 0; if (addCoins) cp.Items.Add(new Offer(ShopItem.Coin, selectedCoin)); if (addPower) { do { selectedPower = powerOptions[random.Next(powerOptions.Length)]; } while (addCoins && selectedPower > selectedCoin); cp.Items.Add(new Offer(ShopItem.WildcardPower, selectedPower)); } if (addCoins && !addPower) cp.BackgroundExportName = "offer_coins"; int totalPrice; if (addCoins && addPower) totalPrice = (int)(selectedCoin * 0.10) + (int)(selectedPower * 0.45); else if (addCoins) totalPrice = (int)(selectedCoin * 0.10); else totalPrice = (int)(selectedPower * 0.45); cp.OldCost = RoundToNearestEndingWith9(totalPrice); cp.Cost = RoundToNearestEndingWith9((int)(totalPrice * 0.70f)); allBundles.Add(cp); } // ── 2. Мега-ящики ───────────────────────────────────────────────────── { OfferBundle box = new OfferBundle { IsDailyDeals = false, EndTime = endTime, Currency = 0, Title = "ОСОБАЯ АКЦИЯ", BackgroundExportName = SpecialBg }; int boxCount = random.Next(1, 5); // 1–4 мега-ящика int pricePerBox = 79; // базовая цена за штуку box.OldCost = boxCount * pricePerBox; box.Cost = RoundToNearestEndingWith9((int)(box.OldCost * 0.70f)); box.Items.Add(new Offer(ShopItem.MegaBox, boxCount)); allBundles.Add(box); } // ── 3. Большие ящики ────────────────────────────────────────────────── { OfferBundle bigBox = new OfferBundle { IsDailyDeals = false, EndTime = endTime, Currency = 0, Title = "ОСОБАЯ АКЦИЯ", BackgroundExportName = SpecialBg }; int bigCount = random.Next(2, 7); // 2–6 больших ящиков int pricePerBig = 29; bigBox.OldCost = bigCount * pricePerBig; bigBox.Cost = RoundToNearestEndingWith9((int)(bigBox.OldCost * 0.70f)); bigBox.Items.Add(new Offer(ShopItem.BigBox, bigCount)); allBundles.Add(bigBox); } // ── 4. Гарантированный боец ─────────────────────────────────────────── { OfferBundle guaranteedBox = new OfferBundle { IsDailyDeals = false, EndTime = endTime, Currency = 0, Title = "ОСОБАЯ АКЦИЯ", BackgroundExportName = SpecialBg }; int boxRarity = random.Next(3, 7); // 3=Epic, 4=MegaEpic, 5=Legendary, 6=Chromatic (int baseCost, int discCost) = boxRarity switch { 3 => (149, 99), 4 => (349, 229), 5 => (699, 449), 6 => (999, 649), _ => (349, 229) }; guaranteedBox.Items.Add(new Offer(ShopItem.GuaranteedBox, 1) { SkinDataId = GlobalId.GetInstanceId(boxRarity) }); guaranteedBox.OldCost = baseCost; guaranteedBox.Cost = discCost; allBundles.Add(guaranteedBox); } // ── 5. Боец + скин ──────────────────────────────────────────────────── { OfferBundle brawlerBundle = new OfferBundle { IsDailyDeals = false, EndTime = endTime, Currency = 0, Title = "ОСОБАЯ АКЦИЯ", BackgroundExportName = SpecialBg }; var rarityPools = new Dictionary> { { 3, new List { 15, 16, 20, 26, 29, 36 } }, { 4, new List { 11, 17, 21, 31, 32, 37 } }, { 5, new List { 5, 12, 23, 28 } }, }; var unlockable = rarityPools.Values.SelectMany(x => x) .Where(id => !HomeMode.HasHeroUnlocked(GlobalId.CreateGlobalId(16, id))) .ToList(); if (unlockable.Count > 0) { int selectedId = unlockable[random.Next(unlockable.Count)]; CharacterData selectedChar = DataTables.Get(DataType.Character) .GetDataByGlobalId(GlobalId.CreateGlobalId(16, selectedId)); int basePrice = rarityPools.FirstOrDefault(p => p.Value.Contains(selectedId)).Key switch { 3 => 149, 4 => 349, 5 => 699, _ => 349 }; brawlerBundle.Items.Add(new Offer(ShopItem.GuaranteedHero, 1) { ItemDataId = GlobalId.CreateGlobalId(16, selectedId) }); brawlerBundle.OldCost = basePrice; brawlerBundle.Cost = 0; // боец бесплатно при покупке скина string[] skinSuffixes = { "Witch","Rockstar","Beach","Pink","Panda","White","Hair","Rudo","Bandita", "Rey","Knight","Caveman","Dragon","Summer","Summertime","Pheonix","Greaser", "GirlPrereg","Box","Santa","Chef","Boombox","Wizard","Reindeer","GalElf", "Hat","Footbull","Popcorn","Hanbok","Cny","Valentine","WarsBox","Nightwitch", "Cart","Shiba","GalBunny","Ms","GirlHotrod","Maple","RR","Mecha","MechaWhite", "MechaNight","FootbullBlue","Outlaw","Hogrider","BoosterDefault","Shark", "HoleBlue","BoxMoonFestival","WizardRed","Pirate","GirlWitch","KnightDark", "DragonDark","DJ","Wolf","Brown","Total","Sally","Leonard","SantaRope","Gift", "GT","Virus","BoosterVirus","HoleStreetNinja","Gamer","Valentines","Koala", "BearKoala","TurretDefault","AgentP","Football","Arena","Tanuki","Horus", "ArenaPSG","DarkBunny","College","TurretTanuki","TotemDefault","Bazaar", "RedDragon","Constructor","Hawaii","Barbking","Trader" }; SkinData selectedSkin = null; foreach (string suffix in skinSuffixes) { SkinData skin = DataTables.Get(DataType.Skin).GetData(selectedChar.Name + suffix); if (skin == null) continue; if (UnlockedSkins.Contains(skin.GetGlobalId())) continue; if (new[] { "RocketGirlRanger", "PowerLevelerKnight", "BlowerTrader" }.Contains(skin.Name)) continue; if (skin.CostLegendaryTrophies > 1) continue; if (skin.Name.EndsWith("Gold") || skin.Name.EndsWith("Silver")) continue; selectedSkin = skin; break; } if (selectedSkin != null) { int baseSkinPrice = selectedSkin.CostGems; int discSkinPrice = baseSkinPrice switch { 29 => 19, 49 => 29, 79 => 49, 149 => 89, 299 => 179, _ => (int)(baseSkinPrice * 0.60f) }; brawlerBundle.Items.Add(new Offer(ShopItem.Skin, 1) { SkinDataId = GlobalId.GetInstanceId(selectedSkin.GetGlobalId()) }); brawlerBundle.Cost += discSkinPrice; brawlerBundle.OldCost += baseSkinPrice; } allBundles.Add(brawlerBundle); } } // ── 6. Пак эмоций ───────────────────────────────────────────────────── { OfferBundle pinPack = new OfferBundle { IsDailyDeals = false, EndTime = endTime, Currency = 0, Title = "ОСОБАЯ АКЦИЯ", BackgroundExportName = SpecialBg, OldCost = 49, Cost = 29 }; pinPack.Items.Add(new Offer(ShopItem.RandomEmotes, 1)); allBundles.Add(pinPack); } // ── 7. Удвоитель монет ──────────────────────────────────────────────── { OfferBundle doubler = new OfferBundle { IsDailyDeals = false, EndTime = endTime, Currency = 0, Title = "ОСОБАЯ АКЦИЯ", BackgroundExportName = SpecialBg }; int doublerAmount = random.Next(1, 4) * 500; // 500, 1000 или 1500 doubler.Items.Add(new Offer(ShopItem.CoinDoubler, doublerAmount)); doubler.OldCost = RoundToNearestEndingWith9(doublerAmount / 10); doubler.Cost = RoundToNearestEndingWith9((int)(doublerAmount / 10 * 0.70f)); allBundles.Add(doubler); } return allBundles; } public void Encode(ByteStream encoder) { DateTime utcNow = DateTime.UtcNow; encoder.WriteVInt(utcNow.Year * 1000 + utcNow.DayOfYear); // 0x78d4b8 encoder.WriteVInt(utcNow.Hour * 3600 + utcNow.Minute * 60 + utcNow.Second); // 0x78d4cc encoder.WriteVInt(HomeMode.Avatar.Trophies); // 0x78d4e0 encoder.WriteVInt(HomeMode.Avatar.Trophies); // 0x78d4f4 encoder.WriteVInt(HomeMode.Avatar.HighestTrophies); // highest trophy again? encoder.WriteVInt(TrophyRoadProgress); encoder.WriteVInt(Exp + 1488); // experience ByteStreamHelper.WriteDataReference(encoder, Thumbnail); // TODO: FIX!!!!! encoder.WriteVInt(43); encoder.WriteVInt(Namecolor); encoder.WriteVInt(18); // Played game modes for (int i = 0; i < 18; i++) { encoder.WriteVInt(i); } encoder.WriteVInt(36); // Selected Skins Dictionary for (int i = 0; i < 36; i++) { encoder.WriteVInt(29); try { encoder.WriteVInt(SelectedSkins[i]); } catch { encoder.WriteVInt(0); SelectedSkins = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; } } encoder.WriteVInt(UnlockedSkins.Count); for (int i = 0; i < UnlockedSkins.Count; i++) { encoder.WriteVInt(29); encoder.WriteVInt(UnlockedSkins[i]); } encoder.WriteVInt(0); encoder.WriteVInt(0); // leaderboard region encoder.WriteVInt(HomeMode.Avatar.HighestTrophies); // 122 encoder.WriteVInt(0); //tokens used in battles encoder.WriteVInt(0); encoder.WriteBoolean(true); encoder.WriteVInt(TokenDoublers); // Remaining Token Doubler TimerSnapshot timerSnapshot = GameTimerConfig.GetSnapshot(DateTime.UtcNow); encoder.WriteVInt(timerSnapshot.SeasonTimeRemaining); // season timer encoder.WriteVInt(timerSnapshot.PowerPlayTimeRemaining); // power play timer encoder.WriteVInt(timerSnapshot.BrawlPassTimeRemaining); // brawl pass timer encoder.WriteVInt(0); encoder.WriteVInt(0); encoder.WriteVInt(0); encoder.WriteBoolean(false); // я хз зачем это encoder.WriteBoolean(false); encoder.WriteBoolean(true); // отображение в ui encoder.WriteBoolean(true); encoder.WriteVInt(2); // Shop Token Doubler encoder.WriteVInt(2); encoder.WriteVInt(2); encoder.WriteVInt(0); encoder.WriteVInt(0); encoder.WriteVInt(OfferBundles.Count); // Shop offers at 0x78e0c4 foreach (OfferBundle offerBundle in OfferBundles) { offerBundle.Encode(encoder); } encoder.WriteVInt(0); encoder.WriteVInt(BattleTokens); // 0x78e228 Battle tokens encoder.WriteVInt(GetbattleTokensRefreshSeconds()); // 0x78e23c Time till Bonus Tokens encoder.WriteVInt(0); // 0x78e250 encoder.WriteVInt(0); // 0x78e3a4 encoder.WriteVInt(0); // 0x78e3a4 ByteStreamHelper.WriteDataReference(encoder, Character); encoder.WriteString("RU"); // Region encoder.WriteString(HomeMode.Avatar.SupportedCreator); // SupportedCreator Code encoder.WriteVInt(12); { encoder.WriteInt(3); encoder.WriteInt(TokenReward); // tokens encoder.WriteInt(4); encoder.WriteInt(TrophiesReward); // trophies encoder.WriteInt(6); encoder.WriteInt(0); // demo account encoder.WriteInt(8); encoder.WriteInt(StarPointsGained); // star points encoder.WriteInt(7); encoder.WriteInt(HomeMode.Avatar.DoNotDisturb ? 1 : 0); // do not disturb encoder.WriteInt(9); encoder.WriteInt(1); // idk encoder.WriteInt(10); encoder.WriteInt(PowerPlayTrophiesReward); // power ply trophird encoder.WriteInt(14); encoder.WriteInt(CoinsGained); encoder.WriteInt(15); encoder.WriteInt(0); encoder.WriteInt(17); encoder.WriteInt(HomeMode.Avatar.DisabledTeamChat ? 1 : 0); // disable team chat encoder.WriteInt(18); encoder.WriteInt(0); // cybersport button encoder.WriteInt(20); encoder.WriteInt(GemsGained); } TokenReward = 0; TrophiesReward = 0; // ну а где ещё. хотя.... StarTokenReward = 0; StarPointsGained = 0; CoinsGained = 0; GemsGained = 0; PowerPlayTrophiesReward = 0; encoder.WriteVInt(0); // array encoder.WriteVInt(1); // BrawlPassSeasonData { encoder.WriteVInt(0); encoder.WriteVInt(BrawlPassTokens); encoder.WriteVInt(PremiumPassProgress); encoder.WriteVInt(BrawlPassProgress); // progress encoder.WriteBoolean(HasPremiumPass); // buyed? encoder.WriteVInt(0); } encoder.WriteVInt(1); { encoder.WriteVInt(2); encoder.WriteVInt(1); } if (Quests != null) { encoder.WriteBoolean(true); Quests.Encode(encoder); } else { encoder.WriteBoolean(true); encoder.WriteVInt(0); } encoder.WriteBoolean(true); encoder.WriteVInt(UnlockedEmotes.Count); for (int i = 0; i < UnlockedEmotes.Count; i++) { ByteStreamHelper.WriteDataReference(encoder, UnlockedEmotes[i]); encoder.WriteVInt(0); } encoder.WriteVInt(utcNow.Year * 1000 + utcNow.DayOfYear); // Shop Timestamp encoder.WriteVInt(100); // Brawl Box Tokens encoder.WriteVInt(10); // Big Box Tokens encoder.WriteVInt(30); // big box cost encoder.WriteVInt(3); // multiplier big box encoder.WriteVInt(80); // mega box cost encoder.WriteVInt(10); // multiplier megabox encoder.WriteVInt(20); // token doubler cost encoder.WriteVInt(1000); // token doubler count encoder.WriteVInt(550); encoder.WriteVInt(0); encoder.WriteVInt(999900); encoder.WriteVInt(0); // Array encoder.WriteVInt(30); for (int i = 1; i <= 30; i++) encoder.WriteVInt(i); encoder.WriteVInt(Events.Length); foreach (EventData data in Events) { data.Encode(encoder); } encoder.WriteVInt(0); encoder.WriteVInt(8); { encoder.WriteVInt(20); encoder.WriteVInt(35); encoder.WriteVInt(75); encoder.WriteVInt(140); encoder.WriteVInt(290); encoder.WriteVInt(480); encoder.WriteVInt(800); encoder.WriteVInt(1250); } encoder.WriteVInt(8); { encoder.WriteVInt(1); encoder.WriteVInt(2); encoder.WriteVInt(3); encoder.WriteVInt(4); encoder.WriteVInt(5); encoder.WriteVInt(10); encoder.WriteVInt(15); encoder.WriteVInt(20); } encoder.WriteVInt(3); { encoder.WriteVInt(10); encoder.WriteVInt(30); encoder.WriteVInt(80); } encoder.WriteVInt(3); { encoder.WriteVInt(6); encoder.WriteVInt(20); encoder.WriteVInt(60); } ByteStreamHelper.WriteIntList(encoder, GoldPacksPrice); ByteStreamHelper.WriteIntList(encoder, GoldPacksAmount); encoder.WriteVInt(2); encoder.WriteVInt(500); // макс баттл токенов encoder.WriteVInt(20); // скок там чево та там encoder.WriteVInt(8640); encoder.WriteVInt(10); encoder.WriteVInt(5); encoder.WriteBoolean(true); //unclock gameModes (ya gey) encoder.WriteBoolean(false); encoder.WriteBoolean(false); encoder.WriteVInt(50); encoder.WriteVInt(604800); encoder.WriteBoolean(true); // box boolean // release entry DateTime psina = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time")); DateTime characterTargetDateTime = new DateTime(2025, 03, 15, 8, 0, 0); TimeSpan characterTimeDifference = characterTargetDateTime - psina; int characterSecondsRemaining = (int)characterTimeDifference.TotalSeconds; encoder.WriteVInt(ReleaseEntry.LogicReleaseEntry.Length); foreach (var entry in ReleaseEntry.LogicReleaseEntry) { encoder.WriteVInt(entry[0]); encoder.WriteVInt(entry[1]); encoder.WriteInt(entry[2]); encoder.WriteInt(1); } // events (лавина монет, удвоенные токены) string eventsFilePath = Supercell.Laser.Logic.Util.LogicHelperConfig.eventsPath; if (!File.Exists(eventsFilePath)) { Console.WriteLine("[402] Файл events.json не найден!"); } int enabledTokensEvent = 0; int enabledCoinsEvent = 0; if (File.Exists(eventsFilePath)) { string eventsJson = File.ReadAllText(eventsFilePath); JObject eventsData = JObject.Parse(eventsJson); if (eventsData["TokensEvent"] != null && int.TryParse(eventsData["TokensEvent"].ToString(), out int parsedEnabledTEvent)) { enabledTokensEvent = parsedEnabledTEvent; } if (eventsData["CoinsEvent"] != null && int.TryParse(eventsData["CoinsEvent"].ToString(), out int parsedEnabledCEvent)) { enabledCoinsEvent = parsedEnabledCEvent; } } encoder.WriteVInt(12); // IntValueEntries { encoder.WriteInt(1); encoder.WriteInt(41000013); // theme encoder.WriteInt(5); encoder.WriteInt(0); // закрытие магазина encoder.WriteInt(6); encoder.WriteInt(0); // запретить боксы encoder.WriteInt(16); encoder.WriteInt(1); // вкладка видео в новостях encoder.WriteInt(15); encoder.WriteInt(0); // коды автора encoder.WriteInt(42); encoder.WriteInt(0); // коробки с банками encoder.WriteInt(46); encoder.WriteInt(1); // подсказки encoder.WriteInt(50); encoder.WriteInt(6); // подсказки encoder.WriteInt(14); encoder.WriteInt(enabledTokensEvent); // ивент удвоители жетонов encoder.WriteInt(31); encoder.WriteInt(enabledCoinsEvent); // лавина монет encoder.WriteInt(17); encoder.WriteInt(0); // активация лунных банок encoder.WriteInt(37); encoder.WriteInt(0); // отруб бп } encoder.WriteVInt(0); encoder.WriteLong(HomeId); encoder.WriteVInt(0); encoder.WriteVInt(0); encoder.WriteBoolean(false); encoder.WriteVInt(0); encoder.WriteVInt(0); } } }