using HISP.Game.Horse; using HISP.Player; using HISP.Security; using HISP.Server; using HISP.Util; using System; using System.Collections.Generic; using System.Linq; using System.Threading; namespace HISP.Game { public class Arena { private static List arenas = new List(); private ThreadSafeList entries; private Timer arenaTimeout; public static int[] ExpRewards; public int Id; public string Type; public int EntryCost; public int RandomId; public int RaceEvery; public int Slots; public string Mode; public int Timeout; public static Arena[] Arenas { get { return arenas.ToArray(); } } public ArenaEntry[] Entries { get { return entries.ToArray(); } } public class ArenaEntry { public User EnteredUser; public HorseInstance EnteredHorse; public int SubmitScore = 0; public bool Done = false; } public Arena(int id, string type, int entryCost, int raceEvery, int slots, int timeOut) { RandomId = RandomID.NextRandomId(); Mode = "TAKINGENTRIES"; Id = id; Type = type; EntryCost = entryCost; RaceEvery = raceEvery; Slots = slots; Timeout = timeOut; arenas.Add(this); entries = new ThreadSafeList(); } public bool HaveAllPlayersCompleted() { int playersCompleted = 0; foreach(ArenaEntry entry in Entries) { if (entry.Done) playersCompleted++; } if (playersCompleted >= Entries.Length) return true; else return false; } public void SubmitScore(User user, int score) { foreach(ArenaEntry entry in Entries) { if(entry.EnteredUser.Id == user.Id) { entry.SubmitScore = score; entry.Done = true; break; } } if (HaveAllPlayersCompleted()) End(); } private string getSwf(ArenaEntry entry) { HorseInfo.StatCalculator speedCalculator = new HorseInfo.StatCalculator(entry.EnteredHorse, HorseInfo.StatType.SPEED, entry.EnteredUser); HorseInfo.StatCalculator strengthCalculator = new HorseInfo.StatCalculator(entry.EnteredHorse, HorseInfo.StatType.STRENGTH, entry.EnteredUser); HorseInfo.StatCalculator enduranceCalculator = new HorseInfo.StatCalculator(entry.EnteredHorse, HorseInfo.StatType.ENDURANCE, entry.EnteredUser); HorseInfo.StatCalculator conformationCalculator = new HorseInfo.StatCalculator(entry.EnteredHorse, HorseInfo.StatType.CONFORMATION, entry.EnteredUser); switch (Type) { case "BEGINNERJUMPING": int bigJumps = Convert.ToInt32(Math.Round((double)strengthCalculator.Total / 100.0))+1; return "jumpingarena1.swf?BIGJUMPS="+bigJumps+"&SPEEEDMAX="+speedCalculator.Total+"&JUNK="; case "JUMPING": int bonus = entry.EnteredHorse.BasicStats.Health + entry.EnteredHorse.BasicStats.Hunger + entry.EnteredHorse.BasicStats.Thirst + entry.EnteredHorse.BasicStats.Shoes; return "jumpingarena2.swf?BONUS=" + bonus + "&STRENGTH=" + strengthCalculator.Total + "&SPEED=" + speedCalculator.Total + "&ENDURANCE=" + enduranceCalculator.Total + "&JUNK="; case "CONFORMATION": int baseScore = conformationCalculator.Total + ((entry.EnteredHorse.BasicStats.Groom > 750) ? 1000 : 500); string swf = "dressagearena.swf?BASESCORE=" + baseScore; int i = 1; foreach (ArenaEntry ent in Entries.ToArray()) { swf += "&HN" + i.ToString() + "=" + ent.EnteredUser.Username; if (ent.EnteredUser.Id == entry.EnteredUser.Id) swf += "&POS=" + i.ToString(); i++; } swf += "&JUNK="; return swf; case "DRAFT": int draftAbility = Convert.ToInt32(Math.Round((((double)entry.EnteredHorse.BasicStats.Health * 2.0 + (double)entry.EnteredHorse.BasicStats.Shoes * 2.0) + (double)entry.EnteredHorse.BasicStats.Hunger + (double)entry.EnteredHorse.BasicStats.Thirst) / 6.0 + (double)strengthCalculator.Total + ((double)enduranceCalculator.Total / 2.0))); swf = "draftarena.swf?DRAFTABILITY=" + draftAbility; i = 1; foreach (ArenaEntry ent in Entries.ToArray()) { swf += "&HN" + i.ToString() + "=" + ent.EnteredUser.Username; if (ent.EnteredUser.Id == entry.EnteredUser.Id) swf += "&POS=" + i.ToString(); i++; } swf += "&J="; return swf; case "RACING": int baseSpeed = Convert.ToInt32(Math.Round((((double)entry.EnteredHorse.BasicStats.Health * 2.0 + (double)entry.EnteredHorse.BasicStats.Shoes * 2.0) + (double)entry.EnteredHorse.BasicStats.Hunger + (double)entry.EnteredHorse.BasicStats.Thirst) / 6.0 + (double)speedCalculator.Total)); swf = "racingarena.swf?BASESPEED=" + baseSpeed + "&ENDURANCE=" + enduranceCalculator.Total; i = 1; foreach (ArenaEntry ent in Entries.ToArray()) { swf += "&HN" + i.ToString() + "=" + ent.EnteredUser.Username; if (ent.EnteredUser.Id == entry.EnteredUser.Id) swf += "&POS=" + i.ToString(); i++; } swf += "&JUNK="; return swf; default: return "test.swf"; } } public void Start() { Mode = "COMPETING"; if (Entries.Length <= 0) { reset(); return; } foreach(ArenaEntry entry in Entries.ToArray()) { string swf = getSwf(entry); string message = ""; switch (Type) { case "RACING": entry.EnteredHorse.BasicStats.Hunger -= 200; entry.EnteredHorse.BasicStats.Thirst -= 200; entry.EnteredHorse.BasicStats.Tiredness -= 200; entry.EnteredHorse.BasicStats.Shoes -= 100; message = Messages.ArenaRacingStartup; break; case "DRAFT": entry.EnteredHorse.BasicStats.Hunger -= 200; entry.EnteredHorse.BasicStats.Thirst -= 200; entry.EnteredHorse.BasicStats.Tiredness -= 200; entry.EnteredHorse.BasicStats.Shoes -= 100; message = Messages.ArenaDraftStartup; break; case "BEGINNERJUMPING": entry.EnteredHorse.BasicStats.Hunger -= 200; entry.EnteredHorse.BasicStats.Thirst -= 200; entry.EnteredHorse.BasicStats.Tiredness -= 200; entry.EnteredHorse.BasicStats.Shoes -= 100; message = Messages.ArenaJumpingStartup; break; case "JUMPING": entry.EnteredHorse.BasicStats.Hunger -= 300; entry.EnteredHorse.BasicStats.Thirst -= 300; entry.EnteredHorse.BasicStats.Tiredness -= 300; entry.EnteredHorse.BasicStats.Shoes -= 100; message = Messages.ArenaJumpingStartup; break; case "CONFORMATION": entry.EnteredHorse.BasicStats.Mood -= 300; entry.EnteredHorse.BasicStats.Tiredness -= 200; message = Messages.ArenaConformationStartup; break; default: message = "Arena Type not recognized.
Why dont you stop asking questions and get to fucking beating the competition."; break; } byte[] startingUpEventPacket = PacketBuilder.CreateChat(message, PacketBuilder.CHAT_BOTTOM_RIGHT); byte[] swfModulePacket = PacketBuilder.CreateSwfModule(swf, PacketBuilder.PACKET_SWF_MODULE_CUTSCENE); Logger.DebugPrint(entry.EnteredUser.Username + " Loading swf: " + swf); entry.EnteredUser.LoggedinClient.SendPacket(swfModulePacket); entry.EnteredUser.LoggedinClient.SendPacket(startingUpEventPacket); } arenaTimeout = new Timer(new TimerCallback(arenaTimedOut), null, Timeout * 60 * 1000, Timeout * 60 * 1000); updateWaitingPlayers(); } private void updateWaitingPlayers() { foreach (World.SpecialTile tile in World.SpecialTiles) { if (tile.Code == null) continue; if (tile.Code.StartsWith("ARENA-")) { string arenaId = tile.Code.Split('-')[1]; int id = int.Parse(arenaId); if (id == this.Id) GameServer.UpdateAreaForAll(tile.X, tile.Y, true); } } } private void arenaTimedOut(object state) { End(); } private void reset() { // Delete all entries entries.Clear(); RandomId = RandomID.NextRandomId(); Mode = "TAKINGENTRIES"; if (arenaTimeout != null) arenaTimeout.Dispose(); arenaTimeout = null; } public void End() { if(Mode == "COMPETING") { string chatMessage = Messages.ArenaResultsMessage; string[] avaliblePlacings = new string[6] { Messages.ArenaFirstPlace, Messages.ArenaSecondPlace, Messages.ArenaThirdPlace, Messages.ArenaFourthPlace, Messages.ArenaFifthPlace, Messages.ArenaSixthPlace }; int place = 0; ArenaEntry[] winners = Entries.OrderByDescending(o => o.SubmitScore).ToArray(); int[] expRewards = new int[winners.Length]; Array.Copy(ExpRewards, expRewards, winners.Length); expRewards = expRewards.Reverse().ToArray(); foreach (ArenaEntry entry in winners) { string placing = avaliblePlacings[place % avaliblePlacings.Length]; chatMessage += Messages.FormatArenaPlacing(placing, entry.EnteredUser.Username, entry.SubmitScore); place++; } place = 0; foreach(ArenaEntry entry in winners) { try { byte[] arenaResults = PacketBuilder.CreateChat(chatMessage, PacketBuilder.CHAT_BOTTOM_RIGHT); entry.EnteredUser.LoggedinClient.SendPacket(arenaResults); int expReward = expRewards[place]; entry.EnteredHorse.BasicStats.Experience += expReward; entry.EnteredUser.Experience += expReward; if (place == 0) // WINNER! { int prize = EntryCost * Entries.Length; entry.EnteredUser.AddMoney(prize); byte[] youWinMessage = PacketBuilder.CreateChat(Messages.FormatArenaYouWinMessage(prize, expReward), PacketBuilder.CHAT_BOTTOM_RIGHT); entry.EnteredUser.LoggedinClient.SendPacket(youWinMessage); // Awards: if (Entries.Length >= 2 && Type == "JUMPING") entry.EnteredUser.Awards.AddAward(Award.GetAwardById(5)); // Good Jumper if (Entries.Length >= 4 && Type == "JUMPING") entry.EnteredUser.Awards.AddAward(Award.GetAwardById(6)); // Great Jumper if (Entries.Length >= 2 && Type == "RACING") entry.EnteredUser.Awards.AddAward(Award.GetAwardById(7)); // Good Racer if (Entries.Length >= 4 && Type == "RACING") entry.EnteredUser.Awards.AddAward(Award.GetAwardById(8)); // Great Racer if (Entries.Length >= 2 && Type == "DRESSAGE") entry.EnteredUser.Awards.AddAward(Award.GetAwardById(9)); // Good Dressage if (Entries.Length >= 4 && Type == "DRESSAGE") entry.EnteredUser.Awards.AddAward(Award.GetAwardById(10)); // Great Dressage if (Entries.Length >= 2 && Type == "DRAFT") entry.EnteredUser.Awards.AddAward(Award.GetAwardById(38)); // Strong Horse Award if (Entries.Length >= 4 && Type == "DRAFT") entry.EnteredUser.Awards.AddAward(Award.GetAwardById(39)); // Strongest Horse Award } else { entry.EnteredUser.TrackedItems.GetTrackedItem(Tracking.TrackableItem.ArenaLoss).Count++; if(entry.EnteredUser.TrackedItems.GetTrackedItem(Tracking.TrackableItem.ArenaLoss).Count >= 100) entry.EnteredUser.Awards.AddAward(Award.GetAwardById(32)); // Perseverance byte[] youDONTWinMessage = PacketBuilder.CreateChat(Messages.FormatArenaOnlyWinnerWinsMessage(expReward), PacketBuilder.CHAT_BOTTOM_RIGHT); entry.EnteredUser.LoggedinClient.SendPacket(youDONTWinMessage); } place++; } catch(Exception) { continue; } } } reset(); updateWaitingPlayers(); } public void DeleteEntry(User user) { if (Mode == "COMPETING") return; foreach(ArenaEntry entry in Entries) if(entry.EnteredUser.Id == user.Id) { entries.Remove(entry); break; } } public void AddEntry(User user, HorseInstance horse) { if (Entries.Length + 1 > Slots) { if (Entries.Length + 1 > Slots) { byte[] enterFailed = PacketBuilder.CreateChat(Messages.ArenaFullErrorMessage, PacketBuilder.CHAT_BOTTOM_RIGHT); user.LoggedinClient.SendPacket(enterFailed); GameServer.UpdateArea(user.LoggedinClient); return; } } if(!UserHasHorseEntered(user)) { ArenaEntry arenaEntry = new ArenaEntry(); arenaEntry.EnteredUser = user; arenaEntry.EnteredHorse = horse; entries.Add(arenaEntry); } user.TakeMoney(EntryCost); byte[] enteredIntoCompetition = PacketBuilder.CreateChat(Messages.ArenaEnteredInto, PacketBuilder.CHAT_BOTTOM_RIGHT); user.LoggedinClient.SendPacket(enteredIntoCompetition); GameServer.UpdateAreaForAll(user.X, user.Y, true); return; } public static Arena GetArenaUserEnteredIn(User user) { foreach (Arena arena in Arenas) if (arena.UserHasHorseEntered(user)) return arena; throw new KeyNotFoundException("user was not entered in any arena."); } public bool UserHasHorseEntered(User user) { foreach (ArenaEntry entry in Entries.ToArray()) if (entry.EnteredUser.Id == user.Id) return true; return false; } public static void StartArenas(int Minutes) { foreach(Arena arena in Arenas) { if ((Minutes % arena.RaceEvery) == 1) { if (arena.Mode == "TAKINGENTRIES") { arena.Start(); } } } } public static bool UserHasEnteredHorseInAnyArena(User user) { foreach (Arena arena in Arenas) if (arena.UserHasHorseEntered(user)) return true; return false; } public static Arena GetAreaById(int id) { foreach (Arena arena in Arenas) if (arena.Id == id) return arena; throw new KeyNotFoundException("Arena with id " + id + " NOT FOUND!"); } } }