public void CalculatePawnCost(ColonistCostDetails cost, CustomPawn pawn) { cost.Clear(); cost.name = pawn.NickName; // Start with the market value plus a bit of a mark-up. cost.marketValue = pawn.Pawn.MarketValue; cost.marketValue += 300; // Calculate passion cost. Each passion above 8 makes all passions // cost more. Minor passion counts as one passion. Major passion // counts as 3. double skillCount = pawn.currentPassions.Keys.Count(); double passionLevelCount = 0; double passionLevelCost = 20; double passionateSkillCount = 0; foreach (SkillDef def in pawn.currentPassions.Keys) { Passion passion = pawn.currentPassions[def]; int level = pawn.GetSkillLevel(def); if (passion == Passion.Major) { passionLevelCount += 3.0; passionateSkillCount += 1.0; } else if (passion == Passion.Minor) { passionLevelCount += 1.0; passionateSkillCount += 1.0; } } double levelCost = passionLevelCost; if (passionLevelCount > 8) { double penalty = passionLevelCount - 8; levelCost += penalty * 0.4; } cost.marketValue += levelCost * passionLevelCount; // Calculate trait cost. if (pawn.TraitCount > Constraints.MaxVanillaTraits) { int extraTraitCount = pawn.TraitCount - Constraints.MaxVanillaTraits; double extraTraitCost = 100; for (int i = 0; i < extraTraitCount; i++) { cost.marketValue += extraTraitCost; extraTraitCost = Math.Ceiling(extraTraitCost * 2.5); } } // Calculate cost of worn apparel. for (int layer = 0; layer < PawnLayers.Count; layer++) { if (PawnLayers.IsApparelLayer(layer)) { var def = pawn.GetAcceptedApparel(layer); if (def == null) { continue; } EquipmentKey key = new EquipmentKey(); key.ThingDef = def; key.StuffDef = pawn.GetSelectedStuff(layer); EquipmentRecord record = PrepareCarefully.Instance.EquipmentDatabase.Find(key); if (record == null) { continue; } EquipmentSelection selection = new EquipmentSelection(record, 1); double c = CalculateEquipmentCost(selection); if (def != null) { // TODO: Discounted materials should be based on the faction, not hard-coded. // TODO: Should we continue with the discounting? if (key.StuffDef != null) { if (key.StuffDef.defName == "Synthread") { if (freeApparel.Contains(key.ThingDef.defName)) { c = 0; } else if (cheapApparel.Contains(key.ThingDef.defName)) { c = c * 0.15d; } } } } cost.apparel += c; } } // Calculate cost for any materials needed for implants. OptionsHealth healthOptions = PrepareCarefully.Instance.Providers.Health.GetOptions(pawn); foreach (Implant option in pawn.Implants) { // Check if there are any ancestor parts that override the selection. UniqueBodyPart uniquePart = healthOptions.FindBodyPartsForRecord(option.BodyPartRecord); if (uniquePart == null) { Log.Warning("Prepare Carefully could not find body part record when computing the cost of an implant: " + option.BodyPartRecord.def.defName); continue; } if (pawn.AtLeastOneImplantedPart(uniquePart.Ancestors.Select((UniqueBodyPart p) => { return(p.Record); }))) { continue; } // Figure out the cost of the part replacement based on its recipe's ingredients. if (option.recipe != null) { RecipeDef def = option.recipe; foreach (IngredientCount amount in def.ingredients) { int count = 0; double totalCost = 0; bool skip = false; foreach (ThingDef ingredientDef in amount.filter.AllowedThingDefs) { if (ingredientDef == ThingDefOf.Medicine) { skip = true; break; } count++; EquipmentRecord entry = PrepareCarefully.Instance.EquipmentDatabase[new EquipmentKey(ingredientDef, null)]; if (entry != null) { totalCost += entry.cost * (double)amount.GetBaseCount(); } } if (skip || count == 0) { continue; } cost.bionics += (int)(totalCost / (double)count); } } } cost.apparel = Math.Ceiling(cost.apparel); cost.bionics = Math.Ceiling(cost.bionics); // Use a multiplier to balance pawn cost vs. equipment cost. // Disabled for now. cost.Multiply(1.0); cost.ComputeTotal(); }
public void CalculatePawnCost(ColonistCostDetails cost, CustomPawn pawn) { cost.Clear(); cost.name = pawn.NickName; // Start with the market value plus a bit of a mark-up. cost.marketValue = pawn.Pawn.MarketValue; cost.marketValue += 300; // Reduce cost if random injuries have been chosen. if (pawn.RandomInjuries) { float ageMultiplier = pawn.BiologicalAge; if (ageMultiplier > 100) { ageMultiplier = 100; } float injuryValue = Mathf.Pow(ageMultiplier, 1.177455f); injuryValue = injuryValue / 10f; injuryValue = Mathf.Floor(injuryValue) * 10f; cost.marketValue -= injuryValue; } // Calculate passion cost. Each passion above 8 makes all passions // cost more. Minor passion counts as one passion. Major passion // counts as 3. double skillCount = pawn.currentPassions.Keys.Count(); double passionLevelCount = 0; double passionLevelCost = 20; double passionateSkillCount = 0; foreach (SkillDef def in pawn.currentPassions.Keys) { Passion passion = pawn.currentPassions[def]; int level = pawn.GetSkillLevel(def); if (passion == Passion.Major) { passionLevelCount += 3.0; passionateSkillCount += 1.0; } else if (passion == Passion.Minor) { passionLevelCount += 1.0; passionateSkillCount += 1.0; } } double levelCost = passionLevelCost; if (passionLevelCount > 8) { double penalty = passionLevelCount - 8; levelCost += penalty * 0.4; } cost.marketValue += levelCost * passionLevelCount; // Calculat cost of worn apparel. for (int layer = 0; layer < PawnLayers.Count; layer++) { if (PawnLayers.IsApparelLayer(layer)) { var def = pawn.GetAcceptedApparel(layer); SelectedEquipment customPawn = new SelectedEquipment(); customPawn.def = def; customPawn.count = 1; if (def != null) { var stuff = pawn.GetSelectedStuff(layer); customPawn.stuffDef = stuff; } double c = CalculateEquipmentCost(customPawn); if (def != null) { if (customPawn.stuffDef != null) { if (customPawn.stuffDef.defName == "Synthread") { if (freeApparel.Contains(customPawn.def.defName)) { c = 0; } else if (cheapApparel.Contains(customPawn.def.defName)) { c = c * 0.15d; } } } } cost.apparel += c; } } // Calculate cost for any materials needed for implants. foreach (Implant option in pawn.Implants) { // Check if there are any ancestor parts that override the selection. if (PrepareCarefully.Instance.HealthManager.ImplantManager.AncestorIsImplant(pawn, option.BodyPartRecord)) { continue; } // Figure out the cost of the part replacement based on its recipe's ingredients. if (option.recipe != null) { RecipeDef def = option.recipe; foreach (IngredientCount amount in def.ingredients) { int count = 0; double totalCost = 0; bool skip = false; foreach (ThingDef ingredientDef in amount.filter.AllowedThingDefs) { if (ingredientDef == ThingDefOf.Medicine) { skip = true; break; } count++; EquipmentDatabaseEntry entry = PrepareCarefully.Instance.EquipmentEntries[new EquipmentKey(ingredientDef, null)]; if (entry != null) { totalCost += entry.cost * (double)amount.GetBaseCount(); } } if (skip || count == 0) { continue; } cost.bionics += (int)(totalCost / (double)count); } } } cost.apparel = Math.Ceiling(cost.apparel); cost.bionics = Math.Ceiling(cost.bionics); // Use a multiplier to balance pawn cost vs. equipment cost. // Disabled for now. cost.Multiply(1.0); cost.ComputeTotal(); }