public static List <GameObject> GetDrops(DropTable dropTable, DropSourceTemplateLink context) { var drops = GetDrops(dropTable, context, ConvertTemplateToDrop); #if DEBUG Log.LogDebug($"Dropping {drops.Count} items:"); foreach (var drop in drops) { Log.LogDebug($"\t{drop}"); } #endif return(drops); }
public static List <ItemDrop.ItemData> GetItemDrops(DropTable dropTable, DropSourceTemplateLink context) { var drops = GetDrops(dropTable, context, ConvertTemplateToItem); #if DEBUG Log.LogDebug($"Dropping {drops.Count} items:"); foreach (var drop in drops) { Log.LogDebug($"\t{drop.m_shared.m_name}"); } #endif return(drops); }
private static List <T> GetDrops <T>(DropTable dropTable, DropSourceTemplateLink context, Func <DropTemplate, IEnumerable <T> > DropConverter) where T : class { var dropTemplates = DropConfigManager.GetPossibleDrops(context, dropTable); if (dropTemplates.Count == 0) { #if DEBUG Log.LogDebug("Skipping drop due to no templates."); #endif return(new(0)); } var entityConfig = context.EntityConfig; bool skipDrop = entityConfig is null ? UnityEngine.Random.value > dropTable.m_dropChance : UnityEngine.Random.value > (entityConfig.SetDropChance / 100); if (skipDrop) { #if DEBUG Log.LogDebug("Skipping drop due to table chance."); #endif return(new(0)); } var workingList = new List <DropTemplate>(dropTemplates); workingList = DropConditionManager.Filter(context, workingList); #if DEBUG Log.LogDebug("Drops after filter:"); foreach (var drop in workingList) { Log.LogDebug("\t" + drop.Drop.m_item.name); } #endif float sumWeight = workingList.Sum(x => x.Drop.m_weight); int dropCount = entityConfig is null ? UnityEngine.Random.Range(dropTable.m_dropMin, dropTable.m_dropMax + 1) : UnityEngine.Random.Range(entityConfig.SetDropMin, entityConfig.SetDropMax + 1); bool dropOnlyOnce = entityConfig is null ? dropTable.m_oneOfEach : entityConfig.SetDropOnlyOnce; List <T> result = new(dropCount); #if DEBUG Log.LogDebug($"Rolling {dropCount} drops."); #endif for (int i = 0; i < dropCount; ++i) { float weight = UnityEngine.Random.Range(0, sumWeight); float accumulatedWeight = 0; try { bool addedDrop = false; // Select drop based on weight. foreach (var template in workingList) { accumulatedWeight += template.Drop.m_weight; if (weight <= accumulatedWeight) { result.AddRange(DropConverter(template)); if (dropOnlyOnce) { workingList.Remove(template); sumWeight -= template.Drop.m_weight; } addedDrop = true; break; } } // Seems like a sanity check. If IG did their logic properly, it should never be necessary. Consider just removing this piece of code. if (!addedDrop && workingList.Count > 0) { result.AddRange(DropConverter(workingList.First())); } } catch (Exception e) { Log.LogWarning("Error while rolling drop. Skipping roll\n", e); } } return(result); }