using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using VeloBrawl.General.NetIsland.LaserBattle.Manager; using VeloBrawl.General.NetIsland.LaserBattle.Objects; using VeloBrawl.General.NetIsland.LaserBattle.Objects.Laser; using VeloBrawl.General.NetIsland.LaserBattle.Render.Help; using VeloBrawl.General.NetIsland.LaserBattle.Render.Tile.Metadata; using VeloBrawl.General.NetIsland.LaserBattle.Significant; using VeloBrawl.General.Networking; using VeloBrawl.General.Networking.LaserUdp; using VeloBrawl.Logic.Environment.LaserMessage.Laser.Node_4; using VeloBrawl.Logic.Environment.LaserMessage.Laser.Node_9; using VeloBrawl.Logic.Environment.LaserMessage.Sepo.Input; using VeloBrawl.Logic.Environment.LaserMessage.Sepo.Player; using VeloBrawl.Supercell.Titan.CommonUtils; using VeloBrawl.Supercell.Titan.CommonUtils.Utils; using VeloBrawl.Titan.DataStream; using VeloBrawl.Titan.Graphic; using VeloBrawl.Titan.Mathematical; using VeloBrawl.Titan.Mathematical.Data; using VeloBrawl.Titan.Utilities; using VeloBrawl.Tools.LaserCsv; using VeloBrawl.Tools.LaserCsv.Manufacturer.Laser; namespace VeloBrawl.General.NetIsland.LaserBattle; public class LogicBattleModeServer { public const int IntroTicks = 180; public const int NormalTicks = 3180; public const int RoboWarsRoboSpawnSeconds1 = 25; public const int RoboWarsRoboSpawnSeconds2 = 75; public const int RoboWarsRoboSpawnSeconds3 = 125; private readonly int _battlePort; private readonly bool _isPolygon; private readonly LogicGameObjectManagerServer _logicGameObjectManagerServer; private readonly List _usedPlayerSpawnCoordinates = []; public readonly Dictionary LogicPetrolServers; public readonly List LogicPlayers; public readonly Dictionary LogicPlayersByObjectGlobalId; public readonly Dictionary LogicPlayersBySessionIdToObjectGlobalId; public readonly Dictionary LogicPlayersConnection; private int _gemGrabCountdown; public readonly int[] TeamBountyScore = { 0, 0 }; public readonly int[] ZoneScore = { 0, 0 }; public readonly int[] BrawlBallScore = { 0, 0 }; public int WinnerTeam = -1; private System.Threading.Timer? _updateTimer; private int _gameModeVariation; private int _location; private LogicTileMetadata _logicTileMetadata = null!; private int _tick; private int _updateTick; public LogicBattleModeServer(int battlePort, bool isPolygon) { _battlePort = battlePort; _isPolygon = isPolygon; _logicGameObjectManagerServer = new LogicGameObjectManagerServer(); LogicPlayers = new List(); LogicPlayersByObjectGlobalId = new Dictionary(); LogicPlayersConnection = new Dictionary(); LogicPlayersBySessionIdToObjectGlobalId = new Dictionary(); _tick = 0; _updateTick = 1; LogicPetrolServers = new Dictionary(); _logicGameObjectManagerServer.SetLogicBattleModeServer(this); ConsoleLogger.WriteTextWithPrefix(ConsoleLogger.Prefixes.Cmd, $"New battle spawned. Battle time to unix: {LogicTimeUtil.GetTimestamp()} / " + $"Battle port: {battlePort} / Battle polygon type: {isPolygon}. Good luck!"); } public void UpdateTime() { _updateTick = LogicMath.Min(_updateTick, 20); } public void TickUpdate() { _updateTimer = new System.Threading.Timer(ExecuteOneTick, null, 0, 1000 / 20); } [SuppressMessage("ReSharper.DPA", "DPA0002: Excessive memory allocations in SOH", MessageId = "type: System.Byte[]; size: 433MB")] [SuppressMessage("ReSharper.DPA", "DPA0003: Excessive memory allocations in LOH", MessageId = "type: System.Byte[]; size: 115MB")] [SuppressMessage("ReSharper.DPA", "DPA0003: Excessive memory allocations in LOH", MessageId = "type: System.Byte[]; size: 124MB")] [SuppressMessage("ReSharper.DPA", "DPA0002: Excessive memory allocations in SOH", MessageId = "type: System.Byte[]; size: 4372MB")] private readonly object _tickLock = new(); private void ExecuteOneTick(object? stateInfo) { if (!System.Threading.Monitor.TryEnter(_tickLock)) return; try { if (WinnerTeam >= 0) { SendBattleEnd(); return; } SendVisionUpdateToPlayers(); PreTick(); Tick(); _tick++; } finally { System.Threading.Monitor.Exit(_tickLock); } } private void SendVisionUpdateToPlayers() { if (_tick < 3) return; if (LogicPlayers.Count == 0) return; try { foreach (var player in LogicPlayers.Where(p => p != null! && p.OwnObjectId > 0 && !p.IsBot())) { if (player.GetPlayerIndex() < 0) continue; var bitStream = new BitStream(1024 / 2); _logicGameObjectManagerServer.Encode(bitStream, player.OwnObjectId, player.GetPlayerIndex(), player.GetTeamIndex()); var visionUpdateMessage = new VisionUpdateMessage(); visionUpdateMessage.Tick = _tick; visionUpdateMessage.Spectators = 0; visionUpdateMessage.InputCounter = player.InputCounter; visionUpdateMessage.SkipIntro = false; visionUpdateMessage.BrawlTvMode = false; visionUpdateMessage.SetVisionBitStream(bitStream); var udpMessage = new UdpMessage(); udpMessage.ByteStream = visionUpdateMessage.ByteStream; udpMessage.PiranhaMessage = visionUpdateMessage; udpMessage.Send(player.SessionId, _battlePort); } } catch (Exception exception) { ConsoleLogger.WriteTextWithPrefix(ConsoleLogger.Prefixes.Error, $"{GetType().Name} -> {exception.Source} \n => {exception.Message} \n => Error{exception.StackTrace}."); foreach (var logicPlayer in LogicPlayers.Where(logicPlayer => !logicPlayer.IsBot())) LogicPlayersConnection[logicPlayer].GetMessaging()!.Send(new ServerErrorMessage(43)); _updateTimer?.Dispose(); _updateTimer = null; } } private bool _battleEnded; public bool BattleEnded => _battleEnded; private void SendBattleEnd() { if (_battleEnded) return; _battleEnded = true; _updateTimer?.Dispose(); _updateTimer = null; foreach (var player in LogicPlayers.Where(p => !p.IsBot())) { var msg = new BattleEndMessage(); msg.Setup( _gameModeVariation, player.GetTeamIndex() == WinnerTeam ? 1 : 2, true, player, LogicPlayers, trophiesReward: player.GetTeamIndex() == WinnerTeam ? 5 : 0, tokensReward: 10, experienceReward: 20, experience: 0 ); LogicPlayersConnection[player].GetMessaging()!.Send(msg); } } private void PreTick() { _logicGameObjectManagerServer.PreTick(); } private void Tick() { try { _logicGameObjectManagerServer.Tick(); TickSpawnHeroes(); AddGameObjects(); TickRespawns(); if (WinnerTeam < 0 && _tick > IntroTicks) { if (_gameModeVariation == 0) TickGemGrabVictory(); else if (_gameModeVariation == 5) TickBrawlBallGoal(); else if (_gameModeVariation == 2) TickHeistVictory(); else if (_gameModeVariation == 17) TickHotZoneVictory(); else if (_gameModeVariation == 7) TickBigGameVictory(); else if (_gameModeVariation == 10) TickBossFightVictory(); else if (_gameModeVariation == 13) TickTrainingEnd(); else if (_gameModeVariation == 20) TickKnockoutVictory(); } } catch (Exception exception) { ConsoleLogger.WriteTextWithPrefix(ConsoleLogger.Prefixes.Error, $"{GetType().Name} -> {exception.Source} \n => {exception.Message} \n => Error{exception.StackTrace}."); foreach (var logicPlayer in LogicPlayers.Where(logicPlayer => !logicPlayer.IsBot())) LogicPlayersConnection[logicPlayer].GetMessaging()!.Send(new ServerErrorMessage(41)); _updateTimer?.Dispose(); _updateTimer = null; } } private bool _heroesSpawned; private void TickSpawnHeroes() { if (_heroesSpawned) return; if (LogicPlayers.Count == 0) return; if (_tick < 3) return; foreach (var logicPlayer in LogicPlayers.Where(p => !p.IsBot())) { logicPlayer.SetPlayerIndex(ObjectIndexHelperTableExtensions.GetIndex(logicPlayer.GetTeamIndex(), logicPlayer.GetPlayerIndex())); SpawnHero(logicPlayer); } _heroesSpawned = true; } private void TickPetrols() { foreach (var logicPetrolServer in LogicPetrolServers) if (logicPetrolServer.Value.PetrolType == 0) LogicPetrolServers.Remove(logicPetrolServer.Key); else logicPetrolServer.Value.Tick(this); } public int GetTeamGemCount(int teamIndex) { var total = 0; foreach (var p in LogicPlayers) if (p.GetTeamIndex() == teamIndex) total += p.ItemCount; return total; } public int GetTeamBountyScore(int teamIndex) { return teamIndex >= 0 && teamIndex < TeamBountyScore.Length ? TeamBountyScore[teamIndex] : 0; } public void AddBountyScore(int teamIndex, int amount) { if (teamIndex >= 0 && teamIndex < TeamBountyScore.Length) TeamBountyScore[teamIndex] += amount; } public int GetSafeHpPercent(int teamIndex) { foreach (var obj in _logicGameObjectManagerServer.GetNumGameObjects()) { if (obj is not LogicCharacterServer ch) continue; if (ch.GetCharacterData().GetName() != "Safe") continue; if (ch.NpcTeamIndex != teamIndex) continue; var max = ch.GetMaxHitPoints(); if (max <= 0) return 0; return ch.GetNowHitPoints() * 100 / max; } return 100; } public LogicCharacterServer? GetBall() { foreach (var obj in _logicGameObjectManagerServer.GetNumGameObjects()) { if (obj is not LogicCharacterServer ch) continue; if (ch.GetCharacterData().GetName() == "LaserBall") return ch; } return null; } private int _ballGoalCooldown; private void TickBrawlBallGoal() { if (_ballGoalCooldown > 0) { _ballGoalCooldown--; return; } var ball = GetBall(); if (ball == null) return; var mapH = _logicTileMetadata.RenderSystem.GetTilemapHeight() * 300; if (ball.GetY() < 600) { BrawlBallScore[0]++; _ballGoalCooldown = 60; ResetBrawlBall(ball); } else if (ball.GetY() > mapH - 600) { BrawlBallScore[1]++; _ballGoalCooldown = 60; ResetBrawlBall(ball); } if (BrawlBallScore[0] >= 3) WinnerTeam = 0; else if (BrawlBallScore[1] >= 3) WinnerTeam = 1; } private void ResetBrawlBall(LogicCharacterServer ball) { var mapW = _logicTileMetadata.RenderSystem.GetTilemapWidth(); var mapH = _logicTileMetadata.RenderSystem.GetTilemapHeight(); ball.SetPosition(mapW * 300 / 2, mapH * 300 / 2, 0); } private void TickHotZoneVictory() { if (ZoneScore[0] >= 100) WinnerTeam = 0; else if (ZoneScore[1] >= 100) WinnerTeam = 1; else if (_tick >= NormalTicks + IntroTicks) { if (ZoneScore[0] > ZoneScore[1]) WinnerTeam = 0; else if (ZoneScore[1] > ZoneScore[0]) WinnerTeam = 1; else WinnerTeam = 0; } } private readonly List<(LogicPlayer player, int respawnTick)> _respawnQueue = []; public void ScheduleRespawn(LogicPlayer player, int respawnTick) { _respawnQueue.Add((player, respawnTick)); } private void TickRespawns() { for (var i = _respawnQueue.Count - 1; i >= 0; i--) { var (player, tick) = _respawnQueue[i]; if (GetTicksGone() < tick) continue; _respawnQueue.RemoveAt(i); player.OwnObjectId = 0; SpawnHero(player, true); } } private int _team0Deaths; private int _team1Deaths; private int _knockoutRoundsTeam0; private int _knockoutRoundsTeam1; private int _knockoutRoundEndTick; private void TickKnockoutVictory() { const int roundsToWin = 3; const int betweenRoundTicks = 100; if (_knockoutRoundEndTick > 0) { if (GetTicksGone() < _knockoutRoundEndTick) return; _knockoutRoundEndTick = 0; foreach (var player in LogicPlayers.Where(p => !p.IsBot())) { player.OwnObjectId = 0; SpawnHero(player, true); } return; } var aliveObjects = _logicGameObjectManagerServer.GetNumGameObjects() .OfType() .Where(c => c.GetCharacterData().IsHero() && c.GetNowHitPoints() > 0) .ToList(); var team0Alive = aliveObjects.Any(c => c.GetIndex() / 16 == 0); var team1Alive = aliveObjects.Any(c => c.GetIndex() / 16 == 1); if (team0Alive && team1Alive) return; if (!team0Alive && !team1Alive) return; if (!team1Alive) { _knockoutRoundsTeam0++; if (_knockoutRoundsTeam0 >= roundsToWin) { WinnerTeam = 0; return; } _knockoutRoundEndTick = GetTicksGone() + betweenRoundTicks; } else { _knockoutRoundsTeam1++; if (_knockoutRoundsTeam1 >= roundsToWin) { WinnerTeam = 1; return; } _knockoutRoundEndTick = GetTicksGone() + betweenRoundTicks; } if (_tick >= NormalTicks + IntroTicks) WinnerTeam = _knockoutRoundsTeam0 >= _knockoutRoundsTeam1 ? 0 : 1; } private void TickBigGameVictory() { var bossAlive = false; foreach (var obj in _logicGameObjectManagerServer.GetNumGameObjects()) { if (obj is not LogicCharacterServer ch) continue; if (ch.GetCharacterData().GetName() != "RaidBoss") continue; if (ch.GetNowHitPoints() > 0) { bossAlive = true; break; } } if (!bossAlive) WinnerTeam = 0; else if (_tick >= NormalTicks + IntroTicks) WinnerTeam = 1; } private void TickTrainingEnd() { if (_tick >= NormalTicks + IntroTicks) WinnerTeam = 0; } private void TickBossFightVictory() { var bossAlive = false; foreach (var obj in _logicGameObjectManagerServer.GetNumGameObjects()) { if (obj is not LogicCharacterServer ch) continue; if (ch.GetCharacterData().GetName() != "RaidBoss") continue; if (ch.GetNowHitPoints() > 0) { bossAlive = true; break; } } if (!bossAlive) WinnerTeam = 0; else if (_tick >= NormalTicks + IntroTicks) WinnerTeam = 1; } private void TickHeistVictory() { if (GetSafeHpPercent(0) <= 0) { WinnerTeam = 1; return; } if (GetSafeHpPercent(1) <= 0) { WinnerTeam = 0; return; } if (_tick >= NormalTicks + IntroTicks) { var hp0 = GetSafeHpPercent(0); var hp1 = GetSafeHpPercent(1); if (hp0 > hp1) WinnerTeam = 0; else if (hp1 > hp0) WinnerTeam = 1; else WinnerTeam = 0; } } private void TickGemGrabVictory() { const int gemsToWin = 10; const int holdSeconds = 17; var team0Gems = GetTeamGemCount(0); var team1Gems = GetTeamGemCount(1); if (team0Gems >= gemsToWin && team0Gems > team1Gems) { if (_gemGrabCountdown == 0) _gemGrabCountdown = _tick + GetTick() * holdSeconds; else if (_tick >= _gemGrabCountdown) WinnerTeam = 0; } else if (team1Gems >= gemsToWin && team1Gems > team0Gems) { if (_gemGrabCountdown == 0) _gemGrabCountdown = _tick + GetTick() * holdSeconds; else if (_tick >= _gemGrabCountdown) WinnerTeam = 1; } else { _gemGrabCountdown = 0; } } public void SpawnHero(LogicPlayer logicPlayer, bool respawn = false) { var logicCharacterServer = new LogicCharacterServer(this, CsvHelperTable.Characters.GetId(), logicPlayer.HeroInfo[0], logicPlayer.GetPlayerIndex()); { logicCharacterServer.InitializeMembers(); } if (!respawn) for (var i = 0; i < _logicTileMetadata.RenderSystem.GetTilemapWidth(); i++) for (var j = 0; j < _logicTileMetadata.RenderSystem.GetTilemapHeight(); j++) { var globalCord = i * _logicTileMetadata.RenderSystem.GetTilemapHeight() + j; var logicTile = _logicTileMetadata.LogicTileMap.GetTile(i, j, true); if (logicTile.TileCode != $"{logicPlayer.GetTeamIndex() + 1}"[0] || _usedPlayerSpawnCoordinates.Contains(globalCord)) continue; logicCharacterServer.SetStartPosition(new LogicVector2(logicTile.LogicX, logicTile.LogicY)); { _usedPlayerSpawnCoordinates.Add(globalCord); { _logicGameObjectManagerServer.AddLogicGameObject(logicCharacterServer); { logicPlayer.OwnObjectId = logicCharacterServer.GetObjectGlobalId(); } LogicPlayersByObjectGlobalId.Add(logicPlayer.OwnObjectId, logicPlayer); { if (logicPlayer.SessionId > -1) LogicPlayersBySessionIdToObjectGlobalId.Add(logicPlayer.SessionId, logicPlayer.OwnObjectId); } if (LogicGameModeUtil.HasSpawnProtectionInTheStart(_gameModeVariation)) Helper.Skip(); // todo. } logicCharacterServer.InitializeMembers(true); return; } } else Helper.Skip(); // todo. } private bool _gameObjectsAdded; public void AddGameObjects() { if (_gameObjectsAdded) return; if (!_heroesSpawned) return; _gameObjectsAdded = true; switch (_gameModeVariation) { case 0: { var mapW = _logicTileMetadata.RenderSystem.GetTilemapWidth(); var mapH = _logicTileMetadata.RenderSystem.GetTilemapHeight(); var centerX = mapW * 300 / 2; var centerY = mapH * 300 / 2; var orbSpawner = new LogicItemServer(this, CsvHelperTable.Items.GetId(), LogicDataTables.GetItemByName("OrbSpawner").GetInstanceId(), 0); orbSpawner.SetPosition(centerX, centerY, 0); _logicGameObjectManagerServer.AddLogicGameObject(orbSpawner); break; } case 5: { var mapW = _logicTileMetadata.RenderSystem.GetTilemapWidth(); var mapH = _logicTileMetadata.RenderSystem.GetTilemapHeight(); var centerX = mapW * 300 / 2; var centerY = mapH * 300 / 2; var ballData = LogicDataTables.GetCharacterByName("LaserBall"); var ball = new LogicCharacterServer(this, CsvHelperTable.Characters.GetId(), ballData.GetInstanceId(), 0); ball.InitializeMembers(); ball.SetPosition(centerX, centerY, 0); ball.NpcTeamIndex = -1; _logicGameObjectManagerServer.AddLogicGameObject(ball); break; } case 2: { var safeData = LogicDataTables.GetCharacterByName("Safe"); var safeIndexes = new[] { 6, 22 }; var safeTeam = 0; for (var i = 0; i < _logicTileMetadata.RenderSystem.GetTilemapWidth(); i++) for (var j = 0; j < _logicTileMetadata.RenderSystem.GetTilemapHeight(); j++) { var tile = _logicTileMetadata.LogicTileMap.GetTile(i, j, true); if (tile.TileCode != '8') continue; if (safeTeam >= 2) break; var safe = new LogicCharacterServer(this, CsvHelperTable.Characters.GetId(), safeData.GetInstanceId(), safeIndexes[safeTeam]); safe.InitializeMembers(); safe.SetPosition(tile.LogicX, tile.LogicY, 0); safe.NpcTeamIndex = safeTeam; _logicGameObjectManagerServer.AddLogicGameObject(safe); safeTeam++; } break; } case 17: { var zoneData = LogicDataTables.GetAreaEffectByName("KingOfHillArea"); if (zoneData == null) { ConsoleLogger.WriteTextWithPrefix(ConsoleLogger.Prefixes.Error, "HotZone: KingOfHillArea not found in AreaEffects CSV!"); break; } var zoneId = 0; for (var i = 0; i < _logicTileMetadata.RenderSystem.GetTilemapWidth(); i++) for (var j = 0; j < _logicTileMetadata.RenderSystem.GetTilemapHeight(); j++) { var tile = _logicTileMetadata.LogicTileMap.GetTile(i, j, true); if (tile.TileCode != '8') continue; var zone = new LogicAreaEffectServer(this, CsvHelperTable.AreaEffects.GetId(), zoneData.GetInstanceId(), 16); zone.SetPosition(tile.LogicX, tile.LogicY, 0); zone.IsPermanent = true; zone.KohZoneId = zoneId; _logicGameObjectManagerServer.AddLogicGameObject(zone); zoneId++; } if (zoneId == 0) ConsoleLogger.WriteTextWithPrefix(ConsoleLogger.Prefixes.Error, $"HotZone: no '8' tiles found on map! Location: {_location}"); break; } case 7: { var bossData = LogicDataTables.GetCharacterByName("RaidBoss"); var mapW = _logicTileMetadata.RenderSystem.GetTilemapWidth(); var mapH = _logicTileMetadata.RenderSystem.GetTilemapHeight(); var boss = new LogicCharacterServer(this, CsvHelperTable.Characters.GetId(), bossData.GetInstanceId(), -16); boss.InitializeMembers(); boss.SetPosition(mapW * 300 / 2, mapH * 300 / 2, 0); boss.NpcTeamIndex = 1; _logicGameObjectManagerServer.AddLogicGameObject(boss); break; } case 10: { var bossData = LogicDataTables.GetCharacterByName("RaidBoss"); var boss = new LogicCharacterServer(this, CsvHelperTable.Characters.GetId(), bossData.GetInstanceId(), -16); boss.InitializeMembers(); boss.SetPosition(3000, 5000, 0); boss.NpcTeamIndex = 1; _logicGameObjectManagerServer.AddLogicGameObject(boss); break; } case 13: { var mapW = _logicTileMetadata.RenderSystem.GetTilemapWidth(); var mapH = _logicTileMetadata.RenderSystem.GetTilemapHeight(); for (var i = 0; i < mapW; i++) for (var j = 0; j < mapH; j++) { var tile = _logicTileMetadata.LogicTileMap.GetTile(i, j, true); string? charName = tile.TileCode switch { '2' => "TrainingDummyMedium", '3' => "TrainingDummyBig", '4' => "TrainingDummyShooting", _ => null }; if (charName == null) continue; try { var dummyData = LogicDataTables.GetCharacterByName(charName); var dummy = new LogicCharacterServer(this, CsvHelperTable.Characters.GetId(), dummyData.GetInstanceId(), -16); dummy.InitializeMembers(); dummy.SetPosition(tile.LogicX, tile.LogicY, 0); dummy.NpcTeamIndex = 1; _logicGameObjectManagerServer.AddLogicGameObject(dummy); } catch { } } break; } } } public void AddPetrol(LogicGameObjectServer creator, int x, int y) { var logicPetrolServer = new LogicPetrolServer(0); { if (creator.GetPlayer() == null) logicPetrolServer.Ignite(creator, x, y, -1); else logicPetrolServer.Ignite(creator, x, y, creator.GetPlayer()!.GetPlayerIndex()); } LogicPetrolServers.Add(LogicPetrolServers.Count, logicPetrolServer); } public void HandleClientInput(ClientInput clientInput) { if (clientInput == null) return; var logicPlayer = LogicPlayers.Find(p => p.SessionId == clientInput.OwnSessionId); if (logicPlayer == null) return; if (logicPlayer.InputCounter >= clientInput.Index) return; logicPlayer.InputCounter = clientInput.Index; if (!LogicPlayersBySessionIdToObjectGlobalId.TryGetValue(clientInput.OwnSessionId, out var objId)) return; var character = _logicGameObjectManagerServer.GetGameObjectById(objId) as LogicCharacterServer; if (character == null && clientInput.Type != 4 && clientInput.Type != 9) return; if (character != null && character.GetNowHitPoints() <= 0 && clientInput.Type != 4) return; switch (clientInput.Type) { case 0: { if (character == null) return; character.UltiDisabled(); var skillData = character.GetSkillData(0); if (skillData != null && !skillData.GetTargeted()) character.ActivateSkill(0, clientInput.X + character.GetX(), clientInput.Y + character.GetY()); else character.ActivateSkill(0, clientInput.X, clientInput.Y); character.ResetAfkTicks(); break; } case 1: { if (character == null) return; if (!logicPlayer.HasUlti()) return; character.UltiEnabled(); var skillData = character.GetSkillData(1); if (skillData != null && !skillData.GetTargeted()) character.ActivateSkill(1, clientInput.X + character.GetX(), clientInput.Y + character.GetY()); else character.ActivateSkill(1, clientInput.X, clientInput.Y); character.ResetAfkTicks(); break; } case 2: { if (character == null) return; character.MoveTo(clientInput.X, clientInput.Y, clientInput.X, clientInput.Y); character.ResetAfkTicks(); break; } case 4: { if (_gameModeVariation == 13) WinnerTeam = 0; break; } case 5: { if (character == null) return; character.UltiEnabled(); character.ResetAfkTicks(); break; } case 6: { if (character == null) return; character.UltiDisabled(); break; } case 8: { if (character == null) return; character.MoveTo(clientInput.X, clientInput.Y, clientInput.X, clientInput.Y); character.ResetAfkTicks(); break; } } } public void GenerateTileMap() { _logicTileMetadata = new LogicTileMetadata(_location); _logicTileMetadata.LogicTileMap.LoadMap(); _logicTileMetadata.LogicTileMap.GenerateTileMap(_logicTileMetadata.LogicGlobalStringData); _gameModeVariation = LogicDataTables .GetGameModeVariationByName(((LogicLocationData)LogicDataTables.GetDataById(GetLocation() < 1000000 ? GlobalId.CreateGlobalId(CsvHelperTable.Locations.GetId(), GetLocation()) : GetLocation())).GetGameModeVariation()).GetVariation(); if (_isPolygon) TileHelper.DestroyAllBlocksInMap(_logicTileMetadata); } public void AddPlayer(LogicPlayer logicPlayer, ServerConnection serverConnection) { LogicPlayers.Add(logicPlayer); LogicPlayersConnection.Add(logicPlayer, serverConnection); } public int GetPlayerCount() { return LogicPlayers.Count; } public bool IsPlayFieldMirroredForPlayer(int teamIndex) { return teamIndex > 0 && LogicGameModeUtil.HasTwoTeams(_gameModeVariation); } public bool IsPlayerAfk(int afkTicks, LogicCharacterServer logicCharacterServer) { var v1 = (LogicGlobalData)LogicDataTables.GetDataFromTable(CsvHelperTable.Globals.GetId()) .GetDataByName("AFK_TIMER_SECONDS"); if (!logicCharacterServer.GetCharacterData().IsHero()) return false; return afkTicks > (v1.GetNumberValue() + 1) * GetTick() && !logicCharacterServer.GetPlayer()!.IsBot(); } public int GetMovementSpeedFactor(int a1, int a2, int a3, int a4, int a5) { return 1; const float v5 = 1.0f; var v6 = a1 == 0; if (a1 != 0) { a4 -= a2; a2 = a5 - a3; v6 = ((a5 - a3) | a4) == 0; } if (v6) return (int)v5; var v7 = 1; { if (a1 < 0) v7 = -1; } var v8 = a4 * v7 / (float)Math.Sqrt(a4 * a4 + a2 * a2); { if (v8 < 0.0f) v8 *= 0.5f; } return (int)(v8 * 0.5f + 1.0f); } public LogicTileMetadata GetTileMap() { return _logicTileMetadata; } public int GetInitialRandomSeed() { return _battlePort; } public int GetTick() { return _updateTick < 20 ? 20 : _updateTick; } public int GetTicksGone() { return _tick; } public LogicGameObjectManagerServer GameObjectManager => _logicGameObjectManagerServer; public int GetGameModeVariation() { return _gameModeVariation; } public int GetLocation() { return _location; } public LogicPlayer? GetPlayer(int findId, bool bySessionId) { return LogicPlayersByObjectGlobalId.GetValueOrDefault(bySessionId ? LogicPlayersBySessionIdToObjectGlobalId.GetValueOrDefault(findId, 0) : findId); } public void SetLocation(int location) { _location = location; } public void SetUpdateTick(int value) { _updateTick = value; } }