public async Task GetInfo(string name) { // Prioritize species first. Species[] species = await BotUtils.GetSpeciesFromDb("", name); if (species.Count() > 0) { if (await BotUtils.ReplyValidateSpeciesAsync(Context, species)) { await SpeciesCommands.ShowSpeciesInfoAsync(Context, species[0]); } } else { // Otherwise, show other taxon. Taxon[] taxa = await BotUtils.GetTaxaFromDb(name); if (taxa.Count() <= 0) { // This command was traditionally used with species, so show the user species suggestions in the event of no matches. await BotUtils.ReplyAsync_SpeciesSuggestions(Context, "", name, async (BotUtils.ConfirmSuggestionArgs args) => await GetInfo(args.Suggestion)); } else if (await BotUtils.ReplyAsync_ValidateTaxa(Context, taxa)) { await BotUtils.Command_ShowTaxon(Context, taxa[0].type, name); } } }
public async Task AppendDescription(string arg0, string arg1) { // Possible input: // +desc <genus> <species> // +desc <species> <description> Species[] species_list = await BotUtils.GetSpeciesFromDb(arg0, arg1); if (species_list.Count() <= 0) { // We weren't able to find a species with the given genus and name, so perhaps the user provided a species and description. // The following method call will handle this situation, as well as the situation where the species was invalid. await AppendDescription("", species : arg0, description : arg1); } else if (await BotUtils.ReplyValidateSpeciesAsync(Context, species_list)) { // Initialize a multistage update for the given species. Species species = species_list[0]; // Ensure that the user has necessary privileges to use this command. if (!await BotUtils.ReplyHasPrivilegeOrOwnershipAsync(Context, PrivilegeLevel.ServerModerator, species)) { return; } await _appendDescriptionAsync(species); } }
public async Task SetSpeciesDescription(string speciesOrGenus, string descriptionOrSpecies) { // Either the user provided a species and a description, or they provided a genus and species and want to use the two-part command. // If the species exists, we'll use the two-part command version. If it doesn't, we'll assume the user was providing a description directly. Species[] species_list = await BotUtils.GetSpeciesFromDb(speciesOrGenus, descriptionOrSpecies); if (species_list.Count() <= 0) { // No such species exists for the given genus/species. We have two possibilities. if (!string.IsNullOrEmpty(speciesOrGenus)) { // The user passed in a species and a description, so attempt to update the description for that species. await SetSpeciesDescription(string.Empty, speciesOrGenus, descriptionOrSpecies); } else { // The user passed in a blank genus and a non-existent species, so reply with some suggestions. await BotUtils.ReplyAsync_SpeciesSuggestions(Context, speciesOrGenus, descriptionOrSpecies); } } else if (await BotUtils.ReplyValidateSpeciesAsync(Context, species_list)) { // A species exists with the given genus/species, so initiate a two-part command. // Ensure that the user has necessary privileges to use this command. if (!await BotUtils.ReplyHasPrivilegeOrOwnershipAsync(Context, PrivilegeLevel.ServerModerator, species_list[0])) { return; } await _setSpeciesDescriptionAsync(species_list[0]); } }
public async Task Predates(string genus, string species = "") { // If the species parameter was not provided, assume the user only provided the species. if (string.IsNullOrEmpty(species)) { species = genus; genus = string.Empty; } Species sp = await BotUtils.ReplyFindSpeciesAsync(Context, genus, species); if (sp is null) { return; } EmbedBuilder embed = new EmbedBuilder(); using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM Predates WHERE eats_id=$eats_id AND species_id NOT IN (SELECT species_id FROM Extinctions);")) { cmd.Parameters.AddWithValue("$eats_id", sp.Id); using (DataTable rows = await Database.GetRowsAsync(cmd)) { if (rows.Rows.Count <= 0) { await BotUtils.ReplyAsync_Info(Context, string.Format("**{0}** has no extant natural predators.", sp.ShortName)); } else { List <string> lines = new List <string>(); foreach (DataRow row in rows.Rows) { Species s = await BotUtils.GetSpeciesFromDb(row.Field <long>("species_id")); string notes = row.Field <string>("notes"); string line_text = s.ShortName; if (!string.IsNullOrEmpty(notes)) { line_text += string.Format(" ({0})", notes.ToLower()); } lines.Add(s.IsExtinct ? string.Format("~~{0}~~", line_text) : line_text); } lines.Sort(); embed.WithTitle(string.Format("Predators of {0} ({1})", sp.ShortName, lines.Count())); embed.WithDescription(string.Join(Environment.NewLine, lines)); await ReplyAsync("", false, embed.Build()); } } } }
public async Task Roles(string nameOrSpecies) { // If a role with this name exists, that's what we'll prioritize (users can use the genus + species overload if they need to). // If no such role exists, check for a species with this name instead. Role role = await BotUtils.GetRoleFromDb(nameOrSpecies); if (role is null) { // No such role exists, so check if a species exists with the given name instead. Species[] matching_species = await BotUtils.GetSpeciesFromDb("", nameOrSpecies); if (matching_species.Count() == 1) { // If only one species was returned, show the roles assigned to that species. await Roles(matching_species[0]); } else if (matching_species.Count() > 1) { // If multiple species were returned, provide a list of matching species for the user to choose from. await BotUtils.ReplyValidateSpeciesAsync(Context, matching_species); } if (matching_species.Count() > 0) { return; } } // If we got here, the role is eiher not null, or it is null, but no species with the given name exists. // In this case, proceed to validate the role, and display its information if possible. if (!await BotUtils.ReplyAsync_ValidateRole(Context, role)) { return; } // List all extant species with this role. List <Species> species_list = new List <Species>(await BotUtils.GetSpeciesFromDbByRole(role)); species_list.RemoveAll(x => x.IsExtinct); species_list.Sort((lhs, rhs) => lhs.ShortName.CompareTo(rhs.ShortName)); Bot.PaginatedMessageBuilder embed = new Bot.PaginatedMessageBuilder(EmbedUtils.SpeciesListToEmbedPages(species_list, fieldName: string.Format("Extant species with this role ({0}):", species_list.Count()))); embed.SetTitle(string.Format("Role: {0}", StringUtils.ToTitleCase(role.name))); embed.SetDescription(role.GetDescriptionOrDefault()); await Bot.DiscordUtils.SendMessageAsync(Context, embed.Build()); }
public async Task Size(string genusOrSpecies, string speciesOrUnits) { // This command can be used in a number of ways: // <genus> <species> -> returns size for that species // <species> <units> -> returns size for that species, using the given units Species species = null; LengthUnit units = LengthUnit.Unknown; // Attempt to get the specified species, assuming the user passed in <genus> <species>. Species[] species_array = await BotUtils.GetSpeciesFromDb(genusOrSpecies, speciesOrUnits); if (species_array.Count() > 1) { await BotUtils.ReplyValidateSpeciesAsync(Context, species_array); } else if (species_array.Count() == 1) { species = species_array[0]; } else if (species_array.Count() <= 0) { // If we didn't get any species by treating the arguments as <genus> <species>, attempt to get the species by <species> only. species = await BotUtils.ReplyFindSpeciesAsync(Context, "", genusOrSpecies); // If this still fails, there's nothing left to do. if (species is null) { return; } // Assume the second argument was the desired units. // Make sure the units given are valid. units = new Length(0.0, speciesOrUnits).Units; if (units == LengthUnit.Unknown) { await BotUtils.ReplyAsync_Error(Context, string.Format("Invalid units (\"{0}\").", speciesOrUnits)); return; } } if (!(species is null)) { await Size(species, units); } }
public async Task AddSpecies(string genus, string species, string zone = "", string description = "") { // Check if the species already exists before attempting to add it. if ((await BotUtils.GetSpeciesFromDb(genus, species)).Count() > 0) { await BotUtils.ReplyAsync_Warning(Context, string.Format("The species \"{0}\" already exists.", BotUtils.GenerateSpeciesName(genus, species))); return; } await BotUtils.AddGenusToDb(genus); Taxon genus_info = await BotUtils.GetGenusFromDb(genus); using (SQLiteCommand cmd = new SQLiteCommand("INSERT INTO Species(name, description, genus_id, owner, timestamp, user_id) VALUES($name, $description, $genus_id, $owner, $timestamp, $user_id);")) { cmd.Parameters.AddWithValue("$name", species.ToLower()); cmd.Parameters.AddWithValue("$description", description); cmd.Parameters.AddWithValue("$genus_id", genus_info.id); cmd.Parameters.AddWithValue("$owner", Context.User.Username); cmd.Parameters.AddWithValue("$user_id", Context.User.Id); cmd.Parameters.AddWithValue("$timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds()); await Database.ExecuteNonQuery(cmd); } Species[] sp_list = await BotUtils.GetSpeciesFromDb(genus, species); Species sp = sp_list.Count() > 0 ? sp_list[0] : null; long species_id = sp == null ? -1 : sp.Id; if (species_id < 0) { await BotUtils.ReplyAsync_Error(Context, "Failed to add species (invalid Species ID)."); return; } // Add to all given zones. await _plusZone(sp, zone, string.Empty, onlyShowErrors : true); // Add the user to the trophy scanner queue in case their species earned them any new trophies. if (OurFoodChainBot.Instance.Config.TrophiesEnabled) { await Global.TrophyScanner.AddToQueueAsync(Context, Context.User.Id); } await BotUtils.ReplyAsync_Success(Context, string.Format("Successfully created new species, **{0}**.", BotUtils.GenerateSpeciesName(genus, species))); }
public async Task Gallery(string speciesOrTaxon) { // Prioritize species galleries first. Species[] species = await BotUtils.GetSpeciesFromDb("", speciesOrTaxon); if (species is null || species.Count() <= 0) { // No such species exists, so check if a taxon exists. Taxon taxon = await BotUtils.GetTaxonFromDb(speciesOrTaxon); if (taxon is null) { // If no such taxon exists, show species recommendations to the user. await BotUtils.ReplyAsync_SpeciesSuggestions(Context, "", speciesOrTaxon); } else { // The taxon does exist, so we'll generate a gallery from this taxon. // First, images for this taxon will be added, followed by the galleries for all species under it. List <Picture> pictures = new List <Picture>(); if (!string.IsNullOrEmpty(taxon.pics)) { pictures.Add(new Picture(taxon.pics)); } foreach (Species sp in await BotUtils.GetSpeciesInTaxonFromDb(taxon)) { pictures.AddRange(await SpeciesUtils.GetPicturesAsync(sp)); } await ShowGalleryAsync(Context, taxon.GetName(), pictures.ToArray()); } }
public async Task SetAncestor(string genus, string species, string ancestorGenus, string ancestorSpecies) { // Get the descendant and ancestor species. Species[] descendant_list = await BotUtils.GetSpeciesFromDb(genus, species); Species[] ancestor_list = await BotUtils.GetSpeciesFromDb(ancestorGenus, ancestorSpecies); if (descendant_list.Count() > 1) { await BotUtils.ReplyAsync_Error(Context, string.Format("The child species \"{0}\" is too vague (there are multiple matches). Try including the genus.", species)); } else if (ancestor_list.Count() > 1) { await BotUtils.ReplyAsync_Error(Context, string.Format("The ancestor species \"{0}\" is too vague (there are multiple matches). Try including the genus.", ancestorSpecies)); } else if (descendant_list.Count() == 0) { await BotUtils.ReplyAsync_Error(Context, "The child species does not exist."); } else if (ancestor_list.Count() == 0) { await BotUtils.ReplyAsync_Error(Context, "The parent species does not exist."); } else if (descendant_list[0].Id == ancestor_list[0].Id) { await BotUtils.ReplyAsync_Error(Context, "A species cannot be its own ancestor."); } else { Species descendant = descendant_list[0]; Species ancestor = ancestor_list[0]; // Check if an ancestor has already been set for this species. If so, update the ancestor, but we'll show a different message later notifying the user of the change. Species existing_ancestor_sp = null; using (SQLiteCommand cmd = new SQLiteCommand("SELECT ancestor_id FROM Ancestors WHERE species_id=$species_id;")) { cmd.Parameters.AddWithValue("$species_id", descendant.Id); DataRow row = await Database.GetRowAsync(cmd); if (!(row is null)) { long ancestor_id = row.Field <long>("ancestor_id"); existing_ancestor_sp = await BotUtils.GetSpeciesFromDb(ancestor_id); } } // If the ancestor has already been set to the species specified, quit. if (!(existing_ancestor_sp is null) && existing_ancestor_sp.Id == ancestor.Id) { await BotUtils.ReplyAsync_Warning(Context, string.Format("**{0}** has already been set as the ancestor of **{1}**.", ancestor.ShortName, descendant.ShortName)); return; } // Insert the new relationship into the database. using (SQLiteCommand cmd = new SQLiteCommand("INSERT OR REPLACE INTO Ancestors(species_id, ancestor_id) VALUES($species_id, $ancestor_id);")) { cmd.Parameters.AddWithValue("$species_id", descendant.Id); cmd.Parameters.AddWithValue("$ancestor_id", ancestor.Id); await Database.ExecuteNonQuery(cmd); } if (existing_ancestor_sp is null) { await BotUtils.ReplyAsync_Success(Context, string.Format("**{0}** has been set as the ancestor of **{1}**.", ancestor.ShortName, descendant.ShortName)); } else { await BotUtils.ReplyAsync_Success(Context, string.Format("**{0}** has replaced **{1}** as the ancestor of **{2}**.", ancestor.ShortName, existing_ancestor_sp.ShortName, descendant.ShortName)); } } }
public async Task SetTaxonDescription(string taxonNameOrGenus, string descriptionOrSpecies) { // Either the user provided a taxon and a description, or they provided a genus and species and want to use a two-part command sequence. // If the species exists, we'll use the two-part command version. If it doesn't, we'll assume the user was providing a description directly. Species[] species_list = await BotUtils.GetSpeciesFromDb(taxonNameOrGenus, descriptionOrSpecies); if (species_list.Count() <= 0) { // No such species exists for the given genus/species, so look for the taxon instead and try to update its description directly. Taxon[] taxa = await BotUtils.GetTaxaFromDb(taxonNameOrGenus); // If we didn't get any matches, show the user species suggestions. if (taxa.Count() <= 0) { await BotUtils.ReplyFindSpeciesAsync(Context, "", taxonNameOrGenus); } else { // Make sure we have one, and only one taxon to update. if (!await BotUtils.ReplyAsync_ValidateTaxa(Context, taxa)) { return; } Taxon taxon = taxa[0]; if (taxon.type == TaxonRank.Species) { // If the taxon is a species, use the species update procedure. await _setSpeciesDescriptionAsync(await BotUtils.GetSpeciesFromDb(taxon.id), descriptionOrSpecies); } else { // Update the taxon in the DB. await BotUtils.Command_SetTaxonDescription(Context, taxon, descriptionOrSpecies); } } } else if (await BotUtils.ReplyValidateSpeciesAsync(Context, species_list)) { // A species exists with the given genus/species, so initiate a two-part command. // Ensure that the user has necessary privileges to use this command. if (!await BotUtils.ReplyHasPrivilegeOrOwnershipAsync(Context, PrivilegeLevel.ServerModerator, species_list[0])) { return; } Bot.MultiPartMessage p = new Bot.MultiPartMessage(Context) { UserData = new string[] { taxonNameOrGenus, descriptionOrSpecies }, Callback = async(args) => { Species[] species = await BotUtils.GetSpeciesFromDb(args.Message.UserData[0], args.Message.UserData[1]); if (await BotUtils.ReplyValidateSpeciesAsync(args.Message.Context, species)) { await _setSpeciesDescriptionAsync(species[0], args.ResponseContent); } } }; await Bot.DiscordUtils.SendMessageAsync(Context, p, string.Format("Reply with the description for **{0}**.\nTo cancel the update, reply with \"cancel\".", species_list[0].ShortName)); } }
public async Task Prey(string genus, string species = "") { // If no species argument was provided, assume the user omitted the genus. if (string.IsNullOrEmpty(species)) { species = genus; genus = string.Empty; } // Get the specified species. Species sp = await BotUtils.ReplyFindSpeciesAsync(Context, genus, species); if (sp is null) { return; } // Get the preyed-upon species. using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM Predates WHERE species_id=$species_id;")) { cmd.Parameters.AddWithValue("$species_id", sp.Id); using (DataTable rows = await Database.GetRowsAsync(cmd)) { if (rows.Rows.Count <= 0) { await BotUtils.ReplyAsync_Info(Context, string.Format("**{0}** does not prey upon any other species.", sp.ShortName)); } else { List <Tuple <Species, string> > prey_list = new List <Tuple <Species, string> >(); foreach (DataRow row in rows.Rows) { prey_list.Add(new Tuple <Species, string>( await BotUtils.GetSpeciesFromDb(row.Field <long>("eats_id")), row.Field <string>("notes"))); } prey_list.Sort((lhs, rhs) => lhs.Item1.ShortName.CompareTo(rhs.Item1.ShortName)); List <string> lines = new List <string>(); foreach (Tuple <Species, string> prey in prey_list) { string line = prey.Item1.IsExtinct ? BotUtils.Strikeout(prey.Item1.ShortName) : prey.Item1.ShortName; if (!string.IsNullOrEmpty(prey.Item2)) { line += (string.Format(" ({0})", prey.Item2.ToLower())); } lines.Add(line); } PaginatedMessageBuilder embed = new PaginatedMessageBuilder(); embed.AddPages(EmbedUtils.LinesToEmbedPages(lines)); embed.SetTitle(string.Format("Species preyed upon by {0} ({1})", sp.ShortName, prey_list.Count())); embed.AddPageNumbers(); await DiscordUtils.SendMessageAsync(Context, embed.Build()); } } } }
public async Task Relationships(string genus, string species) { // Get the species from the DB. Species sp = await BotUtils.ReplyFindSpeciesAsync(Context, genus, species); if (sp is null) { return; } // Get relationships and build the embed. SortedDictionary <string, List <string> > items = new SortedDictionary <string, List <string> >(); // Get relationships where this species is the one acting upon another. using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM SpeciesRelationships LEFT JOIN Relationships ON SpeciesRelationships.relationship_id = Relationships.id WHERE species1_id=$species_id;")) { cmd.Parameters.AddWithValue("$species_id", sp.Id); using (DataTable table = await Database.GetRowsAsync(cmd)) foreach (DataRow row in table.Rows) { long other_species_id = row.Field <long>("species2_id"); Species other_species = await BotUtils.GetSpeciesFromDb(other_species_id); Relationship relationship = Relationship.FromDataRow(row); if (other_species is null) { continue; } if (!items.ContainsKey(relationship.BeneficiaryName(plural: true))) { items[relationship.BeneficiaryName(plural: true)] = new List <string>(); } items[relationship.BeneficiaryName(plural: true)].Add(other_species.IsExtinct ? string.Format("~~{0}~~", other_species.ShortName) : other_species.ShortName); } } // Get relationships where this species is the one being acted upon. using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM SpeciesRelationships LEFT JOIN Relationships ON SpeciesRelationships.relationship_id = Relationships.id WHERE species2_id=$species_id;")) { cmd.Parameters.AddWithValue("$species_id", sp.Id); using (DataTable table = await Database.GetRowsAsync(cmd)) foreach (DataRow row in table.Rows) { long other_species_id = row.Field <long>("species1_id"); Species other_species = await BotUtils.GetSpeciesFromDb(other_species_id); Relationship relationship = Relationship.FromDataRow(row); if (other_species is null) { continue; } if (!items.ContainsKey(relationship.BenefactorName(plural: true))) { items[relationship.BenefactorName(plural: true)] = new List <string>(); } items[relationship.BenefactorName(plural: true)].Add(other_species.IsExtinct ? string.Format("~~{0}~~", other_species.ShortName) : other_species.ShortName); } } // Get any prey/predator relationships. using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM Predates WHERE species_id=$species_id;")) { cmd.Parameters.AddWithValue("$species_id", sp.Id); using (DataTable table = await Database.GetRowsAsync(cmd)) foreach (DataRow row in table.Rows) { long other_species_id = row.Field <long>("eats_id"); Species other_species = await BotUtils.GetSpeciesFromDb(other_species_id); if (other_species is null) { continue; } if (!items.ContainsKey("prey")) { items["prey"] = new List <string>(); } items["prey"].Add(other_species.IsExtinct ? string.Format("~~{0}~~", other_species.ShortName) : other_species.ShortName); } } using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM Predates WHERE eats_id=$species_id;")) { cmd.Parameters.AddWithValue("$species_id", sp.Id); using (DataTable table = await Database.GetRowsAsync(cmd)) foreach (DataRow row in table.Rows) { long other_species_id = row.Field <long>("species_id"); Species other_species = await BotUtils.GetSpeciesFromDb(other_species_id); if (other_species is null) { continue; } if (!items.ContainsKey("predators")) { items["predators"] = new List <string>(); } items["predators"].Add(other_species.IsExtinct ? string.Format("~~{0}~~", other_species.ShortName) : other_species.ShortName); } } // If the species does not have any relationships with other species, state so. if (items.Count() <= 0) { await BotUtils.ReplyAsync_Info(Context, string.Format("**{0}** does not have any relationships with other species.", sp.ShortName)); return; } // Build the embed. EmbedBuilder embed = new EmbedBuilder(); int relationship_count = 0; foreach (string key in items.Keys) { items[key].Sort((lhs, rhs) => lhs.CompareTo(rhs)); embed.AddField(string.Format("{0} ({1})", StringUtils.ToTitleCase(key), items[key].Count()), string.Join(Environment.NewLine, items[key]), inline: true); relationship_count += items[key].Count(); } embed.WithTitle(string.Format("Relationships involving {0} ({1})", sp.ShortName, relationship_count)); await ReplyAsync("", false, embed.Build()); }
public static async Task <Bot.PaginatedMessageBuilder> BuildRecentEventsEmbedAsync(long startTimestamp, long endTimestamp, TimeUnits timeUnit = 0) { // Get all species created within the given timespan. List <Species> new_species = new List <Species>(); TimeAmount time_amount = new TimeAmount(endTimestamp - startTimestamp, TimeUnits.Seconds); if (timeUnit != 0) { time_amount = time_amount.ConvertTo(timeUnit); } else { time_amount = time_amount.Reduce(); } using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM Species WHERE timestamp >= $start_ts AND timestamp < $end_ts")) { cmd.Parameters.AddWithValue("$start_ts", startTimestamp); cmd.Parameters.AddWithValue("$end_ts", endTimestamp); using (DataTable table = await Database.GetRowsAsync(cmd)) foreach (DataRow row in table.Rows) { new_species.Add(await SpeciesUtils.SpeciesFromDataRow(row)); } } new_species.Sort(); // Get all extinctions that occurred recently. List <Species> extinct_species = new List <Species>(); using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM Extinctions WHERE timestamp >= $start_ts AND timestamp < $end_ts")) { cmd.Parameters.AddWithValue("$start_ts", startTimestamp); cmd.Parameters.AddWithValue("$end_ts", endTimestamp); using (DataTable table = await Database.GetRowsAsync(cmd)) foreach (DataRow row in table.Rows) { extinct_species.Add(await BotUtils.GetSpeciesFromDb(row.Field <long>("species_id"))); } } extinct_species.Sort(); // Build embed. Bot.PaginatedMessageBuilder embed = new Bot.PaginatedMessageBuilder(); List <EmbedBuilder> pages = new List <EmbedBuilder>(); List <string> field_lines = new List <string>(); if (new_species.Count() > 0) { foreach (Species sp in new_species) { field_lines.Add(sp.FullName); } EmbedUtils.AddLongFieldToEmbedPages(pages, field_lines, fieldName: string.Format("New species ({0})", new_species.Count())); field_lines.Clear(); } if (extinct_species.Count() > 0) { foreach (Species sp in extinct_species) { field_lines.Add(sp.FullName); } EmbedUtils.AddLongFieldToEmbedPages(pages, field_lines, fieldName: string.Format("Extinctions ({0})", extinct_species.Count())); field_lines.Clear(); } embed.AddPages(pages); embed.SetTitle(string.Format("Recent events ({0})", time_amount.ToString())); embed.SetFooter(string.Empty); // remove page numbers added automatically embed.AddPageNumbers(); if (embed.FieldCount <= 0) { embed.SetDescription("No events"); } return(embed); }
private async Task _endBattle(ICommandContext context) { PlayerState winner = player1.Gotchi.Stats.Hp <= 0.0 ? player2 : player1; PlayerState loser = player1.Gotchi.Stats.Hp <= 0.0 ? player1 : player2; // Calculate the amount of EXP awarded to the winner. // The loser will get 50% of the winner's EXP. double exp = _getExpEarned(winner.Gotchi.Gotchi, loser.Gotchi.Gotchi, won: true); double exp1 = player2.Gotchi.Stats.Hp <= 0.0 ? exp : exp * .5; double exp2 = player1.Gotchi.Stats.Hp <= 0.0 ? exp : exp * .5; long levels1 = player1.Gotchi.Stats.AddExperience((int)exp1); long levels2 = player2.Gotchi.Stats.AddExperience((int)exp2); StringBuilder sb = new StringBuilder(); sb.AppendLine(battleText); // Show the winner's accomplishments, then the loser's. if (!IsCpuGotchi(winner.Gotchi.Gotchi)) { double winner_exp = winner.Gotchi.Gotchi.Id == player1.Gotchi.Gotchi.Id ? exp1 : exp2; long winner_levels = winner.Gotchi.Gotchi.Id == player1.Gotchi.Gotchi.Id ? levels1 : levels2; long winner_g = (long)Math.Round(loser.Gotchi.Stats.Level * (BotUtils.RandomInteger(150, 200) / 100.0)); sb.AppendLine(string.Format("🏆 **{0}** won the battle! Earned **{1} EXP** and **{2}G**.", winner.Gotchi.Gotchi.Name, winner_exp, winner_g)); if (winner_levels > 0) { sb.AppendLine(string.Format("🆙 **{0}** leveled up to level **{1}**!", winner.Gotchi.Gotchi.Name, winner.Gotchi.Stats.Level)); } if (((winner.Gotchi.Stats.Level - winner_levels) / 10) < (winner.Gotchi.Stats.Level / 10)) { if (await GotchiUtils.EvolveAndUpdateGotchiAsync(winner.Gotchi.Gotchi)) { Species sp = await BotUtils.GetSpeciesFromDb(winner.Gotchi.Gotchi.SpeciesId); sb.AppendLine(string.Format("🚩 Congratulations, **{0}** evolved into **{1}**!", winner.Gotchi.Gotchi.Name, sp.ShortName)); } } // Update the winner's G. GotchiUserInfo user_data = await GotchiUtils.GetUserInfoAsync(winner.Gotchi.Gotchi.OwnerId); user_data.G += winner_g; await GotchiUtils.UpdateUserInfoAsync(user_data); sb.AppendLine(); } if (!IsCpuGotchi(loser.Gotchi.Gotchi)) { double loser_exp = loser.Gotchi.Gotchi.Id == player1.Gotchi.Gotchi.Id ? exp1 : exp2; long loser_levels = loser.Gotchi.Gotchi.Id == player1.Gotchi.Gotchi.Id ? levels1 : levels2; sb.AppendLine(string.Format("💀 **{0}** lost the battle... Earned **{1} EXP**.", loser.Gotchi.Gotchi.Name, loser_exp)); if (loser_levels > 0) { sb.AppendLine(string.Format("🆙 **{0}** leveled up to level **{1}**!", loser.Gotchi.Gotchi.Name, loser.Gotchi.Stats.Level)); } if (((loser.Gotchi.Stats.Level - loser_levels) / 10) < (loser.Gotchi.Stats.Level / 10)) { if (await GotchiUtils.EvolveAndUpdateGotchiAsync(loser.Gotchi.Gotchi)) { Species sp = await BotUtils.GetSpeciesFromDb(loser.Gotchi.Gotchi.SpeciesId); sb.AppendLine(string.Format("🚩 Congratulations, **{0}** evolved into **{1}**!", loser.Gotchi.Gotchi.Name, sp.ShortName)); } } } // Update exp in the database. using (SQLiteCommand cmd = new SQLiteCommand("UPDATE Gotchi SET level=$level, exp=$exp WHERE id=$id;")) { cmd.Parameters.AddWithValue("$id", player1.Gotchi.Gotchi.Id); cmd.Parameters.AddWithValue("$level", DBNull.Value); cmd.Parameters.AddWithValue("$exp", player1.Gotchi.Stats.Experience); await Database.ExecuteNonQuery(cmd); } if (!IsCpuGotchi(player2.Gotchi.Gotchi)) { using (SQLiteCommand cmd = new SQLiteCommand("UPDATE Gotchi SET level=$level, exp=$exp WHERE id=$id;")) { cmd.Parameters.AddWithValue("$id", player2.Gotchi.Gotchi.Id); cmd.Parameters.AddWithValue("$level", DBNull.Value); cmd.Parameters.AddWithValue("$exp", player2.Gotchi.Stats.Experience); await Database.ExecuteNonQuery(cmd); } } // Deregister the battle state. DeregisterBattle(context.User.Id); battleText = sb.ToString(); }
public static async Task <bool> EvolveAndUpdateGotchiAsync(Gotchi gotchi, string desiredEvo) { bool evolved = false; if (string.IsNullOrEmpty(desiredEvo)) { // Find all descendatants of this species. using (SQLiteCommand cmd = new SQLiteCommand("SELECT species_id FROM Ancestors WHERE ancestor_id=$ancestor_id;")) { List <long> descendant_ids = new List <long>(); cmd.Parameters.AddWithValue("$ancestor_id", gotchi.SpeciesId); using (DataTable rows = await Database.GetRowsAsync(cmd)) foreach (DataRow row in rows.Rows) { descendant_ids.Add(row.Field <long>("species_id")); } // Pick an ID at random. if (descendant_ids.Count > 0) { gotchi.SpeciesId = descendant_ids[BotUtils.RandomInteger(descendant_ids.Count)]; evolved = true; } } } else { // Get the desired evo. Species[] sp = await BotUtils.GetSpeciesFromDb("", desiredEvo); if (sp is null || sp.Length != 1) { return(false); } // Ensure that the species evolves into the desired evo. using (SQLiteCommand cmd = new SQLiteCommand("SELECT COUNT(*) FROM Ancestors WHERE ancestor_id = $ancestor_id AND species_id = $species_id")) { cmd.Parameters.AddWithValue("$ancestor_id", gotchi.SpeciesId); cmd.Parameters.AddWithValue("$species_id", sp[0].Id); if (await Database.GetScalar <long>(cmd) <= 0) { return(false); } gotchi.SpeciesId = sp[0].Id; evolved = true; } } // Update the gotchi in the database. using (SQLiteCommand cmd = new SQLiteCommand("UPDATE Gotchi SET species_id=$species_id, evolved_ts=$evolved_ts WHERE id=$id;")) { cmd.Parameters.AddWithValue("$species_id", gotchi.SpeciesId); // The "last evolved" timestamp is now only updated in the event the gotchi evolves (in order to make the "IsEvolved" check work correctly). // Note that this means that the background service will attempt to evolve the gotchi at every iteration (unless it evolves by leveling). if (evolved) { cmd.Parameters.AddWithValue("$evolved_ts", DateTimeOffset.UtcNow.ToUnixTimeSeconds()); } cmd.Parameters.AddWithValue("$id", gotchi.Id); await Database.ExecuteNonQuery(cmd); } return(evolved); }