namespace Supercell.Laser.Server.Message { using Supercell.Laser.Logic; using Supercell.Laser.Logic.Avatar; using Supercell.Laser.Logic.Avatar.Structures; using Supercell.Laser.Logic.Battle; using Supercell.Laser.Logic.Battle.Objects; using Supercell.Laser.Logic.Club; using Supercell.Laser.Logic.Command; using Supercell.Laser.Logic.Command.Avatar; using Supercell.Laser.Logic.Command.Home; using Supercell.Laser.Logic.Data; using Supercell.Laser.Logic.Data.Helper; using Supercell.Laser.Logic.Friends; using Supercell.Laser.Logic.Home; 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.Listener; using Supercell.Laser.Logic.Message; using Supercell.Laser.Logic.Message.Account; using Supercell.Laser.Logic.Message.Account.Auth; using Supercell.Laser.Logic.Message.Battle; using Supercell.Laser.Logic.Message.Club; using Supercell.Laser.Logic.Message.Friends; using Supercell.Laser.Logic.Message.Home; using Supercell.Laser.Logic.Message.Ranking; using Supercell.Laser.Logic.Message.Security; using Supercell.Laser.Logic.Message.Team; using Supercell.Laser.Logic.Message.Team.Stream; using Supercell.Laser.Logic.Message.Udp; using Supercell.Laser.Logic.Stream; using Supercell.Laser.Logic.Stream.Entry; using Supercell.Laser.Logic.Team; using Supercell.Laser.Logic.Team.Stream; using Supercell.Laser.Logic.Util; using Supercell.Laser.Server.Database; using Supercell.Laser.Server.Database.Cache; using Supercell.Laser.Server.Database.Models; using Supercell.Laser.Server.Logic; using Supercell.Laser.Server.Logic.Game; using Supercell.Laser.Server.Networking; using Supercell.Laser.Server.Networking.Security; using Supercell.Laser.Server.Networking.Session; using Supercell.Laser.Server.Networking.UDP.Game; using Supercell.Laser.Server.Settings; using Supercell.Laser.Titan.Debug; using System; //using System.Diagnostics; using System.Linq; using System.Security.Cryptography; using System.Security.Principal; using System.Xml.Linq; public class CommandManager { public Connection Connection { get; } public HomeMode HomeMode; public CommandManager(HomeMode homeMode, Connection connection) { HomeMode = homeMode; Connection = connection; } public bool ReceiveCommand(Command command) { try { switch (command.GetCommandType()) { case 500: return LogicGatchaReceived((LogicGatchaCommand)command); case 503: return LogicClaimDailyRewardReceived((LogicClaimDailyRewardCommand)command); case 505: return LogicSetPlayerThumbnailReceived((LogicSetPlayerThumbnailCommand)command); case 506: return LogicSelectSkinReceived((LogicSelectSkinCommand)command); case 509: return LogicPurchaseDoubleCoinsReceived((LogicPurchaseDoubleCoinsCommand)command); case 514: return LogicDeleteNotificationReceived((LogicDeleteNotificationCommand)command); case 515: return LogicClearShopTickersReceived((LogicClearShopTickersCommand)command); case 520: return LogicLevelUpReceived((LogicLevelUpCommand)command); case 517: return LogicClaimRankUpRewardReceived((LogicClaimRankUpRewardCommand)command); case 519: return LogicPurchaseOfferReceived((LogicPurchaseOfferCommand)command); case 521: return LogicPurchaseHeroLvlUpMaterialReceived((LogicPurchaseHeroLvlUpMaterialCommand)command); case 522: return LogicHeroSeenReceived((LogicHeroSeenCommand)command); case 525: return LogicSelectCharacterReceived((LogicSelectCharacterCommand)command); case 527: return LogicSetPlayerNameColorReceived((LogicSetPlayerNameColorCommand)command); case 528: return LogicViewInboxNotificationReceived((LogicViewInboxNotificationCommand)command); case 529: return LogicSelectStarPowerReceived((LogicSelectStarPowerCommand)command); case 533: return LogicQuestsSeenReceived((LogicQuestsSeenCommand)command); case 534: return LogicPurchaseBrawlPassReceived((LogicPurchaseBrawlPassCommand)command); case 535: return LogicClaimTailRewardReceived((LogicClaimTailRewardCommand)command); case 536: return LogicPurchaseBrawlPassProgressReceived((LogicPurchaseBrawlPassProgressCommand)command); case 538: return LogicSelectEmoteReceived((LogicSelectEmoteCommand)command); //yees default: Logger.Print($"CommandManager::ReceiveCommand - no case for {command.GetType().Name} ({command.GetCommandType()})"); return true; } } catch (Exception e) { Console.WriteLine(e); return false; } } private bool LogicHeroSeenReceived(LogicHeroSeenCommand command) { if (command.CharacterId == 0) return false; Hero h = HomeMode.Avatar.GetHero(command.CharacterId); if (h == null) return false; h.IsNew = false; return true; } private bool LogicPurchaseBrawlPassProgressReceived(LogicPurchaseBrawlPassProgressCommand command) { if (HomeMode.Avatar.UseDiamonds(30)) { for (int x = 966; x < 1036 + 1; x++) { MilestoneData milestoneData = DataTables.Get(DataType.Milestone).GetDataByGlobalId(GlobalId.CreateGlobalId((int)DataType.Milestone, x)); if (milestoneData.ProgressStart <= HomeMode.Home.BrawlPassTokens && (milestoneData.ProgressStart + milestoneData.Progress) > HomeMode.Home.BrawlPassTokens) { HomeMode.Home.BrawlPassTokens = milestoneData.ProgressStart + milestoneData.Progress; return true; } } } return false; } private bool LogicViewInboxNotificationReceived(LogicViewInboxNotificationCommand command) { if (command.NotificationIndex < 0) return false; if (command.NotificationIndex >= HomeMode.Home.NotificationFactory.NotificationList.Count) return false; if (HomeMode.Home.NotificationFactory.NotificationList[command.NotificationIndex].IsViewed) return false; if (HomeMode.Home.NotificationFactory.NotificationList[command.NotificationIndex].Id == 79) { foreach (int a in HomeMode.Home.NotificationFactory.NotificationList[command.NotificationIndex].StarpointsAwarded) { HomeMode.Avatar.StarPoints += a; } } if (HomeMode.Home.NotificationFactory.NotificationList[command.NotificationIndex].Id == 89) { LogicGiveDeliveryItemsCommand delivery = new LogicGiveDeliveryItemsCommand(); DeliveryUnit unit = new DeliveryUnit(100); GatchaDrop reward = new GatchaDrop(8); reward.Count = HomeMode.Home.NotificationFactory.NotificationList[command.NotificationIndex].DonationCount; unit.AddDrop(reward); delivery.DeliveryUnits.Add(unit); delivery.Execute(HomeMode); AvailableServerCommandMessage message = new AvailableServerCommandMessage(); message.Command = delivery; HomeMode.GameListener.SendMessage(message); } if (HomeMode.Home.NotificationFactory.NotificationList[command.NotificationIndex].Id == 93) { if (HomeMode.Avatar.HasHero(HomeMode.Home.NotificationFactory.NotificationList[command.NotificationIndex].DonationGlobalId)) return false; LogicGiveDeliveryItemsCommand delivery = new LogicGiveDeliveryItemsCommand(); DeliveryUnit unit = new DeliveryUnit(100); GatchaDrop reward = new GatchaDrop(1); reward.Count = HomeMode.Home.NotificationFactory.NotificationList[command.NotificationIndex].DonationCount; reward.DataGlobalId = HomeMode.Home.NotificationFactory.NotificationList[command.NotificationIndex].DonationGlobalId; unit.AddDrop(reward); delivery.DeliveryUnits.Add(unit); delivery.Execute(HomeMode); AvailableServerCommandMessage message = new AvailableServerCommandMessage(); message.Command = delivery; HomeMode.GameListener.SendMessage(message); } if (HomeMode.Home.NotificationFactory.NotificationList[command.NotificationIndex].Id == 94) { LogicGiveDeliveryItemsCommand delivery = new LogicGiveDeliveryItemsCommand(); DeliveryUnit unit = new DeliveryUnit(100); GatchaDrop reward1 = new GatchaDrop(1); SkinData skinData = DataTables.Get(DataType.Skin).GetDataByGlobalId(HomeMode.Home.NotificationFactory.NotificationList[command.NotificationIndex].DonationGlobalId); SkinConfData sk = DataTables.Get(DataType.SkinConf).GetData(skinData.Conf); CharacterData c = DataTables.Get(DataType.Character).GetData(sk.Character); if (HomeMode.Avatar.HasHero(c.GetGlobalId()) == false) { reward1.Count = 0; reward1.DataGlobalId = c.GetGlobalId(); unit.AddDrop(reward1); } GatchaDrop reward = new GatchaDrop(9); reward.Count = 0; reward.SkinGlobalId = HomeMode.Home.NotificationFactory.NotificationList[command.NotificationIndex].DonationGlobalId; unit.AddDrop(reward); delivery.DeliveryUnits.Add(unit); delivery.Execute(HomeMode); AvailableServerCommandMessage message = new AvailableServerCommandMessage(); message.Command = delivery; HomeMode.GameListener.SendMessage(message); } // HomeMode.Home.NotificationFactory.NotificationList[command.NotificationIndex].IsViewed = true; return true; } private bool LogicDeleteNotificationReceived(LogicDeleteNotificationCommand command) { var list = HomeMode.Home.NotificationFactory.NotificationList; if (command.NotificationIndex < 0 || command.NotificationIndex >= list.Count) return false; list[command.NotificationIndex].IsViewed = true; return true; } private bool LogicClaimTailRewardReceived(LogicClaimTailRewardCommand command) { if (HomeMode.Home.BrawlPassTokens < (500)) return false; HomeMode.Home.BrawlPassTokens -= 500; LogicGiveDeliveryItemsCommand delivery = new LogicGiveDeliveryItemsCommand(); DeliveryUnit unit = new DeliveryUnit(12); HomeMode.SimulateGatcha(unit); delivery.DeliveryUnits.Add(unit); delivery.Execute(HomeMode); AvailableServerCommandMessage message = new AvailableServerCommandMessage(); message.Command = delivery; HomeMode.GameListener.SendMessage(message); return true; } private bool LogicSelectStarPowerReceived(LogicSelectStarPowerCommand command) { var avatar = HomeMode.Avatar; CardData card = DataTables.Get(DataType.Card) .GetDataByGlobalId(GlobalId.CreateGlobalId(29, command.StarpowerInstanceId)); if (card == null) return false; CharacterData character = DataTables.Get(DataType.Character) .GetData(card.Name.Split('_')[0]); if (character == null) return false; Hero hero = avatar.GetHero(character.GetGlobalId()); if (hero == null) return false; bool isGadget = card.MetaType == 5; bool isStarPower = card.MetaType == 4; if (!avatar.UnlockedMeta.Contains(card.GetGlobalId())) return false; var allMeta = DataTables.Get(DataType.Card) .GetDatas() .OfType() .Where(c => c.Target == character.Name && c.MetaType == card.MetaType); foreach (var meta in allMeta) { avatar.SelectedMeta.Remove(meta.GetGlobalId()); } avatar.SelectedMeta.Add(card.GetGlobalId()); hero.HasStarpower = true; if (isStarPower) hero.SelectedStarPowerId = card.GetInstanceId(); else if (isGadget) hero.SelectedGadgetId = card.GetInstanceId(); if (avatar.TeamId > 0) { TeamEntry team = Teams.Get(avatar.TeamId); if (team != null) { TeamMember me = team.GetMember(avatar.AccountId); if (me != null && me.CharacterId == hero.CharacterId) { if (isStarPower) me.Starpower = card.GetGlobalId(); else me.Gadget = card.GetGlobalId(); team.TeamUpdated(); } } } return true; } private bool LogicQuestsSeenReceived(LogicQuestsSeenCommand command) { foreach (Quest quest in HomeMode.Home.Quests.QuestList.ToArray()) { quest.QuestSeen = true; } return true; } private bool LogicPurchaseBrawlPassReceived(LogicPurchaseBrawlPassCommand command) { int price = command.isPurchased ? 249 : 169; if (!HomeMode.Avatar.UseDiamonds(price)) return false; HomeMode.Home.HasPremiumPass = true; if (command.isPurchased) { const int levelsToAdd = 10; List milestones = new(); foreach (MilestoneData milestone in DataTables.Get(DataType.Milestone).Datas) { if (milestone != null && milestone.Type == 10) milestones.Add(milestone); } milestones.Sort((a, b) => a.Index.CompareTo(b.Index)); MilestoneData currentMilestone = null; foreach (MilestoneData milestone in milestones) { if (milestone.ProgressStart <= HomeMode.Home.BrawlPassTokens) currentMilestone = milestone; } if (currentMilestone != null) { MilestoneData targetMilestone = milestones .FirstOrDefault(m => m.Index == currentMilestone.Index + levelsToAdd); if (targetMilestone != null) { HomeMode.Home.BrawlPassTokens = targetMilestone.ProgressStart; } else { int additionalTokens = milestones.Last().Progress * levelsToAdd; HomeMode.Home.BrawlPassTokens += additionalTokens; } } } if (HomeMode.Avatar.AllianceId > 0) { Alliance alliance = Alliances.Load(HomeMode.Avatar.AllianceId); AllianceMember member = alliance.GetMemberById(HomeMode.Avatar.AccountId); if (member != null) member.DisplayData.HighNameColorId = HomeMode.Home.NameColorId; } foreach (Friend friend in HomeMode.Avatar.Friends) { Friend entry = friend.Avatar.GetFriendById(HomeMode.Avatar.AccountId); if (entry == null) continue; entry.DisplayData.HighNameColorId = HomeMode.Home.NameColorId; if (LogicServerListener.Instance.IsPlayerOnline(friend.Avatar.AccountId)) { FriendListUpdateMessage update = new() { Entry = entry }; LogicServerListener.Instance .GetGameListener(friend.AccountId) .SendTCPMessage(update); } } return true; } private bool LogicGatchaReceived(LogicGatchaCommand command) { if (command.BoxIndex == 3) { if (!HomeMode.Avatar.UseDiamonds(80)) return false; LogicGiveDeliveryItemsCommand LogicGiveDeliveryItems = new(); DeliveryUnit unit = new(11); HomeMode.SimulateGatcha(unit); LogicGiveDeliveryItems.DeliveryUnits.Add(unit); LogicGiveDeliveryItems.Execute(HomeMode); AvailableServerCommandMessage message = new() { Command = LogicGiveDeliveryItems }; HomeMode.GameListener.SendMessage(message); } else if (command.BoxIndex == 1) { if (!HomeMode.Avatar.UseDiamonds(30)) return false; LogicGiveDeliveryItemsCommand LogicGiveDeliveryItems = new(); DeliveryUnit unit = new(12); HomeMode.SimulateGatcha(unit); LogicGiveDeliveryItems.DeliveryUnits.Add(unit); LogicGiveDeliveryItems.Execute(HomeMode); AvailableServerCommandMessage message = new() { Command = LogicGiveDeliveryItems }; HomeMode.GameListener.SendMessage(message); } else if (command.BoxIndex == 4) { if (!HomeMode.Avatar.UseStarTokens(10)) return false; LogicGiveDeliveryItemsCommand LogicGiveDeliveryItems = new(); DeliveryUnit unit = new(12); HomeMode.SimulateGatcha(unit); LogicGiveDeliveryItems.DeliveryUnits.Add(unit); LogicGiveDeliveryItems.Execute(HomeMode); AvailableServerCommandMessage message = new() { Command = LogicGiveDeliveryItems }; HomeMode.GameListener.SendMessage(message); } else if (command.BoxIndex == 5) { if (!HomeMode.Avatar.UseTokens(100)) return false; LogicGiveDeliveryItemsCommand LogicGiveDeliveryItems = new(); DeliveryUnit unit = new(10); HomeMode.SimulateGatcha(unit); LogicGiveDeliveryItems.DeliveryUnits.Add(unit); LogicGiveDeliveryItems.Execute(HomeMode); AvailableServerCommandMessage message = new() { Command = LogicGiveDeliveryItems }; HomeMode.GameListener.SendMessage(message); } else { } return true; } private bool LogicSelectSkinReceived(LogicSelectSkinCommand command) { int skin = GlobalId.CreateGlobalId(29, command.SkinId); SkinData skinData = DataTables.Get(DataType.Skin) .GetData(command.SkinId); if (skinData == null) return false; if (command.SkinId != 63 && !skinData.Name.EndsWith("Default") && !HomeMode.Home.UnlockedSkins.Contains(skin)) { return false; } SkinConfData skinConf = DataTables.Get(DataType.SkinConf) .GetData(skinData.Conf); if (skinConf == null) return false; CharacterData character = DataTables.Get(DataType.Character) .GetData(skinConf.Character); if (character == null) return false; Hero hero = HomeMode.Avatar.GetHero(character.GetGlobalId()); if (hero == null) return false; hero.SelectedSkinId = command.SkinId; if (HomeMode.Avatar.TeamId > 0) { TeamEntry team = Teams.Get(HomeMode.Avatar.TeamId); TeamMember member = team?.GetMember(HomeMode.Avatar.AccountId); if (member != null) { member.SkinId = skin; team.TeamUpdated(); } } return true; } private bool LogicClaimDailyRewardReceived(LogicClaimDailyRewardCommand command) { if (Events.CollectEvent(HomeMode.Avatar.AccountId, command.Slot)) { if (command.Slot != 7) { HomeMode.Avatar.AddTokens(10); } else { HomeMode.Avatar.AddTokens(10); //HomeMode.Home.Tickets += 1; //TODO: } return true; } return true; } private bool LogicLevelUpReceived(LogicLevelUpCommand command) { Hero hero = HomeMode.Avatar.GetHero(command.CharacterId); if (hero == null) return false; if (hero.PowerLevel > Hero.UpgradeCostTable.Length) return false; if (hero.PowerPoints < Hero.UpgradePowerPointsTable[hero.PowerLevel]) return false; if (!HomeMode.Avatar.UseGold(Hero.UpgradeCostTable[hero.PowerLevel])) return false; hero.PowerLevel++; return true; } private bool LogicPurchaseOfferReceived(LogicPurchaseOfferCommand command) { HomeMode.Home.PurchaseOffer(command.OfferIndex); return true; } private bool LogicSelectCharacterReceived(LogicSelectCharacterCommand command) { int globalId = GlobalId.CreateGlobalId(16, command.CharacterInstanceId); if (!HomeMode.Avatar.HasHero(globalId)) return false; HomeMode.Home.CharacterId = globalId; HomeMode.CharacterChanged.Invoke(globalId); /* if (HomeMode.Avatar.TeamId > 0) { Hero hero = HomeMode.Avatar.GetHero(globalId); TeamEntry team = Teams.Get(HomeMode.Avatar.TeamId); TeamMember member = team?.GetMember(HomeMode.Avatar.AccountId); if (member != null) { member.CharacterId = globalId; member.HeroLevel = hero.PowerLevel; member.Starpower = 0; member.Gadget = 0; if (hero.SelectedStarPowerId > 0) { int globalSp = GlobalId.CreateGlobalId(23, hero.SelectedStarPowerId); if (HomeMode.Avatar.UnlockedMeta.Contains(globalSp)) { member.Starpower = globalSp; member.HeroLevel = Math.Max(member.HeroLevel, 9); } } if (hero.SelectedGadgetId > 0) { int globalGadget = GlobalId.CreateGlobalId(23, hero.SelectedGadgetId); if (HomeMode.Avatar.UnlockedMeta.Contains(globalGadget)) { member.Gadget = globalGadget; } } member.SkinId = GlobalId.CreateGlobalId(29, hero.SelectedSkinId); member.HeroTrophies = hero.Trophies; member.HeroHighestTrophies = hero.HighestTrophies; team.TeamUpdated(); } }*/ return true; } private bool LogicSetPlayerThumbnailReceived(LogicSetPlayerThumbnailCommand command) { if (command.ThumbnailInstanceId < 0) return false; if (command.ThumbnailInstanceId > DataTables.Get(DataType.PlayerThumbnail).Count) return false; HomeMode.Home.ThumbnailId = GlobalId.CreateGlobalId(28, command.ThumbnailInstanceId); if (HomeMode.Avatar.AllianceId > 0) { Alliance alliance = Alliances.Load(HomeMode.Avatar.AllianceId); AllianceMember member = alliance.GetMemberById(HomeMode.Avatar.AccountId); member.DisplayData.ThumbnailId = HomeMode.Home.ThumbnailId; AllianceDataMessage data = new() { Alliance = alliance, IsMyAlliance = true }; //alliance.SendToAlliance(data); } foreach (Friend friend in HomeMode.Avatar.Friends) { Friend entry = friend.Avatar.GetFriendById(HomeMode.Avatar.AccountId); entry.DisplayData.ThumbnailId = HomeMode.Home.ThumbnailId; if (LogicServerListener.Instance.IsPlayerOnline(friend.Avatar.AccountId)) { FriendListUpdateMessage update = new() { Entry = entry }; LogicServerListener.Instance.GetGameListener(friend.AccountId).SendTCPMessage(update); } } return true; } private bool LogicSetPlayerNameColorReceived(LogicSetPlayerNameColorCommand command) { if (command.NameColorInstanceId < 0) return false; if (command.NameColorInstanceId > (DataTables.Get(DataType.NameColor).Count)) return false; HomeMode.Home.NameColorId = GlobalId.CreateGlobalId(43, command.NameColorInstanceId); if (HomeMode.Avatar.AllianceId > 0) { Alliance alliance = Alliances.Load(HomeMode.Avatar.AllianceId); if (alliance == null) { HomeMode.Avatar.AllianceId = -1; return true; } AllianceMember member = alliance.GetMemberById(HomeMode.Avatar.AccountId); if (member == null) { return true; } member.DisplayData.NameColorId = HomeMode.Home.NameColorId; AllianceDataMessage data = new() { Alliance = alliance, IsMyAlliance = true }; //alliance.SendToAlliance(data); } foreach (Friend friend in HomeMode.Avatar.Friends) { Friend entry = friend.Avatar.GetFriendById(HomeMode.Avatar.AccountId); entry.DisplayData.NameColorId = HomeMode.Home.NameColorId; if (LogicServerListener.Instance.IsPlayerOnline(friend.Avatar.AccountId)) { FriendListUpdateMessage update = new() { Entry = entry }; LogicServerListener.Instance.GetGameListener(friend.AccountId).SendTCPMessage(update); } } return true; } private bool LogicClearShopTickersReceived(LogicClearShopTickersCommand command) { if (HomeMode.Home.OfferBundles == null) return true; OfferBundle[] bundles = HomeMode.Home.OfferBundles.ToArray(); foreach (OfferBundle bundle in bundles) { bundle.State = 2; } return true; } private bool LogicPurchaseDoubleCoinsReceived(LogicPurchaseDoubleCoinsCommand command) { if (HomeMode.Avatar.UseDiamonds(40)) { HomeMode.Home.TokenDoublers += 1000; return true; } return false; } private bool LogicPurchaseHeroLvlUpMaterialReceived(LogicPurchaseHeroLvlUpMaterialCommand command) { if (command.PackIndex < 0 || command.PackIndex > ClientHome.GoldPacksAmount.Length) return false; if (!HomeMode.Avatar.UseDiamonds(ClientHome.GoldPacksPrice[command.PackIndex])) return false; HomeMode.Avatar.AddGold(ClientHome.GoldPacksAmount[command.PackIndex]); return true; } private bool LogicClaimRankUpRewardReceived(LogicClaimRankUpRewardCommand command) { Debugger.Print($"Claim rankup reward: milestone: {command.MilestoneId}, data: {command.UnknownDataId}, Unk2: {command.Unk2}, Unk3: {command.Unk3}"); if (command.MilestoneId == 6) { string name = $"goal_6_{HomeMode.Home.TrophyRoadProgress - 1}"; MilestoneData milestoneData = DataTables.Get(DataType.Milestone).GetData(name); if (milestoneData == null) { Debugger.Error($"Milestone data is NULL - {name}"); return false; } if (HomeMode.Avatar.HighestTrophies < milestoneData.Progress + milestoneData.ProgressStart) { Debugger.Warning($"current progress: {HomeMode.Avatar.HighestTrophies}, required progress: {milestoneData.Progress + milestoneData.ProgressStart}"); return false; } if (command.ProcessReward(HomeMode, milestoneData, false, 6, HomeMode.Home.TrophyRoadProgress + 1, false) != 0) return false; HomeMode.Home.TrophyRoadProgress++; } else if (command.MilestoneId == 9 || command.MilestoneId == 10) { string name = $"Goal_{command.MilestoneId}_{HomeMode.Home.BrawlPassSeason}_{(command.MilestoneId == 10 ? command.RequieredMilestone : command.RequieredMilestone)}"; if (command.MilestoneId == 9 && !HomeMode.Home.HasPremiumPass) { return false; } MilestoneData milestoneData = DataTables.Get(DataType.Milestone).GetData(name); if (milestoneData == null) { Debugger.Error($"Milestone data is NULL - {name}"); return false; } if (HomeMode.Home.BrawlPassTokens < milestoneData.Progress + milestoneData.ProgressStart) { Debugger.Warning($"current progress: {HomeMode.Home.BrawlPassTokens}, required progress: {milestoneData.Progress + milestoneData.ProgressStart}"); return false; } if (command.MilestoneId == 9 && LogicBitHelper.Get(HomeMode.Home.PremiumPassProgress, command.RequieredMilestone + 2)) return false; if (command.MilestoneId == 10 && LogicBitHelper.Get(HomeMode.Home.BrawlPassProgress, command.RequieredMilestone + 2)) return false; if (command.MilestoneId == 9) HomeMode.Home.PremiumPassProgress = LogicBitHelper.Set(HomeMode.Home.PremiumPassProgress, command.RequieredMilestone + 2, true); else HomeMode.Home.BrawlPassProgress = LogicBitHelper.Set(HomeMode.Home.BrawlPassProgress, command.RequieredMilestone + 2, true); try { if (command.ProcessReward(HomeMode, milestoneData, false, command.MilestoneId, command.RequieredMilestone + 2, true) != 0) Debugger.Error($"ProcessReward returned non-zero for milestone {name}, but claim progress bit is already set and will not be reverted."); } catch (Exception ex) { Debugger.Error($"ProcessReward threw while claiming {name}: {ex}. Claim progress bit is already set, player keeps the claim; reward contents may be incomplete."); } } else { return false; } return true; } private bool LogicSelectEmoteReceived(LogicSelectEmoteCommand command) { if (command == null) { Logger.Print("EMOTE: command is null"); return false; } int emoteId = command.EmoteId; int slot = command.EmoteSlot; Logger.Print($"EMOTE: received emoteId={emoteId}, slot={slot}"); if (slot < 0 || slot > 6) { Logger.Print($"EMOTE ERROR: invalid slot={slot}"); return false; } if (HomeMode?.Home?.PlayerSelectedEmotes == null) { Logger.Print("EMOTE ERROR: PlayerSelectedEmotes is null"); return false; } Logger.Print($"EMOTE: array size={HomeMode.Home.PlayerSelectedEmotes.Count}, slot={slot}"); EmoteData emoteData = DataTables.Get(DataType.Emote) .GetDataWithId(emoteId); if (emoteData == null) { Logger.Print($"EMOTE ERROR: emoteData not found id={emoteId}"); return false; } Logger.Print($"EMOTE: emote found name={emoteData.Name}, isPicto={emoteData.IsPicto}, character={emoteData.Character}"); bool isUnlocked = emoteData.IsPicto || emoteId <= 300 || emoteId == 910 || HomeMode.Home.UnlockedEmotes.Contains(emoteId) || HomeMode.Home.UnlockedEmotes.Contains(52000000 + emoteId); Logger.Print($"EMOTE: unlock check result={isUnlocked}"); if (!isUnlocked) { Logger.Print($"EMOTE DENIED: emoteId={emoteId}"); return false; } if (slot == 4 || slot == 5) { Logger.Print($"EMOTE: writing slot {slot} (dictionary)"); if (!HomeMode.Home.PlayerSelectedEmotes.ContainsKey(slot)) { HomeMode.Home.PlayerSelectedEmotes[slot] = 0; } HomeMode.Home.PlayerSelectedEmotes[slot] = emoteId; int before = HomeMode.Home.PlayerSelectedEmotes[slot]; HomeMode.Home.PlayerSelectedEmotes[slot] = emoteId; int after = HomeMode.Home.PlayerSelectedEmotes[slot]; Logger.Print($"EMOTE SLOT {slot}: before={before}, after={after}"); return true; } CharacterData characterData = DataTables.Get(DataType.Character) .GetData(emoteData.Character); if (characterData == null) { Logger.Print($"EMOTE ERROR: characterData not found id={emoteData.Character}"); return false; } int characterGlobalId = characterData.GetGlobalId(); Hero hero = HomeMode.Avatar.GetHero(characterGlobalId); if (hero == null) { Logger.Print($"EMOTE ERROR: hero not found globalId={characterGlobalId}"); return false; } Logger.Print($"EMOTE: assigning emote to hero={characterGlobalId}, slot={slot}, emoteId={emoteId}"); HomeMode.Avatar.SetEmoteForBrawler(characterGlobalId, slot, emoteId); Account emoteAcc = Accounts.Load(HomeMode.Avatar.AccountId); if (emoteAcc != null) { emoteAcc.Home = HomeMode.Home; emoteAcc.Avatar = HomeMode.Avatar; Accounts.Save(emoteAcc); } return true; } } }