diff --git a/DataCollection/gamedata.json b/DataCollection/gamedata.json index 4e258fb..c9c1de2 100755 --- a/DataCollection/gamedata.json +++ b/DataCollection/gamedata.json @@ -194,9 +194,10 @@ "venus_flytrap_format":"The Giant Venus Flytrap chomped at you!
OUCH!!
It chomped your pocket, taking $%MONEY% with it!!", "password_input":"
^PLReply:|^PS14|ANSWER^R1", "last_poet":"^R1^LLast Player Poet:%USERNAME% ^R1", + "hammock":"You and all of your horses have fully rested.", "horse_games":{ "select_a_horse":"
^LSelect a horse to compete with:^R1", - "horse_entry":"^I252^T7#%PLACING%:%HORSENAME%^BM%SWF%^R1" + "horse_entry":"^I252^T7#%PLACING%: %HORSENAME%^BM%SWF%^R1" }, "mail":{ "mail_received":"A message has been sent to you from another player. It is in your inventory now.", @@ -293,10 +294,16 @@ "fifth_place":"Fifth place:", "sixth_place":"Sixth place:", "enter_into":"You entered your horse in the competition. The event will begin when it is time!", + "already_entered":"You are already entered into an arena event!", + "cant_afford":"You cannot afford to enter the competition.", "your_score":"Your score was %SCORE%! Once the other results are in, the placings will be reported.", - "starting_up":"Starting up your Jumping Competition event!!", + + "jumping_start_up":"Starting up your Jumping Competition event!!", + "draft_start_up":"Starting up your Draft Competition event!!", + "racing_start_up":"Starting up your Racing Competition event!!", + "conformation_start_up":"Starting up your Conformation Competition event!!", "winner":"You were the winner of the competition! You won $%PRIZE%! (+%EXP% Exp)", "only_winner_wins":"(gained +%EXP% Exp) Only first place gets prize money.", @@ -306,6 +313,17 @@ "farrier":"Your poor horse needs a farrier!", "too_tired":"Your poor horse is too tired to compete!", "needs_vet":"Your poor horse needs a vet!", + + + "event_name":"EVENT: %EVENTNAME%", + "currently_taking_entries":"
Currently taking entries for the competition.
For the next competition at: %HOUR%:%MINUTE%%AMORPM% (%TIMEUNTIL% min)
", + "competition_in_progress":"
Competition in progress! Please wait until all competitors are finished.", + "horse_entered":"
You have a horse entered. Good Luck!", + "competiton_full":"
All Competition slots are full for this race, try back when finished!", + + "enter_horse":"^T6Enter your horse %HORSENAME% for $%ENTRYCOST%^B3A%HORSERANDOMID%^R1", + "current_competitors":"^R0^LThe current competitors:^R1", + "competing_horses":"^T6 Player %USERNAME% Riding %HORSENAME%^B3L%HORSERANDOMID%^R1" }, "ranch":{ "unowned_ranch":"This is an unowned ranch.
It is available for purchase for $%PRICE%
", @@ -550100,5 +550118,18 @@ {"trainer_id":8,"improves_stat":"conformation","improves_amount":10,"thirst_cost":5,"mood_cost":80,"hunger_cost":5,"money_cost":750,"experience":10}, {"trainer_id":9,"improves_stat":"agility","improves_amount":10,"thirst_cost":50,"mood_cost":20,"hunger_cost":50,"money_cost":750,"experience":10}, {"trainer_id":10,"improves_stat":"endurance","improves_amount":10,"thirst_cost":80,"mood_cost":20,"hunger_cost":80,"money_cost":750,"experience":5} - ] + ], + "arena":[ + {"arena_id":1,"arena_type":"JUMPING","entry_cost":1000,"race_every":60,"slots":6,"timeout":2}, + {"arena_id":2,"arena_type":"RACING","entry_cost":1000,"race_every":60,"slots":6,"timeout":2}, + {"arena_id":3,"arena_type":"CONFORMATION","entry_cost":1000,"race_every":60,"slots":5,"timeout":2}, + {"arena_id":4,"arena_type":"DRAFT","entry_cost":1000,"race_every":60,"slots":6,"timeout":2}, + {"arena_id":5,"arena_type":"BEGINNERJUMPING","entry_cost":500,"race_every":60,"slots":6,"timeout":2}, + {"arena_id":6,"arena_type":"JUMPING","entry_cost":10000,"race_every":60,"slots":6,"timeout":2}, + {"arena_id":7,"arena_type":"RACING","entry_cost":10000,"race_every":60,"slots":6,"timeout":2}, + {"arena_id":8,"arena_type":"CONFORMATION","entry_cost":10000,"race_every":60,"slots":5,"timeout":2}, + {"arena_id":9,"arena_type":"DRAFT","entry_cost":10000,"race_every":60,"slots":6,"timeout":2}, + {"arena_id":10,"arena_type":"BEGINNERJUMPING","entry_cost":500,"race_every":60,"slots":6,"timeout":2}, + {"arena_id":11,"arena_type":"BEGINNERJUMPING","entry_cost":500,"race_every":60,"slots":6,"timeout":2} + ] } diff --git a/Horse Isle Server/HorseIsleServer/Game/Arena.cs b/Horse Isle Server/HorseIsleServer/Game/Arena.cs new file mode 100644 index 0000000..4cab3a7 --- /dev/null +++ b/Horse Isle Server/HorseIsleServer/Game/Arena.cs @@ -0,0 +1,351 @@ +using HISP.Game.Horse; +using HISP.Player; +using HISP.Security; +using HISP.Server; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace HISP.Game +{ + public class Arena + { + public class ArenaEntry + { + public User EnteredUser; + public HorseInstance EnteredHorse; + public int SubmitScore = 0; + public bool Done = false; + } + public static List Arenas = new List(); + 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 List(); + } + 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 List Entries; + private Timer arenaTimeout; + + public bool HaveAllPlayersCompleted() + { + int playersCompleted = 0; + foreach(ArenaEntry entry in Entries.ToArray()) + { + if (entry.Done) + playersCompleted++; + } + if (playersCompleted >= Entries.Count) + 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); + int pos = GetUserPos(entry.EnteredUser); + string swf = "dressagearena.swf?BASESCORE=" + baseScore; + int i = 1; + foreach (ArenaEntry ent in Entries.ToArray()) + swf += "&HN" + i.ToString() + "=" + ent.EnteredUser.Username; + swf += "&POS="+pos+"&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))); + pos = GetUserPos(entry.EnteredUser); + swf = "draftarena.swf?DRAFTABILITY=" + draftAbility; + i = 1; + foreach (ArenaEntry ent in Entries.ToArray()) + swf += "&HN" + i.ToString() + "=" + ent.EnteredUser.Username; + swf += "&POS="+pos+"&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)); + pos = GetUserPos(entry.EnteredUser); + swf = "racingarena.swf?BASESPEED=" + baseSpeed + "&ENDURANCE=" + enduranceCalculator.Total; + i = 1; + foreach (ArenaEntry ent in Entries.ToArray()) + swf += "&HN" + i.ToString() + "=" + ent.EnteredUser.Username; + swf += "&POS=" + pos + "&JUNK="; + return swf; + default: + return "test.swf"; + } + + } + public int GetUserPos(User user) + { + int pos = 0; + foreach (ArenaEntry entry in Entries.ToArray()) + { + pos++; + if (entry.EnteredUser.Id != user.Id) + break; + } + + + return pos; + } + public void Start() + { + if(Entries.Count <= 0) + { + reset(); + return; + } + Mode = "COMPETING"; + 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 "DRESSAGE": + entry.EnteredHorse.BasicStats.Mood -= 300; + entry.EnteredHorse.BasicStats.Tiredness -= 200; + message = Messages.ArenaConformationStartup; + break; + } + byte[] startingUpEventPacket = PacketBuilder.CreateChat(message, PacketBuilder.CHAT_BOTTOM_RIGHT); + byte[] swfModulePacket = PacketBuilder.CreateSwfModulePacket(swf, PacketBuilder.PACKET_SWF_CUTSCENE); + entry.EnteredUser.LoggedinClient.SendPacket(swfModulePacket); + entry.EnteredUser.LoggedinClient.SendPacket(startingUpEventPacket); + } + + arenaTimeout = new Timer(new TimerCallback(ArenaTimedOut), null, Timeout * 60 * 1000, Timeout * 60 * 1000); + + 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[] expRewards = new int[Entries.Count]; + expRewards[0] = 1; + int expAwardMul = 1; + for(int i = 1; i < Entries.Count; i++) + { + expRewards[i] = 2 * expAwardMul; + + if (expAwardMul == 1) + expAwardMul = 2; + else + expAwardMul += 2; + } + + expRewards = expRewards.ToArray().Reverse().ToArray(); + + int place = 0; + ArenaEntry[] winners = Entries.OrderByDescending(o => o.SubmitScore).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.Count; + entry.EnteredUser.Money += prize; + + byte[] youWinMessage = PacketBuilder.CreateChat(Messages.FormatArenaYouWinMessage(prize, expReward), PacketBuilder.CHAT_BOTTOM_RIGHT); + entry.EnteredUser.LoggedinClient.SendPacket(youWinMessage); + } + else + { + byte[] youDONTWinMessage = PacketBuilder.CreateChat(Messages.FormatArenaOnlyWinnerWinsMessage(expReward), PacketBuilder.CHAT_BOTTOM_RIGHT); + entry.EnteredUser.LoggedinClient.SendPacket(youDONTWinMessage); + } + place++; + } + catch(Exception) + { + continue; + } + + } + + } + reset(); + } + 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, Horse.HorseInstance horse) + { + ArenaEntry arenaEntry = new ArenaEntry(); + arenaEntry.EnteredUser = user; + arenaEntry.EnteredHorse = horse; + Entries.Add(arenaEntry); + } + + 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 == 0) + 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!"); + } + } +} diff --git a/Horse Isle Server/HorseIsleServer/Game/Horse/HorseInfo.cs b/Horse Isle Server/HorseIsleServer/Game/Horse/HorseInfo.cs index 978b7f3..1879d2e 100755 --- a/Horse Isle Server/HorseIsleServer/Game/Horse/HorseInfo.cs +++ b/Horse Isle Server/HorseIsleServer/Game/Horse/HorseInfo.cs @@ -3,6 +3,7 @@ using HISP.Game.Items; using System.Collections.Generic; using System.Globalization; +using HISP.Player; namespace HISP.Game.Horse { @@ -20,14 +21,15 @@ namespace HISP.Game.Horse } public class StatCalculator { - public StatCalculator(HorseInstance horse, StatType type) + public StatCalculator(HorseInstance horse, StatType type, User user=null) { baseHorse = horse; horseStat = type; + baseUser = user; } private StatType horseStat; private HorseInstance baseHorse; - + private User baseUser; public int BaseValue { get @@ -119,6 +121,31 @@ namespace HISP.Game.Horse } } } + public int CompetitionGearOffset + { + get + { + if(baseUser != null) + { + int offsetBy = 0; + if(baseUser.EquipedCompetitionGear.Head != null) + offsetBy += getOffsetFrom(baseUser.EquipedCompetitionGear.Head); + if (baseUser.EquipedCompetitionGear.Body != null) + offsetBy += getOffsetFrom(baseUser.EquipedCompetitionGear.Body); + if (baseUser.EquipedCompetitionGear.Legs != null) + offsetBy += getOffsetFrom(baseUser.EquipedCompetitionGear.Legs); + if (baseUser.EquipedCompetitionGear.Feet != null) + offsetBy += getOffsetFrom(baseUser.EquipedCompetitionGear.Feet); + return offsetBy; + } + else + { + return 0; + } + + } + } + public int CompanionOffset { get @@ -149,7 +176,7 @@ namespace HISP.Game.Horse { get { - return BreedValue + CompanionOffset + TackOffset; + return BreedValue + CompanionOffset + TackOffset + CompetitionGearOffset; } } @@ -414,10 +441,13 @@ namespace HISP.Game.Horse } set { + // Lol turns out pinto forgot to do this and u can have negative mood :D + /* if (value > 1000) value = 1000; if (value < 0) value = 0; + */ mood = value; Database.SetHorseMood(baseHorse.RandomId, value); } diff --git a/Horse Isle Server/HorseIsleServer/Game/Messages.cs b/Horse Isle Server/HorseIsleServer/Game/Messages.cs index 4beb118..b8a104e 100755 --- a/Horse Isle Server/HorseIsleServer/Game/Messages.cs +++ b/Horse Isle Server/HorseIsleServer/Game/Messages.cs @@ -16,10 +16,57 @@ namespace HISP.Game // Click public static string PlayerHereFormat; + // Hammock + public static string HammockText; + // Horse Games public static string HorseGamesSelectHorse; public static string HorseGamesHorseEntryFormat; + // Competitions + public static string ArenaResultsMessage; + public static string ArenaPlacingFormat; + + public static string ArenaFirstPlace; + public static string ArenaSecondPlace; + public static string ArenaThirdPlace; + public static string ArenaFourthPlace; + public static string ArenaFifthPlace; + public static string ArenaSixthPlace; + + public static string ArenaEnteredInto; + + public static string ArenaAlreadyEntered; + public static string ArenaCantAfford; + + public static string ArenaYourScoreFormat; + + public static string ArenaJumpingStartup; + public static string ArenaDraftStartup; + public static string ArenaRacingStartup; + public static string ArenaConformationStartup; + + public static string ArenaYouWinFormat; + public static string ArenaOnlyWinnerWins; + + public static string ArenaTooHungry; + public static string ArenaTooThirsty; + public static string ArenaNeedsFarrier; + public static string ArenaTooTired; + public static string ArenaNeedsVet; + + public static string ArenaEventNameFormat; + + public static string ArenaCurrentlyTakingEntriesFormat; + public static string ArenaCompetitionInProgress; + public static string ArenaYouHaveHorseEntered; + public static string ArenaCompetitionFull; + + public static string ArenaEnterHorseFormat; + public static string ArenaCurrentCompetitors; + public static string ArenaCompetingHorseFormat; + + // City Hall public static string CityHallMenu; public static string CityHallMailSendMeta; @@ -795,6 +842,38 @@ namespace HISP.Game // Click public static string NothingInterestingHere; + public static string FormatArenaCompetingHorseEntry(string userName, string horseName, int horseRandomId) + { + return ArenaCompetingHorseFormat.Replace("%USERNAME%", userName).Replace("%HORSENAME%", horseName).Replace("%HORSERANDOMID%", horseRandomId.ToString()); + } + public static string FormatArenaEnterHorseButton(string horseName, int entryCost, int horseRandomId) + { + return ArenaEnterHorseFormat.Replace("%HORSENAME%", horseName).Replace("%ENTRYCOST%", entryCost.ToString("N0", CultureInfo.InvariantCulture)).Replace("%HORSERANDOMID%", horseRandomId.ToString()); + } + public static string FormatArenaCurrentlyTakingEntries(int hour, int minute, string amOrPm, int timeUntil) + { + return ArenaCurrentlyTakingEntriesFormat.Replace("%HOUR%", hour.ToString()).Replace("%MINUTE%", minute.ToString("00")).Replace("%AMORPM%", amOrPm).Replace("%TIMEUNTIL%", timeUntil.ToString()); + } + public static string FormatArenaEventName(string eventName) + { + return ArenaEventNameFormat.Replace("%EVENTNAME%", eventName); + } + public static string FormatArenaOnlyWinnerWinsMessage(int experience) + { + return ArenaOnlyWinnerWins.Replace("%EXP%", experience.ToString("N0", CultureInfo.InvariantCulture)); + } + public static string FormatArenaYouWinMessage(int prizeMoney, int experience) + { + return ArenaYouWinFormat.Replace("%PRIZE%", prizeMoney.ToString("N0", CultureInfo.InvariantCulture)).Replace("%EXP%", experience.ToString("N0", CultureInfo.InvariantCulture)); + } + public static string FormatArenaYourScore(int score) + { + return ArenaYourScoreFormat.Replace("%SCORE%", score.ToString("N0", CultureInfo.InvariantCulture)); + } + public static string FormatArenaPlacing(string place, string playerName, int score) + { + return ArenaPlacingFormat.Replace("%PLACE%", place).Replace("%USERNAME%", playerName).Replace("%SCORE%", score.ToString("N0", CultureInfo.InvariantCulture)); + } public static string FormatHorseGamesEntry(int placing, string horseName, string Swf) { diff --git a/Horse Isle Server/HorseIsleServer/Game/Meta.cs b/Horse Isle Server/HorseIsleServer/Game/Meta.cs index 8fcadad..f099fc1 100755 --- a/Horse Isle Server/HorseIsleServer/Game/Meta.cs +++ b/Horse Isle Server/HorseIsleServer/Game/Meta.cs @@ -1239,7 +1239,7 @@ namespace HISP.Game string message = Messages.CityHallTop25Ranches; int total = 1; - foreach(Ranch ranch in Ranch.Ranches.OrderBy(o => o.InvestedMoney).Reverse().ToList()) + foreach(Ranch ranch in Ranch.Ranches.OrderByDescending(o => o.InvestedMoney).ToList()) { if (ranch.OwnerId == -1) continue; @@ -1264,13 +1264,15 @@ namespace HISP.Game HorseInstance[] horses = Database.GetCheapestHorseAutoSell(); foreach(HorseInstance horse in horses) { - message += Messages.FormatCityHallCheapAutoSellEntry(horse.AutoSell, Database.GetUsername(horse.Owner), horse.Name, horse.Color, horse.Breed.Name, horse.BasicStats.Experience); + if(horse.AutoSell > 0) + message += Messages.FormatCityHallCheapAutoSellEntry(horse.AutoSell, Database.GetUsername(horse.Owner), horse.Name, horse.Color, horse.Breed.Name, horse.BasicStats.Experience); } message += Messages.CityHallMostExpAutoSells; horses = Database.GetBiggestExpAutoSell(); foreach (HorseInstance horse in horses) { - message += Messages.FormatCityHallBestExpAutoSellEntry(horse.BasicStats.Experience, Database.GetUsername(horse.Owner), horse.Name, horse.AutoSell, horse.Color, horse.Breed.Name); + if(horse.AutoSell > 0) + message += Messages.FormatCityHallBestExpAutoSellEntry(horse.BasicStats.Experience, Database.GetUsername(horse.Owner), horse.Name, horse.AutoSell, horse.Color, horse.Breed.Name); } message += Messages.BackToMap; message += Messages.MetaTerminator; @@ -2230,6 +2232,62 @@ namespace HISP.Game message += Messages.MetaTerminator; return message; } + private static string buildArena(User user, Arena arena) + { + string message = Messages.FormatArenaEventName(arena.Type); + if(arena.Mode == "TAKINGENTRIES") + { + int minutes = World.ServerTime.Minutes % 60; + + int lastMinutes = minutes - (minutes % arena.RaceEvery); + int lastHours = (lastMinutes / 60); + + string amOrPm = "am"; + if (lastHours == 0) + { + amOrPm = "am"; + lastHours = 12; + } + if (lastHours > 12) + { + lastHours -= 12; + amOrPm = "pm"; + } + + message += Messages.FormatArenaCurrentlyTakingEntries(lastHours, lastMinutes, amOrPm, arena.RaceEvery - minutes); + if (arena.Entries.Count > arena.Slots) + { + message += Messages.ArenaCompetitionFull; + } + else if (!arena.UserHasHorseEntered(user)) + { + + foreach(HorseInstance horseInstance in user.HorseInventory.HorseList) + { + if(horseInstance.Equipment.Saddle != null && horseInstance.Equipment.SaddlePad != null && horseInstance.Equipment.Bridle != null) + message += Messages.FormatArenaEnterHorseButton(horseInstance.Name, arena.EntryCost, horseInstance.RandomId); + } + } + else + { + message += Messages.ArenaYouHaveHorseEntered; + } + + } + else if(arena.Mode == "COMPETING") + { + message += Messages.ArenaCompetitionInProgress; + } + + message += Messages.ArenaCurrentCompetitors; + foreach(Arena.ArenaEntry entries in arena.Entries) + { + message += Messages.FormatArenaCompetingHorseEntry(entries.EnteredUser.Username, entries.EnteredHorse.Name, entries.EnteredHorse.RandomId); + } + message += Messages.ExitThisPlace; + message += Messages.MetaTerminator; + return message; + } public static string BuildSpecialTileInfo(User user, World.SpecialTile specialTile) { string message = ""; @@ -2328,6 +2386,10 @@ namespace HISP.Game { message += buildRiddlerRiddle(user); } + if(TileCode == "ARENA") + { + message += buildArena(user, Arena.GetAreaById(int.Parse(TileArg))); + } if(TileCode == "TRAINER") { message += buildTrainer(user, Trainer.GetTrainerById(int.Parse(TileArg))); diff --git a/Horse Isle Server/HorseIsleServer/Game/World.cs b/Horse Isle Server/HorseIsleServer/Game/World.cs index 7aa5cd5..9eeb733 100755 --- a/Horse Isle Server/HorseIsleServer/Game/World.cs +++ b/Horse Isle Server/HorseIsleServer/Game/World.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using HISP.Player; using HISP.Server; @@ -155,9 +156,16 @@ namespace HISP.Game } - public struct Time + public class Time { - public int Minutes; + public double PreciseMinutes; + public int Minutes + { + get + { + return Convert.ToInt32(Math.Floor(PreciseMinutes)); + } + } public int Days; public int Years; } @@ -189,42 +197,18 @@ namespace HISP.Game public static void TickWorldClock() { - ServerTime.Minutes += 1; - - int hours = ServerTime.Minutes / 60; - - // Periodically write time to database: - if (ServerTime.Minutes % 10 == 0) // every 10-in-game minutes) - Database.SetServerTime(ServerTime.Minutes, ServerTime.Days, ServerTime.Years); - - // Ranch Windmill Payments - if(ServerTime.Minutes % 720 == 0) // every 12 hours - { - Logger.DebugPrint("Paying windmill owners . . . "); - foreach (Ranch ranch in Ranch.Ranches) - { - int ranchOwner = ranch.OwnerId; - if (ranchOwner != -1) - { - int moneyToAdd = 5000 * ranch.GetBuildingCount(8); // Windmill - if (GameServer.IsUserOnline(ranchOwner)) - GameServer.GetUserById(ranchOwner).Money += moneyToAdd; - else - Database.SetPlayerMoney(Database.GetPlayerMoney(ranchOwner) + moneyToAdd, ranchOwner); - } - } - } + ServerTime.PreciseMinutes += 0.1; - if (hours == 24) // 1 day + if (ServerTime.Minutes > 1440) // 1 day { ServerTime.Days += 1; - ServerTime.Minutes = 0; + ServerTime.PreciseMinutes = 0.0; Database.DoIntrestPayments(ConfigReader.IntrestRate); } - if (ServerTime.Days == 366) // 1 year! + if (ServerTime.Days > 365) // 1 year! { ServerTime.Days = 0; ServerTime.Years += 1; @@ -234,7 +218,7 @@ namespace HISP.Game public static void ReadWorldData() { Logger.DebugPrint("Reading time from database..."); - ServerTime.Minutes = Database.GetServerTime(); + ServerTime.PreciseMinutes = Database.GetServerTime(); ServerTime.Days = Database.GetServerDay(); ServerTime.Years = Database.GetServerYear(); Logger.InfoPrint("It is " + ServerTime.Minutes / 60 + ":" + ServerTime.Minutes % 60 + " on Day " + ServerTime.Days + " in Year " + ServerTime.Years + "!!!"); diff --git a/Horse Isle Server/HorseIsleServer/Server/GameClient.cs b/Horse Isle Server/HorseIsleServer/Server/GameClient.cs index 06664d2..a5934eb 100755 --- a/Horse Isle Server/HorseIsleServer/Server/GameClient.cs +++ b/Horse Isle Server/HorseIsleServer/Server/GameClient.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Net.Sockets; -using System.Net; using System.Text; using System.Threading; using HISP.Player; @@ -20,7 +19,6 @@ namespace HISP.Server private Thread recvPackets; - private Timer updateTimer; private Timer inactivityTimer; private Timer warnTimer; @@ -29,7 +27,6 @@ namespace HISP.Server private bool isDisconnecting = false; private int keepAliveInterval = 60 * 1000; - private int updateInterval = 60 * 1000; private int totalMinutesElapsed = 0; private int oneMinute = 60 * 1000; @@ -57,24 +54,19 @@ namespace HISP.Server } - // unsure of actural timings, would be more or less impossible to know - // without the original source code :( - // From testing hunger seemed to go down fastest, then thirst, and finally tiredness. - - foreach(HorseInstance horse in LoggedinUser.HorseInventory.HorseList) { if (totalMinutesElapsed % 2 == 0) { horse.BasicStats.Thirst--; horse.BasicStats.Hunger--; + + if (horse.BasicStats.Thirst <= 0) + horse.BasicStats.Health -= 5; } - if (totalMinutesElapsed % 2 == 0 && (horse.BasicStats.Thirst <= 100 || horse.BasicStats.Thirst <= 100 || horse.BasicStats.Tiredness <= 100)) - horse.BasicStats.Health--; if (totalMinutesElapsed % 60 == 0) { - horse.BasicStats.Mood--; horse.BasicStats.Shoes--; horse.BasicStats.Tiredness--; } @@ -83,11 +75,12 @@ namespace HISP.Server } - if (totalMinutesElapsed % 1 == 0) + if (totalMinutesElapsed % 2 == 0) + { LoggedinUser.Thirst--; - - if (totalMinutesElapsed % 5 == 0) LoggedinUser.Hunger--; + } + if (totalMinutesElapsed % 10 == 0) LoggedinUser.Tiredness--; @@ -120,11 +113,7 @@ namespace HISP.Server { Kick(Messages.FormatIdleKickMessage()); } - private void updateTimerTick(object state) - { - GameServer.UpdateWorld(this); - GameServer.UpdatePlayer(this); - } + public void Login(int id) { // Check for duplicate @@ -141,7 +130,6 @@ namespace HISP.Server Database.SetIpAddress(id, RemoteIp); - updateTimer = new Timer(new TimerCallback(updateTimerTick), null, updateInterval, updateInterval); inactivityTimer = new Timer(new TimerCallback(keepAliveTimerTick), null, keepAliveInterval, keepAliveInterval); } private bool receivePackets() @@ -193,8 +181,6 @@ namespace HISP.Server // Stop Timers - if (updateTimer != null) - updateTimer.Dispose(); if(inactivityTimer != null) inactivityTimer.Dispose(); if(warnTimer != null) @@ -290,6 +276,9 @@ namespace HISP.Server case PacketBuilder.PACKET_ITEM_INTERACTION: GameServer.OnItemInteraction(this,Packet); break; + case PacketBuilder.PACKET_ARENA_SCORE: + GameServer.OnArenaScored(this, Packet); + break; case PacketBuilder.PACKET_QUIT: GameServer.OnQuitPacket(this, Packet); break; diff --git a/Horse Isle Server/HorseIsleServer/Server/GameDataJson.cs b/Horse Isle Server/HorseIsleServer/Server/GameDataJson.cs index 192d2e4..61a4b8f 100755 --- a/Horse Isle Server/HorseIsleServer/Server/GameDataJson.cs +++ b/Horse Isle Server/HorseIsleServer/Server/GameDataJson.cs @@ -723,6 +723,19 @@ namespace HISP.Server Trainer.Trainers.Add(trainer); Logger.DebugPrint("Registered Training Pen: " + trainer.Id + " for " + trainer.ImprovesStat); } + int totalArenas = gameData.arena.Count; + for(int i = 0; i < totalArenas; i++) + { + int arenaId = gameData.arena[i].arena_id; + string arenaType = gameData.arena[i].arena_type; + int arenaEntryCost = gameData.arena[i].entry_cost; + int raceEvery = gameData.arena[i].race_every; + int slots = gameData.arena[i].slots; + int timeout = gameData.arena[i].timeout; + + Arena arena = new Arena(arenaId, arenaType, arenaEntryCost, raceEvery, slots, timeout); + Logger.DebugPrint("Registered Arena: " + arena.Id.ToString()+" as " + arena.Type); + } HorseInfo.HorseNames = gameData.horses.names.ToObject(); @@ -746,6 +759,50 @@ namespace HISP.Server Map.ModIsleX = gameData.messages.commands.mod_isle.x; Map.ModIsleY = gameData.messages.commands.mod_isle.y; + // Hammock Text + Messages.HammockText = gameData.messages.meta.hammock; + + // Competitions + Messages.ArenaResultsMessage = gameData.messages.meta.arena.results; + Messages.ArenaPlacingFormat = gameData.messages.meta.arena.placing; + Messages.ArenaAlreadyEntered = gameData.messages.meta.arena.already_entered; + + Messages.ArenaFirstPlace = gameData.messages.meta.arena.first_place; + Messages.ArenaSecondPlace = gameData.messages.meta.arena.second_place; + Messages.ArenaThirdPlace = gameData.messages.meta.arena.thirst_place; + Messages.ArenaFourthPlace = gameData.messages.meta.arena.fourth_place; + Messages.ArenaFifthPlace = gameData.messages.meta.arena.fifth_place; + Messages.ArenaSixthPlace = gameData.messages.meta.arena.sixth_place; + + Messages.ArenaEnteredInto = gameData.messages.meta.arena.enter_into; + Messages.ArenaCantAfford = gameData.messages.meta.arena.cant_afford; + + Messages.ArenaYourScoreFormat = gameData.messages.meta.arena.your_score; + + Messages.ArenaJumpingStartup = gameData.messages.meta.arena.jumping_start_up; + Messages.ArenaDraftStartup = gameData.messages.meta.arena.draft_start_up; + Messages.ArenaRacingStartup = gameData.messages.meta.arena.racing_start_up; + Messages.ArenaConformationStartup = gameData.messages.meta.arena.conformation_start_up; + + Messages.ArenaYouWinFormat = gameData.messages.meta.arena.winner; + Messages.ArenaOnlyWinnerWins = gameData.messages.meta.arena.only_winner_wins; + + Messages.ArenaTooHungry = gameData.messages.meta.arena.too_hungry; + Messages.ArenaTooThirsty = gameData.messages.meta.arena.too_thisty; + Messages.ArenaNeedsFarrier = gameData.messages.meta.arena.farrier; + Messages.ArenaTooTired = gameData.messages.meta.arena.too_tired; + Messages.ArenaNeedsVet = gameData.messages.meta.arena.needs_vet; + + Messages.ArenaEventNameFormat = gameData.messages.meta.arena.event_name; + Messages.ArenaCurrentlyTakingEntriesFormat = gameData.messages.meta.arena.currently_taking_entries; + Messages.ArenaCompetitionInProgress = gameData.messages.meta.arena.competition_in_progress; + Messages.ArenaYouHaveHorseEntered = gameData.messages.meta.arena.horse_entered; + Messages.ArenaCompetitionFull = gameData.messages.meta.arena.competiton_full; + + Messages.ArenaEnterHorseFormat = gameData.messages.meta.arena.enter_horse; + Messages.ArenaCurrentCompetitors = gameData.messages.meta.arena.current_competitors; + Messages.ArenaCompetingHorseFormat = gameData.messages.meta.arena.competing_horses; + // Horse Games Messages.HorseGamesSelectHorse = gameData.messages.meta.horse_games.select_a_horse; Messages.HorseGamesHorseEntryFormat = gameData.messages.meta.horse_games.horse_entry; diff --git a/Horse Isle Server/HorseIsleServer/Server/GameServer.cs b/Horse Isle Server/HorseIsleServer/Server/GameServer.cs index eb54fd3..5cb1e65 100755 --- a/Horse Isle Server/HorseIsleServer/Server/GameServer.cs +++ b/Horse Isle Server/HorseIsleServer/Server/GameServer.cs @@ -40,17 +40,46 @@ namespace HISP.Server /* * Private stuff */ - private static int gameTickSpeed = 4320; // Changing this to ANYTHING else will cause desync with the client. + private static int gameTickSpeed = 480; // Changing this to ANYTHING else will cause desync with the client. private static int totalMinutesElapsed = 0; private static int oneMinute = 1000 * 60; private static List connectedClients = new List(); private static Timer gameTimer; // Controls in-game time. private static Timer minuteTimer; // ticks every real world minute. + private static int lastServerTime = 0; private static void onGameTick(object state) { World.TickWorldClock(); - Database.DecHorseTrainTimeout(); - gameTimer.Change(gameTickSpeed, gameTickSpeed); + if(World.ServerTime.Minutes != lastServerTime) + { + Arena.StartArenas(World.ServerTime.Minutes); + + Database.DecHorseTrainTimeout(); + + // write time to database: + Database.SetServerTime(World.ServerTime.Minutes, World.ServerTime.Days, World.ServerTime.Years); + + // Ranch Windmill Payments + if (World.ServerTime.Minutes % 720 == 0) // every 12 hours + { + Logger.DebugPrint("Paying windmill owners . . . "); + foreach (Ranch ranch in Ranch.Ranches) + { + int ranchOwner = ranch.OwnerId; + if (ranchOwner != -1) + { + int moneyToAdd = 5000 * ranch.GetBuildingCount(8); // Windmill + if (GameServer.IsUserOnline(ranchOwner)) + GameServer.GetUserById(ranchOwner).Money += moneyToAdd; + else + Database.SetPlayerMoney(Database.GetPlayerMoney(ranchOwner) + moneyToAdd, ranchOwner); + } + } + } + gameTimer.Change(gameTickSpeed, gameTickSpeed); + lastServerTime = World.ServerTime.Minutes; + } + } private static void onMinuteTick(object state) { @@ -89,15 +118,20 @@ namespace HISP.Server Update(client); byte[] BaseStatsPacketData = PacketBuilder.CreatePlayerData(client.LoggedinUser.Money, GameServer.GetNumberOfPlayers(), client.LoggedinUser.MailBox.UnreadMailCount); client.SendPacket(BaseStatsPacketData); + + UpdateWorld(client); + UpdatePlayer(client); } Database.IncPlayerTirednessForOfflineUsers(); + if(totalMinutesElapsed % 60 == 0) { foreach (HorseInstance horse in Database.GetMostSpoiledHorses()) { - horse.BasicStats.Tiredness = 1000; + horse.BasicStats.Health = 1000; + horse.BasicStats.Mood = 1000; horse.BasicStats.Hunger = 1000; horse.BasicStats.Thirst = 1000; } @@ -756,7 +790,7 @@ namespace HISP.Server break; } trainHorseInst.BasicStats.Experience += trainer.ExperienceGained; - trainHorseInst.TrainTimer = trainer.ImprovesAmount + trainer.ExperienceGained * 50; + trainHorseInst.TrainTimer = 1440; byte[] trainSuccessfulMessage = PacketBuilder.CreateChat(Messages.FormatTrainedInStatFormat(trainHorseInst.Name, trainer.ImprovesStat), PacketBuilder.CHAT_BOTTOM_RIGHT); sender.SendPacket(trainSuccessfulMessage); @@ -893,6 +927,95 @@ namespace HISP.Server Logger.HackerPrint(sender.LoggedinUser.Username + " Tried to feed a non existant item to a horse."); break; } + case PacketBuilder.HORSE_ENTER_ARENA: + randomId = 0; + packetStr = Encoding.UTF8.GetString(packet); + randomIdStr = packetStr.Substring(2, packetStr.Length - 4); + try + { + randomId = int.Parse(randomIdStr); + + } + catch (Exception) + { + Logger.ErrorPrint(sender.LoggedinUser.Username + " Sent an invalid randomid to horse interaction packet "); + break; + } + if (sender.LoggedinUser.HorseInventory.HorseIdExist(randomId)) + { + HorseInstance horseInstance = sender.LoggedinUser.HorseInventory.GetHorseById(randomId); + World.SpecialTile tile = World.GetSpecialTile(sender.LoggedinUser.X, sender.LoggedinUser.Y); + if (tile.Code.StartsWith("ARENA-")) + { + string[] arenaInfo = tile.Code.Split('-'); + int arenaId = int.Parse(arenaInfo[1]); + Arena arena = Arena.GetAreaById(arenaId); + if(!Arena.UserHasEnteredHorseInAnyArena(sender.LoggedinUser)) + { + if(horseInstance.BasicStats.Thirst <= 300) + { + byte[] tooThirsty = PacketBuilder.CreateChat(Messages.ArenaTooThirsty, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(tooThirsty); + break; + } + else if (horseInstance.BasicStats.Hunger <= 300) + { + byte[] tooHungry = PacketBuilder.CreateChat(Messages.ArenaTooHungry, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(tooHungry); + break; + } + else if (horseInstance.BasicStats.Shoes <= 300) + { + byte[] needsFarrier = PacketBuilder.CreateChat(Messages.ArenaNeedsFarrier, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(needsFarrier); + break; + } + else if (horseInstance.BasicStats.Tiredness <= 300) + { + byte[] tooTired = PacketBuilder.CreateChat(Messages.ArenaTooTired, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(tooTired); + break; + } + else if (horseInstance.BasicStats.Health <= 300) + { + byte[] needsVet = PacketBuilder.CreateChat(Messages.ArenaNeedsVet, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(needsVet); + break; + } + + + + if (sender.LoggedinUser.Money >= arena.EntryCost) + { + arena.AddEntry(sender.LoggedinUser, horseInstance); + sender.LoggedinUser.Money -= arena.EntryCost; + + byte[] enteredIntoCompetition = PacketBuilder.CreateChat(Messages.ArenaEnteredInto, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(enteredIntoCompetition); + UpdateAreaForAll(sender.LoggedinUser.X, sender.LoggedinUser.Y, true); + break; + } + else + { + byte[] cantAffordEntryFee = PacketBuilder.CreateChat(Messages.ArenaCantAfford, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(cantAffordEntryFee); + break; + } + } + else + { + byte[] allreadyEntered = PacketBuilder.CreateChat(Messages.ArenaAlreadyEntered, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(allreadyEntered); + } + + } + } + else + { + Logger.ErrorPrint(sender.LoggedinUser.Username + " Tried to enter a non existant horse into a competition."); + break; + } + break; case PacketBuilder.HORSE_RELEASE: randomId = 0; packetStr = Encoding.UTF8.GetString(packet); @@ -2336,6 +2459,43 @@ namespace HISP.Server break; } } + public static void OnArenaScored(GameClient sender, byte[] packet) + { + if (!sender.LoggedIn) + { + Logger.ErrorPrint(sender.RemoteIp + " Requested user information when not logged in."); + return; + } + if(packet.Length <= 3) + { + Logger.ErrorPrint(sender.LoggedinUser.Username + "Sent invalid Arena Scored Packet."); + return; + } + string packetStr = Encoding.UTF8.GetString(packet); + string scoreStr = packetStr.Substring(1, packet.Length - 3); + int score = -1; + try + { + score = int.Parse(scoreStr); + } + catch(FormatException) + { + Logger.ErrorPrint(sender.LoggedinUser.Username + " Scored NAN in an arena."); + return; + } + + if(Arena.UserHasEnteredHorseInAnyArena(sender.LoggedinUser)) + { + Arena enteredArena = Arena.GetArenaUserEnteredIn(sender.LoggedinUser); + enteredArena.SubmitScore(sender.LoggedinUser, score); + } + else + { + Logger.ErrorPrint(sender.LoggedinUser.Username + " Scored in an arena while not in one"); + } + return; + + } public static void OnUserInfoRequest(GameClient sender, byte[] packet) { if (!sender.LoggedIn) @@ -2984,16 +3144,33 @@ namespace HISP.Server sender.SendPacket(bestScoreBeaten); sender.LoggedinUser.Money += 2500; } - else if (newHighscore && !time) + else if (newHighscore) { - byte[] chatPacket = PacketBuilder.CreateChat(Messages.FormatHighscoreBeatenMessage(value), PacketBuilder.CHAT_BOTTOM_RIGHT); - sender.SendPacket(chatPacket); - } - else - { - byte[] chatPacket = PacketBuilder.CreateChat(Messages.FormatTimeBeatenMessage(value), PacketBuilder.CHAT_BOTTOM_RIGHT); - sender.SendPacket(chatPacket); + if(time) + { + byte[] chatPacket = PacketBuilder.CreateChat(Messages.FormatTimeBeatenMessage(value), PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(chatPacket); + } + else + { + byte[] chatPacket = PacketBuilder.CreateChat(Messages.FormatHighscoreBeatenMessage(value), PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(chatPacket); + } + } + + if(sender.LoggedinUser.Highscores.HighscoreList.Length >= 30) + sender.LoggedinUser.Awards.AddAward(Award.GetAwardById(12)); // Minigame Player + + if (sender.LoggedinUser.Highscores.HighscoreList.Length >= 60) + sender.LoggedinUser.Awards.AddAward(Award.GetAwardById(13)); // Minigame Master + + if (Database.GetPlayerTotalMinigamesPlayed(sender.LoggedinUser.Id) >= 1000) + sender.LoggedinUser.Awards.AddAward(Award.GetAwardById(14)); // Minigame Nut + + if (Database.GetPlayerTotalMinigamesPlayed(sender.LoggedinUser.Id) >= 10000) + sender.LoggedinUser.Awards.AddAward(Award.GetAwardById(15)); // Minigame Crazy + } else { @@ -5377,12 +5554,19 @@ namespace HISP.Server public static void OnDisconnect(GameClient sender) { - connectedClients.Remove(sender); if (sender.LoggedIn) { Database.SetPlayerLastLogin(Convert.ToInt32(new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds()), sender.LoggedinUser.Id); // Set last login date Database.RemoveOnlineUser(sender.LoggedinUser.Id); + + // Delete Arena Entries + if(Arena.UserHasEnteredHorseInAnyArena(sender.LoggedinUser)) + { + Arena arena = Arena.GetArenaUserEnteredIn(sender.LoggedinUser); + arena.DeleteEntry(sender.LoggedinUser); + } + // Send disconnect message byte[] logoutMessageBytes = PacketBuilder.CreateChat(Messages.FormatLogoutMessage(sender.LoggedinUser.Username), PacketBuilder.CHAT_BOTTOM_LEFT); foreach (GameClient client in ConnectedClients) @@ -5397,6 +5581,7 @@ namespace HISP.Server if (client.LoggedinUser.Id != sender.LoggedinUser.Id) client.SendPacket(playerRemovePacket); } + connectedClients.Remove(sender); } @@ -5404,7 +5589,7 @@ namespace HISP.Server * Get(Some Information) */ - + public static bool IsUserOnline(int id) { try @@ -5950,6 +6135,17 @@ namespace HISP.Server } } } + if(mapCode == "HAMMOCK") + { + byte[] hammockText = PacketBuilder.CreateChat(Messages.HammockText, PacketBuilder.CHAT_BOTTOM_RIGHT); + forClient.SendPacket(hammockText); + + forClient.LoggedinUser.Tiredness = 1000; + foreach(HorseInstance horse in forClient.LoggedinUser.HorseInventory.HorseList) + { + horse.BasicStats.Tiredness = 1000; + } + } return true; } public static void StartServer() diff --git a/Horse Isle Server/HorseIsleServer/Server/PacketBuilder.cs b/Horse Isle Server/HorseIsleServer/Server/PacketBuilder.cs index 95b108c..4ff68b7 100755 --- a/Horse Isle Server/HorseIsleServer/Server/PacketBuilder.cs +++ b/Horse Isle Server/HorseIsleServer/Server/PacketBuilder.cs @@ -37,6 +37,7 @@ namespace HISP.Server public const byte PACKET_KEEP_ALIVE = 0x7C; public const byte PACKET_DYNAMIC_BUTTON = 0x45; public const byte PACKET_DYNAMIC_INPUT = 0x46; + public const byte PACKET_ARENA_SCORE = 0x2D; public const byte PACKET_PLAYER = 0x18; public const byte PACKET_INVENTORY = 0x17; public const byte PACKET_TRANSPORT = 0x29; @@ -62,6 +63,7 @@ namespace HISP.Server public const byte HORSE_LIST = 0x0A; public const byte HORSE_LOOK = 0x14; public const byte HORSE_FEED = 0x15; + public const byte HORSE_ENTER_ARENA = 0x2D; public const byte HORSE_PET = 0x18; public const byte HORSE_PROFILE = 0x2C; public const byte HORSE_PROFILE_EDIT = 0x14;