public MobSpawnTable( Dictionary <int, MobSpawnTable> spawnTables, MobTypeSet mob_types, MobSpawnTables db_table, List <MobSpawnTableEntries> db_entries) { m_table_id = db_table.MobSpawnTableID; m_table_name = db_table.MobSpawnTableName; if (db_entries.Count > 0) { // Compute the total non normalized weight float weight_sum = (float)db_entries.Sum(e => e.Weight); // Sort the source list by weight and then store in the internal entry array m_entries = new MobSpawnTableEntry[db_entries.Count]; // Copy over the source entries into the table // Normalize the weights for (int entry_index = 0; entry_index < db_entries.Count; entry_index++) { MobSpawnTableEntries db_entry = db_entries[entry_index]; MobSpawnTableEntry entry = new MobSpawnTableEntry(); entry.cumulative_weight = (float)db_entry.Weight / weight_sum; if (db_entry.ReferenceIsMobType) { entry.mob_type = mob_types.GetMobTypeById(db_entry.ReferenceID); entry.mob_spawn_table = null; } else { entry.mob_type = null; entry.mob_spawn_table = spawnTables[db_entry.ReferenceID]; } m_entries[entry_index] = entry; } // Sort the weights. Largest weight first. // We do this so that when we search through the CDF // we're more likely to find the random entry we're looking for earlier in the array. m_entries.OrderByDescending(e => e.cumulative_weight); // Convert the probability density function (PDF) into a cumulative distribution function (CDF) float accumulator = 0f; for (int entry_index = 0; entry_index < m_entries.Length; entry_index++) { MobSpawnTableEntry entry = m_entries[entry_index]; float weight = entry.cumulative_weight; entry.cumulative_weight = Math.Min(accumulator + entry.cumulative_weight, 1.0f); accumulator = accumulator + weight; } } }
public void ParseMobSpawnTables( AsyncRPGDataContext db_context, string mob_spawn_tables_file_path) { MobTypeSet mobTypeSet = new MobTypeSet(); // Load the mob spawn types from the DB mobTypeSet.Initialize(db_context); // Clear out any existing room templates db_context.ExecuteCommand("DELETE FROM mob_spawn_table_entries"); db_context.ExecuteCommand("DELETE FROM mob_spawn_tables"); // Read in the given JSON file and save it into the mob spawn table db table string jsonString = ""; JSONMobSpawnTableSet jsonMobSpawnTableSet = null; // Read the spawn table file into a string using (StreamReader streamReader = new StreamReader(mob_spawn_tables_file_path)) { jsonString = streamReader.ReadToEnd(); if (jsonString.Length == 0) { throw new Exception("MobSpawnTableParser: Mob spawn table file empty:" + mob_spawn_tables_file_path); } } // Parse the JSON into an object jsonMobSpawnTableSet = JsonMapper.ToObject <JSONMobSpawnTableSet>(jsonString); // Parse and verify each spawn table given { Dictionary <string, JSONMobSpawnTable> validMobSpawnTables = new Dictionary <string, JSONMobSpawnTable>(); Dictionary <string, int> spawnTableNameToId = new Dictionary <string, int>(); foreach (JSONMobSpawnTable jsonMobSpawnTable in jsonMobSpawnTableSet.mob_spawn_table_set) { if (ValidateMobSpawnTable(jsonMobSpawnTable, validMobSpawnTables)) { bool validTable = true; // Verify each entry references either a valid spawn table or mob type // and has a valid weight foreach (JSONMobSpawnTableEntry jsonSpawnTableEntry in jsonMobSpawnTable.entries) { if (!ValidateMobSpawnTableEntry( jsonSpawnTableEntry, mobTypeSet, validMobSpawnTables)) { validTable = false; } } // If all the table entries look good, add the spawn table to the DB if (validTable) { // Insert the spawn table first MobSpawnTables dbMobSpawnTable = new MobSpawnTables { MobSpawnTableName = jsonMobSpawnTable.mob_spawn_table_name, }; db_context.MobSpawnTables.InsertOnSubmit(dbMobSpawnTable); db_context.SubmitChanges(); // Then insert all the entries associated with the table foreach (JSONMobSpawnTableEntry jsonEntry in jsonMobSpawnTable.entries) { MobSpawnTableEntries dbMobSpawnTableEntry = null; if (jsonEntry.mob_spawn_table_name.Length > 0) { dbMobSpawnTableEntry = new MobSpawnTableEntries { MobSpawnTableID = dbMobSpawnTable.MobSpawnTableID, ReferenceID = spawnTableNameToId[jsonEntry.mob_spawn_table_name], ReferenceIsMobType = false, Weight = jsonEntry.weight }; } else { dbMobSpawnTableEntry = new MobSpawnTableEntries { MobSpawnTableID = dbMobSpawnTable.MobSpawnTableID, ReferenceID = mobTypeSet.GetMobTypeByName(jsonEntry.mob_type_name).ID, ReferenceIsMobType = true, Weight = jsonEntry.weight }; } db_context.MobSpawnTableEntries.InsertOnSubmit(dbMobSpawnTableEntry); db_context.SubmitChanges(); } _logger.LogInfo("MobSpawnTableParser: Added Mob Spawn Table:"); _logger.LogInfo(jsonMobSpawnTable.mob_spawn_table_name); // Keep track of each valid table added and what it's DB id is validMobSpawnTables.Add( jsonMobSpawnTable.mob_spawn_table_name, jsonMobSpawnTable); spawnTableNameToId.Add( jsonMobSpawnTable.mob_spawn_table_name, dbMobSpawnTable.MobSpawnTableID); } else { throw new Exception("MobSpawnTableParser: Problem(s) validating mob spawn table entries: " + jsonMobSpawnTable.mob_spawn_table_name); } } else { throw new Exception("MobSpawnTableParser: Problem(s) validating mob spawn table: " + jsonMobSpawnTable.mob_spawn_table_name); } } } }