diff --git a/src/CommandHandlers/ChatMessageHandler.cs b/src/CommandHandlers/ChatMessageHandler.cs index 8928e92..9801f51 100644 --- a/src/CommandHandlers/ChatMessageHandler.cs +++ b/src/CommandHandlers/ChatMessageHandler.cs @@ -11,6 +11,7 @@ class ChatMessageHandler : CommandHandler { string message = receivedObject.Get("p").Get("chm"); if (ManagementCommandProcessor.ProcessCommand(message, client)) return Task.CompletedTask; + if (CheckIllegalName(client)) return Task.CompletedTask; if (client.TempMuted) { ClientMuted(client); return Task.CompletedTask; @@ -23,6 +24,14 @@ class ChatMessageHandler : CommandHandler { return Task.CompletedTask; } + public static bool CheckIllegalName(Client client) { + if (client.PlayerData.DiplayName.Equals("Server", StringComparison.InvariantCultureIgnoreCase)) { + client.Send(Utils.BuildServerSideMessage("You may not use chat with that name.", "Server")); + return true; + } + return false; + } + public void ChatDisabled(Client client) { client.Send(Utils.BuildServerSideMessage("Unfortunately, chat has been disabled by server administrators", "Server")); } @@ -38,8 +47,8 @@ class ChatMessageHandler : CommandHandler { } client.Room.Send(Utils.BuildChatMessage(client.PlayerData.Uid, message, client.PlayerData.DiplayName), client); - DiscordManager.SendMessage(client.PlayerData.DiplayName+">"+message, client.Room); - + DiscordManager.SendPlayerBasedMessage(message, ":speech_balloon: {1}>{0}", client.Room, client.PlayerData); + NetworkObject cmd = new(); NetworkObject data = new(); data.Add("arr", new string[] { "SCA", "-1", "1", message, "", "1" }); diff --git a/src/CommandHandlers/GenericMessageHandler.cs b/src/CommandHandlers/GenericMessageHandler.cs index cd7fb60..93fee57 100644 --- a/src/CommandHandlers/GenericMessageHandler.cs +++ b/src/CommandHandlers/GenericMessageHandler.cs @@ -1,6 +1,7 @@ using sodoffmmo.Attributes; using sodoffmmo.Core; using sodoffmmo.Data; +using sodoffmmo.Management; namespace sodoffmmo.CommandHandlers; @@ -8,6 +9,43 @@ namespace sodoffmmo.CommandHandlers; class GenericMessageHandler : CommandHandler { public override Task Handle(Client client, NetworkObject receivedObject) { NetworkPacket packet = NetworkObject.WrapObject(0, 7, receivedObject).Serialize(); + if (receivedObject.Get("m") is string message) { + if (message.StartsWith("C:")) { // chat + if (!ChatMessageHandler.CheckIllegalName(client)) { + bool sent = false; + if (int.TryParse(message.AsSpan(2), out int num)) { + string? text = Configuration.GetVersioned(num, client.GameVersion, Configuration.CannedChat); + if (text != null) { + DiscordManager.SendPlayerBasedMessage("", ":loudspeaker: {1}>"+text, client.Room, client.PlayerData); + sent = true; + } + } + if (!sent) DiscordManager.SendPlayerBasedMessage(message.Substring(2), ":loudspeaker: {1}>*Unknown quickchat {0}*", client.Room, client.PlayerData); + } else { + return Task.CompletedTask; + } + } else if (message.StartsWith("EID:")) { // Emoticons + bool sent = false; + if (int.TryParse(message.AsSpan(4), out int num)) { + string? text = Configuration.GetVersioned(num, client.GameVersion, Configuration.Emoticons); + if (text != null) { + DiscordManager.SendPlayerBasedMessage("", ":wireless: {1} used "+text, client.Room, client.PlayerData); + sent = true; + } + } + if (!sent) DiscordManager.SendPlayerBasedMessage(message.Substring(4), ":wireless: {1} used *unknown emoticon {0}*", client.Room, client.PlayerData); + } else if (message.StartsWith("AID:")) { // Actions + bool sent = false; + if (int.TryParse(message.AsSpan(4), out int num)) { + string? text = Configuration.GetVersioned(num, client.GameVersion, client.PlayerData.EMDDriving() ? Configuration.EMDCarActions : Configuration.Actions); + if (text != null) { + DiscordManager.SendPlayerBasedMessage("", ":dancer: {1} performed "+text, client.Room, client.PlayerData); + sent = true; + } + } + if (!sent) DiscordManager.SendPlayerBasedMessage(message.Substring(4), ":dancer: {1} performed *unknown action {0}*", client.Room, client.PlayerData); + } + } client.Room.Send(packet); return Task.CompletedTask; } diff --git a/src/CommandHandlers/LoginHandler.cs b/src/CommandHandlers/LoginHandler.cs index 0714226..89d95d6 100644 --- a/src/CommandHandlers/LoginHandler.cs +++ b/src/CommandHandlers/LoginHandler.cs @@ -86,6 +86,8 @@ class LoginHandler : CommandHandler if (info.Authenticated) { client.PlayerData.DiplayName = info.DisplayName; client.PlayerData.Role = info.Role; + client.PlayerData.VikingId = info.Id; + client.GameVersion = info.Version; return true; } } catch (Exception ex) { diff --git a/src/Core/Client.cs b/src/Core/Client.cs index 0ff7659..911ea00 100644 --- a/src/Core/Client.cs +++ b/src/Core/Client.cs @@ -1,4 +1,5 @@ using sodoffmmo.Data; +using sodoffmmo.Management; using System; using System.Net.Sockets; using System.Runtime.CompilerServices; @@ -18,6 +19,7 @@ public class Client { SocketBuffer socketBuffer = new(); private volatile bool scheduledDisconnect = false; private readonly object clientLock = new(); + public uint GameVersion { get; set; } public Client(Socket clientSocket) { socket = clientSocket; @@ -59,6 +61,7 @@ public class Client { data.Add("r", Room.Id); data.Add("u", ClientID); Room.Send(NetworkObject.WrapObject(0, 1004, data).Serialize()); + DiscordManager.SendPlayerBasedMessage("", ":red_square: {1} has left the room.", Room, PlayerData); } // set new room (null when SetRoom is used as LeaveRoom) @@ -70,6 +73,7 @@ public class Client { Send(Room.SubscribeRoom()); if (Room.Name != "LIMBO") UpdatePlayerUserVariables(); // do not update user vars if room is limbo + DiscordManager.SendPlayerBasedMessage("", ":green_square: {1} has joined the room.", Room, PlayerData); } } } diff --git a/src/Core/Configuration.cs b/src/Core/Configuration.cs index f8b2687..653a053 100644 --- a/src/Core/Configuration.cs +++ b/src/Core/Configuration.cs @@ -1,5 +1,8 @@ using System; +using System.Collections; using System.Collections.Generic; +using System.Collections.Specialized; +using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -10,9 +13,15 @@ internal static class Configuration { public static ServerConfiguration ServerConfiguration { get; private set; } = new ServerConfiguration(); + public static SortedDictionary Emoticons = new(); + public static SortedDictionary Actions = new(); + public static SortedDictionary EMDCarActions = new(); + public static SortedDictionary CannedChat = new(); + public static void Initialize() { IConfigurationRoot config = new ConfigurationBuilder() .AddJsonFile("appsettings.json", true) + .AddJsonFile("emote_data.json", true) .Build(); ServerConfiguration? serverConfiguration = config.GetSection("MMOServer").Get(); @@ -23,6 +32,45 @@ internal static class Configuration { if (string.IsNullOrEmpty(ServerConfiguration.ApiUrl)) { ServerConfiguration.Authentication = AuthenticationMode.Disabled; } + + // Emoticons (the emojis that float above your head) + SortAndVersion(config.GetSection("Emoticons"), Emoticons); + // Actions (such as dances) + SortAndVersion(config.GetSection("Actions"), Actions); + // In EMD, there are seperate actions when in car that share IDs with normal actions. + // Since this is easy to check MMO-side (SPM uservar), we can just store these seperate + SortAndVersion(config.GetSection("EMDCarActions"), EMDCarActions); + // Canned Chat options (which can vary game to game) + SortAndVersion(config.GetSection("CannedChat"), CannedChat); + } + + // While version checking isn't exactly necessary for Actions when using vanilla files, it's nice to support it anyway. + private static void SortAndVersion(IConfigurationSection section, IDictionary dataOut) { + foreach (IConfigurationSection config in section.GetChildren()) { + if (config.Value != null) { + // Consistent for all games + dataOut.Add(int.Parse(config.Key), config.Value); + } else { + // Requires version checks + OrderedDictionary versioned = new(); + dataOut.Add(int.Parse(config.Key), versioned); + foreach (IConfigurationSection version in config.GetChildren().OrderByDescending(v=>uint.Parse(v.Key))) { + versioned.Add(uint.Parse(version.Key, NumberStyles.AllowHexSpecifier), version.Value); + } + } + } + } + + public static string? GetVersioned(int id, uint version, IDictionary data) { + object? value = data[id]; + if (value is null or string) { + return value as string; + } else if (value is OrderedDictionary versions) { + foreach (DictionaryEntry ver in versions) + if (version >= (uint)ver.Key) + return (string)ver.Value; + } + return null; } } diff --git a/src/Data/PlayerData.cs b/src/Data/PlayerData.cs index 47eed62..e94c542 100644 --- a/src/Data/PlayerData.cs +++ b/src/Data/PlayerData.cs @@ -2,6 +2,7 @@ using System.Globalization; using sodoffmmo.Core; using sodoffmmo.Management; +using System.Text.Json; namespace sodoffmmo.Data; public class PlayerData { @@ -37,6 +38,7 @@ public class PlayerData { public string DiplayName { get; set; } = "placeholder"; public Role Role { get; set; } = Role.User; + public int VikingId { get; set; } public long last_ue_time { get; set; } = 0; @@ -90,6 +92,25 @@ public class PlayerData { value = FixMountState(value); } + // update the playername (sent with avatardata) if it changes + // this is also hit when the player joins the room + if (varName == "A" && variables.GetValueOrDefault("A") != value) { + try { + // Gonna surround this in a try/catch in case for some + // reason it breaks so that it doesn't break MMO. + string? name = JsonSerializer.Deserialize(value)?.DisplayName; + if (name != null && name != DiplayName) { + string msg = ":label: {1} has changed their name to {0}"; + if (name.Equals("Server", StringComparison.InvariantCultureIgnoreCase)) { + msg += ". *This name will block them from speaking.*"; + } + DiscordManager.SendPlayerBasedMessage(name, msg, player: this); + DiplayName = name; + } + } + catch (Exception) {} // Pokemon-style exception handling + } + // store in directory variables[varName] = value; return value; @@ -211,6 +232,10 @@ public class PlayerData { return value; } } + + public bool EMDDriving() { + return variables.TryGetValue("SPM", out string? value) && value == "Driver"; + } } public enum PetGeometryType { diff --git a/src/Management/AuthenticationInfo.cs b/src/Management/AuthenticationInfo.cs index 266ebc1..b3c7b21 100644 --- a/src/Management/AuthenticationInfo.cs +++ b/src/Management/AuthenticationInfo.cs @@ -12,6 +12,12 @@ public class AuthenticationInfo { [XmlElement] public Role Role { get; set; } + + [XmlElement] + public int Id { get; set; } + + [XmlElement] + public uint Version { get; set; } } [Serializable] diff --git a/src/Management/AvatarData.cs b/src/Management/AvatarData.cs new file mode 100644 index 0000000..6c6a70d --- /dev/null +++ b/src/Management/AvatarData.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace sodoffmmo.Management; + +public class AvatarData { + public string? DisplayName { get; set; } +} diff --git a/src/Management/DiscordManager.cs b/src/Management/DiscordManager.cs index 8363e53..ce0c24e 100644 --- a/src/Management/DiscordManager.cs +++ b/src/Management/DiscordManager.cs @@ -4,6 +4,8 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.Collections.Concurrent; using sodoffmmo.Core; +using Discord.Rest; +using sodoffmmo.Data; namespace sodoffmmo.Management; @@ -51,69 +53,278 @@ class DiscordManager { return; } client = new DiscordSocketClient(new DiscordSocketConfig { - GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.MessageContent + GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.GuildMembers | GatewayIntents.MessageContent, + AlwaysDownloadUsers = true }); - client.Ready += OnBotReady; + client.Ready += async () => { + channel = client.GetGuild(config.Server).GetTextChannel(config.Channel); + }; client.MessageReceived += OnDiscordMessage; await client.LoginAsync(TokenType.Bot, config.Token); DiscordManager.config = config; Log("Loaded bot config from "+token_file+" and bot is running."); await client.StartAsync(); while (true) { - if (queue.TryDequeue(out QueuedMessage message)) { - SocketTextChannel? destination = channel; - if (message.room != null) { - string room = message.room.Name; - destination = channel.Threads.SingleOrDefault(x => x.Name == room); - if (destination == null) { - // A discord channel can have up to 1000 active threads - // and an unlimited number of archived threads. - if (message.room.AutoRemove) { - // Set temporary rooms (such as user rooms) to shorter archive times. - destination = await channel.CreateThreadAsync(room, autoArchiveDuration: ThreadArchiveDuration.OneDay); - } else { - // Persistent rooms should stay around for longer. - destination = await channel.CreateThreadAsync(room, autoArchiveDuration: ThreadArchiveDuration.OneWeek); - } - foreach (SocketGuildUser? user in channel.Users) { - await ((SocketThreadChannel)destination).AddUserAsync(user); + try { + if (!queue.IsEmpty && queue.TryDequeue(out QueuedMessage message)) { + SocketTextChannel? destination = channel; + if (message.room != null) { + if (message.room.Name == "LIMBO") continue; + string room = message.room.Name; + destination = channel.Threads.SingleOrDefault(x => x.Name == room); + if (destination == null) { + // A discord channel can have up to 1000 active threads + // and an unlimited number of archived threads. + if (message.room.AutoRemove) { + // Set temporary rooms (such as user rooms) to shorter archive times. + destination = await channel.CreateThreadAsync(room, autoArchiveDuration: ThreadArchiveDuration.OneHour); + } else { + // Persistent rooms should stay around for longer. + destination = await channel.CreateThreadAsync(room, autoArchiveDuration: ThreadArchiveDuration.OneWeek); + } } } + await destination.SendMessageAsync(message.msg); } - await destination.SendMessageAsync(message.msg); + } catch (Exception e) { + Log(e.ToString(), ConsoleColor.Red); } } } - private static async Task OnBotReady() { - channel = client.GetGuild(config.Server).GetTextChannel(config.Channel); - } - // For handling commands sent directly in the channel. private static async Task OnDiscordMessage(SocketMessage arg) { // Check that message is from a user in the correct place. - if (arg.Channel.Id != config.Channel || arg is not SocketUserMessage socketMessage || socketMessage.Author.IsBot) return; + bool roomChannel = arg.Channel is SocketThreadChannel thr && thr.ParentChannel.Id == config.Channel; + if (!( + arg.Channel.Id == config.Channel || + roomChannel + ) || + arg is not SocketUserMessage socketMessage || + socketMessage.Author.IsBot + ) return; string[] message = socketMessage.Content.Split(' '); if (message.Length >= 1) { - if (message[0] == "help") { - SendMessage("No-one can help you."); + string[] everywhereCommands = new string[] { + // Denotes commands that work identically regardless + // of whether you're in a room thread. + "!tempmute [string... reason] - Mute someone until they reconnect." + }; + bool un_command = message[0].StartsWith("!un"); + if (message[0] == "!tempmute" || message[0] == "!untempmute") { + if (message.Length > 1 && int.TryParse(message[1], out int id)) { + foreach (Room room in Room.AllRooms()) { + foreach (Client player in room.Clients) { + if (player.PlayerData.VikingId == id) { + if (player.TempMuted != un_command) { + await arg.Channel.SendMessageAsync($"This player is {(un_command ? "not" : "already")} tempmuted.", messageReference: arg.Reference); + } else { + player.TempMuted = !un_command; + string reason = string.Empty; + string msg = un_command ? "Un-tempmuted" : "Tempmuted"; + msg += $" {player.PlayerData.DiplayName}."; + if (message.Length >= 2) { + reason = string.Join(' ', message, 2, message.Length - 2); + msg += " Reason: "+reason; + } + await arg.Channel.SendMessageAsync(msg, messageReference: arg.Reference); + } + goto tempmute_search_loop_end; + } + } + } + tempmute_search_loop_end:;// StackOverflow said to do it like this (no labeled break like in Java). + } else { + await arg.Channel.SendMessageAsync("Input a valid vikingid!", messageReference: arg.Reference); + } + } else if (roomChannel) { + if (message[0] == "!help") { + await arg.Channel.SendMessageAsync(string.Join(Environment.NewLine, new string[] { + "### List of commands:", + "!help - Prints the help message. That's this message right here!", + "!list - Lists all players in this room.", + "!say - Say something in this room." + }.Concat(everywhereCommands) + )); + } else if (message[0] == "!list") { + if (!Room.Exists(arg.Channel.Name)) { + await arg.Channel.SendMessageAsync("This room is currently unloaded.", messageReference: arg.Reference); + } else { + Room room = Room.Get(arg.Channel.Name); + if (room.ClientsCount > 0) { + string msg = "Players in Room:\n"; + foreach (Client player in room.Clients) { + string vikingid; + if (player.PlayerData.VikingId != 0) { + vikingid = "||VikingId: "+player.PlayerData.VikingId+"||"; + } else { + vikingid = "||(Not Authenticated!)||"; + } + msg += $"* {SanitizeString(player.PlayerData.DiplayName)} {vikingid}\n"; + } + SendMessage(msg, room); // Sent like this in case it's longer than 2000 characters (handled by this method). + } else { + await arg.Channel.SendMessageAsync("This room is empty.", messageReference: arg.Reference); + } + } + } else if (message[0] == "!say") { + if (message.Length > 1) { + // Due to client-based restrictions, this probably only works in SoD and maybe MaM. + // Unless we want to create an MMOAvatar instance for the server "user". + if (Room.Exists(arg.Channel.Name)) { + Room room = Room.Get(arg.Channel.Name); + if (room.ClientsCount > 0) { + room.Send(Utils.BuildChatMessage(Guid.Empty.ToString(), string.Join(' ', message, 1, message.Length-1), "Server")); + await arg.AddReactionAsync(Emote.Parse(":white_check_mark:")); + } else { + await arg.Channel.SendMessageAsync("There is no-one in this room to see your message.", messageReference: arg.Reference); + } + } else { + await arg.Channel.SendMessageAsync("This room is currently unloaded.", messageReference: arg.Reference); + } + } else { + await arg.Channel.SendMessageAsync("You didn't include any message content!", messageReference: arg.Reference); + } + } + } else { + if (message[0] == "!help") { + await arg.Channel.SendMessageAsync(string.Join(Environment.NewLine, new string[] { + "### List of commands:", + "!help - Prints the help message. That's this message right here!", + "!rooms - Ping you in all active Room threads you aren't already in.", + " This will add you to all of the room threads. :warning: **This may generate a lot of pings for you!** :warning:", + "!list - Lists all players on the server." + }.Concat(everywhereCommands) + .Append("*Using !help in a room thread yields a different set of commands. Try using !help in a room thread!*") + )); + } else if (message[0] == "!rooms") { + IEnumerable threads = await channel.GetActiveThreadsAsync(); + Console.WriteLine(threads.Count()); + ulong uid = socketMessage.Author.Id; + foreach (RestThreadChannel thread in threads) { + // If the user is already in the thread no need to ping them. + if (await thread.GetThreadUsersAsync().Flatten().AnyAsync(user => user.Id == uid)) continue; + + // Ping the user and then delete the message. + RestUserMessage ping = await thread.SendMessageAsync("<@"+uid+"> making this thread visible for you ;)"); + await ping.DeleteAsync(); + } + } else if (message[0] == "!list") { + string msg = string.Empty; + foreach (Room room in Room.AllRooms()) { + foreach (Client player in room.Clients) { + if (msg == string.Empty) msg = "Players Online:\n"; + + string vikingid; + if (player.PlayerData.VikingId != 0) { + vikingid = "||VikingId: "+player.PlayerData.VikingId+"||"; + } else { + vikingid = "||(Not Authenticated!)||"; + } + msg += $"* {SanitizeString(player.PlayerData.DiplayName)} {vikingid} ({room.Name})\n"; + } + } + if (msg == string.Empty) { + await arg.Channel.SendMessageAsync("Nobody is online.", messageReference: arg.Reference); + } else { + SendMessage(msg); // Sent like this in case it's longer than 2000 characters (handled by this method). + } + } } } } + /// + /// Send a message through the bot. + /// If the message is larger than 2000 characters it will be split until if fit. + /// + /// Message to send + /// Room to send message in - can be null public static void SendMessage(string msg, Room? room=null) { - if (client != null) queue.Enqueue(new QueuedMessage { - msg = msg - .Replace("*", "\\*") // Prevent most Discord formatting - .Replace("_", "\\_") // Prevent some other formatting - .Replace("~", "\\~") // Prevent Strikethrough - .Replace("`", "\\`") // Prevent Code Blocks - .Replace(":", "\\:") // Prevent Links - .Replace("<", "\\<") // So that Masked Links with embed disabled don't look strange - .Replace("](", "]\\("), // Prevent Masked Links - room = room - }); + if (client != null) { + while (msg.Length > 0) { + string piece = msg; + if (msg.Length > 2000) { // Discord character limit is 2000. + // Find a good place to break the message, if possible. + int breakIndex = msg.LastIndexOfAny(new char[2] {' ','\n'}, 2000); + if (breakIndex <= 0) breakIndex = 2000; + // Split the first part of the message and recycle the rest. + piece = msg.Substring(0, breakIndex); + msg = msg.Substring(breakIndex); + } else { + // Exit the loop when the time comes. + msg = string.Empty; + } + queue.Enqueue(new QueuedMessage { + msg = piece, + room = room + }); + } + } + } + + /// + /// Sends a message through the bot, but include data about the user and sanitize it. + /// + /// Message to send + /// + /// Surround the message using formatting. + /// {0} corresponds to sanitized msg. + /// {1} correspongs to sanitaize playername. + /// + /// Room to send message in - can be null + /// PlayerData to associate the message with - can be null + public static void SendPlayerBasedMessage(string msg, string surround="{1} **-->** {0}", Room? room=null, PlayerData? player=null) { + try { + if (client != null) { + // We need to sanitize things first so that people can't + // use Discord's formatting features inside a chat message. + msg = SanitizeString(msg); + string name = SanitizeString(player?.DiplayName ?? ""); + + if (player != null) { + if (player.VikingId != 0) { + surround = "||VikingId: "+player.VikingId+"||\n"+surround; + } else { + surround = "||(Not Authenticated!)||\n"+surround; + } + } + + // Send the sanitized message, headed with the viking id (if authenticated). + SendMessage(string.Format(surround, msg, name), room); + } + } catch (Exception e) { + Log(e.ToString(), ConsoleColor.Red); + } + } + + public static string SanitizeString(string str) { + string sanitizedStr = ""; + for (int i=0;i' + (i > 0 && c == '(' && str[i-1] == ']') // Cleanse Masked Links themselves + ) { + sanitizedStr += '\\'; // Add a backslash to escape it. + } + if (c == '@') { // Cleanse pings to @everyone and @here + sanitizedStr += "`@`"; + } else { + // Append the character as normal, unless + // overridden in the single case above. + sanitizedStr += c; + } + } + return sanitizedStr; } class BotConfig { diff --git a/src/appsettings.json b/src/appsettings.json index a9a6b85..aacbd03 100644 --- a/src/appsettings.json +++ b/src/appsettings.json @@ -61,7 +61,7 @@ "// Authentication Optional": "authentication is required only for moderation activities", "// Authentication RequiredForChat": "authentication is required only for moderation activities and using chat (if chat is enabled)", "// Authentication Required": "authentication is required to connect to mmo", - "Authentication": "Disabled", + "Authentication": "Optional", "// ApiUrl": "SoDOff API server URL for authentication calls", "ApiUrl": "http://localhost:5000", diff --git a/src/emote_data.json b/src/emote_data.json new file mode 100644 index 0000000..c410bbb --- /dev/null +++ b/src/emote_data.json @@ -0,0 +1,969 @@ +{ + "Emoticons": { + "1": { + "04000001": ":grimacing:", + "04000000": ":nauseated_face:", + "0": ":grimacing:" + }, + "2": ":confused:", + "3": ":sunglasses:", + "4": ":cry:", + "5": ":smiling_imp:", + "6": ":flushed:", + "7": ":grinning:", + "8": ":headphones:", + "9": ":rage:", + "10": { + "02000000": ":person_with_crown:", + "0": ":prince:" + }, + "11": ":laughing:", + "12": ":heart_eyes:", + "13": ":ninja:", + "14": { + "02000000": ":zipper_mouth:", + "0": ":partying_face:" + }, + "15": "\\:pirate\\:", + "16": { + "02000000": "\\:smug\\:", + "0": ":person_with_crown:" + }, + "17": ":relieved:", + "18": ":slight_frown:", + "19": ":innocent:", + "20": { + "04000001": ":sick:", + "04000000": ":thermometer_face:", + "0": ":sick:" + }, + "21": ":astonished:", + "22": ":yum:", + "23": { + "02000000": ":partying_face:", + "0": ":police_officer:" + }, + "24": ":firefighter:", + "25": ":health_worker:", + "26": ":mask:", + "27": "\\:hunter\\:", + "28": ":construction_worker:", + "29": ":cat:", + "30": ":dog:", + "31": ":mouse:", + "32": ":balloon:", + "33": ":bell:", + "34": ":hatched_chick:", + "35": ":bomb:", + "36": ":books:", + "37": ":tropical_fish:", + "38": ":butterfly:", + "39": ":birthday_cake:", + "40": ":camera:", + "41": ":candy:", + "42": ":cherries", + "43": ":timer_clock:", + "44": ":four_leaf_clover", + "45": ":cookie:", + "46": ":sunflower:", + "47": ":doughnut:", + "48": ":drum:", + "49": ":envelope:", + "50": ":exclamation:", + "51": ":fish:", + "52": ":tulip:", + "53": ":french_fries:", + "54": ":cooking:", + "55": ":gem:", + "56": ":ghost:", + "57": ":gift:", + "58": ":green_apple:", + "59": ":hamburger:", + "60": ":heart:", + "61": ":trumpet:", + "62": ":hotdog:", + "63": ":house:", + "64": ":icecream:", + "65": ":lady_beetle:", + "66": ":computer:", + "67": ":leaves:", + "68": ":zap:", + "69": ":lollipop:", + "70": ":magnet:", + "71": ":mag_right:", + "72": "\\:mittens\\:", + "73": ":crescent_moon:", + "74": "\\:muffin\\:", + "75": ":brown_mushroom:", + "76": ":musical_note:", + "77": ":tangerine:", + "78": ":pancakes:", + "79": ":hyacinth:", + "80": ":peach:", + "81": ":pear:", + "82": ":pie:", + "83": ":pizza:", + "84": ":popcorn:", + "85": ":jack_o_lantern:", + "86": ":question_mark:", + "87": ":rose:", + "88": ":santa:", + "89": ":shield:", + "90": ":shopping_cart:", + "91": ":skull:", + "92": ":snowflake:", + "93": ":socks:", + "94": ":flying_saucer:", + "95": ":star:", + "96": "\\:starfish\\:", + "97": ":stopwatch:", + "98": ":sun:", + "99": ":taco:", + "100": ":trophy:", + "101": ":poultry_leg:" + }, + "Actions": { + "1": "Fist Pump", + "2": "Excited", + "3": "Shrug", + "4": "Toe Touch", + "5": "Sad", + "6": "Hello", + "7": "Flex", + "8": "Yes", + "9": "Salute", + "10": "Pushup", + "11": "Come Here", + "12": "Clap", + "13": "Laugh", + "14": "Chin-Up", + "15": "No Way", + "16": "Listen Up", + "17": "Bye", + "18": "Kisses", + "19": "Break Dance", + "20": "Cabbage Patch", + "21": "Head Banger", + "22": "Macarena", + "23": "Running Man", + "24": "Shy", + "25": "Ta Da!", + "26": "Talk", + "27": "Yawn", + "28": "What!", + "29": "Handstand", + "30": "Beg", + "31": "Rub Head and Pat Stomach", + "32": "Cheer", + "33": "Scold", + "34": "Bow", + "35": "Cry", + "36": "Dance 01", + "37": "Dance 02", + "38": "Dance 03", + "39": "Dance 04", + "40": "Dance 05", + "41": "Dance 06" + }, + "EMDCarActions": { + "1": "Burn Out", + "2": "Donut", + "3": "Hydraulics", + "4": "Hydraulic Dancing", + "5": "Wheel Spin", + "6": "Endo", + "7": "Wheelie", + "8": "Flip" + }, + "CannedChat": { + "10001": "Hi.", + "10500": "Hello.", + "11000": "Hi there.", + "11500": "What's up?", + "12001": "Greetings.", + "12002": "Greetings earthlings.", + "12003": { + "08000000": "Greetings my fellow Blasters.", + "0": "Greetings my fellow Jumpeez." + }, + "12500": "Nice to meet you.", + "13000": "Good morning.", + "13500": "Good afternoon.", + "1400": "Good evening.", + "14500": "Hola!", + "15000": "Howdy partner!", + "20000": "Bye.", + "20500": "Goodbye.", + "21000": "See ya!", + "21500": "Have a great day!", + "22001": "See you tomorrow morning.", + "22002": "See you tomorrow afternoon.", + "22003": "See you tomorrow night.", + "22500": "Goodnight.", + "23000": "See you later alligator\u2026", + "23500": "In a while crocodile!", + "24000": "Nice meeting you!", + "24500": "Adios!", + "25000": "Toodle-loo!", + "26000": "Later.", + "30001": "I am happy.", + "30002": "I am sad.", + "30003": "I am excited!", + "30004": "I am bored.", + "30005": "I am scared.", + "30006": "I am surprised!", + "30007": "I am hungry.", + "30008": "I am tired.", + "30009": "I am grumpy.", + "30010": "I am amused.", + "30050": "I am smart.", + "30051": "I am goofy.", + "30052": "I am funny.", + "30053": "I am serious.", + "50054": "I am a cool cat.", + "30055": "I am awesome!", + "30056": "I am a troublemaker.", + "30057": "I am bad to the bone!", + "30101": "I am an artist.", + "30102": "I am a pirate.", + "30103": "I am a prince.", + "30104": "I am a princess", + "30105": "I am a wizard.", + "30106": "I am a mad scientist.", + "30107": "I am a scuba diver.", + "30108": "I am a gold miner.", + "30109": "I am a rock star.", + "30110": "I am a movie star.", + "30111": "I am a secret agent.", + "30112": "I am a singer.", + "30113": "I am a writer.", + "30150": "I am an athlete.", + "30151": "I am a volleyball player.", + "30152": "I am a basketball player.", + "30153": "I am a baseball player.", + "30154": "I am a softball player.", + "30155": "I am a football player.", + "30156": "I am a hockey player.", + "30157": "I am a water polo player.", + "30158": "I am a soccer player.", + "30159": "I am a tennis player.", + "30160": "I am a cheerleader.", + "30161": "I am a gymnast.", + "30162": "I am a swimmer.", + "30200": { + "08000000": "I am a Blaster Cadet.", + "0": "I am a level 1." + }, + "30201": { + "08000000": "I am a Blaster Cadet 1st Class.", + "0": "I am a level 2." + }, + "30202": { + "08000000": "I am a Blaster Private.", + "0": "I am a level 3." + }, + "30203": { + "08000000": "I am a Blaster Private 1st Class.", + "0": "I am a level 4." + }, + "30204": { + "08000000": "I am a Blaster Corporal.", + "0": "I am a level 5." + }, + "30205": { + "08000000": "I am a Blaster Corporal 1st Class.", + "0": "I am a level 6." + }, + "31001": "I like to explore.", + "31002": "I like to sing.", + "31003": "I like to dance.", + "31004": "I like to chat.", + "31005": "I like to fly.", + "31010": "I like to make friends.", + "31011": "I like to learn.", + "31020": "I like Alien Wrangler.", + "31021": "I like B-Force Blaster.", + "31022": "I like Blast Attack.", + "31023": "I like Bolt Cruncher.", + "31024": "I like Dodge-N-Dash.", + "31025": "I like Droid Defense.", + "31026": "I like Galaxy Grand Prix.", + "31027": "I like Hyper Blast.", + "31028": "I like Monster Mutts.", + "31029": "I like Morph Madness.", + "31030": "I like Oozami.", + "31031": "I like Red Alert.", + "31032": "I like Roller Ball Rally.", + "31033": "I like Zapper.", + "31050": { + "08000000": "I like the Math Academy.", + "0": "I like MainStreet." + }, + "31051": { + "08000000": "I like the Spaceport.", + "0": "I like DownTown." + }, + "31052": { + "08000000": "I like the Ready Room.", + "0": "I like the Arcade." + }, + "31053": { + "08000000": "I like Planet Avatarus.", + "0": "I like New York." + }, + "31054": { + "08000000": "I like Planet Blizzard.", + "0": "I like the Enchanted Sanctuary." + }, + "31055": { + "08000000": "I like the Park.", + "0": "I like StoryLand." + }, + "31056": { + "08000000": "I like Fitness Training.", + "0": "I like AdventureLand." + }, + "31057": { + "08000000": "I like the Training Center.", + "0": "I like MarineLand." + }, + "31058": { + "08000000": "I like the Larva Den.", + "0": "I like FutureLand." + }, + "31059": { + "08000000": "I like the Alien Wrangler Arena.", + "0": "I like Ghost Town Grab" + }, + "31060": { + "08000000": "I like my Pod.", + "0": "I like Hidden Treasure Hollow." + }, + "31150": "I like cats.", + "31151": "I like dogs.", + "31152": "I like goldfish.", + "31153": "I like hamsters.", + "31154": "I like guinea pigs.", + "31155": "I like bunnies.", + "31156": "I like birds", + "31157": "I like snakes.", + "31158": "I like turtles.", + "31159": "I like frogs.", + "31200": "I like tigers.", + "31201": "I like lions.", + "31202": "I like bears.", + "31203": "I like jaguars.", + "31204": "I like elephants.", + "31205": "I like giraffes.", + "31206": "I like hawks.", + "31207": "I like dinosaurs.", + "31208": "I like unicorns.", + "31250": "I like fish.", + "31251": "I like sharks.", + "31252": "I like dolphins.", + "31253": "I like eels.", + "31254": "I like stingrays.", + "31255": "I like whales.", + "31256": "I like jellyfish", + "31257": "I like sea turtles.", + "31258": "I like penguins.", + "31259": "I like sea monsters.", + "31300": "I like red.", + "31301": "I like orange.", + "31302": "I like yellow.", + "31303": "I like green.", + "31304": "I like blue.", + "31305": "I like purple.", + "31306": "I like pink.", + "31307": "I like white.", + "31308": "I like black.", + "31309": "I like silver.", + "31310": "I like gold.", + "31311": "I like brown.", + "31350": "I like popsicles.", + "31351": "I like pizza.", + "31352": "I like hamburgers.", + "31353": "I like veggies.", + "31354": "I like grilled cheese.", + "31355": "I like spaghetti.", + "31356": "I like candy.", + "31357": "I like ice cream.", + "31358": "I like peanut butter.", + "31359": "I like cookies.", + "31400": "I like to rock out.", + "31401": "I like all music.", + "31402": "I like hip hop music.", + "31403": "I like country music.", + "31404": "I like classical music.", + "31405": "I like techno music.", + "31406": "I like jazz music", + "31407": "I like blues music.", + "31408": "I like rock music.", + "31500": "I like the Ickasaur.", + "31501": "I like the Grubble.", + "31502": "I like the Eye-Clops.", + "31503": "I like the larva.", + "32001": "I live near the ocean.", + "32002": "I live in the desert.", + "32003": "I live in the city.", + "32004": "I live on a farm.", + "32005": "I live in a tree house.", + "32006": "I live in outer space.", + "32007": "I live in the jungle.", + "32008": "I live on a boat.", + "32009": "I live on an island.", + "32010": "I live on Mars.", + "32011": "I live in a spaceship.", + "32012": "I live on Earth.", + "32013": "I live with aliens.", + "32014": "I live among the stars.", + "40001": "Let's dance!", + "40002": "Let's race!", + "40003": { + "08000000": "Let's zap!", + "0": "Let's jump!" + }, + "40004": "Let's explore!", + "40007": { + "08000000": "Add me as a B.F.F.", + "0": "Add me as a buddy" + }, + "40008": "Look at that!", + "40009": "I am lost.", + "40010": "I don't know what to do.", + "40011": "Ready...set...go!", + "41001": { + "08000000": "I am going to train in Hyper Blast.", + "0": "I am going to MainStreet." + }, + "41002": { + "08000000": "I am going to the Ready Room.", + "0": "I am going to DownTown." + }, + "41003": { + "08000000": "I am going to B-Force Blaster.", + "0": "I am going to the Arcade." + }, + "41004": { + "08000000": "I am going to Zapper.", + "0": "I am going to New York." + }, + "41005": { + "08000000": "I am going to Alien Wrangler.", + "0": "I am going to the Enchanted Sanctuary." + }, + "41006": { + "08000000": "I am going to play Oozami.", + "0": "I am going to StoryLand." + }, + "41007": { + "08000000": "I am going to Monster Mutt Rescue.", + "0": "I am going to AdventureLand." + }, + "41008": { + "08000000": "I am going to Roller Ball Rally.", + "0": "I am going to MarineLand." + }, + "41009": { + "08000000": "I am going to Morph Madness.", + "0": "I am going to FutureLand." + }, + "41010": { + "08000000": "I am going to Planet Avatarus.", + "0": "I am going to Ghost Town Grab." + }, + "41011": { + "08000000": "I am going to Planet Blizzard.", + "0": "I am going to Hidden Treasure Hollow." + }, + "41012": { + "08000000": "I am going to play Bolt Cruncher.", + "0": "I am going to the Amphitheatre." + }, + "41013": { + "08000000": "I am going to my Pod.", + "0": "I am going to the Stadium." + }, + "41014": { + "08000000": "I am going to my Mutt Pod.", + "0": "I am going to the Zoo." + }, + "41050": { + "08000000": "I am going to tame a wild alien.", + "0": "I am going to buy clothes." + }, + "41051": { + "08000000": "I am going to change my look.", + "0": "I am going to change clothes." + }, + "41052": "I am going to dance.", + "41053": "I am going to explore.", + "41059": { + "08000000": "I am going to decorate my Pod.", + "0": "I am going to buy a ride." + }, + "41060": { + "08000000": "I am going to throw a party.", + "0": "I am going to save Lost Island." + }, + "41061": { + "08000000": "I am going to watch a movie.", + "0": "I am going to defeat the Punk Punks." + }, + "41062": "I am to rate your Pod.", + "41063": "I am going to play with my Monster Mutt.", + "41064": "I am going to create some morphs in the Chem Lab.", + "50001": "Where are you going?", + "50002": "What do you like to do?", + "50003": { + "08000000": "What rank are you?", + "0": "What level are you?" + }, + "50004": "What should we do?", + "50005": "Did you see that?", + "50006": "Will you follow me?", + "50008": "Will you show me your favorite place?", + "50009": "Can you show me a secret portal?", + "50010": "Did you see the new game?", + "50011": { + "08000000": "Have you rated my Pod?", + "0": "Please unlock my Surprise Box in My House." + }, + "51001": { + "08000000": "Want to be my B.F.F.?", + "0": "Want to be my friend?" + }, + "51004": "Want to dance?", + "51005": { + "08000000": "Want to race at G.G.P.?", + "0": "Want to race?" + }, + "51006": "Want to explore?", + "51007": "Want to play B-Force Blaster?", + "51008": "Come to my party in my Pod!", + "51009": "Rate my Pod!", + "52001": "What is your favorite animal?", + "52002": "What is your favorite color?", + "52003": "What is your favorite food?", + "52004": "What type of music do you like?", + "52005": "Where do you live?", + "53001": "What did you say?", + "60001": "Haha!", + "60002": "Hehe!", + "60003": "Ho-ho-ho!", + "60004": "Tee-he-he!", + "60005": "Bwa-ha-ha-ha!", + "61001": "Ahoy!", + "61002": "Aye aye, captain!", + "61003": "Landlubber!", + "61004": "Arg!", + "61005": "Shiver me timbers!", + "61006": "Yo-ho-ho!", + "61007": "It's a pirate's life for me.", + "61008": "Walk the plank!", + "61009": "There be squalls ahead!", + "62001": "Woof!", + "62002": "Meow!", + "62003": "Quack!", + "62004": "Roar!", + "62005": "Ribbit!", + "63001": "Just call me Agent X.", + "63002": "Over and out.", + "63003": "Sorry, that's classified.", + "63004": "My cover is blown!", + "63005": "Alpha. Bravo. Charlie. Delta.", + "64001": "Error. Does not compute.", + "64002": "Beep. Beep.", + "64003": "Bzzzurp!", + "65001": "Fee fi fo fum!", + "65002": "Dun dun dun...", + "65003": "Mumbo jumbo!", + "65004": "Fiddlesticks!", + "65005": "Boogie woogie!", + "65006": "La-di-da!", + "65007": "Kersplat!", + "65008": "Achoo!", + "65009": "Blah blah blah...", + "66001": "LOL", + "66002": "BFF", + "66003": "JK", + "66004": "IDK", + "66005": "PLZ", + "66006": "THX", + "66007": "BRB", + "66008": "CYA", + "66009": "TTYL", + "80001": "Stop that!", + "80002": "Please do not do that.", + "80003": "Go away!", + "80004": "That is not very nice.", + "80005": "You are in my personal bubble.", + "80006": "Hurry up!", + "80007": "Wait for me!", + "80008": "Please slow down.", + "80009": { + "08000000": "You are a grumpy Blaster.", + "0": "You are a grumpy Jumpee." + }, + "70001": "Wow!", + "70002": "That was awesome!", + "70003": "Super cool!", + "70004": "I'm glad you are here.", + "71001": "I like your style.", + "71002": "I like your outfit.", + "71005": "I like your name.", + "71006": "I like your hair.", + "71008": { + "08000000": "I like your mouth.", + "0": "I like your pants." + }, + "71009": { + "08000000": "I like your boots.", + "0": "I like your shoes." + }, + "71010": "I like your eyes.", + "71011": { + "08000000": "I like your Monster Mutt.", + "0": "I like your hat." + }, + "71012": { + "08000000": "I like your Pod.", + "0": "I like your mythie." + }, + "71013": "I like your Mutt Pod.", + "72001": "You are awesome!", + "72002": "You are funny!", + "72003": "You are pretty.", + "72004": "You are handsome.", + "72005": "You are kind.", + "72006": "You are silly.", + "72007": "You are cool.", + "72008": "You are great.", + "72009": "You are goofy.", + "72010": "You are one of a kind.", + "72011": "You are my best friend.", + "72012": { + "08000000": "You are the coolest Blaster!", + "0": "You're the coolest Jumpee I know!" + }, + "72013": "You are the bee's knees!", + "73001": "Thanks!", + "73002": "Thank you!", + "73003": "Thanks a bunch!", + "73004": "Thanks for being my friend.", + "73005": "Thanks for showing me that.", + "73006": "You're welcome.", + "73007": "No problem!", + "73008": "Anytime.", + "74001": "Sorry!", + "74002": "Oops, sorry!", + "74003": "Sorry, I have to go.", + "74004": "Sorry, I am busy.", + "74005": "Sorry, I didn't mean that.", + "74006": "I take it back.", + "74007": "It's okay.", + "74008": "Don't worry about it.", + "74009": "I forgive you.", + "90001": "Yes.", + "90002": "No.", + "90003": "Maybe.", + "90004": "Follow me.", + "90005": "Me too.", + "90006": "Happy Birthday!", + "551": "Hello", + "552": "Hey!", + "553": "Hi", + "554": "Hi there.", + "555": "Sup?", + "556": "Hi, I'm new...", + "557": "Nice to meet you.", + "558": "How's it goin?", + "559": "Hola!", + "651": "See ya!", + "652": "Good bye.", + "653": "L8tr.", + "654": "Bye.", + "655": "Catch ya!", + "656": "See you tomorrow.", + "657": "Night!", + "658": "Later.", + "659": "TTYL", + "660": "Take care!", + "751": "I am happy.", + "752": "I am sooo excited!", + "753": "I am scared.", + "754": "I am hungry.", + "755": "I am good.", + "715": "I am sorry.", + "756": "I am tired.", + "758": "I am heartbroken.", + "850": "I am smart.", + "851": "I am goofy.", + "853": "I am serious.", + "854": "I am cool.", + "855": "I am awesome!", + "856": { + "04000000": "I am a racer.", + "0": "I am a princess." + }, + "857": "I am laid back!", + "858": "I am a dork!", + "859": "I am a rebel!", + "860": "I am an artist.", + "861": "I am a pirate.", + "865": "I am a dancer.", + "868": "I am a rock star.", + "869": "I am a movie star.", + "870": "I am a secret agent", + "950": "I like to make friends.", + "951": "I like to be creative.", + "952": "I like to dance.", + "953": "I like to chat.", + "955": "I like to text.", + "956": "I like to learn.", + "957": "I like to watch t.v.", + "958": "I like to hang with my friends.", + "3050": "I like to go to concerts.", + "3051": "I like to go to the movies.", + "3053": "I like to travel.", + "3055": "I like to hangout in my room.", + "3056": "I like to hang with my family.", + "3150": "I like cats.", + "3151": "I like dogs.", + "3152": "I like goldfish.", + "3153": "I like hamsters.", + "3154": "I like sloths.", + "3155": "I like bunnies.", + "3156": "I like birds", + "3157": "I like koalas.", + "3158": "I like turtles.", + "3159": "I like platypus.", + "3250": "I like tigers.", + "3251": "I like lions.", + "3252": "I like bears.", + "3253": "I like jaguars.", + "3254": "I like elephants.", + "3255": "I like giraffes.", + "3256": "I like unicorns.", + "3257": "I like Gumby.", + "3258": "I like Pokey.", + "3350": "I like red.", + "3351": "I like orange.", + "3352": "I like yellow.", + "3353": "I like green.", + "3354": "I like blue.", + "3355": "I like purple.", + "3356": "I like pink.", + "3357": "I like white.", + "3358": "I like black.", + "3359": "I like silver.", + "3360": "I like gold.", + "3450": "I like popsicles.", + "3451": "I like pizza.", + "3452": "I like hamburgers.", + "3453": "I like veggies.", + "3455": "I like spaghetti.", + "4356": "I like candy.", + "3457": "I like ice cream.", + "3458": "I like peanut butter.", + "3459": "I like cookies.", + "4550": "I like to rock out.", + "4551": "I like all music.", + "4552": "I like hip hop music.", + "4553": "I like country music.", + "4554": "I like classical music.", + "4555": "I like techno music.", + "4557": "I like jazz music", + "4558": "I like blues music.", + "4559": "I like rock music.", + "4650": "I live near the ocean.", + "4651": "I live in the desert.", + "4652": "I live in the city.", + "4653": "I live on a farm.", + "4654": "I live in a tree house.", + "4655": "I live in outer space.", + "4656": "I live in the jungle.", + "4657": "I live on a boat.", + "4658": "I live on an island.", + "4750": "Let's dance!", + "4751": "Let's race!", + "4752": "Let's hang out!", + "4753": "Let's chill!", + "4754": "Add me as a friend.", + "4755": "Look at that!", + "4756": "I am lost.", + "4757": "I don't know what to do.", + "4758": "Ready...set...go!", + "4860": { + "04000000": "I am going to change my car.", + "0": "I am going to change clothes." + }, + "1564": { + "04000000": "I am going to race.", + "0": "I am going to dance." + }, + "4862": { + "04000000": "I am going to buy parts.", + "0": "I am going to buy clothes." + }, + "4863": { + "04000000": "I am going to get Street Cred.", + "0": "I am going to get Style Points." + }, + "4864": "I am going to hang out.", + "5050": "Where are you going?", + "5051": "What do you like to do?", + "5052": "What should we do?", + "5053": "Will you follow me?", + "5054": "Will you show me your favorite place?", + "5056": "Want to be my friend?", + "5057": { + "04000000": "Want to race?", + "0": "Want to dance?" + }, + "5059": "Want to explore?", + "5250": "What is your favorite animal?", + "5251": "What is your favorite color?", + "5252": "What is your favorite food?", + "5253": "What type of music do you like?", + "5255": "What did you say?", + "6050": "Haha!", + "6051": "Hehe!", + "6052": "Bwa-ha-ha-ha!", + "6150": "Woof!", + "6151": "Meow!", + "6152": "Quack!", + "6153": "Roar!", + "6154": "Ribbit!", + "6350": "LOL", + "6351": "BFF", + "6352": "JK", + "6353": "IDK", + "6354": "PLZ", + "6355": "THX", + "6356": "BRB", + "6357": "CYA", + "6358": "TTYL", + "6550": "Stop that!", + "6551": "Please do not do that.", + "6552": "Go away!", + "6553": "That is not very nice.", + "6554": "You are in my personal bubble.", + "6555": "Hurry up!", + "6556": "Wait for me!", + "6557": "Please slow down.", + "6650": "Wow!", + "6651": "That was awesome!", + "6652": "Super cool!", + "6653": "I'm glad you are here.", + "6750": "You are awesome!", + "6751": "You are funny!", + "6752": "You are pretty.", + "6753": "You are handsome.", + "6754": "You are stunning.", + "6755": "You are crazy.", + "6756": "You are cool.", + "6757": "You are great.", + "6758": "You are goofy.", + "6759": "You are one of a kind.", + "6760": "You are my best friend.", + "6850": "Thanks!", + "6851": "Thank you!", + "6852": "Thanks a bunch!", + "6853": "Thanks for being my friend.", + "6854": "Thanks for showing me that.", + "6855": "You're welcome.", + "6856": "No problem!", + "6857": "Anytime.", + "6950": "Sorry!", + "6951": "Oops, sorry!", + "6952": "Sorry, I have to go.", + "6953": "Sorry, I am busy.", + "6954": "Sorry, I didn't mean that.", + "6955": "I take it back.", + "6956": "It's okay.", + "6957": "Don't worry about it.", + "6958": "I forgive you.", + "7050": "Yes.", + "7051": "No.", + "7052": "Maybe.", + "7053": "Follow me.", + "7054": "Me too.", + "14000": "Good evening", + "30100": "I am a mythie trainer.", + "30206": "I am a level 7.", + "30207": "I am a level 8.", + "30208": "I am a level 9.", + "30209": "I am a level 10.", + "31006": "I like to train mythies.", + "31007": "I like to earn coins.", + "31008": "I like to buy new pets.", + "31009": "I like to buy new rides.", + "31061": "I like the Amphitheatre.", + "31062": "I like the Stadium.", + "31100": "I like all of my mythies.", + "31101": "I like training my mythies.", + "31102": "I like when my mythies are babies.", + "31103": "I like when my mythies are learning to fly.", + "31104": "I like when my mythies are grown up.", + "31105": "I like seeing all the different mythies.", + "31209": "I like mythies.", + "33001": "I would be a famous lion.", + "33002": "I would be a hilarious zebra.", + "33003": "I would be a fabulous hippo.", + "33004": "I would be an anxious giraffe.", + "33005": "I would be an adventurous penguin.", + "33006": "I would be a soaring lemur.", + "33007": "I would be a curious chimp.", + "40006": "Let's have a party!", + "41054": "I am going to get JumpStars.", + "41055": "I am going to see my mythie.", + "41056": "I am going to decorate my house.", + "41057": "I am going to play arcade games.", + "41058": "I am going to buy a pet.", + "50007": "Have you seen any Punk Punks?", + "51002": "Want to be my neighbor?", + "51003": "Want to see my house?", + "71003": "I like your pet.", + "71004": "I like your ride.", + "71007": "I like your shirt.", + "863": "I am a princess", + "864": "I am a fashion designer.", + "866": "I am a diva.", + "867": "I am a shopaholic.", + "954": "I like to shop.", + "3052": "I like to go to the mall.", + "3054": "I like to go to school dances.", + "4850": "I am going to play Rodeo Racing", + "4851": "I am going to Dance Off", + "4852": "I am going to play Fashion Show.", + "4853": "I am going to the Enchanted Sanctuary", + "5058": "Want to race at Rodeo Racing?", + "6250": "Girl, you're rockin that outfit!", + "6251": "That Rocks!", + "6252": "That is soo cute!", + "6253": "You go girlfriend!", + "6254": "I love your style!", + "6255": "That's adorable", + "6256": "The whole look is fierce!", + "6257": "Like, totally!", + "6258": "Awesome!", + "6259": "You're so sweet!", + "6260": "Chill!", + "6261": "Dun dun dun...", + "6262": "Mojo no no!", + "6263": "Are you serious?!", + "6264": "Sweet!", + "6265": "La-di-da!", + "6266": "Kersplat!", + "6267": "Achoo!", + "6654": "I like your style.", + "6655": "I like your look.", + "6656": "I like your name.", + "6657": "I like your hair.", + "6658": "I like your mouth.", + "6659": "I like your shoes.", + "6660": "I like your eyes.", + "6761": "You are lovely darling." + } +} diff --git a/src/sodoffmmo.csproj b/src/sodoffmmo.csproj index aff0588..7824dd8 100644 --- a/src/sodoffmmo.csproj +++ b/src/sodoffmmo.csproj @@ -21,5 +21,8 @@ PreserveNewest + + PreserveNewest +