using Supercell.Laser.Logic.Battle; using System.Threading.Tasks; namespace Supercell.Laser.Logic.Battle { using Supercell.Laser.Logic.Avatar; using Supercell.Laser.Logic.Battle.Component; using Supercell.Laser.Logic.Battle.Objects; using Supercell.Laser.Logic.Battle.Input; using Supercell.Laser.Logic.Battle.Level; using Supercell.Laser.Logic.Battle.Level.Factory; using Supercell.Laser.Logic.Battle.Structures; using Supercell.Laser.Logic.Data; using Supercell.Laser.Logic.Data.Helper; using Supercell.Laser.Logic.Home; using Supercell.Laser.Logic.Home.Structures; using Supercell.Laser.Logic.Listener; using Supercell.Laser.Logic.Message.Battle; using Supercell.Laser.Logic.Time; using Supercell.Laser.Logic.Util; using Supercell.Laser.Titan.DataStream; using Supercell.Laser.Titan.Debug; using Supercell.Laser.Titan.Math; using System; using System.Threading; using System.Security.Cryptography.X509Certificates; using System.Numerics; using Supercell.Laser.Titan.Json; using System.Security.Cryptography; using Supercell.Laser.Logic.Command.Home; using Supercell.Laser.Logic.Message.Home; using Supercell.Laser.Logic.Notification; using Supercell.Laser.Logic.Message.Account; using System.Security.Principal; using Supercell.Laser.Logic.Message.Club; using Supercell.Laser.Logic.Home.Items; using System.Text.RegularExpressions; using System.Diagnostics.Contracts; using System.ComponentModel; using System.Reflection.Metadata; using System.Reflection.Emit; using System.ComponentModel.Design; using System.Collections.Concurrent; using System; using System.Text; using Supercell.Laser.Logic.Ranked; using Supercell.Laser.Logic.Message.Account.Auth; public struct DiedEntry { public int DeathTick; public BattlePlayer Player; } public class KingOfHillState { public int ZoneIndex; public int ZonePercentage; public bool CaptureEffectActiveTeam0 { get; set; } public bool CaptureEffectActiveTeam1 { get; set; } public AreaEffect CurrentCaptureEffectTeam0 { get; set; } public AreaEffect CurrentCaptureEffectTeam1 { get; set; } public bool GaugeTeam0 { get; set; } public bool GaugeTeam1 { get; set; } public AreaEffect GaugeTeam0Effect { get; set; } public AreaEffect GaugeTeam1Effect { get; set; } public int LastUpTickTeam0 { get; set; } public int LastUpTickTeam1 { get; set; } public bool HillCompleteEffectSpawnedTeam0 { get; set; } public bool CanContinueUpTeam0 = true; public bool HillCompleteEffectSpawnedTeam1 { get; set; } public bool CanContinueUpTeam1 = true; public KingOfHillState(int zoneIndex) { this.ZoneIndex = zoneIndex; } } public class BattleMode { private static StringBuilder FileLogger; public const int ORBS_TO_COLLECT_NORMAL = 0xA; public const int INTRO_TICKS = 100; public const int NO_TIME_TICKS = 16000; public const int NORMAL_TICKS = 3180; public StartLoadingMessage Dummy; public Timer m_updateTimer; public int m_locationId; public int m_gameModeVariation; public BattlePlayerMap PlayerMap; private int m_playersCountWithGameModeVariation; public bool BattleWithTrophies; private Queue m_inputQueue; List printobjects = new List(); public List m_players; private Dictionary m_playersBySessionId; private Dictionary m_spectators; private GameObjectManager m_gameObjectManager; private Rect m_playArea; private TileMap m_tileMap; public GameTime m_time; private LogicRandom m_random; private int m_randomSeed; public List StoryModeStuffs; public int m_winnerTeam; private int m_playersAlive; private int m_gemGrabCountdown; public bool IsStoryMode; public bool IsGameOver { get; set; } public List EventModifiers; private int Zone1Score; private int Zone2Score; private int Team0Zone1Score; private int Team1Zone1Score; private int Team0Zone2Score; private int Team1Zone2Score; private int Team0Zone3Score; private int Team1Zone3Score; public int _playersAliveForDuo; public int _StopTicks; public bool _SetStopTicks; private int Team1King; private int Team2King; List PlayerIndexesForTeam1 = new List { 0, 1, 2 }; List PlayerIndexesForTeam2 = new List { 3, 4, 5 }; private int m_ticksSinceLastExplosion = 0; private const int ExplosionInterval = 20 * 15; private List _koHStates = new List(); public Character Carryable; public Character CarryableTeam0; public Character CarryableTeam1; public bool IsRanked; public int RankedId; public int Round; private bool _tmpb = false; private int _tmpi = 0; private bool _rankedRestartIssued = false; private bool IsEnding; private int EndTick; private const int GameOverTicks = 300; public int CurrentRound = 0; public int[] RoundWinners = new int[] { -1, -1, -1 }; public int RoundEndTick = -1; public int RoundEndTickBlock = -1; public bool IsRoundEnding = false; public int RoundStartTime = 0; public int RoundTicks; public int ToGoalTeam = -1; public int GoalTicks; public bool CanReset = true; public int TmpBrawlballTick; public int RoundResetTicks; public List TScore = new List { 0, 0 }; public int GoalPauseEndTick; public BattlePlayerMap BattlePlayerMap; private LogicPathFinder _logicPathFinder; public LogicPathFinder GetPathFinder() => _logicPathFinder ??= new LogicPathFinder(GetTileMap(), true); public BattleMode(int locationId) { FileLogger = new(); m_winnerTeam = -1; m_locationId = locationId; m_gameModeVariation = GameModeUtil.GetGameModeVariation(Location.GameMode); m_playersCountWithGameModeVariation = GamePlayUtil.GetPlayerCountWithGameModeVariation(m_gameModeVariation); m_inputQueue = new Queue(); m_randomSeed = 0; m_random = new LogicRandom(m_randomSeed); m_players = new List(); m_playersBySessionId = new Dictionary(); m_time = new GameTime(); //for (int i = 0; i < 120; i++) m_time.IncreaseTick(); m_tileMap = TileMapFactory.CreateTileMap(Location.AllowedMaps); m_playArea = new Rect(0, 0, m_tileMap.LogicWidth, m_tileMap.LogicHeight); m_gameObjectManager = new GameObjectManager(this); m_spectators = new Dictionary(); EventModifiers = new List(); PlayerIndexesForTeam1.Clear(); PlayerIndexesForTeam2.Clear(); } public BattleMode(BattlePlayerMap playerMap) { FileLogger = new(); m_winnerTeam = -1; PlayerMap = playerMap; m_locationId = playerMap.MapEnvironmentData; m_gameModeVariation = playerMap.GMV; m_playersCountWithGameModeVariation = GamePlayUtil.GetPlayerCountWithGameModeVariation(m_gameModeVariation); m_inputQueue = new Queue(); m_randomSeed = 0; m_random = new LogicRandom(m_randomSeed); m_players = new List(); m_playersBySessionId = new Dictionary(); m_time = new GameTime(); m_tileMap = TileMapFactory.CreatePlayerMap(playerMap.MapData.Data); m_playArea = new Rect(0, 0, m_tileMap.LogicWidth, m_tileMap.LogicHeight); m_gameObjectManager = new GameObjectManager(this); m_spectators = new Dictionary(); EventModifiers = new List(); PlayerIndexesForTeam1.Clear(); PlayerIndexesForTeam2.Clear(); } public void SetPlayerMap(BattlePlayerMap map) { BattlePlayerMap = map; m_tileMap = TileMapFactory.CreatePlayerMap(map.MapData?.Data); m_gameModeVariation = map.GMV; m_playersCountWithGameModeVariation = GamePlayUtil.GetPlayerCountWithGameModeVariation(map.GMV); } private static int[] GetShowdownTrophiesTable(int brawlerTrophies) { if (brawlerTrophies >= 0 && brawlerTrophies <= 49) { return new[] { 20, 16, 14, 12, 8, 4, 4, 2, 0, 0 }; } else if (brawlerTrophies >= 50 && brawlerTrophies <= 99) { return new[] { 20, 16, 14, 12, 8, 4, 4, 2, 0, 0 }; } else if (brawlerTrophies >= 100 && brawlerTrophies <= 199) { return new[] { 20, 16, 14, 12, 6, 4, 4, 0, -2, -4 }; } else if (brawlerTrophies >= 200 && brawlerTrophies <= 299) { return new[] { 20, 16, 14, 12, 6, 2, 0, -2, -4, -4 }; } else if (brawlerTrophies >= 300 && brawlerTrophies <= 399) { return new[] { 20, 16, 12, 10, 6, 2, 0, -4, -6, -6 }; } else if (brawlerTrophies >= 400 && brawlerTrophies <= 499) { return new[] { 20, 16, 12, 10, 4, 0, 0, -6, -8, -8 }; } else if (brawlerTrophies >= 500 && brawlerTrophies <= 599) { return new[] { 20, 16, 12, 10, 4, -2, -4, -6, -10, -10 }; } else if (brawlerTrophies >= 600 && brawlerTrophies <= 899) { return new[] { 20, 16, 12, 8, 4, -2, -4, -10, -12, -12 }; } else if (brawlerTrophies >= 900 && brawlerTrophies <= 999) { return new[] { 20, 16, 12, 8, 2, -4, -4, -10, -14, -16 }; } else if (brawlerTrophies >= 1000 && brawlerTrophies <= 1049) { return new[] { 20, 16, 12, 8, 2, -6, -8, -10, -16, -18 }; } else if (brawlerTrophies >= 1050 && brawlerTrophies <= 1099) { return new[] { 18, 14, 10, 4, 0, -6, -8, -14, -18, -20 }; } else if (brawlerTrophies >= 1100 && brawlerTrophies <= 1149) { return new[] { 16, 12, 8, 2, -2, -6, -12, -16, -20, -22 }; } else if (brawlerTrophies >= 1150 && brawlerTrophies <= 1199) { return new[] { 12, 10, 6, 2, -4, -10, -12, -18, -22, -24 }; } else if (brawlerTrophies >= 1200 && brawlerTrophies <= 1249) { return new[] { 10, 8, 2, 0, -4, -12, -14, -20, -24, -26 }; } else { return new[] { 10, 6, 0, -2, -4, -12, -16, -22, -24, -26 }; } } private static readonly int[] ShowdownExperienceRewards = new[] { 30, 24, 18, 12, 10, 8, 6, 4, 2, 0 }; private static readonly int[] ShowdownTokensRewards = new[] { 60, 48, 42, 30, 24, 16, 12, 8, 4, 0 }; private static int[] GetTrioTrophiesTable(int brawlerTrophies) { if (brawlerTrophies >= 0 && brawlerTrophies <= 49) { return new[] { 4500, 0, 2 }; } else if (brawlerTrophies >= 50 && brawlerTrophies <= 99) { return new[] { 16, -2, 2 }; } else if (brawlerTrophies >= 100 && brawlerTrophies <= 199) { return new[] { 16, -4, 2 }; } else if (brawlerTrophies >= 200 && brawlerTrophies <= 299) { return new[] { 16, -6, 0 }; } else if (brawlerTrophies >= 300 && brawlerTrophies <= 399) { return new[] { 16, -8, 0 }; } else if (brawlerTrophies >= 400 && brawlerTrophies <= 499) { return new[] { 16, -10, 0 }; } else if (brawlerTrophies >= 500 && brawlerTrophies <= 599) { return new[] { 16, -10, 0 }; } else if (brawlerTrophies >= 600 && brawlerTrophies <= 899) { return new[] { 16, -12, 0 }; } else if (brawlerTrophies >= 900 && brawlerTrophies <= 999) { return new[] { 16, -14, 0 }; } else if (brawlerTrophies >= 1000 && brawlerTrophies <= 1049) { return new[] { 14, -14, 0 }; } else if (brawlerTrophies >= 1050 && brawlerTrophies <= 1099) { return new[] { 12, -16, 0 }; } else if (brawlerTrophies >= 1100 && brawlerTrophies <= 1149) { return new[] { 10, -18, 0 }; } else if (brawlerTrophies >= 1150 && brawlerTrophies <= 1199) { return new[] { 8, -20, 0 }; } else if (brawlerTrophies >= 1200 && brawlerTrophies <= 1249) { return new[] { 6, -24, 0 }; } else { return new[] { 6, -26, -2 }; } } public KingOfHillState GetZoneByUID(int a1) { if (_koHStates[a1] != null) { return _koHStates[a1]; } return null; } public int GetKOHZoneCount() { return _koHStates.Count; } public bool HasEventModifier(int m) => EventModifiers.Contains(m); public void SetEventModifiers(List ms) { EventModifiers = ms.ToList(); } public int GetGemGrabCountdown() { return m_gemGrabCountdown; } public LogicRandom GetLogicRandom() { return m_random; } public GameObjectManager GetGameObjectManager() { return m_gameObjectManager; } public int GetPlayersAliveCountForBattleRoyale() { return m_playersAlive; } public void AddWinInLaserBall(int teamIndex) { BattlePlayer plr = m_players.Find(p => p.PlayerIndex == teamIndex); if (plr != null) { plr.AddScore(1); } } public void SetGoalLaserBall(int team) { ToGoalTeam = team; GoalTicks = 3 * 20; } public int GetGoalTeam() => ToGoalTeam; public void ResetRoundLaserBall(bool ballr, bool isResettedByServerError = false) { if (!CanReset && ballr) return; if (_SetStopTicks) return; if (isResettedByServerError) Carryable.CauseDamage(null, 99999, 99999, false, null, false); foreach (Character character in m_gameObjectManager.GetCharacters()) { character.CauseDamage(null, 99999, 99999, false, null, false); m_gameObjectManager.RemoveGameObject(character); // if (character.GetPlayer() != null && character.CharacterData.IsHero()) // { // m_gameObjectManager.RemoveGameObject(character); // } // else character.CauseDamage(null, 99999, 99999, false, null, false); } foreach (BattlePlayer playerrrr in m_players) { InstantRespawn(playerrrr); } foreach (Item item in m_gameObjectManager.GetItems()) { m_gameObjectManager.RemoveGameObject(item); } foreach (AreaEffect area in m_gameObjectManager.GetAreaEffects()) { m_gameObjectManager.RemoveGameObject(area); } foreach (Projectile proj in m_gameObjectManager.GetProjectiles()) { m_gameObjectManager.RemoveGameObject(proj); } m_gameObjectManager.Petrols.Clear(); if(m_gameModeVariation == 5) { Character ball = new(DataTables.Get(16).GetData("LaserBall")); ball.SetPosition(3150, 4950, 0); ball.SetIndex(1); m_gameObjectManager.AddGameObject(ball); Carryable = ball; } else { Character volleyball = new(DataTables.Get(16).GetData("VolleyBall")); volleyball.SetPosition(3150, 4950, 0); volleyball.SetIndex(1); m_gameObjectManager.AddGameObject(volleyball); } } public bool ResetCarryableState; public void ResetCarryable() { if(Carryable == null) return; Carryable.CarringCharacter = null; Carryable.StopKicking(); Carryable.CauseDamage(null, 99999, 99999, false, null, false); Carryable = null; foreach (Character cha in m_gameObjectManager.GetCharacters()) { cha.CarryablePersonImunTicks = 0; } } public void InstantRespawn(BattlePlayer player) { foreach (Character sahur in m_gameObjectManager.GetCharacters()) { if (sahur.GetPlayer() != null && sahur.GetPlayer().PlayerIndex == player.PlayerIndex) m_gameObjectManager.RemoveGameObject(sahur); } Character character = SpawnHero(player.CharacterData, player.HeroPowerLevel, player.TeamIndex * 16 + player.PlayerIndex, 0, false); LogicVector2 spawnPoint = player.GetSpawnPoint(); character.TriggerBlink(spawnPoint.X, spawnPoint.Y, null, null, 0, 0); //character.SetPosition(spawnPoint.X, spawnPoint.Y, 0); character.SetBot(player.IsBot()); character.SpawnTick = GetTicksGone(); player.OwnObjectId = character.GetGlobalID(); player.IsAlive = true; } private void TickSpawnHeroes() { if (m_gameModeVariation != 9) { foreach (BattlePlayer player in m_players) { if (player.IsAlive) continue; if (m_gameModeVariation == 6) return; LogicVector2 spawnPoint = player.GetSpawnPoint(); if (player.CharacterData.Name == "WeaponThrower") player.ChargeUlti(4000, false, false); AreaEffect v90 = GameObjectFactory.CreateGameObjectByData(DataTables.GetAreaEffectByName("HeroSpawn")); int randomindex = 0; if (m_gameModeVariation == 5 || m_gameModeVariation == 23) { randomindex = player.PlayerIndex % 3; } if (GetTicksGone() == player.DeathTick + 20 * GameModeUtil.GetRespawnSeconds(m_gameModeVariation)) { if (player.DeathTick != 1) { if (m_gameModeVariation == 5 || m_gameModeVariation == 23) { if (player.TeamIndex == 0) v90.SetPosition( GetTileMap().LaserBallInstantRespawnTileTeam1[randomindex].X + 150, GetTileMap().LaserBallInstantRespawnTileTeam1[randomindex].Y + 150, 0); else if (player.TeamIndex == 1) v90.SetPosition( GetTileMap().LaserBallInstantRespawnTileTeam2[randomindex].X + 150, GetTileMap().LaserBallInstantRespawnTileTeam2[randomindex].Y + 150, 0); } else { v90.SetPosition(spawnPoint.X, spawnPoint.Y, 0); } v90.SetIndex(player.TeamIndex * 16 + player.PlayerIndex); m_gameObjectManager.AddGameObject(v90); v90.Trigger(); } } if (GetTicksGone() == player.DeathTick + 20 * GameModeUtil.GetRespawnSeconds(m_gameModeVariation) + 40) { Character character = SpawnHero(player.CharacterData, player.HeroPowerLevel, player.TeamIndex * 16 + player.PlayerIndex, 0, false); if (m_gameModeVariation == 5 || m_gameModeVariation == 23) { if (player.TeamIndex == 0) character.SetPosition( GetTileMap().LaserBallInstantRespawnTileTeam1[randomindex].X + 150, GetTileMap().LaserBallInstantRespawnTileTeam1[randomindex].Y + 150, 0); else if (player.TeamIndex == 1) character.SetPosition( GetTileMap().LaserBallInstantRespawnTileTeam2[randomindex].X + 150, GetTileMap().LaserBallInstantRespawnTileTeam2[randomindex].Y + 150, 0); } else { character.SetPosition(spawnPoint.X, spawnPoint.Y, 0); } character.SetBot(player.IsBot()); character.SpawnTick = GetTicksGone(); character.IsInvincible = true; player.OwnObjectId = character.GetGlobalID(); player.IsAlive = true; } } } else if (m_gameModeVariation == 9) { foreach (BattlePlayer player in m_players) { if (player.IsAlive) continue; if (m_gameModeVariation == 6) return; List aliveTeammates = GetAliveCharactersByTeam(player.TeamIndex); bool hasAliveTeammate = aliveTeammates.Count > 0; if (!hasAliveTeammate && !player.RespawnStarted) continue; if (player.CharacterData.Name == "WeaponThrower") player.ChargeUlti(4000, false, false); int respawnBaseTick = player.DeathTick + 20 * GameModeUtil.GetRespawnSeconds(m_gameModeVariation); if (!player.RespawnStarted && GetTicksGone() == respawnBaseTick) { if (player.DeathTick != 1) { if (aliveTeammates.Count == 0) continue; Character anchor = aliveTeammates[0]; player.RespawnX = anchor.GetX(); player.RespawnY = anchor.GetY(); player.RespawnStarted = true; AreaEffect v90 = GameObjectFactory.CreateGameObjectByData(DataTables.GetAreaEffectByName("HeroSpawn")); v90.SetPosition(player.RespawnX, player.RespawnY, 0); v90.SetIndex(player.TeamIndex * 16 + player.PlayerIndex); m_gameObjectManager.AddGameObject(v90); v90.Trigger(); } } if (player.RespawnStarted && GetTicksGone() == respawnBaseTick + 40) { Character character = SpawnHero(player.CharacterData, player.HeroPowerLevel, player.TeamIndex * 16 + player.PlayerIndex, 0, false); character.SetPosition(player.RespawnX, player.RespawnY, 0); character.SetBot(player.IsBot()); character.SpawnTick = GetTicksGone(); character.IsInvincible = true; player.OwnObjectId = character.GetGlobalID(); player.IsAlive = true; player.RespawnStarted = false; } } } } public Character SpawnHero(CharacterData a2, int a3, int a4, int a5, bool a6) { Character v9 = new Character(a2); m_gameObjectManager.AddGameObject(v9); if (a2.AreaEffect != null) { v9.AddAreaEffect(0, 0, null, 1, false); } v9.SetIndex(a4); // if(!BattleWithTrophies) v9.SetUpgrades(11); // else v9.SetUpgrades(a3); // if (m_gameModeVariation == 13 && v9.GetPlayer() != null) v9.ChargeUlti(4095, true, true, v9.GetPlayer(), null); return v9; } public void PlayerDied(BattlePlayer player) { if (m_gameModeVariation == 9) { if (player.IsBot() == 2) return; player.IsAlive = false; player.DeathTick = GetTicksGone(); player.RespawnStarted = false; bool teamHasAlive = GetAliveCharactersByTeam(player.TeamIndex).Count > 0; bool teamHasRespawn = HasRespawningPlayersOnTeam(player.TeamIndex); if (!teamHasAlive && !teamHasRespawn) { int rank = GetAliveTeamsCountForDuo() + 1; foreach (BattlePlayer teammate in m_players) { if (teammate.TeamIndex != player.TeamIndex) continue; if (teammate.BattleEndSent) continue; if (teammate.BattleRoyaleRank == -1) teammate.BattleRoyaleRank = rank; teammate.RespawnStarted = false; teammate.IsAlive = false; SendBattleEndToPlayer(teammate); } } return; } if (m_gameModeVariation == 6) { if (player.IsBot() != 0) { m_playersAlive--; player.IsAlive = false; player.BattleRoyaleRank = m_playersAlive + 1; return; } int rank = m_playersAlive; m_playersAlive--; player.IsAlive = false; player.BattleRoyaleRank = rank; BattleEndMessage message = new BattleEndMessage(); message.GameMode = 2; message.IsPvP = true; message.Result = player.BattleRoyaleRank; message.Players = m_players; message.OwnPlayer = player; if (BattleWithTrophies) { HomeMode homeMode = LogicServerListener.Instance.GetHomeMode(player.AccountId); if (homeMode != null) { if (homeMode.Home.Quests != null) { message.ProgressiveQuests = homeMode.Home.Quests.UpdateQuestsProgress(m_gameModeVariation, player.CharacterId, player.Kills, player.Damage, player.Heals, homeMode.Home); } } } if (player.Avatar == null) return; player.Avatar.BattleId = -1; if (player.GameListener == null) return; Hero hero = player.Avatar.GetHero(player.CharacterId); int brawlerTrophies = player.Avatar.GetHero(player.CharacterId).Trophies; int[] Trophies = GetShowdownTrophiesTable(brawlerTrophies); int[] ExperienceRewards = ShowdownExperienceRewards; int[] TokensRewards = ShowdownTokensRewards; if (BattleWithTrophies) { int premiumTrophies = 0; int trophiesReward = (int)(Trophies[rank - 1]) + premiumTrophies; int tokensReward = TokensRewards[rank - 1]; int experienceResult = ExperienceRewards[rank - 1]; message.ExperienceReward = experienceResult; message.TokensReward = tokensReward; message.TrophiesReward = trophiesReward; message.UnderdogTrophies = premiumTrophies; message.Experience = player.Home.Experience; player.Avatar.SoloWins++; CommunityEvent.AddWin(); player.Avatar.AddTokens(tokensReward); hero.AddTrophies(trophiesReward); player.Home.TokenReward += tokensReward; player.Home.TrophiesReward += trophiesReward; } if (player.Avatar.Trophies > player.Avatar.HighestTrophies) { player.Avatar.HighestTrophies = player.Avatar.Trophies; } player.BattleEndSent = true; player.GameListener.SendTCPMessage(message); return; } if (m_gameModeVariation == 0) { player.ResetScore(); } player.OwnObjectId = 0; DiedEntry entry = new DiedEntry(); entry.Player = player; entry.DeathTick = GetTicksGone(); } public BattlePlayer GetPlayerWithObject(int globalId) { GameObject gameObject = m_gameObjectManager.GetGameObjectByID(globalId); if (gameObject == null) return null; return gameObject.GetPlayer(); } public TileMap GetTileMap() { return m_tileMap; } public void Start() { m_updateTimer = new Timer(new TimerCallback(Update), null, 0, 1000 / 20); } public void Update(object stateInfo) { this.ExecuteOneTick(); //Debugger.Print("shid"); } public BattlePlayer GetPlayer(int globalId) { return m_gameObjectManager.GetGameObjectByID(globalId).GetPlayer(); } // Все UDP session id этого боя (игроки + зрители) — чтобы при завершении // боя освободить соответствующие UDPSocket и не копить их бессрочно. public List GetAllSessionIds() { var ids = new List(); foreach (var player in m_players) { if (player != null && player.SessionId > 0) ids.Add(player.SessionId); } foreach (var sessionId in m_spectators.Keys) { if (sessionId > 0) ids.Add(sessionId); } return ids; } public void AddSpectator(long sessionId, LogicGameListener gameListener) { if (m_spectators.ContainsKey(sessionId)) { m_spectators.Remove(sessionId); } while (!m_spectators.ContainsKey(sessionId)) { if (gameListener != null) m_spectators.Add(sessionId, gameListener); } } public Petrol AddPetrol(int a2, int a3, int a4, int a5, int a6, int a7) { Petrol v32 = new Petrol(a2, a3, a4, a5, a6, a7); m_gameObjectManager.Petrols.Add(v32); return v32; } public void ChangePlayerSessionId(long old, long newId) { if (m_playersBySessionId.ContainsKey(old)) { BattlePlayer player = m_playersBySessionId[old]; player.LastHandledInput = 0; m_playersBySessionId.Remove(old); m_playersBySessionId.Add(newId, player); //this.m_updateTimer.Dispose(); //this.GameOver(); //this.IsGameOver = true; //return; } } public BattlePlayer GetPlayerBySessionId(long sessionId) { if (m_playersBySessionId.ContainsKey(sessionId)) { return m_playersBySessionId[sessionId]; } return null; } public void AddPlayer(BattlePlayer player, long sessionId) { if (Debugger.DoAssert(player != null, "LogicBattle::AddPlayer - player is NULL!")) { player.SessionId = sessionId; m_players.Add(player); if (sessionId > 0) { m_playersBySessionId.Add(sessionId, player); } if (player.Avatar != null) { player.Avatar.BattleId = Id; player.Avatar.TeamIndex = player.TeamIndex; player.Avatar.OwnIndex = player.PlayerIndex; } if (HasEventModifier(13) || player.IsAdmin) player.AddUltiCharge(4000); player.Accessory = null; player.AccessoryCardDatas[0] = null; player.AccessoryDatas[0] = null; player.StarPowerDatas[0] = null; } } public void RemovePlayer(BattlePlayer player) { if (Debugger.DoAssert(player != null, "LogicBattle::AddPlayer - player is NULL!")) { player.GameListener = null; m_playersBySessionId.Remove(player.SessionId); if (player.Avatar != null) { player.Avatar.BattleId = -1; } } } public void AddGameObjects() { m_playersAlive = m_players.Count; double averageLevel = m_players.Average(p => p.HeroPowerLevel); int team1Indexer = 0; int team2Indexer = 0; if (m_gameModeVariation == 19) { PlayerIndexesForTeam1 = GetPlayerIndexesByTeam(0); PlayerIndexesForTeam2 = GetPlayerIndexesByTeam(1); Team1King = PlayerIndexesForTeam1[new Random().Next(PlayerIndexesForTeam1.Count)]; Team2King = PlayerIndexesForTeam2[new Random().Next(PlayerIndexesForTeam2.Count)]; } foreach (BattlePlayer player in m_players) { Character character = SpawnHero(player.CharacterData, player.HeroPowerLevel, player.TeamIndex * 16 + player.PlayerIndex, 0, false); if (player.CharacterData.Name == "WeaponThrower") player.ChargeUlti(4000, false, false); player.IsAlive = true; character.SetBot(player.IsBot()); //if (player.IsBot() && GetGameModeVariation() == 24) character.m_isBot = 2; //character.SetImmunity(60, 100); //if (player != null && player.Gear1 != null) character.Gear1 = new Gear(DataTables.Get(DataType.Gear).GetDataWithId(0)); //else character.Gear1 = character.Gear2 = new Gear(DataTables.Get(DataType.Gear).GetDataWithId(0)); //if (player != null && player.Gear2 != null) character.Gear2 = new Gear(DataTables.Get(DataType.Gear).GetDataWithId(0)); //else character.Gear2 = character.Gear2 = new Gear(DataTables.Get(DataType.Gear).GetDataWithId(0)); if (GameModeUtil.HasTwoTeams(m_gameModeVariation)) { if (player.TeamIndex == 0) { Tile tile = m_tileMap.SpawnPointsTeam1[team1Indexer++ % m_tileMap.SpawnPointsTeam1.Count]; character.SetPosition(tile.X + 150, tile.Y + 150, 0); player.SetSpawnPoint(tile.X + 150, tile.Y + 150); } else { Tile tile = m_tileMap.SpawnPointsTeam2[team2Indexer++ % m_tileMap.SpawnPointsTeam2.Count]; character.SetPosition(tile.X + 150, tile.Y + 150, 0); player.SetSpawnPoint(tile.X + 150, tile.Y + 150); } } else if (m_gameModeVariation == 9) { int spawnPointIndex = player.TeamIndex % 5; int safeIndex = spawnPointIndex * 2; if (safeIndex >= m_tileMap.SpawnPointsTeam1.Count) safeIndex = safeIndex % m_tileMap.SpawnPointsTeam1.Count; Tile baseTile = m_tileMap.SpawnPointsTeam1[safeIndex]; int positionInTeam = player.PlayerIndex % 2; int offsetX = positionInTeam == 0 ? -300 : 300; int offsetY = 0; character.SetPosition(baseTile.X + 150 + offsetX, baseTile.Y + 150 + offsetY, 0); player.SetSpawnPoint(baseTile.X + 150 + offsetX, baseTile.Y + 150 + offsetY); } else if (GameModeUtil.HasFiveTeams(m_gameModeVariation)) { Dictionary teamSpawnCounters = null; if (teamSpawnCounters == null) { teamSpawnCounters = new Dictionary(); for (int i = 0; i < 5; i++) { teamSpawnCounters[i] = 0; } } int spawnPointIndex = player.TeamIndex % 5; Tile baseTile = m_tileMap.SpawnPointsTeam1[spawnPointIndex * 2]; int positionInTeam = teamSpawnCounters[player.TeamIndex] % 2; teamSpawnCounters[player.TeamIndex]++; int offsetX = positionInTeam * 600 * 2; int offsetY = 0; character.SetPosition(baseTile.X + 150 + offsetX, baseTile.Y + 150 + offsetY, 0); player.SetSpawnPoint(baseTile.X + 150 + offsetX, baseTile.Y + 150 + offsetY); } else { Tile tile = m_tileMap.SpawnPointsTeam1[team1Indexer++ % m_tileMap.SpawnPointsTeam1.Count]; character.SetPosition(tile.X + 150, tile.Y + 150, 0); player.SetSpawnPoint(tile.X + 150, tile.Y + 150); } //m_gameObjectManager.AddGameObject(character); player.OwnObjectId = character.GetGlobalID(); character.SetHeroLevel(player.HeroPowerLevel - 1); if (m_gameModeVariation == 19) { if (player.PlayerIndex == Team2King) character.SetKing(); if (player.PlayerIndex == Team1King) character.SetKing(); } // character.SetPosition(1, 1, 0); // player.SetSpawnPoint(1, 1); // player.OwnObjectId = character.GetGlobalID(); //if (character.CharacterData.AreaEffect != null) //{ // AreaEffectData effectData = DataTables.Get(17).GetData(character.CharacterData.AreaEffect); // character.CharacterAreaEffect = new AreaEffect(17, effectData.GetInstanceId()); // character.CharacterAreaEffect.SetPosition(character.GetX(), character.GetY(), 0); // character.CharacterAreaEffect.SetSource(character); // character.CharacterAreaEffect.SetIndex(character.GetIndex()); // character.CharacterAreaEffect.SetDamage(0); // m_gameObjectManager.AddGameObject(character.CharacterAreaEffect); //} //if (m_gameModeVariation == 3) character.SetPosition(2950, 4950, 0); //foreach (CardData carddata in DataTables.Get(DataType.Card).GetDatas()) //{ // if (carddata.Target == character.CharacterData.Name && carddata.MetaType == 5) // { // player.AccessoryCardData = carddata; // break; // } //} //character.tms = new AreaEffect(17, 17); //character.tms.SetPosition(0, 0, 0); //character.tms.SetIndex(character.GetIndex()); //m_gameObjectManager.AddGameObject(character.tms); } if (m_gameModeVariation == 0) { Item item = new Item(DataTables.GetItemByName("OrbSpawner")); item.SetPosition(3150, 4950, 0); item.SetIndex(16); m_gameObjectManager.AddGameObject(item); } if (m_gameModeVariation == 3) { Item item = new Item(DataTables.GetItemByName("Money")); item.SetPosition(3150, 4950, 0); // item.SetIndex(16); m_gameObjectManager.AddGameObject(item); } if (m_gameModeVariation == 6 || m_gameModeVariation == 9) { CharacterData data = DataTables.Get(16).GetData("LootBox"); for (int i = 0; i < m_tileMap.Height; i++) { for (int j = 0; j < m_tileMap.Width; j++) { Tile tile = m_tileMap.GetTile(i, j, true); if (tile.Code == '4') { bool sh = GetRandomInt(0, 120) < 80; if (sh) { Character box = new Character(data); box.SetPosition(tile.X + 150, tile.Y + 150, 0); box.SetIndex(170); box.m_hitpoints = 4300; box.m_maxHitpoints = 4300; m_gameObjectManager.AddGameObject(box); } } } } } if (m_gameModeVariation == 7) { //CharacterData characterData = DataTables.Get(16).GetData("FleaPet"); //Character boss = new Character(characterData); //boss.SetPosition(10000, 10000, 0); //boss.SetIndex(32); //m_gameObjectManager.AddGameObject(boss); //CharacterData characterData1 = DataTables.Get(16).GetData("ShamanPet"); //Character boss1 = new Character(16, characterData1.GetInstanceId()); //boss1.SetPosition(10000, 9000, 0); //boss1.SetIndex(16); //m_gameObjectManager.AddGameObject(boss1); //CharacterData characterData2 = DataTables.Get(16).GetData("RaidBoss"); //Character boss2 = new Character(16, characterData2.GetInstanceId()); //boss2.SetPosition(10000, 8000, 0); //boss2.SetIndex(16); //m_gameObjectManager.AddGameObject(boss2); //CharacterData characterData3 = DataTables.Get(16).GetData("ShieldTank"); //Character boss3 = new Character(16, characterData3.GetInstanceId()); //boss3.SetPosition(8000, 8000, 0); //m_gameObjectManager.AddGameObject(boss3); } /* if (m_gameModeVariation == 2) { CharacterData b = DataTables.GetCharacterByName("Safe"); Character base1 = new Character(b); base1.SetPosition(m_tileMap.SpawnPointsBases[0].X + 150, m_tileMap.SpawnPointsBases[0].Y + 150, 0); // base1.SetIndex(22); // base1.TeamIndex = 1; m_gameObjectManager.AddGameObject(base1); Character base2 = new Character(b); base2.SetPosition(m_tileMap.SpawnPointsBases[1].X + 150, m_tileMap.SpawnPointsBases[1].Y + 150, 0); // base2.SetIndex(6); // base2.TeamIndex = 0; // m_gameObjectManager.AddGameObject(base2); }*/ if (m_gameModeVariation == 5) { Character ball = new Character(DataTables.GetCharacterByName("LaserBall")); ball.SetPosition(3150, 4950, 0); ball.SetIndex(1); // item.DisableAppearAnimation(); m_gameObjectManager.AddGameObject(ball); Carryable = ball; } if (m_gameModeVariation == 10) { Character TrainingDummyBig = new Character(DataTables.Get(16).GetData("RaidBoss")); TrainingDummyBig.SetPosition(m_tileMap.RaidBossSpawn.X, m_tileMap.RaidBossSpawn.Y, 0); TrainingDummyBig.SetIndex(16); m_gameObjectManager.AddGameObject(TrainingDummyBig); } if (m_gameModeVariation == 2) //2 была, ограба { CharacterData b = DataTables.GetCharacterByName("Safe"); Character base1 = new Character(b); base1.SetPosition(m_tileMap.SpawnPointsBases[0].X + 150, m_tileMap.SpawnPointsBases[0].Y + 150, 0); base1.SetIndex(22); base1.TeamIndex = 1; m_gameObjectManager.AddGameObject(base1); Character base2 = new Character(b); base2.SetPosition(m_tileMap.SpawnPointsBases[1].X + 150, m_tileMap.SpawnPointsBases[1].Y + 150, 0); base2.SetIndex(6); base2.TeamIndex = 0; m_gameObjectManager.AddGameObject(base2); } if (m_gameModeVariation == 13) { Character TrainingDummyBig = new Character(DataTables.Get(16).GetData("TrainingDummyBig")); Character TrainingDummyMedium = new Character(DataTables.Get(16).GetData("TrainingDummyMedium")); Character TrainingDummyMedium1 = new Character(DataTables.Get(16).GetData("TrainingDummyMedium")); Character TrainingDummyMedium2 = new Character(DataTables.Get(16).GetData("TrainingDummyMedium")); Character TrainingDummyMedium3 = new Character(DataTables.Get(16).GetData("TrainingDummyMedium")); Character TrainingDummySmall = new Character(DataTables.Get(16).GetData("TrainingDummySmall")); Character TrainingDummyShooting = new Character(DataTables.Get(16).GetData("TrainingDummyShooting")); // TrainingDummyBig.SetPosition(m_tileMap.TrainingDummyBigSpawners[0].X + 150, m_tileMap.TrainingDummyBigSpawners[0].Y + 150, 0); TrainingDummyBig.SetIndex(16); m_gameObjectManager.AddGameObject(TrainingDummyBig); for (int i = 0; i < m_tileMap.TrainingDummySmallSpawners.Count; i++) { Tile tile = m_tileMap.TrainingDummySmallSpawners[i++ % m_tileMap.TrainingDummySmallSpawners.Count]; Tile spawner = m_tileMap.TrainingDummySmallSpawners[i]; //////Logger.Print(i); TrainingDummySmall.SetPosition(tile.X + 150, tile.Y + 150, 0); TrainingDummySmall.SetIndex(16); } for (int i = 0; i < m_tileMap.TrainingDummyShooting.Count; i++) { Tile spawner = m_tileMap.TrainingDummyShooting[i]; TrainingDummyShooting.SetPosition(spawner.X + 150, spawner.Y + 150, 0); TrainingDummyShooting.SetIndex(16); m_gameObjectManager.AddGameObject(TrainingDummyShooting); } TrainingDummyMedium.SetPosition(m_tileMap.TrainingDummyMediumSpawners[0].X + 150, m_tileMap.TrainingDummyMediumSpawners[0].Y + 150, 0); TrainingDummyMedium.SetIndex(16); m_gameObjectManager.AddGameObject(TrainingDummyMedium); TrainingDummyMedium1.SetPosition(m_tileMap.TrainingDummyMediumSpawners[1].X + 150, m_tileMap.TrainingDummyMediumSpawners[1].Y + 150, 0); TrainingDummyMedium1.SetIndex(16); m_gameObjectManager.AddGameObject(TrainingDummyMedium1); TrainingDummyMedium2.SetPosition(m_tileMap.TrainingDummyMediumSpawners[2].X + 150, m_tileMap.TrainingDummyMediumSpawners[2].Y + 150, 0); TrainingDummyMedium2.SetIndex(16); m_gameObjectManager.AddGameObject(TrainingDummyMedium2); TrainingDummyMedium3.SetPosition(m_tileMap.TrainingDummyMediumSpawners[3].X + 150, m_tileMap.TrainingDummyMediumSpawners[3].Y + 150, 0); TrainingDummyMedium3.SetIndex(16); m_gameObjectManager.AddGameObject(TrainingDummyMedium3); } if (m_gameModeVariation == 17) { for (int i = 0; i < m_tileMap.ZonesSpawnPoints.Count; i++) { AreaEffect area = new AreaEffect(DataTables.Get(DataType.AreaEffect).GetData("KingOfHillArea")); area.SetPosition(m_tileMap.ZonesSpawnPoints[i].X + 150, m_tileMap.ZonesSpawnPoints[i].Y + 150, 0); area.SetIndex(16); area.KOHUID = i; _koHStates.Add(new KingOfHillState(i)); m_gameObjectManager.AddGameObject(area); area.Trigger(); } } if (m_gameModeVariation == 16) { AreaEffect area = new AreaEffect(DataTables.Get(DataType.AreaEffect).GetData("CTFHomeBase")); area.SetPosition(m_tileMap.CTFBaseSpawn[0].X + 150, m_tileMap.CTFBaseSpawn[0].Y + 150, 0); area.SetIndex(16); m_gameObjectManager.AddGameObject(area); area.Trigger(); Character teleport = SpawnHero(DataTables.Get(16).GetData("CaptureFlag"), 11, -16, 0, false); teleport.SetPosition(m_tileMap.CTFBaseSpawn[0].X + 150, m_tileMap.CTFBaseSpawn[0].Y + 150, 0); CarryableTeam0 = teleport; AreaEffect area1 = new AreaEffect(DataTables.Get(DataType.AreaEffect).GetData("CTFHomeBase")); area1.SetPosition(m_tileMap.CTFBaseSpawn[1].X + 150, m_tileMap.CTFBaseSpawn[1].Y + 150, 0); area1.SetIndex(16); m_gameObjectManager.AddGameObject(area1); area1.Trigger(); Character teleport1 = SpawnHero(DataTables.Get(16).GetData("CaptureFlag"), 11, 0 + (16 * 0), 0, false); teleport1.SetPosition(m_tileMap.CTFBaseSpawn[1].X + 150, m_tileMap.CTFBaseSpawn[1].Y + 150, 0); CarryableTeam1 = teleport1; } if (m_gameModeVariation == 23) { Character volley = new Character(DataTables.GetCharacterByName("VolleyBall")); volley.SetPosition(3150, 4950, 0); m_gameObjectManager.AddGameObject(volley); volley.SetIndex(16); } } public void RespawnCTFCarryable(Character carryable) { if (carryable == CarryableTeam0) { CarryableTeam0.CauseDamage(null, 99999, 99999, false, null, false); CarryableTeam0.CarringCharacter = null; Character teleport1 = SpawnHero(DataTables.Get(16).GetData("CaptureFlag"), 11, -16, 0, false); teleport1.SetPosition(m_tileMap.CTFBaseSpawn[0].X + 150, m_tileMap.CTFBaseSpawn[0].Y + 150, 0); CarryableTeam0 = teleport1; } if (carryable == CarryableTeam1) { CarryableTeam1.CauseDamage(null, 99999, 99999, false, null, false); CarryableTeam1.CarringCharacter = null; Character teleport1 = SpawnHero(DataTables.Get(16).GetData("CaptureFlag"), 11, 0, 0, false); teleport1.SetPosition(m_tileMap.CTFBaseSpawn[1].X + 150, m_tileMap.CTFBaseSpawn[1].Y + 150, 0); CarryableTeam1 = teleport1; } } public void RemoveSpectator(long id) { if (m_spectators.ContainsKey(id)) { m_spectators.Remove(id); } } public bool IsInPlayArea(int x, int y) { return m_playArea.IsInside(x + 150, y + 150); } public int GetTeamPlayersCount(int teamIndex) { int result = 0; foreach (BattlePlayer player in GetPlayers()) { if (player.TeamIndex == teamIndex) result++; } return result; } public void AddClientInput(ClientInput input, long sessionId) { if (!m_playersBySessionId.ContainsKey(sessionId) || input == null) return; try { input.OwnerSessionId = sessionId; m_inputQueue.Enqueue(input); } catch (Exception ex) when (ex is ArgumentException || ex is InvalidOperationException || ex is IndexOutOfRangeException) { Interlocked.Exchange(ref m_inputQueue, new Queue()); m_inputQueue.Enqueue(input); } } public void HandleSpectatorInput(ClientInput input, long sessionId) { if (input == null) return; if (!m_spectators.ContainsKey(sessionId)) return; m_spectators[sessionId].HandledInputs = input.Index; } private void HandleClientInput(ClientInput input) { if (input == null) return; BattlePlayer player = GetPlayerBySessionId(input.OwnerSessionId); if (player == null) return; if (player.LastHandledInput >= input.Index) return; player.LastHandledInput = input.Index; Character character1 = (Character)m_gameObjectManager.GetGameObjectByID(player.OwnObjectId); if ((character1 == null || !character1.IsAlive()) && input.Type != 4 && input.Type != 9) return; if (character1 != null && character1.ViusalChargeType > 0 && input.Type >= 2 && input.Type <= 8) return; //Debugger.Print(input.Type.ToString()); switch (input.Type)//0普攻 1大招 2移动 5捏大 6松大 8妙具 9发倒指 { case 0: { //Debugger.Print("TG:" + GetTicksGone()); //Debugger.Print("Active:"+GetTicksGone().ToString()); Character character = (Character)m_gameObjectManager.GetGameObjectByID(player.OwnObjectId); if (character == null) return; //character.MoveTo(0, character.GetX(), character.GetY()-2000, 0, 0, 0, 0); //return; Skill skill = character.GetWeaponSkill(); if (skill == null) return; character.UltiDisabled(); if (input.AutoAttack) { Character target = (Character)m_gameObjectManager.GetGameObjectByID(input.AutoAttackTarget); if (target != null) { input.X = target.GetX(); input.Y = target.GetY(); } else { target = character.GetClosestVisibleEnemy(); if (target != null) { input.X = target.GetX(); input.Y = target.GetY(); } } character.ActivateSkill(0, input.X, input.Y); break; } else if (skill.SkillData.IsPositionalTargeted()) character.ActivateSkill(0, input.X, input.Y); else character.ActivateSkill(0, input.X + character.GetX(), input.Y + character.GetY()); if (skill.SkillData.ButtonExportName == "rapid_fire_button") { character.IsRapidFireHeld = true; character.RapidFireRepeatX = input.X + character.GetX(); character.RapidFireRepeatY = input.Y + character.GetY(); character.RapidFireRepeatTick = GetTicksGone(); } var counter = character1.GetFadeCounter(); character1.IncrementFadeCounter(); character.SetFadeCounter(counter); character1.ResetAFKTicks(); /* foreach(Character character1488 in m_gameObjectManager.GetCharacters()) { if(character1488 != null && character1488.ParentGID == character1.GetGlobalID()) { character1488.ActivateSkill(0, input.X, input.Y); } }*/ break; } case 1: { //return; //Debugger.Print("ulti"); Character character = (Character)m_gameObjectManager.GetGameObjectByID(player.OwnObjectId); if (character == null) return; character.m_skills[1].SeemToBeActive = false; if (character.DisplayUltiTmp) return; Skill skill = character.GetUltimateSkill(); if (skill == null) return; character?.UltiDisabled(); if (!player.HasUlti()) return; //if (character.CharacterData.Name == "Mummy") //{ // if (character.TransformationState == 0) // { // character.TransformationState = 1; // int charges = character.m_skills[0].Charge; // character.IsRage = true; // character.m_skills[0] = new Skill(20000133, false); // character.m_skills[0].Charge = charges; // } // else // { // int charges = character.m_skills[0].Charge; // character.TransformationState = 0; // character.IsRage = false; // character.m_skills[0] = new Skill(20000132, false); // character.m_skills[0].Charge = charges; // } // return; //} character.UltiEnabled(); skill.IsFromAutoAttack = input.AutoAttack; if (input.AutoAttack) { Character target = (Character)m_gameObjectManager.GetGameObjectByID(input.AutoAttackTarget); if (target != null) { input.X = target.GetX(); input.Y = target.GetY(); } else { target = character.GetClosestVisibleEnemy(); if (target != null) { input.X = target.GetX(); input.Y = target.GetY(); } } character.ActivateSkill(1, input.X, input.Y); break; } else if(skill.SkillData.IsPositionalTargeted()) character.ActivateSkill(1, input.X, input.Y); else character.ActivateSkill(1, input.X + character.GetX(), input.Y + character.GetY()); var counter = character1.GetFadeCounter(); character1.IncrementFadeCounter(); character.SetFadeCounter(counter); character1.ResetAFKTicks(); break; } case 2: { Character character = (Character)m_gameObjectManager.GetGameObjectByID(player.OwnObjectId); //List clonecharacters = (Character)m_gameObjectManager.GetGameObjectByCloneOfObjectGlobalId(player.OwnObjectId); if (character == null) return; LogicVector2 old = new LogicVector2(character.GetX(), character.GetY()); LogicVector2 destin = new LogicVector2(input.X, input.Y); int v15 = old.GetDistanceSquaredTo(input.X, input.Y); //Debugger.Print(v15.ToString()); ////if (v15 >= 810001) //{ // int v16 = LogicMath.Sqrt(v15); // int v18 = 900 * (input.X - character.GetX()) / v16; // int dx= v18 + character.GetX(); // int v14 = 900 * (input.Y - character.GetY()) / v16 + character.GetY(); //if(character.ControlledCharacter != null) //{ // character.ControlledCharacter.MoveTo(0, input.X, input.Y, 0, 0, 0, 0); //break; //} if (character.Slippery) { int dx = input.X - character.GetX(); int dy = input.Y - character.GetY(); int distSq = dx * dx + dy * dy; int dist = distSq > 0 ? LogicMath.Sqrt(distSq) : 0; if (dist < 60) { character.MoveTo(0, input.X, input.Y, 0, 0, 0, 0); break; } int targetAngle = dist > 0 ? LogicMath.GetAngle(dx, dy) : character.MoveAngle; int angleDiff = (targetAngle - character.MoveAngle) % 360; if (angleDiff > 180) angleDiff -= 360; if (angleDiff < -180) angleDiff += 360; const int maxTurn = 20; if (angleDiff > maxTurn) targetAngle = character.MoveAngle + maxTurn; else if (angleDiff < -maxTurn) targetAngle = character.MoveAngle - maxTurn; targetAngle = LogicMath.NormalizeAngle360(targetAngle); if (dist < 40) dist = 40; input.X = character.GetX() + LogicMath.GetRotatedX(dist, 0, targetAngle); input.Y = character.GetY() + LogicMath.GetRotatedY(dist, 0, targetAngle); } character.MoveTo(0, input.X, input.Y, 0, 0, 0, 0); /*foreach (Character character1488 in m_gameObjectManager.GetCharacters()) { if (character1488!= null && character1488.ParentGID == character1.GetGlobalID()) { character1488.MoveTo(0, character1488.GetX() + (character1488.GetX() - input.X), character1488.GetY() + (character1488.GetY() - input.Y), 0, 0, 0, 0); } } */ //AreaEffectData effectData = DataTables.Get(17).GetData(skill.SkillData.AreaEffectObject); //if (character.m_movementDestination != null) //{ // AreaEffect effect = new AreaEffect(17, 51); // effect.SetPosition(character.m_movementDestination.X, character.m_movementDestination.Y, 0); // effect.SetSource(character); // effect.SetIndex(character.GetIndex()); // m_gameObjectManager.AddGameObject(effect); //} //} //AreaEffect area = new AreaEffect(DataTables.Get(DataType.AreaEffect).GetData("ExplosionSpawn")); //area.SetPosition(character.GetX(), character.GetY(), 0); //area.SetIndex(16); //area.m_ticksElapsed = GetTicksGone(); //m_gameObjectManager.AddGameObject(area); //area.Trigger(); character1.ResetAFKTicks(); break; } case 4: { if (m_gameModeVariation == 13) { SendBattleEndToPlayer(player); RemovePlayer(player); return; } break; } case 5: { Character character = (Character)m_gameObjectManager.GetGameObjectByID(player.OwnObjectId); character?.UltiEnabled(); character1.ResetAFKTicks(); //if (character?.Ultiing ?? false) character.UltiButtonPressedTimes = 1; break; } case 6: { Character character = (Character)m_gameObjectManager.GetGameObjectByID(player.OwnObjectId); character?.UltiDisabled(); character1.ResetAFKTicks(); //if (character != null) character.m_skills[1].SeemToBeActive = false; //if (character?.UltiButtonPressedTimes == 1) character.UltiButtonPressedTwice(); break; } case 8: { if (character1.IsControlled) return; Accessory accessory = player.Accessory; Character character = (Character)m_gameObjectManager.GetGameObjectByID(player.OwnObjectId); if (accessory != null) accessory.TriggerAccessory(character, input.X, input.Y); //if (player.AccessoryCoolDown > 0) return; //player.AccessoryCoolDown = player.AccessoryData.Cooldown; //player.AccessoryUsesLeft--; //} break; } case 9: { if(player.LastPinUseTicks + 200 < GetTicksGone()) player.UsePin(input.EmoteIndex, GetTicksGone()); break; } case 10: { if (character1.IsSteerMovementActive()) { if ((input.X | input.Y) < 0) character1.SteerAngle = -1; else character1.SteerAngle = LogicMath.GetAngle(-input.X + character1.GetX(), -input.Y + character1.GetY()); return; } Projectile projectile = character1.GetControlledProjectile(); if (projectile == null) return; int v26; if ((input.X | input.Y) < 0) v26 = -1; else { v26 = LogicMath.GetAngle(input.X - projectile.GetX(), input.Y - projectile.GetY()); } projectile.SteerAngle = v26; character1.ResetAFKTicks(); break; } case 13: input.X = input.X * 150 / 100; if (character1.GetSkillHoldedTicks() <= 0) { character1.HoldSkillStarted(); if (character1.m_skills[0].SkillData.AttackPattern == 13) break; AreaEffect areaEffect = GameObjectFactory.CreateGameObjectByData(DataTables.GetAreaEffectByName("Tara005UltiSuck")); areaEffect.SetIndex(character1.GetIndex()); areaEffect.SetPosition(character1.GetX(), character1.GetY(), 0); m_gameObjectManager.AddGameObject(areaEffect); //areaEffect.Trigger } if (character1.m_skills[0].SkillData.AttackPattern == 13) break; character1.SetForcedAngle(LogicMath.NormalizeAngle360(LogicMath.GetAngle(input.X, input.Y) - character1.GetIndex() / 16 * 180)); character1.SetVisionOverride(input.X + character1.GetX(), input.Y + character1.GetY(), 2); character1.StopMovement(); character1.SetForcedVisible(); character1.BlockHealthRegen(); character1.m_skills[1].SeemToBeActive = true; //character1.m_state = 2; //character1.ActivateSkill(1, 0, 0); //character1.m_skills[1].OnActivate = true; //character1.m_skills[1].TicksActive = 100; character1.ResetAFKTicks(); break; default: if(input.Type != 7) Debugger.Warning("Input is unhandled: " + input.Type); break; } } public bool IsTileOnPoisonArea(int xTile, int yTile) { if (m_gameModeVariation != 6 && m_gameModeVariation != 9) return false; int tick = GetTicksGone(); if (tick > 500) { int poisons = 0; poisons += (tick - 500) / 100; if (xTile <= poisons || xTile >= 59 - poisons || yTile <= poisons || yTile >= 59 - poisons) { return true; } } return false; } private void HandleIncomingInputMessages() { while (m_inputQueue.Count > 0) { this.HandleClientInput(m_inputQueue.Dequeue()); } } public void ExecuteOneTick() { try { int tick = this.m_time.GetTick(); if (!IsEnding && tick >= 110 && CalculateIsGameOver()) { IsEnding = true; EndTick = tick; this.GameOver(); foreach (BattlePlayer player in GetPlayers()) { player.ResetUsingPin(); } } if (IsEnding) { this.HandleIncomingInputMessages(); try { this.SendVisionUpdateToPlayers(); } catch { } if (tick >= EndTick + GameOverTicks) { this.m_updateTimer.Dispose(); this.IsGameOver = true; return; } this.m_gameObjectManager.PreTick(); this.Tick(); this.m_time.IncreaseTick(); return; } this.HandleIncomingInputMessages(); try { this.SendVisionUpdateToPlayers(); } catch { } foreach (BattlePlayer player in GetPlayers()) { player.KillList.Clear(); } this.m_gameObjectManager.PreTick(); this.Tick(); this.m_time.IncreaseTick(); } catch (Exception e) { string trace = $"[{DateTime.Now}] Battle crashed! Mode={m_gameModeVariation} Tick={m_time?.GetTick()} Players={m_players?.Count}\nMessage: {e.Message}\nTrace: {e.StackTrace}\n"; Console.WriteLine(trace); try { FileLogger.Append(trace); File.AppendAllText("/home/buzz/v36/Supercell.Laser.Server/crash-logs.txt", FileLogger.ToString()); FileLogger.Clear(); } catch { } try { m_updateTimer.Dispose(); } catch { } IsGameOver = true; var players = m_players?.ToList() ?? new List(); Parallel.ForEach(players, player => { try { if (player?.GameListener != null) { AuthenticationFailedMessage serverErrorMessage = new AuthenticationFailedMessage(); serverErrorMessage.ErrorCode = 5; serverErrorMessage.Message = "Бой упал из-за неизвестной ошибки!"; player.GameListener.SendTCPMessage(serverErrorMessage); } } catch { } }); } } private void TickSpawnEventStuffDelayed() { ; } public void GameOver() { SendBattleEndToPlayers(); } private void SendEndRoundRanked(RankedMatch r) { foreach (BattlePlayer player in m_players) { if (player.Avatar == null || player.GameListener == null) continue; BattleEndMessage message = new BattleEndMessage(); message.RankedMatch = true; message.GameMode = 1; message.Result = (m_winnerTeam == player.TeamIndex) ? 0 : 1; message.Players = m_players; message.OwnPlayer = player; message.BlueTeamWins = r.BlueWins; message.RedTeamWins = r.RedWins; message.Round = r.CurrentRound; message.Solo = r.IsSoloMatch; player.GameListener.SendTCPMessage(message); } Task.Delay(5000).ContinueWith(_ => { this.m_updateTimer.Dispose(); }); } private void SendBattleEndRanked(RankedMatch r) { Random rnd = new Random(); bool isSolo = r.IsSoloMatch; int logType = isSolo ? 0 : 1; int battleDurationTicks = GetTicksGone(); bool isFriendly = false; long starPlayerId = 0; List playersInfoList = new List(); foreach (BattlePlayer player in m_players) { if (player.Avatar == null || player.Home == null) continue; bool isVictory = (m_winnerTeam == player.TeamIndex); int oldProgress = isSolo ? player.Home.RankedSoloProgress : player.Home.RankedTrioProgress; int currentRank = (oldProgress / 1000) + 1; int delta = CalculateRankedDelta(currentRank, isVictory, rnd); if (!isVictory && delta > 0) delta = -delta; if (player.Avatar.IsPremium && player.Home.PremiumEndTime > DateTime.UtcNow) { int vipBonus = isVictory ? rnd.Next(25, 50) : rnd.Next(10, 20); delta += vipBonus; } int newProgress = oldProgress + delta; if (newProgress < 1000) newProgress = 1000; int newRank = (newProgress / 1000) + 1; if (newRank > 19) newRank = 19; if (isSolo) { player.Home.RankedSoloProgress = newProgress; player.Home.RankedSoloRank = newRank; player.Home.RankedSoloMaxProgress = Math.Max(player.Home.RankedSoloMaxProgress, newProgress); player.Home.RankedSoloMaxRank = Math.Max(player.Home.RankedSoloMaxRank, newRank); } else { player.Home.RankedTrioProgress = newProgress; player.Home.RankedTrioRank = newRank; player.Home.RankedTrioMaxProgress = Math.Max(player.Home.RankedTrioMaxProgress, newProgress); player.Home.RankedTrioMaxRank = Math.Max(player.Home.RankedTrioMaxRank, newRank); } BattleEndMessage message = new BattleEndMessage(); message.RankedMatch = true; message.GameMode = 1; message.Result = isVictory ? 0 : 1; message.Players = m_players; message.OwnPlayer = player; message.BlueTeamWins = r.BlueWins; message.RedTeamWins = r.RedWins; message.Round = 0; message.Solo = isSolo; message.ELO = oldProgress; message.NewELO = newProgress; message.Add = delta; message.Rank = currentRank; message.UpRank = newRank; message.TokensReward = isVictory ? 40 : 15; player.Avatar.AddTokens(message.TokensReward); if (player.IsBot() == 0 && player.GameListener != null) { BattleLogPlayer logPlayer = new BattleLogPlayer { AccountId = player.AccountId, TeamIndex = player.TeamIndex, BrawlerTrophies = player.Trophies, BrawlerId = player.CharacterId, BrawlerLevel = player.HeroPowerLevel + 1, DisplayData = player.DisplayData }; playersInfoList.Add(logPlayer); int trophiesResult = 0; player.Home.BattleLogs.Add(new BattleLogStructure(), 1, trophiesResult, GetTicksGone() / 20, !BattleWithTrophies, m_locationId, message.Result, playersInfoList); player.GameListener.SendTCPMessage(message); player.Avatar.RankedRank = newRank; } Console.WriteLine($"[Ranked End] {player.Avatar.Name} | Delta: {delta} | Rank: {newRank}"); } r.Stop(); Task.Delay(4000).ContinueWith(_ => { this.IsGameOver = true; this.m_updateTimer.Dispose(); }); } private int CalculateRankedDelta(int rank, bool isVictory, Random rnd) { if (isVictory) { // Ускоренная Бронза (1-3 ранг) if (rank <= 3) return rnd.Next(4000, 4000); // Серебро if (rank <= 6) return rnd.Next(4000, 4000); // Золото и Алмаз if (rank <= 12) return rnd.Next(4000, 4000); // Мифик if (rank <= 15) return rnd.Next(4000, 4000); // Легенда if (rank <= 18) return rnd.Next(4000, 4000); // Мастер (очень мало очков) return rnd.Next(4000, 5000); } else { if (rank >= 19) return rnd.Next(50, 150); // На макс ранге не сливаем if (rank <= 3) return rnd.Next(40, 70); // Бронза (штраф чуть выше, раз можно сливать) if (rank <= 6) return rnd.Next(60, 90); // Серебро if (rank <= 12) return rnd.Next(80, 120); // Золото-Алмаз if (rank <= 18) return rnd.Next(100, 160); // Мифик-Лега return 0; } } public void SendBattleEndToPlayers() { Random rand = new Random(); if (IsRanked) { RankedMatch ranked = LogicServerListener.Instance.GetRankedMatch(RankedId); if (ranked != null) { // Важно: m_winnerTeam - это команда ПОБЕДИТЕЛЯ // Team0 = Blue, Team1 = Red Console.WriteLine($"[BattleEnd] ВНИМАНИЕ! Передаю winnerTeam={m_winnerTeam} в OnRoundFinished. Текущий раунд={ranked.CurrentRound}, счет Blue={ranked.BlueWins}, Red={ranked.RedWins}"); ranked.OnRoundFinished(m_winnerTeam); Console.WriteLine($"[BattleEnd] Раунд завершен. Победитель: Team{m_winnerTeam}. Счет: Blue={ranked.BlueWins}, Red={ranked.RedWins}"); if (ranked.BlueWins >= 2 || ranked.RedWins >= 2) { Console.WriteLine("[BattleEnd] Матч завершен по победам (2 победы)."); SendBattleEndRanked(ranked); } else { Console.WriteLine($"[BattleEnd] Переход к следующему раунду"); SendEndRoundRanked(ranked); } } return; } foreach (BattlePlayer player in m_players) { if (player.SessionId < 0) continue; if (player.BattleEndSent) continue; if (player.BattleRoyaleRank == -1) player.BattleRoyaleRank = 1; if (player.Avatar == null) continue; int rank = player.BattleRoyaleRank; player.Avatar.BattleId = -1; bool isVictory = m_winnerTeam == player.TeamIndex; BattleEndMessage message = new BattleEndMessage(); Hero hero = player.Avatar.GetHero(player.CharacterId); if (player.IsBot() != 2 && BattleWithTrophies) { HomeMode homeMode = LogicServerListener.Instance.GetHomeMode(player.AccountId); if (homeMode != null) { if (homeMode.Home.Quests != null) { message.ProgressiveQuests = homeMode.Home.Quests.UpdateQuestsProgress(m_gameModeVariation, player.CharacterId, player.Kills, player.Damage, player.Heals, homeMode.Home); } } } if (m_gameModeVariation != 6 && m_gameModeVariation != 9) { message.GameMode = 1; message.IsPvP = BattleWithTrophies; message.Players = m_players; message.OwnPlayer = player; int[] ExperienceRewards = new[] { 8, 4, 6 }; int[] TokensRewards = new[] { 14, 7, 10 }; int[] TrophiesRewards = GetTrioTrophiesTable(hero.Trophies); int experienceResult = 0; int trophiesResult = 0; int tokensResult = 0; int premiumTrophies = 0; if (m_winnerTeam == -1) // Draw { message.Result = 2; experienceResult = ExperienceRewards[message.Result]; trophiesResult = TrophiesRewards[message.Result]; tokensResult = TokensRewards[message.Result]; message.ExperienceReward = experienceResult; message.TokensReward = tokensResult; message.TrophiesReward = trophiesResult; if (BattleWithTrophies) { hero.AddTrophies(trophiesResult); player.Avatar.AddTokens(tokensResult); player.Home.Experience += experienceResult; player.Home.TrophiesReward += trophiesResult; if (player.Avatar.Trophies > player.Avatar.HighestTrophies) { player.Avatar.HighestTrophies = player.Avatar.Trophies; } } } if (isVictory) { message.Result = 0; experienceResult = ExperienceRewards[message.Result]; trophiesResult = TrophiesRewards[message.Result]; tokensResult = TokensRewards[message.Result]; if (BattleWithTrophies) { if (player.Avatar.PremiumLevel > 0) { switch (player.Avatar.PremiumLevel) { case 1: premiumTrophies = trophiesResult * 1; break; } } hero.AddTrophies(trophiesResult); player.Avatar.AddTokens(tokensResult); player.Home.Experience += experienceResult; player.Avatar.TrioWins++; // Общий ивент CommunityEvent.AddWin(); // === ИВЕНТ: гемы за победы === // Настройки ивента int[] eventModes = new[] { 0, 1, 2, 3, 4 }; // режимы в которых работает ивент (все) int winsNeeded = 5; // побед для награды int gemsReward = 10; // сколько гемов выдать DateTime eventStart = new DateTime(2026, 7, 19, 8, 0, 0, DateTimeKind.Utc); DateTime eventEnd = new DateTime(2026, 8, 12, 12, 0, 0, DateTimeKind.Utc); DateTime now = DateTime.UtcNow; if (now >= eventStart && now <= eventEnd && System.Array.IndexOf(eventModes, m_gameModeVariation) >= 0) { player.Avatar.EventWins++; if (player.Avatar.EventWins >= winsNeeded) { player.Avatar.EventWins = 0; player.Avatar.AddDiamonds(gemsReward); HomeMode eventHome = LogicServerListener.Instance.GetHomeMode(player.AccountId); if (eventHome != null) { string key = $"event_gems_{player.AccountId}_{now.Ticks}"; eventHome.Home.SendNotification(key, 89, $"Награда за {winsNeeded} побед в ивенте!", donationCount: gemsReward); } } } // === КОНЕЦ ИВЕНТА === message.ExperienceReward = experienceResult; message.TokensReward = tokensResult; message.TrophiesReward = trophiesResult; message.UnderdogTrophies = premiumTrophies; player.Home.TokenReward += tokensResult; player.Home.TrophiesReward = LogicMath.Max(player.Home.TrophiesReward + trophiesResult + premiumTrophies, 0); if (player.Avatar.Trophies > player.Avatar.HighestTrophies) { player.Avatar.HighestTrophies = player.Avatar.Trophies; } } } else if (m_winnerTeam != -1) { message.Result = 1; experienceResult = ExperienceRewards[message.Result]; trophiesResult = TrophiesRewards[message.Result]; tokensResult = TokensRewards[message.Result]; int newSystem = 0; if (hero.Trophies < 1200) { for (int indexTrophies = 1; indexTrophies < 40; indexTrophies++) { if ( hero.Trophies>= 1500 + newSystem && hero.Trophies <= 2000 + newSystem) { trophiesResult = trophiesResult * 1; } newSystem = newSystem + 500; } } if (hero.Trophies < -trophiesResult) trophiesResult = -hero.Trophies; message.TrophiesReward = trophiesResult; if (BattleWithTrophies) { hero.AddTrophies(trophiesResult); player.Avatar.AddTokens(tokensResult); player.Home.Experience += experienceResult; player.Home.TokenReward += tokensResult; player.Home.TrophiesReward = LogicMath.Max(player.Home.TrophiesReward + trophiesResult, 0); if (player.Avatar.Trophies > player.Avatar.HighestTrophies) { player.Avatar.HighestTrophies = player.Avatar.Trophies; } } } if(BattleWithTrophies) { List playersInfoList = new List(); foreach (BattlePlayer player1 in m_players) { BattleLogPlayer logPlayer = new BattleLogPlayer { AccountId = player1.AccountId, TeamIndex = player1.TeamIndex, BrawlerTrophies = player1.Trophies, BrawlerId = player1.CharacterId, BrawlerLevel = player1.HeroPowerLevel + 1, DisplayData = player1.DisplayData }; playersInfoList.Add(logPlayer); } player.Home.BattleLogs.Add(new BattleLogStructure(), 1, trophiesResult, GetTicksGone() / 20, !BattleWithTrophies, m_locationId, message.Result, playersInfoList); } } else if (m_gameModeVariation == 6) { message.IsPvP = true; message.GameMode = 2; message.Result = player.BattleRoyaleRank; message.Players = m_players; message.OwnPlayer = player; int brawlerTrophies = player.Avatar.GetHero(player.CharacterId).Trophies; int[] Trophies = GetShowdownTrophiesTable(brawlerTrophies); int[] ExperienceRewards = ShowdownExperienceRewards; int[] TokensRewards = ShowdownTokensRewards; if (BattleWithTrophies) { int premiumTrophies = 0; int trophiesReward = (int)(Trophies[rank-1]); int tokensReward = TokensRewards[rank - 1]; message.TokensReward = tokensReward; message.TrophiesReward = trophiesReward; message.UnderdogTrophies = premiumTrophies; player.Avatar.SoloWins++; CommunityEvent.AddWin(); player.Avatar.AddTokens(tokensReward); hero.AddTrophies(trophiesReward); player.Home.TokenReward += tokensReward; player.Home.TrophiesReward += trophiesReward; } if (player.Avatar.Trophies > player.Avatar.HighestTrophies) { player.Avatar.HighestTrophies = player.Avatar.Trophies; } /*List playersInfoList = new List(); foreach (BattlePlayer player1 in m_players) { BattleLogPlayer logPlayer = new BattleLogPlayer { AccountId = player1.AccountId, TeamIndex = player1.TeamIndex, BrawlerTrophies = player1.Trophies, BrawlerId = player1.CharacterId, BrawlerLevel = player1.HeroPowerLevel + 1, BattleRoyaleRank = player1.BattleRoyaleRank, DisplayData = player1.DisplayData }; playersInfoList.Add(logPlayer); }*/ //player.Home.BattleLogs.Add(new BattleLogStructure(), 2, message.TrophiesReward, GetTicksGone() / 20, !BattleWithTrophies, m_locationId, player.BattleRoyaleRank, playersInfoList); } else if (m_gameModeVariation == 9) { message.IsPvP = BattleWithTrophies; message.GameMode = 5; message.Result = player.BattleRoyaleRank; message.Players = new List(); message.Players.Add(player); message.OwnPlayer = player; bool teamHasAlive = GetAliveCharactersByTeam(player.TeamIndex).Count > 0; bool teamHasRespawn = HasRespawningPlayersOnTeam(player.TeamIndex); { int rank1 = GetAliveTeamsCountForDuo() + 1; foreach (BattlePlayer teammate in m_players) { if (teammate.TeamIndex != player.TeamIndex) continue; if (teammate.BattleRoyaleRank != -1) continue; teammate.BattleRoyaleRank = rank1; teammate.RespawnStarted = false; teammate.IsAlive = false; message.Players.Add(teammate); } } int brawlerTrophies = player.Avatar.GetHero(player.CharacterId).Trophies; int[] Trophies = GetShowdownTrophiesTable(brawlerTrophies); int[] ExperienceRewards = ShowdownExperienceRewards; int[] TokensRewards = ShowdownTokensRewards; if (BattleWithTrophies) { int premiumTrophies = 0; int trophiesReward = (int)(Trophies[rank - 1]); int tokensReward = TokensRewards[rank - 1]; message.TokensReward = tokensReward; message.TrophiesReward = trophiesReward; message.UnderdogTrophies = premiumTrophies; if (rank == 1) { player.Avatar.DuoWins++; CommunityEvent.AddWin(); } player.Avatar.AddTokens(tokensReward); hero.AddTrophies(trophiesReward); player.Home.TokenReward += tokensReward; player.Home.TrophiesReward += trophiesReward; } if (player.Avatar.Trophies > player.Avatar.HighestTrophies) { player.Avatar.HighestTrophies = player.Avatar.Trophies; } } if (player.Avatar == null) continue; player.BattleEndSent = true; if (player.GameListener == null) continue; player.GameListener.SendTCPMessage(message); } } public void SendBattleEndToPlayer(BattlePlayer player) { if (player.BattleEndSent) return; if (m_gameModeVariation == 13) { if (player.BattleEndSent) return; if (player.Avatar == null) return; if (player.GameListener == null) return; player.Avatar.BattleId = -1; BattleEndMessage msg13 = new BattleEndMessage(); // message.GameMode = 13; // либо другое значение, если клиент ожидает другое msg13.IsPvP = false; msg13.Players = new List(); msg13.Players.Add(player); msg13.OwnPlayer = player; player.GameListener.SendTCPMessage(msg13); player.BattleEndSent = true; // RemovePlayer(player); return; } if (m_gameModeVariation == 6) { int rank = m_playersAlive; m_playersAlive--; player.IsAlive = false; player.BattleRoyaleRank = rank; BattleEndMessage message = new BattleEndMessage(); message.GameMode = 2; message.IsPvP = true; message.Players = new List(); message.Players.Add(player); message.OwnPlayer = player; if (player.IsBot() != 2) { HomeMode homeMode = LogicServerListener.Instance.GetHomeMode(player.AccountId); if (homeMode != null) { if (homeMode.Home.Quests != null) { message.ProgressiveQuests = homeMode.Home.Quests.UpdateQuestsProgress(m_gameModeVariation, player.CharacterId, player.Kills, player.Damage, player.Heals, homeMode.Home); } } } if (player.Avatar == null) return; player.Avatar.BattleId = -1; if (player.GameListener == null) return; Hero hero = player.Avatar.GetHero(player.CharacterId); int brawlerTrophies = player.Avatar.GetHero(player.CharacterId).Trophies; int[] Trophies = GetShowdownTrophiesTable(brawlerTrophies); int[] ExperienceRewards = ShowdownExperienceRewards; int[] TokensRewards = ShowdownTokensRewards; if (BattleWithTrophies) { int premiumTrophies = 0; int trophiesReward = (int)(Trophies[rank-1]); int tokensReward = TokensRewards[rank - 1]; message.TokensReward = tokensReward; message.TrophiesReward = trophiesReward; message.UnderdogTrophies = premiumTrophies; player.Avatar.SoloWins++; CommunityEvent.AddWin(); player.Avatar.AddTokens(tokensReward); hero.AddTrophies(trophiesReward); player.Home.TokenReward += tokensReward; player.Home.TrophiesReward += trophiesReward; } if (player.Avatar.Trophies > player.Avatar.HighestTrophies) { player.Avatar.HighestTrophies = player.Avatar.Trophies; } player.GameListener.SendTCPMessage(message); player.BattleEndSent = true; return; } else if (m_gameModeVariation == 9) { BattleEndMessage message = new BattleEndMessage(); message.GameMode = 5; message.IsPvP = BattleWithTrophies; message.Result = player.BattleRoyaleRank; message.Players = new List(); message.Players.Add(player); message.OwnPlayer = player; bool teamHasAlive = GetAliveCharactersByTeam(player.TeamIndex).Count > 0; bool teamHasRespawn = HasRespawningPlayersOnTeam(player.TeamIndex); if (!teamHasAlive && !teamHasRespawn) { int rank = GetAliveTeamsCountForDuo() + 1; foreach (BattlePlayer teammate in m_players) { if (teammate.TeamIndex != player.TeamIndex) continue; if (teammate.BattleRoyaleRank != -1) continue; teammate.BattleRoyaleRank = rank; teammate.RespawnStarted = false; teammate.IsAlive = false; message.Players.Add(teammate); } } if (player.Avatar == null) return; player.Avatar.BattleId = -1; if (player.GameListener == null) return; Hero hero = player.Avatar.GetHero(player.CharacterId); int brawlerTrophies = player.Avatar.GetHero(player.CharacterId).Trophies; int[] Trophies = GetShowdownTrophiesTable(brawlerTrophies); int[] ExperienceRewards = ShowdownExperienceRewards; int[] TokensRewards = ShowdownTokensRewards; if (BattleWithTrophies) { int premiumTrophies = 0; int trophiesReward = (int)(Trophies[player.BattleRoyaleRank - 1]); int tokensReward = TokensRewards[player.BattleRoyaleRank - 1]; message.TokensReward = tokensReward; message.TrophiesReward = trophiesReward; message.UnderdogTrophies = premiumTrophies; if (player.BattleRoyaleRank == 1) { player.Avatar.DuoWins++; CommunityEvent.AddWin(); } player.Avatar.AddTokens(tokensReward); hero.AddTrophies(trophiesReward); player.Home.TokenReward += tokensReward; player.Home.TrophiesReward += trophiesReward; } if (player.Avatar.Trophies > player.Avatar.HighestTrophies) { player.Avatar.HighestTrophies = player.Avatar.Trophies; } player.GameListener.SendTCPMessage(message); player.BattleEndSent = true; RemovePlayer(player); return; } } public int GetTeamScore(int team) { int score = 0; foreach (BattlePlayer player in m_players) { if (player.TeamIndex == team) score += player.GetScore(); } return score; } private bool CalculateIsGameOver() { // m_winnerTeam = 0; // return true; switch (m_gameModeVariation) { case 0: if (GetTeamScore(0) > GetTeamScore(1) && GetTeamScore(0) >= 10) { if (m_gemGrabCountdown == 0) { m_gemGrabCountdown = GetTicksGone() + 20 * 17; } else if (GetTicksGone() > m_gemGrabCountdown) { m_winnerTeam = 0; foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } } else if (GetTeamScore(0) < GetTeamScore(1) && GetTeamScore(1) >= 10) { if (m_gemGrabCountdown == 0) { m_gemGrabCountdown = GetTicksGone() + 20 * 17; } else if (GetTicksGone() > m_gemGrabCountdown) { m_winnerTeam = 1; foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } } else { m_gemGrabCountdown = 0; } break; case 3: if (GetTeamScore(0) >= 20) { m_winnerTeam = 0; foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } else if (GetTeamScore(1) >= 20) { m_winnerTeam = 1; foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } break; case 5: if (GetTeamScore(0) >= 2) { CanReset = false; m_winnerTeam = 0; foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } else if (GetTeamScore(1) >= 2) { m_winnerTeam = 1; CanReset = false; foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } break; case 23: if (GetTeamScore(0) >= 3) { CanReset = false; m_winnerTeam = 0; foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } else if (GetTeamScore(1) >= 3) { m_winnerTeam = 1; CanReset = false; foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } break; case 25: if (GetTeamScore(0) >= 10) { m_winnerTeam = 0; foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } else if (GetTeamScore(1) >= 10) { m_winnerTeam = 1; foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } break; case 9: if (GetAliveTeams() <= 1) { List aliveTeams = GetAliveTeamsList(); m_winnerTeam = aliveTeams.Count == 1 ? aliveTeams[0] : -1; if (m_winnerTeam >= 0) { foreach (BattlePlayer player in m_players) { if (player.TeamIndex == m_winnerTeam && player.BattleRoyaleRank == -1) { player.BattleRoyaleRank = 1; } } } foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } else { bool anyRealPlayerAlive = m_players.Any(p => p.IsBot() == 0 && p.IsAlive); if (!anyRealPlayerAlive) { foreach (Character character in m_gameObjectManager.GetCharacters()) character.StopAI = true; if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 20 * 5; _SetStopTicks = true; if (GetTicksGone() >= _StopTicks) return true; } } break; case 17: if (Zone1Score >= 100) { m_winnerTeam = 0; foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } else if (Zone2Score >= 100) { m_winnerTeam = 1; foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } break; case 6: if (m_playersAlive <= 1) { m_winnerTeam = 1; if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } else { bool anyRealPlayerAlive = m_players.Any(p => p.IsBot() == 0 && p.IsAlive); if (!anyRealPlayerAlive) { m_winnerTeam = 1; if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 20 * 5; _SetStopTicks = true; if (GetTicksGone() >= _StopTicks) return true; } } break; case 19: int Base1Alive = 0; int Base2Alive = 0; foreach (Character character in m_gameObjectManager.GetCharacters()) { if (!character.CharacterData.IsHero()) continue; if (!character.IsAlive()) continue; if (character.GetPlayer() != null && character.GetPlayer().PlayerIndex == GetTeam1King()) Base1Alive = character.GetHitpointPercentage(); if (character.GetPlayer() != null && character.GetPlayer().PlayerIndex == GetTeam2King()) Base2Alive = character.GetHitpointPercentage(); } if (Base1Alive <= 0 || Base2Alive <= 0) { if (Base1Alive <= 0) { m_winnerTeam = 1; } else if (Base2Alive <= 0) { m_winnerTeam = 0; } foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone(); _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } break; } if (m_gameModeVariation == 20) { int team0Wins = 0; int team1Wins = 0; for (int i = 0; i < 3; i++) { if (RoundWinners[i] == 0) team0Wins++; else if (RoundWinners[i] == 1) team1Wins++; } if (team0Wins >= 2 || team1Wins >= 2) { m_winnerTeam = (team0Wins > team1Wins) ? 0 : 1; return true; } if (CurrentRound >= 2 && IsRoundEnding && GetTicksGone() >= RoundEndTick) { if (team0Wins == team1Wins) m_winnerTeam = -1; else m_winnerTeam = (team0Wins > team1Wins) ? 0 : 1; return true; } return false; } if (GameModeUtil.HasTwoBases(m_gameModeVariation)) { int Base1Alive = 0; int Base2Alive = 0; foreach (Character character in m_gameObjectManager.GetCharacters()) { if (character.CharacterData.IsBase()) { if (character.GetIndex() / 16 == 0) Base1Alive = character.GetHitpointPercentage(); else Base2Alive = character.GetHitpointPercentage(); } } if (Base1Alive <= 0 || Base2Alive <= 0) { if (Base1Alive <= 0) { m_winnerTeam = 1; } else if (Base2Alive <= 0) { m_winnerTeam = 0; } foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } } if (GetTicksGone() >= GameModeUtil.GetBattleTicks(m_gameModeVariation) - 1) { if (GameModeUtil.HasTwoBases(m_gameModeVariation)) { int Base1Alive = 0; int Base2Alive = 0; foreach (Character character in m_gameObjectManager.GetCharacters()) { if (character.CharacterData.IsBase()) { if (character.GetIndex() / 16 == 0) Base1Alive = character.GetHitpointPercentage(); else Base2Alive = character.GetHitpointPercentage(); } } foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (Base1Alive > Base2Alive) m_winnerTeam = 0; else if (Base1Alive < Base2Alive) m_winnerTeam = 1; else m_winnerTeam = -1; } foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone() + 10; _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } if (GetTicksGone() >= GameModeUtil.GetBattleTicks(m_gameModeVariation) - 1) { if (m_gameModeVariation == 19) { int Base1Alive = 0; int Base2Alive = 0; foreach (Character character in m_gameObjectManager.GetCharacters()) { if (!character.CharacterData.IsHero()) continue; if (!character.IsAlive()) continue; if (character.GetPlayer() != null && character.GetPlayer().PlayerIndex == GetTeam1King()) Base1Alive = character.GetHitpointPercentage(); if (character.GetPlayer() != null && character.GetPlayer().PlayerIndex == GetTeam2King()) Base2Alive = character.GetHitpointPercentage(); } foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (Base1Alive > Base2Alive) m_winnerTeam = 0; else if (Base1Alive < Base2Alive) m_winnerTeam = 1; else m_winnerTeam = -1; } foreach (Character character in m_gameObjectManager.GetCharacters()) { character.StopAI = true; } if (!_SetStopTicks || _StopTicks == 0) _StopTicks = GetTicksGone(); _SetStopTicks = true; if (GetTicksGone() == _StopTicks) return true; } return false; } private bool HasRespawningPlayersOnTeam(int teamIndex) { foreach (BattlePlayer player in m_players) { if (player.TeamIndex == teamIndex && !player.IsAlive && player.RespawnStarted) return true; } return false; } private bool IsTeamAliveOrRespawning(int teamIndex) { List alive = GetAliveCharactersByTeam(teamIndex); if (alive != null && alive.Count > 0) return true; return m_gameModeVariation == 9 && HasRespawningPlayersOnTeam(teamIndex); } private int GetAliveTeamsCountForDuo() { int count = 0; for (int i = 0; i < 5; i++) { if (IsTeamAliveOrRespawning(i)) count++; } return count; } public int GetAliveTeams() { List teams = new List(); for (int i = 0; i < 5; i++) { if (IsTeamAliveOrRespawning(i)) teams.Add(i); } return teams.Count; } public List GetAliveTeamsList() { List teams = new List(); for (int i = 0; i < 5; i++) { if (IsTeamAliveOrRespawning(i)) teams.Add(i); } return teams; } public List GetAliveCharactersByTeam(int teamIndex) { if (m_gameObjectManager == null) return null; List teamCharacters = new List(); foreach (Character character in m_gameObjectManager.GetCharacters()) { BattlePlayer player = character.GetPlayer(); if (player != null && player.TeamIndex == teamIndex) { if (player.IsAlive) teamCharacters.Add(character); } } return teamCharacters; } public List GetPlayerIndexesByTeam(int teamIndex) { List teamCharacters = new List(); foreach (BattlePlayer player in m_players) { if (player != null && player.TeamIndex == teamIndex) { teamCharacters.Add(player.PlayerIndex); } } return teamCharacters; } public List GetCharactersByTeam(int teamIndex) { if (m_gameObjectManager == null) return null; List teamCharacters = new List(); foreach (Character character in m_gameObjectManager.GetCharacters()) { BattlePlayer player = character.GetPlayer(); if (player != null && player.TeamIndex == teamIndex) { teamCharacters.Add(character); } } return teamCharacters; } public void TickTimers() { if (m_gameModeVariation == 9) _playersAliveForDuo = GetAliveTeams(); if (TmpBrawlballTick > 1) TmpBrawlballTick--; if (TmpBrawlballTick == 1) ResetCarryable(); if (m_gameModeVariation == 5 || m_gameModeVariation == 23 && GoalTicks > 0) GoalTicks--; if (GoalTicks <= 1 && ToGoalTeam != -1) ResetRoundLaserBall(GetGameModeVariation() == 5 || GetGameModeVariation() == 23); if (GoalTicks <= 1 && ToGoalTeam != -1) ToGoalTeam = -1; } private void Tick() { m_gameObjectManager.Tick(); m_tileMap.Tick(m_gameObjectManager); TickSpawnEventStuffDelayed(); if(m_gameModeVariation != 20) TickSpawnHeroes(); UpdatePlayerStatus(); TickPetrols(); TickTimers(); if (m_gameModeVariation == 20) TickKnockout(); } private void TickKnockout() { if (IsRoundEnding) { if (GetTicksGone() >= RoundEndTick) { IsRoundEnding = false; if (RoundWinners[CurrentRound] == -1) { RoundWinners[CurrentRound] = 2; RestartKnockoutRound(); return; } if (RoundWinners.Count(w => w == 0) >= 2 || RoundWinners.Count(w => w == 1) >= 2) return; CurrentRound++; RestartKnockoutRound(); } return; } RoundTicks = GetTicksGone() - RoundStartTime; int alive0 = m_players.Count(p => p.TeamIndex == 0 && p.IsAlive); int alive1 = m_players.Count(p => p.TeamIndex == 1 && p.IsAlive); if (alive0 == 0 || alive1 == 0) { RoundWinners[CurrentRound] = alive0 > alive1 ? 0 : alive1 > alive0 ? 1 : -1; IsRoundEnding = true; RoundEndTick = GetTicksGone() + 70; RoundEndTickBlock = GetTicksGone() + 180; } else if (RoundTicks >= 20 * 60 * 3) { RoundWinners[CurrentRound] = -1; IsRoundEnding = true; RoundEndTick = GetTicksGone() + 70; RoundEndTickBlock = GetTicksGone() + 180; } } public void RestartKnockoutRound() { var allObjects = m_gameObjectManager.GetGameObjects().ToList(); foreach (var obj in allObjects) { if (obj is Character character) { character.CauseDamage(null, 99999, 99999, false, null, false); m_gameObjectManager.RemoveGameObject(obj); } else { m_gameObjectManager.RemoveGameObject(obj); } } this.RoundStartTime = GetTicksGone(); RoundTicks = 0; foreach (BattlePlayer player in m_players) { // player.IsAlive = true; // player.DeathTick = 0; SpawnHeroAtSpawnPoint(player); } } public void SpawnHeroAtSpawnPoint(BattlePlayer player) { LogicVector2 spawnPoint = player.GetSpawnPoint(); Character character = SpawnHero(player.CharacterData, player.HeroPowerLevel, player.TeamIndex * 16 + player.PlayerIndex, 0, a6: false); if (character != null) { character.TriggerBlink(spawnPoint.X, spawnPoint.Y, null, null, 0, 0); //character2.SetPosition(spawnPoint.X, spawnPoint.Y, 0); character.SetBot(player.IsBot()); character.SpawnTick = GetTicksGone(); character.IsInvincible = true; player.OwnObjectId = character.GetGlobalID(); player.IsAlive = true; } } public int[] GetKnockoutRoundWinners(int teamIndex) { int[] Winners = new int[3]; for (int i = 0; i < 3; i++) { int winner = RoundWinners[i]; Winners[i] = winner; } return Winners; } private void TickPetrols() { List ToRemove = new List(); foreach (Petrol v5 in m_gameObjectManager.Petrols) { if (v5.Tick(m_gameObjectManager)) { ToRemove.Add(v5); foreach (Petrol v9 in m_gameObjectManager.Petrols) { if (v9.TeamIndex == v5.TeamIndex && LogicMath.Abs(v9.X - v5.X) <= 1 && LogicMath.Abs(v9.Y - v5.Y) <= 1) v9.Ignite(m_gameObjectManager, v5.Damage); } } } foreach (Petrol v1 in ToRemove) { m_gameObjectManager.Petrols.Remove(v1); } //Debugger.Print(m_gameObjectManager.Petrols.Count); } public void UpdatePlayerStatus() { foreach (BattlePlayer player in m_players) { //v6 = *(a1[18] + 4 * i); if (m_gameObjectManager.GetGameObjectByID(player.OwnObjectId) == null && player.IsAlive && m_gameObjectManager.AddObjects.ToList().Find(obj => obj.GetGlobalID() == player.OwnObjectId) == null) { player.IsAlive = false; player.DeathTick = GetTicksGone(); } Character character = (Character)m_gameObjectManager.GetGameObjectByID(player.OwnObjectId); if (character != null) { //v8 = v7; //ZN11LogicPlayer9coinsHeldEi(v6, *(v7 + 480)); Accessory v9 = player.Accessory; if (v9 != null) v9.UpdateAccessory(character); //if (*(v8 + 672)) // ZN11LogicPlayer9coinsHeldEi(v6, 2); //if (!ZN17LogicGameModeUtil10isSoloModeEi(a1[41])) //{ // if (*(v6 + 49) || a1[3] < DEPLOY_TICKS_FIRST_SPAWN) // { // *(v6 + 120) = 0; // } // else // { // v4 = a1[41]; // v5 = v4 == 5; // if (v4 == 5) // v5 = *(a1 + 195) == 0; // if (!v5) // ++*(v6 + 120); // } //} } } } public int GetZone1Score() { return Zone1Score; } public void AddScoreTo1Zone() { Zone1Score++; } public void AddScoreTo2Zone() { Zone2Score++; } public int GetZone2Score() { return Zone2Score; } public int GetTeam1King() { return Team1King; } public int GetTeam2King() { return Team2King; } private void SendVisionUpdateToPlayers() { int tick = GetTicksGone(); Parallel.ForEach(m_players, player => { if (player.GameListener != null) { BitStream visionBitStream = new BitStream(1024); m_gameObjectManager.Encode(visionBitStream, m_tileMap, player.OwnObjectId, player.PlayerIndex, player.TeamIndex); VisionUpdateMessage visionUpdate = new VisionUpdateMessage(); visionUpdate.Tick = GetTicksGone(); visionUpdate.HandledInputs = player.LastHandledInput; visionUpdate.Viewers = m_spectators.Count; visionUpdate.VisionBitStream = visionBitStream; player.GameListener.SendMessage(visionUpdate); // Debugger.Print("Send!"); } }); BitStream spectateStream = new BitStream(64); m_gameObjectManager.Encode(spectateStream, m_tileMap, 0, -1, -1); Task.Run(() => { foreach (LogicGameListener gameListener in m_spectators.Values.ToArray()) { VisionUpdateMessage visionUpdate = new VisionUpdateMessage(); visionUpdate.Tick = GetTicksGone(); visionUpdate.HandledInputs = gameListener.HandledInputs; visionUpdate.Viewers = m_spectators.Count; visionUpdate.VisionBitStream = spectateStream; gameListener.SendMessage(visionUpdate); } }); } public BattlePlayer[] GetPlayers() { return m_players.ToArray(); } public int GetRandomInt(int min, int max) { return m_random.Rand(max - min) + min; } public int GetRandomInt(int max) { return m_random.Rand(max); } public int GetTicksGone() { return m_time.GetTick(); } public int GetGameModeVariation() { return m_gameModeVariation; } public int GetPlayersCountWithGameModeVariation() { return m_playersCountWithGameModeVariation; } public int GetRandomSeed() { return m_randomSeed; } public bool IsPlayFieldMirroredForPlayer(int teamIndex) { return teamIndex > 0 && GameModeUtil.HasTwoTeams(m_gameModeVariation); } public LocationData Location { get { return DataTables.Get(DataType.Location).GetDataByGlobalId(m_locationId); } } public long Id { get; set; } } } /* * update 12/21: * added Colette super logic * added charging logic * battle will end when server errors * update 12/28: * done emote logic and encode * (tried) to fix auto attack * decoded speed and slow CharacterServer * * 1/23: * fix logic of speacial brawlers * 1/25: * fixed club * 2/2: * fixing attack logic * 2/5 * ⬆️ * 2/6 */ /* * ChargeSpeed:(logic/20 ticks) * CastingRange:(tile) * tile to logic:*100 */