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;