Boss gate: a boss zone spawns its faction's boss, and RunGoal derives whether the exit gate is open
EntityPack.Boss (key 21) carries Entity.IsBoss through save and Continue. GenerateZone adds one boss per BossZones entry before the ambient return, flying the faction's BossHull or, with the gap logged, its most expensive available ship hull. RunGoal (ServerShared) is the one owner of boss life and exit state, derived from Zone.Entities. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
85d0a14808
commit
db4617d832
8 changed files with 285 additions and 5 deletions
|
|
@ -140,6 +140,18 @@ public class LoadoutGenerator
|
|||
// required item falls back to any manufacturer when none of those make one, which means the product table
|
||||
// lacks variety, so it is logged rather than hidden.
|
||||
public (FactionProductData product, T design)[] RandomProducts<T>(int count, float sizeExponent, Predicate<T> filter = null, bool required = false) where T : EquippableItemData
|
||||
{
|
||||
var (available, preferManufacturers) = AvailableProducts(filter, required);
|
||||
return available.WeightedRandomElements(ref Random, entry =>
|
||||
(preferManufacturers ? ManufacturerPreference(entry.product.Manufacturer) : 1) *
|
||||
pow(entry.design.Shape.Coordinates.Length, sizeExponent) / // Prioritize larger items
|
||||
pow(entry.design.Price, PriceExponent), // Penalize item price to a controllable degree
|
||||
count);
|
||||
}
|
||||
|
||||
// The products this faction can be offered for a design kind, and whether manufacturer preference applies (it does
|
||||
// not once a required item has fallen back to any manufacturer). The one availability rule for every selection.
|
||||
private ((FactionProductData product, T design)[] available, bool preferManufacturers) AvailableProducts<T>(Predicate<T> filter, bool required) where T : EquippableItemData
|
||||
{
|
||||
var hulls = ItemManager.ItemData.GetAll<HullData>().ToArray();
|
||||
var candidates = ItemManager.ItemData.GetAll<FactionProductData>()
|
||||
|
|
@ -160,11 +172,27 @@ public class LoadoutGenerator
|
|||
preferManufacturers = false;
|
||||
}
|
||||
|
||||
return available.WeightedRandomElements(ref Random, entry =>
|
||||
(preferManufacturers ? ManufacturerPreference(entry.product.Manufacturer) : 1) *
|
||||
pow(entry.design.Shape.Coordinates.Length, sizeExponent) / // Prioritize larger items
|
||||
pow(entry.design.Price, PriceExponent), // Penalize item price to a controllable degree
|
||||
count);
|
||||
return (available, preferManufacturers);
|
||||
}
|
||||
|
||||
// A faction's boss: its BossHull when the faction sets one and a product sells it, else the most expensive ship hull
|
||||
// the faction can be offered, with the gap logged. Null only when no ship hull is on offer at all.
|
||||
public EntityPack GenerateBossLoadout()
|
||||
{
|
||||
var bossHull = Faction != null && Faction.BossHull.IsSet() ? ItemManager.ItemData.Get(Faction.BossHull) : null;
|
||||
if (bossHull != null)
|
||||
{
|
||||
var boss = GenerateShipLoadout(hull => hull == bossHull);
|
||||
if (boss != null) return boss;
|
||||
ItemManager.Log($"{Faction.Name}'s BossHull {bossHull.Name} is not sold by any product; its boss flies the most expensive ship hull instead.");
|
||||
}
|
||||
else
|
||||
ItemManager.Log($"{Faction?.Name ?? "This faction"} has no BossHull; its boss flies the most expensive ship hull instead.");
|
||||
|
||||
var (available, _) = AvailableProducts<HullData>(hull => hull.HullType == HullType.Ship, required: true);
|
||||
if (available.Length == 0) return null;
|
||||
var priciest = available.OrderByDescending(entry => entry.design.Price).ThenBy(entry => entry.design.Name, StringComparer.Ordinal).First().design;
|
||||
return GenerateShipLoadout(hull => hull == priciest);
|
||||
}
|
||||
|
||||
// Hardpoint gear that no hull in the catalog can mount has no home (operator, 2026-09-30: "we'll need to author a
|
||||
|
|
|
|||
Loading…
Reference in a new issue