diff --git a/src/NadekoBot/Migrations/20161127233843_PokeGame.Designer.cs b/src/NadekoBot/Migrations/20161127233843_PokeGame.Designer.cs new file mode 100644 index 00000000..47f998c4 --- /dev/null +++ b/src/NadekoBot/Migrations/20161127233843_PokeGame.Designer.cs @@ -0,0 +1,802 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using NadekoBot.Services.Database; +using NadekoBot.Services.Database.Models; +using NadekoBot.Modules.Music.Classes; + +namespace NadekoBot.Migrations +{ + [DbContext(typeof(NadekoContext))] + [Migration("20161127233843_PokeGame")] + partial class PokeGame + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.1.0-rtm-22752"); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("ItemId"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("BlacklistItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BotConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BufferSize"); + + b.Property("CurrencyGenerationChance"); + + b.Property("CurrencyGenerationCooldown"); + + b.Property("CurrencyName"); + + b.Property("CurrencyPluralName"); + + b.Property("CurrencySign"); + + b.Property("DMHelpString"); + + b.Property("ForwardMessages"); + + b.Property("ForwardToAllOwners"); + + b.Property("HelpString"); + + b.Property("MigrationVersion"); + + b.Property("RemindMessageFormat"); + + b.Property("RotatingStatuses"); + + b.HasKey("Id"); + + b.ToTable("BotConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BaseDestroyed"); + + b.Property("CallUser"); + + b.Property("ClashWarId"); + + b.Property("SequenceNumber"); + + b.Property("Stars"); + + b.Property("TimeAdded"); + + b.HasKey("Id"); + + b.HasIndex("ClashWarId"); + + b.ToTable("ClashCallers"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashWar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("EnemyClan"); + + b.Property("GuildId"); + + b.Property("Size"); + + b.Property("StartedAt"); + + b.Property("WarState"); + + b.HasKey("Id"); + + b.ToTable("ClashOfClans"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CommandName"); + + b.Property("GuildConfigId"); + + b.Property("Seconds"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandCooldown"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ConvertUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("InternalTrigger"); + + b.Property("Modifier"); + + b.Property("UnitType"); + + b.HasKey("Id"); + + b.ToTable("ConversionUnits"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Currency"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("Reason"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.ToTable("CurrencyTransactions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildId"); + + b.Property("IsRegex"); + + b.Property("OwnerOnly"); + + b.Property("Response"); + + b.Property("Trigger"); + + b.HasKey("Id"); + + b.ToTable("CustomReactions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("Name"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Donators"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Text"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("EightBallResponses"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.Property("GuildConfigId1"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.HasIndex("GuildConfigId1"); + + b.ToTable("FilterChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildConfigId"); + + b.Property("Word"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilteredWord"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.Property("GuildId"); + + b.Property("Type"); + + b.Property("Username"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FollowedStream"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("GCChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AutoAssignRoleId"); + + b.Property("AutoDeleteByeMessages"); + + b.Property("AutoDeleteByeMessagesTimer"); + + b.Property("AutoDeleteGreetMessages"); + + b.Property("AutoDeleteGreetMessagesTimer"); + + b.Property("AutoDeleteSelfAssignedRoleMessages"); + + b.Property("ByeMessageChannelId"); + + b.Property("ChannelByeMessageText"); + + b.Property("ChannelGreetMessageText"); + + b.Property("CleverbotEnabled"); + + b.Property("DefaultMusicVolume"); + + b.Property("DeleteMessageOnCommand"); + + b.Property("DmGreetMessageText"); + + b.Property("ExclusiveSelfAssignedRoles"); + + b.Property("FilterInvites"); + + b.Property("FilterWords"); + + b.Property("GreetMessageChannelId"); + + b.Property("GuildId"); + + b.Property("LogSettingId"); + + b.Property("MuteRoleName"); + + b.Property("PermissionRole"); + + b.Property("RootPermissionId"); + + b.Property("SendChannelByeMessage"); + + b.Property("SendChannelGreetMessage"); + + b.Property("SendDmGreetMessage"); + + b.Property("VerbosePermissions"); + + b.Property("VoicePlusTextEnabled"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.HasIndex("LogSettingId"); + + b.HasIndex("RootPermissionId"); + + b.ToTable("GuildConfigs"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("LogSettingId"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredLogChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("LogSettingId"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredVoicePresenceCHannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelCreated"); + + b.Property("ChannelDestroyed"); + + b.Property("ChannelId"); + + b.Property("ChannelUpdated"); + + b.Property("IsLogging"); + + b.Property("LogUserPresence"); + + b.Property("LogVoicePresence"); + + b.Property("MessageDeleted"); + + b.Property("MessageUpdated"); + + b.Property("UserBanned"); + + b.Property("UserJoined"); + + b.Property("UserLeft"); + + b.Property("UserPresenceChannelId"); + + b.Property("UserUnbanned"); + + b.Property("UserUpdated"); + + b.Property("VoicePresenceChannelId"); + + b.HasKey("Id"); + + b.ToTable("LogSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("ModuleName"); + + b.Property("Prefix"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("ModulePrefixes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Author"); + + b.Property("AuthorId"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.ToTable("MusicPlaylists"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("NextId"); + + b.Property("PrimaryTarget"); + + b.Property("PrimaryTargetId"); + + b.Property("SecondaryTarget"); + + b.Property("SecondaryTargetName"); + + b.Property("State"); + + b.HasKey("Id"); + + b.HasIndex("NextId") + .IsUnique(); + + b.ToTable("Permission"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Status"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("PlayingStatus"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("MusicPlaylistId"); + + b.Property("Provider"); + + b.Property("ProviderType"); + + b.Property("Query"); + + b.Property("Title"); + + b.Property("Uri"); + + b.HasKey("Id"); + + b.HasIndex("MusicPlaylistId"); + + b.ToTable("PlaylistSong"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuthorId"); + + b.Property("AuthorName") + .IsRequired(); + + b.Property("GuildId"); + + b.Property("Keyword") + .IsRequired(); + + b.Property("Text") + .IsRequired(); + + b.HasKey("Id"); + + b.ToTable("Quotes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Icon"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("RaceAnimals"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("IsPrivate"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("UserId"); + + b.Property("When"); + + b.HasKey("Id"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildId"); + + b.Property("Interval"); + + b.Property("Message"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.ToTable("Repeaters"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildId"); + + b.Property("RoleId"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique(); + + b.ToTable("SelfAssignableRoles"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UserPokeTypes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("UserId"); + + b.Property("type"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("PokeGame"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("Blacklist") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b => + { + b.HasOne("NadekoBot.Services.Database.Models.ClashWar", "ClashWar") + .WithMany("Bases") + .HasForeignKey("ClashWarId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("EightBallResponses") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId"); + + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId1"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany() + .HasForeignKey("LogSettingId"); + + b.HasOne("NadekoBot.Services.Database.Models.Permission", "RootPermission") + .WithMany() + .HasForeignKey("RootPermissionId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("IgnoredChannels") + .HasForeignKey("LogSettingId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("IgnoredVoicePresenceChannelIds") + .HasForeignKey("LogSettingId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("ModulePrefixes") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next") + .WithOne("Previous") + .HasForeignKey("NadekoBot.Services.Database.Models.Permission", "NextId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("RotatingStatusMessages") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist") + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("RaceAnimals") + .HasForeignKey("BotConfigId"); + }); + } + } +} diff --git a/src/NadekoBot/Migrations/20161127233843_PokeGame.cs b/src/NadekoBot/Migrations/20161127233843_PokeGame.cs new file mode 100644 index 00000000..1b1a2ab0 --- /dev/null +++ b/src/NadekoBot/Migrations/20161127233843_PokeGame.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace NadekoBot.Migrations +{ + public partial class PokeGame : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "PokeGame", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(nullable: false), + type = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PokeGame", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_PokeGame_UserId", + table: "PokeGame", + column: "UserId", + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "PokeGame"); + } + } +} diff --git a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs index dd4b8543..d209fb74 100644 --- a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs @@ -658,6 +658,23 @@ namespace NadekoBot.Migrations b.ToTable("SelfAssignableRoles"); }); + modelBuilder.Entity("NadekoBot.Services.Database.Models.UserPokeTypes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("UserId"); + + b.Property("type"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("PokeGame"); + }); + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b => { b.HasOne("NadekoBot.Services.Database.Models.BotConfig") diff --git a/src/NadekoBot/Modules/Pokemon/PokeStats.cs b/src/NadekoBot/Modules/Pokemon/PokeStats.cs new file mode 100644 index 00000000..b9795043 --- /dev/null +++ b/src/NadekoBot/Modules/Pokemon/PokeStats.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace NadekoBot.Modules.Pokemon +{ + class PokeStats + { + //Health left + public int Hp { get; set; } = 500; + public int MaxHp { get; } = 500; + //Amount of moves made since last time attacked + public int MovesMade { get; set; } = 0; + //Last people attacked + public List LastAttacked { get; set; } = new List(); + } +} diff --git a/src/NadekoBot/Modules/Pokemon/Pokemon.cs b/src/NadekoBot/Modules/Pokemon/Pokemon.cs new file mode 100644 index 00000000..8a4227f3 --- /dev/null +++ b/src/NadekoBot/Modules/Pokemon/Pokemon.cs @@ -0,0 +1,375 @@ +using Discord.Commands; +using NadekoBot.Attributes; +using NadekoBot.Extensions; +using System.Linq; +using NadekoBot.Services; +using NadekoBot.Services.Database.Models; +using System.Collections.Generic; +using System.Threading.Tasks; +using Discord; +using NLog; +using System; +using Newtonsoft.Json; +using System.IO; +using System.Collections.Concurrent; +using static NadekoBot.Modules.Gambling.Gambling; + +namespace NadekoBot.Modules.Pokemon +{ + + [NadekoModule("PokeGame", ">")] + public partial class Pokemon : DiscordModule + { + private static List PokemonTypes = new List(); + private static ConcurrentDictionary Stats = new ConcurrentDictionary(); + + public const string PokemonTypesFile = "data/pokemon_types.json"; + + private Logger _pokelog { get; } + + public Pokemon(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client) + { + _pokelog = LogManager.GetCurrentClassLogger(); + if (File.Exists(PokemonTypesFile)) + { + PokemonTypes = JsonConvert.DeserializeObject>(File.ReadAllText(PokemonTypesFile)); + } + else + { + _pokelog.Warn(PokemonTypesFile + " is missing. Pokemon types not loaded."); + } + } + + + private int GetDamage(PokemonType usertype, PokemonType targetType) + { + var rng = new Random(); + int damage = rng.Next(40, 60); + foreach (PokemonMultiplier Multiplier in usertype.Multipliers) + { + if (Multiplier.Type == targetType.Name) + { + var multiplier = Multiplier.Multiplication; + damage = (int)(damage * multiplier); + } + } + + return damage; + } + + + private PokemonType GetPokeType(ulong id) + { + + Dictionary setTypes; + using (var uow = DbHandler.UnitOfWork()) + { + setTypes = uow.PokeGame.GetAll().ToDictionary(x => x.UserId, y => y.type); + } + + if (setTypes.ContainsKey(id)) + { + return StringToPokemonType(setTypes[id]); + } + int count = PokemonTypes.Count; + + int remainder = Math.Abs((int)(id % (ulong)count)); + + return PokemonTypes[remainder]; + } + + + + private PokemonType StringToPokemonType(string v) + { + var str = v?.ToUpperInvariant(); + var list = PokemonTypes; + foreach (PokemonType p in list) + { + if (str == p.Name) + { + return p; + } + } + return null; + } + + + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + public async Task Attack(IUserMessage umsg, string move, IGuildUser targetUser = null) + { + var channel = (ITextChannel)umsg.Channel; + IGuildUser user = (IGuildUser)umsg.Author; + + if (string.IsNullOrWhiteSpace(move)) { + return; + } + + if (targetUser == null) + { + await channel.SendMessageAsync("No such person.").ConfigureAwait(false); + return; + } + else if (targetUser == user) + { + await channel.SendMessageAsync("You can't attack yourself.").ConfigureAwait(false); + return; + } + + + // Checking stats first, then move + //Set up the userstats + PokeStats userStats; + userStats = Stats.GetOrAdd(user.Id, new PokeStats()); + + //Check if able to move + //User not able if HP < 0, has made more than 4 attacks + if (userStats.Hp < 0) + { + await channel.SendMessageAsync($"{user.Mention} has fainted and was not able to move!").ConfigureAwait(false); + return; + } + if (userStats.MovesMade >= 5) + { + await channel.SendMessageAsync($"{user.Mention} has used too many moves in a row and was not able to move!").ConfigureAwait(false); + return; + } + if (userStats.LastAttacked.Contains(targetUser.Id)) + { + await channel.SendMessageAsync($"{user.Mention} can't attack again without retaliation!").ConfigureAwait(false); + return; + } + //get target stats + PokeStats targetStats; + targetStats = Stats.GetOrAdd(targetUser.Id, new PokeStats()); + + //If target's HP is below 0, no use attacking + if (targetStats.Hp <= 0) + { + await channel.SendMessageAsync($"{targetUser.Mention} has already fainted!").ConfigureAwait(false); + return; + } + + //Check whether move can be used + PokemonType userType = GetPokeType(user.Id); + + var enabledMoves = userType.Moves; + if (!enabledMoves.Contains(move.ToLowerInvariant())) + { + await channel.SendMessageAsync($"{user.Mention} is not able to use **{move}**. Type {NadekoBot.ModulePrefixes[typeof(Pokemon).Name]}ml to see moves").ConfigureAwait(false); + return; + } + + //get target type + PokemonType targetType = GetPokeType(targetUser.Id); + //generate damage + int damage = GetDamage(userType, targetType); + //apply damage to target + targetStats.Hp -= damage; + + var response = $"{user.Mention} used **{move}**{userType.Icon} on {targetUser.Mention}{targetType.Icon} for **{damage}** damage"; + + //Damage type + if (damage < 40) + { + response += "\nIt's not effective.."; + } + else if (damage > 60) + { + response += "\nIt's super effective!"; + } + else + { + response += "\nIt's somewhat effective"; + } + + //check fainted + + if (targetStats.Hp <= 0) + { + response += $"\n**{targetUser.Mention}** has fainted!"; + } + else + { + response += $"\n**{targetUser.Mention}** has {targetStats.Hp} HP remaining"; + } + + //update other stats + userStats.LastAttacked.Add(targetUser.Id); + userStats.MovesMade++; + targetStats.MovesMade = 0; + if (targetStats.LastAttacked.Contains(user.Id)) + { + targetStats.LastAttacked.Remove(user.Id); + } + + //update dictionary + //This can stay the same right? + Stats[user.Id] = userStats; + Stats[targetUser.Id] = targetStats; + + await channel.SendMessageAsync(response).ConfigureAwait(false); + } + + + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + public async Task Movelist(IUserMessage umsg) + { + var channel = (ITextChannel)umsg.Channel; + IGuildUser user = (IGuildUser)umsg.Author; + + var userType = GetPokeType(user.Id); + var movesList = userType.Moves; + var str = $"**Moves for `{userType.Name}` type.**"; + foreach (string m in movesList) + { + str += $"\n{userType.Icon}{m}"; + } + await channel.SendMessageAsync(str).ConfigureAwait(false); + } + + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + public async Task Heal(IUserMessage umsg, IGuildUser targetUser = null) + { + var channel = (ITextChannel)umsg.Channel; + IGuildUser user = (IGuildUser)umsg.Author; + + if (targetUser == null) { + await channel.SendMessageAsync("No such person.").ConfigureAwait(false); + return; + } + + if (Stats.ContainsKey(targetUser.Id)) + { + var targetStats = Stats[targetUser.Id]; + if (targetStats.Hp == targetStats.MaxHp) + { + await channel.SendMessageAsync($"{targetUser.Mention} already has full HP!").ConfigureAwait(false); + return; + } + //Payment~ + var amount = 1; + + var target = (targetUser.Id == user.Id) ? "yourself" : targetUser.Mention; + if (amount > 0) + { + if (!await CurrencyHandler.RemoveCurrencyAsync(user, $"Poke-Heal {target}", amount, true).ConfigureAwait(false)) + { + try { await channel.SendMessageAsync($"{user.Mention} You don't have enough {CurrencyName}s.").ConfigureAwait(false); } catch { } + return; + } + } + + //healing + targetStats.Hp = targetStats.MaxHp; + if (targetStats.Hp < 0) + { + //Could heal only for half HP? + Stats[targetUser.Id].Hp = (targetStats.MaxHp / 2); + if (target == "yourself") + { + await channel.SendMessageAsync($"You revived yourself with one {CurrencySign}").ConfigureAwait(false); + } + else + { + await channel.SendMessageAsync($"{user.Mention} revived {targetUser.Mention} with one {CurrencySign}").ConfigureAwait(false); + } + return; + } + await channel.SendMessageAsync($"{user.Mention} healed {targetUser.Mention} with one {CurrencySign}").ConfigureAwait(false); + return; + } + else + { + await channel.SendMessageAsync($"{targetUser.Mention} already has full HP!").ConfigureAwait(false); + } + } + + + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + public async Task Type(IUserMessage umsg, IGuildUser targetUser = null) + { + var channel = (ITextChannel)umsg.Channel; + IGuildUser user = (IGuildUser)umsg.Author; + + if (targetUser == null) + { + return; + } + + var pType = GetPokeType(targetUser.Id); + await channel.SendMessageAsync($"Type of {targetUser.Mention} is **{pType.Name.ToLowerInvariant()}**{pType.Icon}").ConfigureAwait(false); + + } + + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + public async Task Settype(IUserMessage umsg, [Remainder] string typeTargeted = null) + { + var channel = (ITextChannel)umsg.Channel; + IGuildUser user = (IGuildUser)umsg.Author; + + var targetType = StringToPokemonType(typeTargeted); + if (targetType == null) + { + await channel.SendTableAsync("`Available types:`\n", PokemonTypes, (t) => $"{t.Icon} {t.Name,-10}").ConfigureAwait(false); + return; + } + if (targetType == GetPokeType(user.Id)) + { + await channel.SendMessageAsync($"Your type is already {targetType.Name.ToLowerInvariant()}{targetType.Icon}").ConfigureAwait(false); + return; + } + + //Payment~ + var amount = 1; + if (amount > 0) + { + if (!await CurrencyHandler.RemoveCurrencyAsync(user, $"{user.Mention} change type to {typeTargeted}", amount, true).ConfigureAwait(false)) + { + try { await channel.SendMessageAsync($"{user.Mention} You don't have enough {CurrencyName}s.").ConfigureAwait(false); } catch { } + return; + } + } + + //Actually changing the type here + Dictionary setTypes; + + using (var uow = DbHandler.UnitOfWork()) + { + var pokeUsers = uow.PokeGame.GetAll(); + setTypes = pokeUsers.ToDictionary(x => x.UserId, y => y.type); + var pt = new UserPokeTypes + { + UserId = user.Id, + type = targetType.Name, + }; + if (!setTypes.ContainsKey(user.Id)) + { + //create user in db + uow.PokeGame.Add(pt); + } + else + { + //update user in db + var pokeUserCmd = pokeUsers.Where(p => p.UserId == user.Id).FirstOrDefault(); + pokeUserCmd.type = targetType.Name; + uow.PokeGame.Update(pokeUserCmd); + } + await uow.CompleteAsync(); + } + + //Now for the response + await channel.SendMessageAsync($"Set type of {user.Mention} to {typeTargeted}{targetType.Icon} for a {CurrencySign}").ConfigureAwait(false); + } + + } +} + + + + diff --git a/src/NadekoBot/Modules/Pokemon/PokemonType.cs b/src/NadekoBot/Modules/Pokemon/PokemonType.cs new file mode 100644 index 00000000..d4cf9007 --- /dev/null +++ b/src/NadekoBot/Modules/Pokemon/PokemonType.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Modules.Pokemon +{ + public class PokemonType + { + public PokemonType(string n, string i, string[] m, List multi) + { + Name = n; + Icon = i; + Moves = m; + Multipliers = multi; + } + public string Name { get; set; } + public List Multipliers { get; set; } + public string Icon { get; set; } + public string[] Moves { get; set; } + } + public class PokemonMultiplier + { + public PokemonMultiplier(string t, double m) + { + Type = t; + Multiplication = m; + } + public string Type { get; set; } + public double Multiplication { get; set; } + } +} diff --git a/src/NadekoBot/Resources/CommandStrings.Designer.cs b/src/NadekoBot/Resources/CommandStrings.Designer.cs index 9bee88cc..9c0b8ac7 100644 --- a/src/NadekoBot/Resources/CommandStrings.Designer.cs +++ b/src/NadekoBot/Resources/CommandStrings.Designer.cs @@ -491,6 +491,33 @@ namespace NadekoBot.Resources { } } + /// + /// Looks up a localized string similar to attack. + /// + public static string attack_cmd { + get { + return ResourceManager.GetString("attack_cmd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Attacks a target with the given move. Use `{0}movelist` to see a list of moves your type can use.. + /// + public static string attack_desc { + get { + return ResourceManager.GetString("attack_desc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `{0}attack "vine whip" @someguy`. + /// + public static string attack_usage { + get { + return ResourceManager.GetString("attack_usage", resourceCulture); + } + } + /// /// Looks up a localized string similar to autoassignrole aar. /// @@ -2894,6 +2921,33 @@ namespace NadekoBot.Resources { } } + /// + /// Looks up a localized string similar to heal. + /// + public static string heal_cmd { + get { + return ResourceManager.GetString("heal_cmd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Heals someone. Revives those who fainted. Costs a NadekoFlower. + /// + public static string heal_desc { + get { + return ResourceManager.GetString("heal_desc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `{0}heal @someone`. + /// + public static string heal_usage { + get { + return ResourceManager.GetString("heal_usage", resourceCulture); + } + } + /// /// Looks up a localized string similar to hearthstone hs. /// @@ -4271,6 +4325,33 @@ namespace NadekoBot.Resources { } } + /// + /// Looks up a localized string similar to movelist ml. + /// + public static string movelist_cmd { + get { + return ResourceManager.GetString("movelist_cmd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lists the moves you are able to use. + /// + public static string movelist_desc { + get { + return ResourceManager.GetString("movelist_desc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `{0}ml`. + /// + public static string movelist_usage { + get { + return ResourceManager.GetString("movelist_usage", resourceCulture); + } + } + /// /// Looks up a localized string similar to moveperm mp. /// @@ -6269,6 +6350,33 @@ namespace NadekoBot.Resources { } } + /// + /// Looks up a localized string similar to settype. + /// + public static string settype_cmd { + get { + return ResourceManager.GetString("settype_cmd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Set your poketype. Costs a NadekoFlower. Provide no arguments to see a list of available types.. + /// + public static string settype_desc { + get { + return ResourceManager.GetString("settype_desc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `{0}settype fire` or `{0}settype`. + /// + public static string settype_usage { + get { + return ResourceManager.GetString("settype_usage", resourceCulture); + } + } + /// /// Looks up a localized string similar to shorten. /// @@ -6971,6 +7079,33 @@ namespace NadekoBot.Resources { } } + /// + /// Looks up a localized string similar to type. + /// + public static string type_cmd { + get { + return ResourceManager.GetString("type_cmd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Get the poketype of the target.. + /// + public static string type_desc { + get { + return ResourceManager.GetString("type_desc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `{0}type @someone`. + /// + public static string type_usage { + get { + return ResourceManager.GetString("type_usage", resourceCulture); + } + } + /// /// Looks up a localized string similar to typeadd. /// diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 26c79ade..18b60146 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -2718,4 +2718,49 @@ {0}yodify I was once an adventurer like you` or `{0}yoda my feelings hurt` + + attack + + + Attacks a target with the given move. Use `{0}movelist` to see a list of moves your type can use. + + + `{0}attack "vine whip" @someguy` + + + heal + + + Heals someone. Revives those who fainted. Costs a NadekoFlower + + + `{0}heal @someone` + + + movelist ml + + + Lists the moves you are able to use + + + `{0}ml` + + + settype + + + Set your poketype. Costs a NadekoFlower. Provide no arguments to see a list of available types. + + + `{0}settype fire` or `{0}settype` + + + type + + + Get the poketype of the target. + + + `{0}type @someone` + \ No newline at end of file diff --git a/src/NadekoBot/Services/Database/IUnitOfWork.cs b/src/NadekoBot/Services/Database/IUnitOfWork.cs index 66359ef2..c90d9736 100644 --- a/src/NadekoBot/Services/Database/IUnitOfWork.cs +++ b/src/NadekoBot/Services/Database/IUnitOfWork.cs @@ -21,6 +21,7 @@ namespace NadekoBot.Services.Database ICurrencyRepository Currency { get; } ICurrencyTransactionsRepository CurrencyTransactions { get; } IMusicPlaylistRepository MusicPlaylists { get; } + IPokeGameRepository PokeGame { get; } int Complete(); Task CompleteAsync(); diff --git a/src/NadekoBot/Services/Database/Models/PokeType.cs b/src/NadekoBot/Services/Database/Models/PokeType.cs new file mode 100644 index 00000000..402ffd28 --- /dev/null +++ b/src/NadekoBot/Services/Database/Models/PokeType.cs @@ -0,0 +1,15 @@ +using Discord; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Services.Database.Models +{ + public class UserPokeTypes : DbEntity + { + public ulong UserId { get; set; } + public string type { get; set; } + } +} diff --git a/src/NadekoBot/Services/Database/NadekoContext.cs b/src/NadekoBot/Services/Database/NadekoContext.cs index da16e598..6752343a 100644 --- a/src/NadekoBot/Services/Database/NadekoContext.cs +++ b/src/NadekoBot/Services/Database/NadekoContext.cs @@ -22,6 +22,7 @@ namespace NadekoBot.Services.Database public DbSet MusicPlaylists { get; set; } public DbSet CustomReactions { get; set; } public DbSet CurrencyTransactions { get; set; } + public DbSet PokeGame { get; set; } //logging public DbSet LogSettings { get; set; } @@ -43,6 +44,7 @@ namespace NadekoBot.Services.Database this.Database.Migrate(); EnsureSeedData(); } + //Uncomment this to db initialisation with dotnet ef migration add [module] //protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) //{ // optionsBuilder.UseSqlite("Filename=./data/NadekoBot.db"); @@ -69,7 +71,8 @@ namespace NadekoBot.Services.Database new ModulePrefix() { ModuleName = "Permissions", Prefix = ";" }, new ModulePrefix() { ModuleName = "Pokemon", Prefix = ">" }, new ModulePrefix() { ModuleName = "Utility", Prefix = "." }, - new ModulePrefix() { ModuleName = "CustomReactions", Prefix = "." } + new ModulePrefix() { ModuleName = "CustomReactions", Prefix = "." }, + new ModulePrefix() { ModuleName = "PokeGame", Prefix = ">" } }); bc.RaceAnimals.AddRange(new HashSet { @@ -216,7 +219,17 @@ namespace NadekoBot.Services.Database .HasMany(p => p.Songs) .WithOne() .OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Cascade); - + + + #endregion + + #region PokeGame + var pokeGameEntity = modelBuilder.Entity(); + + pokeGameEntity + .HasIndex(pt => pt.UserId) + .IsUnique(); + #endregion } diff --git a/src/NadekoBot/Services/Database/Repositories/IPokeGameRepository.cs b/src/NadekoBot/Services/Database/Repositories/IPokeGameRepository.cs new file mode 100644 index 00000000..ca698422 --- /dev/null +++ b/src/NadekoBot/Services/Database/Repositories/IPokeGameRepository.cs @@ -0,0 +1,10 @@ +using NadekoBot.Services.Database.Models; +using System.Collections.Generic; + +namespace NadekoBot.Services.Database.Repositories +{ + public interface IPokeGameRepository : IRepository + { + //List GetAllPokeTypes(); + } +} diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/PokeGameRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/PokeGameRepository.cs new file mode 100644 index 00000000..f23f17ca --- /dev/null +++ b/src/NadekoBot/Services/Database/Repositories/Impl/PokeGameRepository.cs @@ -0,0 +1,23 @@ +using NadekoBot.Services.Database.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.EntityFrameworkCore; + +namespace NadekoBot.Services.Database.Repositories.Impl +{ + public class PokeGameRepository : Repository, IPokeGameRepository + { + public PokeGameRepository(DbContext context) : base(context) + { + + } + + //List GetAllPokeTypes() + //{ + // var toReturn = _set.Include(pt => pt.UserId).ToList(); + // toReturn.ForEach(pt => pt.).ToList(); + // return toReturn; + //} + } +} diff --git a/src/NadekoBot/Services/Database/UnitOfWork.cs b/src/NadekoBot/Services/Database/UnitOfWork.cs index 7ba343ee..9601145d 100644 --- a/src/NadekoBot/Services/Database/UnitOfWork.cs +++ b/src/NadekoBot/Services/Database/UnitOfWork.cs @@ -48,6 +48,9 @@ namespace NadekoBot.Services.Database private ICustomReactionRepository _customReactions; public ICustomReactionRepository CustomReactions => _customReactions ?? (_customReactions = new CustomReactionsRepository(_context)); + private IPokeGameRepository _pokegame; + public IPokeGameRepository PokeGame => _pokegame ?? (_pokegame = new PokeGameRepository(_context)); + public UnitOfWork(NadekoContext context) { _context = context; diff --git a/src/NadekoBot/credentials.json b/src/NadekoBot/credentials.json index 31a9414f..ea5d4f0c 100644 --- a/src/NadekoBot/credentials.json +++ b/src/NadekoBot/credentials.json @@ -1,9 +1,9 @@ { "ClientId": 123123123, "BotId": null, - "Token": "", + "Token": "MTE5Nzc3MDIxMzE5NTc3NjEw.CyXckQ.fmDOe4x1QRK_6hQYvS8drohUwNM", "OwnerIds": [ - 0 + 105635576866156544 ], "LoLApiKey": "", "GoogleApiKey": "", diff --git a/src/NadekoBot/data/pokemon_types.json b/src/NadekoBot/data/pokemon_types.json new file mode 100644 index 00000000..6d7ac74a --- /dev/null +++ b/src/NadekoBot/data/pokemon_types.json @@ -0,0 +1,699 @@ +[ + { + "Name": "NORMAL", + "Multipliers": [ + { + "Type": "ROCK", + "Multiplication": 0.5 + }, + { + "Type": "GHOST", + "Multiplication": 0 + }, + { + "Type": "STEEL", + "Multiplication": 0.5 + } + ], + "Moves": [ + "sonic boom", + "quick attack", + "doubleslap", + "headbutt" + ], + "Icon": "⭕️" + }, + { + "Name": "FIRE", + "Multipliers": [ + { + "Type": "FIRE", + "Multiplication": 0.5 + }, + { + "Type": "WATER", + "Multiplication": 0.5 + }, + { + "Type": "GRASS", + "Multiplication": 2 + }, + { + "Type": "ICE", + "Multiplication": 2 + }, + { + "Type": "BUG", + "Multiplication": 2 + }, + { + "Type": "ROCK", + "Multiplication": 0.5 + }, + { + "Type": "DRAGON", + "Multiplication": 0.5 + }, + { + "Type": "STEEL", + "Multiplication": 2 + } + ], + "Moves": [ + "incinerate", + "ember", + "fire punch", + "fiery dance" + ], + "Icon": "🔥" + }, + { + "Name": "WATER", + "Multipliers": [ + { + "Type": "FIRE", + "Multiplication": 2 + }, + { + "Type": "WATER", + "Multiplication": 0.5 + }, + { + "Type": "GRASS", + "Multiplication": 0.5 + }, + { + "Type": "GROUND", + "Multiplication": 2 + }, + { + "Type": "ROCK", + "Multiplication": 2 + }, + { + "Type": "DRAGON", + "Multiplication": 0.5 + } + ], + "Moves": [ + "bubblebeam", + "dive", + "whirlpool", + "aqua tail" + ], + "Icon": "💦" + }, + { + "Name": "ELECTRIC", + "Multipliers": [ + { + "Type": "WATER", + "Multiplication": 2 + }, + { + "Type": "ELECTRIC", + "Multiplication": 0.5 + }, + { + "Type": "GRASS", + "Multiplication": 0.5 + }, + { + "Type": "GROUND", + "Multiplication": 0 + }, + { + "Type": "FLYING", + "Multiplication": 2 + }, + { + "Type": "DRAGON", + "Multiplication": 0.5 + } + ], + "Moves": [ + "nuzzle", + "thunderbolt", + "thundershock", + "discharge" + ], + "Icon": "⚡" + }, + { + "Name": "GRASS", + "Multipliers": [ + { + "Type": "FIRE", + "Multiplication": 0.5 + }, + { + "Type": "WATER", + "Multiplication": 2 + }, + { + "Type": "GRASS", + "Multiplication": 0.5 + }, + { + "Type": "ICE", + "Multiplication": 0.5 + }, + { + "Type": "BUG", + "Multiplication": 0.5 + }, + { + "Type": "ROCK", + "Multiplication": 2 + }, + { + "Type": "DRAGON", + "Multiplication": 0.5 + }, + { + "Type": "STEEL", + "Multiplication": 0.5 + }, + { + "Type": "POISON", + "Multiplication": 0.5 + }, + { + "Type": "GROUND", + "Multiplication": 2 + } + ], + "Moves": [ + "absorb", + "mega drain", + "vine whip", + "razor leaf" + ], + "Icon": "🍃" + }, + { + "Name": "ICE", + "Multipliers": [ + { + "Type": "FIRE", + "Multiplication": 0.5 + }, + { + "Type": "WATER", + "Multiplication": 0.5 + }, + { + "Type": "GRASS", + "Multiplication": 2 + }, + { + "Type": "ICE", + "Multiplication": 0.5 + }, + { + "Type": "GROUND", + "Multiplication": 2 + }, + { + "Type": "FLYING", + "Multiplication": 2 + }, + { + "Type": "DRAGON", + "Multiplication": 2 + }, + { + "Type": "STEEL", + "Multiplication": 0.5 + } + ], + "Moves": [ + "ice ball", + "powder snow", + "avalanche", + "icy wind" + ], + "Icon": "❄" + }, + { + "Name": "FIGHTING", + "Multipliers": [ + { + "Type": "NORMAL", + "Multiplication": 2 + }, + { + "Type": "ICE", + "Multiplication": 2 + }, + { + "Type": "POISON", + "Multiplication": 0.5 + }, + { + "Type": "FLYING", + "Multiplication": 0.5 + }, + { + "Type": "PSYCHIC", + "Multiplication": 0.5 + }, + { + "Type": "BUG", + "Multiplication": 0.5 + }, + { + "Type": "ROCK", + "Multiplication": 2 + }, + { + "Type": "GHOST", + "Multiplication": 0 + }, + { + "Type": "DARK", + "Multiplication": 2 + }, + { + "Type": "STEEL", + "Multiplication": 2 + }, + { + "Type": "FAIRY", + "Multiplication": 0.5 + } + ], + "Moves": [ + "low kick", + "force palm", + "mach punch", + "double kick" + ], + "Icon": "✊" + }, + { + "Name": "POISON", + "Multipliers": [ + { + "Type": "GRASS", + "Multiplication": 2 + }, + { + "Type": "POISON", + "Multiplication": 0.5 + }, + { + "Type": "GROUND", + "Multiplication": 0.5 + }, + { + "Type": "ROCK", + "Multiplication": 0.5 + }, + { + "Type": "GHOST", + "Multiplication": 0.5 + }, + { + "Type": "STEEL", + "Multiplication": 0 + }, + { + "Type": "FAIRY", + "Multiplication": 2 + } + ], + "Moves": [ + "acid", + "smog", + "sludge", + "poison jab" + ], + "Icon": "☠" + }, + { + "Name": "GROUND", + "Multipliers": [ + { + "Type": "FIRE", + "Multiplication": 2 + }, + { + "Type": "ELECTRIC", + "Multiplication": 2 + }, + { + "Type": "GRASS", + "Multiplication": 0.5 + }, + { + "Type": "POISON", + "Multiplication": 2 + }, + { + "Type": "FLYING", + "Multiplication": 0 + }, + { + "Type": "BUG", + "Multiplication": 0.5 + }, + { + "Type": "ROCK", + "Multiplication": 2 + }, + { + "Type": "STEEL", + "Multiplication": 2 + } + ], + "Moves": [ + "mud-slap", + "earthquake", + "bulldoze", + "dig" + ], + "Icon": "🗻" + }, + { + "Name": "FLYING", + "Multipliers": [ + { + "Type": "ELECTRIC", + "Multiplication": 0.5 + }, + { + "Type": "GRASS", + "Multiplication": 2 + }, + { + "Type": "FIGHTING", + "Multiplication": 2 + }, + { + "Type": "BUG", + "Multiplication": 2 + }, + { + "Type": "ROCK", + "Multiplication": 0.5 + }, + { + "Type": "STEEL", + "Multiplication": 0.5 + } + ], + "Moves": [ + "peck", + "pluck", + "gust", + "aerial ace" + ], + "Icon": "☁" + }, + { + "Name": "PSYCHIC", + "Multipliers": [ + { + "Type": "FIGHTING", + "Multiplication": 2 + }, + { + "Type": "POISON", + "Multiplication": 2 + }, + { + "Type": "PSYCHIC", + "Multiplication": 0.5 + }, + { + "Type": "DARK", + "Multiplication": 0 + }, + { + "Type": "STEEL", + "Multiplication": 0.5 + } + ], + "Moves": [ + "confusion", + "psybeam", + "psywave", + "heart stamp" + ], + "Icon": "🔮" + }, + { + "Name": "BUG", + "Multipliers": [ + { + "Type": "FIRE", + "Multiplication": 0.5 + }, + { + "Type": "GRASS", + "Multiplication": 2 + }, + { + "Type": "FIGHTING", + "Multiplication": 0.5 + }, + { + "Type": "POISON", + "Multiplication": 0.5 + }, + { + "Type": "FLYING", + "Multiplication": 0.5 + }, + { + "Type": "PSYCHIC", + "Multiplication": 2 + }, + { + "Type": "ROCK", + "Multiplication": 0.5 + }, + { + "Type": "DARK", + "Multiplication": 2 + }, + { + "Type": "STEEL", + "Multiplication": 0.5 + }, + { + "Type": "FAIRY", + "Multiplication": 0.5 + } + ], + "Moves": [ + "bug bite", + "infestation", + "x-scissors", + "twineedle" + ], + "Icon": "🐛" + }, + { + "Name": "ROCK", + "Multipliers": [ + { + "Type": "FIRE", + "Multiplication": 2 + }, + { + "Type": "ICE", + "Multiplication": 2 + }, + { + "Type": "FIGHTING", + "Multiplication": 0.5 + }, + { + "Type": "GROUND", + "Multiplication": 0.5 + }, + { + "Type": "FLYING", + "Multiplication": 2 + }, + { + "Type": "BUG", + "Multiplication": 2 + }, + { + "Type": "STEEL", + "Multiplication": 0.5 + } + ], + "Moves": [ + "rock throw", + "rollout", + "rock tomb", + "rock blast" + ], + "Icon": "💎" + }, + { + "Name": "GHOST", + "Multipliers": [ + { + "Type": "NORMAL", + "Multiplication": 0 + }, + { + "Type": "PSYCHIC", + "Multiplication": 2 + }, + { + "Type": "GHOST", + "Multiplication": 2 + }, + { + "Type": "DARK", + "Multiplication": 0.5 + } + ], + "Moves": [ + "astonish", + "night shade", + "lick", + "ominous wind", + "hex" + ], + "Icon": "👻" + }, + { + "Name": "DRAGON", + "Multipliers": [ + { + "Type": "DRAGON", + "Multiplication": 2 + }, + { + "Type": "STEEL", + "Multiplication": 0.5 + }, + { + "Type": "FAIRY", + "Multiplication": 0 + } + ], + "Moves": [ + "dragon tail", + "dragon rage", + "dragonbreath", + "twister" + ], + "Icon": "🐉" + }, + { + "Name": "DARK", + "Multipliers": [ + { + "Type": "FIGHTING", + "Multiplication": 0.5 + }, + { + "Type": "PSYCHIC", + "Multiplication": 2 + }, + { + "Type": "GHOST", + "Multiplication": 2 + }, + { + "Type": "DARK", + "Multiplication": 0.5 + }, + { + "Type": "FAIRY", + "Multiplication": 0.5 + } + ], + "Moves": [ + "pursuit", + "assurance", + "bite", + "faint attack" + ], + "Icon": "✴" + }, + { + "Name": "STEEL", + "Multipliers": [ + { + "Type": "FIRE", + "Multiplication": 0.5 + }, + { + "Type": "WATER", + "Multiplication": 0.5 + }, + { + "Type": "ELECTRIC", + "Multiplication": 0.5 + }, + { + "Type": "ICE", + "Multiplication": 2 + }, + { + "Type": "ROCK", + "Multiplication": 2 + }, + { + "Type": "STEEL", + "Multiplication": 0.5 + }, + { + "Type": "FAIRY", + "Multiplication": 2 + } + ], + "Moves": [ + "bullet punch", + "metal burst", + "gear grind", + "magnet bomb" + ], + "Icon": "🔩" + }, + { + "Name": "FAIRY", + "Multipliers": [ + { + "Type": "FIGHTING", + "Multiplication": 2 + }, + { + "Type": "FIRE", + "Multiplication": 0.5 + }, + { + "Type": "DARK", + "Multiplication": 2 + }, + { + "Type": "POISON", + "Multiplication": 0.5 + }, + { + "Type": "STEEL", + "Multiplication": 0.5 + }, + { + "Type": "DRAGON", + "Multiplication": 2 + } + ], + "Moves": [ + "fairy wind", + "draining kiss", + "dazzling gleam", + "play rough" + ], + "Icon": "💫" + } +]