diff --git a/Mods/Core/Defs/Genes/Content.json b/Mods/Core/Defs/Genes/Content.json new file mode 100644 index 0000000..17d9258 --- /dev/null +++ b/Mods/Core/Defs/Genes/Content.json @@ -0,0 +1,29 @@ +{ + "type": "Gene", + // Контент-гены (фаза G4+): плодоношение, добыча, цвет, производные и дискретные морфы. + "defs": [ + { "defName": "GeneFruitYield", "parent": "BaseNumericGene", "label": "gene.fruitYield", + "default": 0, "min": 0, "max": 12, "tags": ["fruiting"], + "effects": { "fruitYield": "value" } }, + { "defName": "GeneFruitSeason", "parent": "BaseNumericGene", "label": "gene.fruitSeason", + "default": 1, "min": 0, "max": 3, "spread": 0, "mutationChance": 0, "tags": ["fruiting"], + "effects": { "fruitSeason": "value" } }, + { "defName": "GeneHarvestAmount", "parent": "BaseNumericGene", "label": "gene.harvestAmount", + "default": 1, "min": 0, "max": 50, "tags": ["harvest"], + "effects": { "harvestAmount": "value" } }, + { "defName": "GeneLeafHue", "parent": "BaseNumericGene", "label": "gene.leafHue", + "default": 0.33, "min": 0, "max": 1, "spread": 0.04, "tags": ["morphology", "color"], + "effects": { "leafHue": "value" } }, + + // Производный ген: признак собирается группировкой по регэкспу — сумма всех генов-толерантностей + // (демонстрация gsom-функций фазы G5). Собственное значение гена не используется. + { "defName": "GeneHardiness", "parent": "BaseNumericGene", "label": "gene.hardiness", + "default": 0, "min": 0, "max": 1, "spread": 0, "mutationChance": 0, "tags": ["derived"], + "effects": { "hardiness": "gsum('Gene.*Tolerance')" } }, + + // Дискретный ген морфы: вариант 0 доминирует, 1 (рецессивный) виден только в гомозиготе. + { "defName": "GeneMorph", "kind": "Discrete", "label": "gene.morph", + "variants": 2, "variantWeights": [0.82, 0.18], "mutationChance": 0.05, "tags": ["morphology"], + "effects": { "variant": "value" } } + ] +} diff --git a/Mods/Core/Defs/Genes/Environment.json b/Mods/Core/Defs/Genes/Environment.json new file mode 100644 index 0000000..ca5fa61 --- /dev/null +++ b/Mods/Core/Defs/Genes/Environment.json @@ -0,0 +1,34 @@ +{ + "type": "Gene", + // Гены среды: свет, температура, почва. Покрывают экологические измерения генома растения, + // которые читают системы роста/жизненного цикла. + "defs": [ + { "defName": "GeneOptimalLight", "parent": "BaseNumericGene", "label": "gene.optimalLight", + "default": 0.6, "min": 0.0, "max": 1.0, "tags": ["environment", "light"], + "effects": { "optimalLight": "value" } }, + { "defName": "GeneLightTolerance", "parent": "BaseNumericGene", "label": "gene.lightTolerance", + "default": 0.5, "min": 0.05, "max": 1.0, "tags": ["environment", "light"], + "effects": { "lightTolerance": "value" } }, + { "defName": "GeneOptimalTemperature", "parent": "BaseNumericGene", "label": "gene.optimalTemperature", + "default": 14, "min": -20, "max": 45, "tags": ["environment", "temperature"], + "effects": { "optimalTemperature": "value" } }, + { "defName": "GeneTemperatureTolerance", "parent": "BaseNumericGene", "label": "gene.temperatureTolerance", + "default": 16, "min": 2, "max": 40, "tags": ["environment", "temperature"], + "effects": { "temperatureTolerance": "value" } }, + // Жёсткие края диапазона роста (модель RimWorld): на сколько °C ниже/выше плато оптимума рост + // спадает до нуля. Ниже (optimal-tolerance-coldHardiness) или выше (optimal+tolerance+heatHardiness) + // растение дормантно и копит температурный стресс. Асимметрично: вид может терпеть жару лучше холода. + { "defName": "GeneColdHardiness", "parent": "BaseNumericGene", "label": "gene.coldHardiness", + "default": 8, "min": 0, "max": 40, "tags": ["environment", "temperature"], + "effects": { "coldHardiness": "value" } }, + { "defName": "GeneHeatHardiness", "parent": "BaseNumericGene", "label": "gene.heatHardiness", + "default": 10, "min": 0, "max": 40, "tags": ["environment", "temperature"], + "effects": { "heatHardiness": "value" } }, + { "defName": "GeneOptimalFertility", "parent": "BaseNumericGene", "label": "gene.optimalFertility", + "default": 1.4, "min": 0.1, "max": 3.0, "tags": ["environment", "soil"], + "effects": { "optimalFertility": "value" } }, + { "defName": "GeneFertilityTolerance", "parent": "BaseNumericGene", "label": "gene.fertilityTolerance", + "default": 0.9, "min": 0.1, "max": 3.0, "tags": ["environment", "soil"], + "effects": { "fertilityTolerance": "value" } } + ] +} diff --git a/Mods/Core/Defs/Genes/Growth.json b/Mods/Core/Defs/Genes/Growth.json new file mode 100644 index 0000000..c382b81 --- /dev/null +++ b/Mods/Core/Defs/Genes/Growth.json @@ -0,0 +1,24 @@ +{ + "type": "Gene", + // Гены роста и размножения: бодрость, продолжительность жизни, расселение, репродукция. + "defs": [ + { "defName": "GeneVigor", "parent": "BaseNumericGene", "label": "gene.vigor", + "default": 1.0, "min": 0.1, "max": 3.0, "tags": ["growth"], + "effects": { "vigor": "value" } }, + { "defName": "GeneLifespan", "parent": "BaseNumericGene", "label": "gene.lifespan", + "default": 160, "min": 5, "max": 500, "tags": ["lifecycle"], + "effects": { "lifespan": "value" } }, + { "defName": "GeneDispersalRange", "parent": "BaseNumericGene", "label": "gene.dispersalRange", + "default": 2, "min": 1, "max": 8, "tags": ["lifecycle", "reproduction"], + "effects": { "dispersalRange": "value" } }, + { "defName": "GeneReproduceInterval", "parent": "BaseNumericGene", "label": "gene.reproduceInterval", + "default": 14, "min": 1, "max": 60, "tags": ["lifecycle", "reproduction"], + "effects": { "reproduceInterval": "value" } }, + { "defName": "GeneSelfPollination", "parent": "BaseNumericGene", "label": "gene.selfPollination", + "default": 0.2, "min": 0.0, "max": 1.0, "tags": ["reproduction"], + "effects": { "selfPollination": "value" } }, + { "defName": "GeneMutationRate", "parent": "BaseNumericGene", "label": "gene.mutationRate", + "default": 0.05, "min": 0.0, "max": 1.0, "tags": ["reproduction"], + "effects": { "mutationRate": "value" } } + ] +} diff --git a/Mods/Core/Defs/Genes/_Bases.json b/Mods/Core/Defs/Genes/_Bases.json new file mode 100644 index 0000000..19a0530 --- /dev/null +++ b/Mods/Core/Defs/Genes/_Bases.json @@ -0,0 +1,10 @@ +{ + "type": "Gene", + // Общие (абстрактные) гены: база наследования для конкретных генов. Каждый ген задаёт, как + // генерируются/мутируют аллели и как ген вкладывается в признаки (effects: имя признака → + // формула; value — выраженное значение гена). Конкретные гены лежат рядом по подтемам. + "defs": [ + { "defName": "BaseNumericGene", "abstract": true, "kind": "Numeric", + "spread": 0.08, "mutationChance": 0.05, "mutationMagnitude": 0.12 } + ] +} diff --git a/Mods/Core/Defs/patches.json b/Mods/Core/Defs/Patches/Patches.json similarity index 100% rename from Mods/Core/Defs/patches.json rename to Mods/Core/Defs/Patches/Patches.json diff --git a/Mods/Core/Defs/pawns.json b/Mods/Core/Defs/Pawns/Animals.json similarity index 62% rename from Mods/Core/Defs/pawns.json rename to Mods/Core/Defs/Pawns/Animals.json index dfcc2ce..b4a2662 100644 --- a/Mods/Core/Defs/pawns.json +++ b/Mods/Core/Defs/Pawns/Animals.json @@ -1,14 +1,7 @@ { "type": "Pawn", + // Животные. "defs": [ - { "defName": "BaseBeing", "abstract": true, "kind": "being", "sizeCells": 1.1 }, - { "defName": "BeingMale", "parent": "BaseBeing", "label": "pawn.being", "texture": "things/pawn/humanlike/bodies/FurCovered_Male_south" }, - { "defName": "BeingFemale", "parent": "BaseBeing", "label": "pawn.being", "texture": "things/pawn/humanlike/bodies/FurCovered_Female_south" }, - { "defName": "BeingThin", "parent": "BaseBeing", "label": "pawn.being", "texture": "things/pawn/humanlike/bodies/FurCovered_Thin_south" }, - { "defName": "BeingFat", "parent": "BaseBeing", "label": "pawn.being", "texture": "things/pawn/humanlike/bodies/FurCovered_Fat_south" }, - { "defName": "BeingHulk", "parent": "BaseBeing", "label": "pawn.being", "texture": "things/pawn/humanlike/bodies/FurCovered_Hulk_south" }, - - { "defName": "BaseAnimal", "abstract": true, "kind": "animal" }, { "defName": "Bear", "parent": "BaseAnimal", "label": "pawn.bear", "texture": "things/pawn/animal/bear/Bear_east", "sizeCells": 1.7 }, { "defName": "DeerDoe", "parent": "BaseAnimal", "label": "pawn.deer", "texture": "things/pawn/animal/deer/DeerFemale_east", "sizeCells": 1.4 }, { "defName": "DeerBuck", "parent": "BaseAnimal", "label": "pawn.deer", "texture": "things/pawn/animal/deer/DeerMale_east", "sizeCells": 1.6 }, diff --git a/Mods/Core/Defs/Pawns/Beings.json b/Mods/Core/Defs/Pawns/Beings.json new file mode 100644 index 0000000..7b206a3 --- /dev/null +++ b/Mods/Core/Defs/Pawns/Beings.json @@ -0,0 +1,11 @@ +{ + "type": "Pawn", + // Жители: варианты тел. + "defs": [ + { "defName": "BeingMale", "parent": "BaseBeing", "label": "pawn.being", "texture": "things/pawn/humanlike/bodies/FurCovered_Male_south" }, + { "defName": "BeingFemale", "parent": "BaseBeing", "label": "pawn.being", "texture": "things/pawn/humanlike/bodies/FurCovered_Female_south" }, + { "defName": "BeingThin", "parent": "BaseBeing", "label": "pawn.being", "texture": "things/pawn/humanlike/bodies/FurCovered_Thin_south" }, + { "defName": "BeingFat", "parent": "BaseBeing", "label": "pawn.being", "texture": "things/pawn/humanlike/bodies/FurCovered_Fat_south" }, + { "defName": "BeingHulk", "parent": "BaseBeing", "label": "pawn.being", "texture": "things/pawn/humanlike/bodies/FurCovered_Hulk_south" } + ] +} diff --git a/Mods/Core/Defs/Pawns/_Bases.json b/Mods/Core/Defs/Pawns/_Bases.json new file mode 100644 index 0000000..1cca457 --- /dev/null +++ b/Mods/Core/Defs/Pawns/_Bases.json @@ -0,0 +1,8 @@ +{ + "type": "Pawn", + // Общие (абстрактные) существа: база для жителей и животных. + "defs": [ + { "defName": "BaseBeing", "abstract": true, "kind": "being", "sizeCells": 1.1 }, + { "defName": "BaseAnimal", "abstract": true, "kind": "animal" } + ] +} diff --git a/Mods/Core/Defs/Plants/Berries.json b/Mods/Core/Defs/Plants/Berries.json new file mode 100644 index 0000000..fc594ab --- /dev/null +++ b/Mods/Core/Defs/Plants/Berries.json @@ -0,0 +1,8 @@ +{ + "type": "Plant", + // Ягодный почвопокров луга (еда). + "defs": [ + { "defName": "Strawberry", "parent": "BaseBerryBush", "label": "plant.strawberry", "sizeCells": 1.0, "texture": "things/plant/strawberryplant/StrawberryPlant" }, + { "defName": "Raspberry", "parent": "BaseBerryBush", "label": "plant.raspberry", "texture": "things/plant/raspberryplant/raspberrybusha" } + ] +} diff --git a/Mods/Core/Defs/Plants/Bushes.json b/Mods/Core/Defs/Plants/Bushes.json new file mode 100644 index 0000000..b42727d --- /dev/null +++ b/Mods/Core/Defs/Plants/Bushes.json @@ -0,0 +1,9 @@ +{ + "type": "Plant", + // Кусты: ягодный подлесок. Патч даёт им древесину при сборе (веточки) — см. Patches/Patches.json. + "defs": [ + { "defName": "BushA", "parent": "BaseBush", "texture": "things/plant/bush/BushA" }, + { "defName": "BushB", "parent": "BaseBush", "texture": "things/plant/bush/BushB" }, + { "defName": "BushC", "parent": "BaseBush", "texture": "things/plant/bush/BushC" } + ] +} diff --git a/Mods/Core/Defs/Plants/Cacti.json b/Mods/Core/Defs/Plants/Cacti.json new file mode 100644 index 0000000..a26bff3 --- /dev/null +++ b/Mods/Core/Defs/Plants/Cacti.json @@ -0,0 +1,15 @@ +{ + "type": "Plant", + // Пустыня: кактусы и агава на песке. Большинство без плодов; сагуаро/агава плодоносят. + "defs": [ + { "defName": "SaguaroCactusA", "parent": "BaseCactus", "label": "plant.saguaro", "sizeCells": 2.2, "trunkRadiusCells": 0.18, + "fruitProduct": "ProductBerry", "texture": "things/plant/saguarocactus/SaguaroCactusA" }, + { "defName": "SaguaroCactusB", "parent": "BaseCactus", "label": "plant.saguaro", "sizeCells": 2.2, "trunkRadiusCells": 0.18, + "fruitProduct": "ProductBerry", "texture": "things/plant/saguarocactus/SaguaroCactusB" }, + { "defName": "PebbleCactusA", "parent": "BaseCactus", "sizeCells": 1.0, "texture": "things/plant/pebblecactus/PebbleCactusA" }, + { "defName": "PebbleCactusB", "parent": "BaseCactus", "sizeCells": 1.0, "texture": "things/plant/pebblecactus/PebbleCactusB" }, + { "defName": "PincushionCactusA", "parent": "BaseCactus", "sizeCells": 0.9, "texture": "things/plant/pincushioncactus/PincushionCactusA" }, + { "defName": "AgaveA", "parent": "BaseCactus", "label": "plant.agave", "sizeCells": 1.3, "fruitProduct": "ProductBerry", "texture": "things/plant/agave/AgaveA" }, + { "defName": "AgaveB", "parent": "BaseCactus", "label": "plant.agave", "sizeCells": 1.3, "fruitProduct": "ProductBerry", "texture": "things/plant/agave/AgaveB" } + ] +} diff --git a/Mods/Core/Defs/Plants/Flowers.json b/Mods/Core/Defs/Plants/Flowers.json new file mode 100644 index 0000000..191e326 --- /dev/null +++ b/Mods/Core/Defs/Plants/Flowers.json @@ -0,0 +1,12 @@ +{ + "type": "Plant", + // Луг: декоративные цветы с быстрым расселением. + "defs": [ + { "defName": "DandelionA", "parent": "BaseFlower", "label": "plant.dandelion", "texture": "things/plant/dandelion/Dandelion" }, + { "defName": "DandelionB", "parent": "BaseFlower", "label": "plant.dandelion", "texture": "things/plant/dandelion/DandelionB" }, + { "defName": "DandelionC", "parent": "BaseFlower", "label": "plant.dandelion", "texture": "things/plant/dandelion/DandelionC" }, + { "defName": "DaylilyA", "parent": "BaseFlower", "label": "plant.daylily", "texture": "things/plant/daylily/DaylilyA" }, + { "defName": "DaylilyB", "parent": "BaseFlower", "label": "plant.daylily", "texture": "things/plant/daylily/DaylilyB" }, + { "defName": "RoseA", "parent": "BaseFlower", "label": "plant.rose", "sizeCells": 1.1, "texture": "things/plant/rose/RoseA" } + ] +} diff --git a/Mods/Core/Defs/Plants/Grass.json b/Mods/Core/Defs/Plants/Grass.json new file mode 100644 index 0000000..93bac6f --- /dev/null +++ b/Mods/Core/Defs/Plants/Grass.json @@ -0,0 +1,18 @@ +{ + "type": "Plant", + // Трава: быстрый почвопокров, основной скаттер лугов и леса. + "defs": [ + { "defName": "GrassA", "label": "plant.grass", "texture": "things/plant/grass/grassa", "sizeCells": 1.5, + "harvestProduct": "ProductGrass", + "genome": { "optimalLight": 0.85, "lightTolerance": 0.35, "optimalTemperature": 19, "temperatureTolerance": 8, + "coldHardiness": 9, "heatHardiness": 6, + "optimalFertility": 1.0, "fertilityTolerance": 1.0, "vigor": 1.3, + "lifespan": 22, "dispersalRange": 3, "reproduceInterval": 3, "selfPollination": 0.8, + "mutationRate": 0.06, "variantChance": 0.2, "spread": 0.1, + "harvestAmount": 2, "leafHue": 0.36 }, + "stages": [ + { "texture": "things/plant/seed_default", "sizeCells": 0.5, "growDays": 2, "label": "plant.stage.sprout" }, + { "sizeCells": 1.5, "label": "plant.stage.mature" } + ] } + ] +} diff --git a/Mods/Core/Defs/Plants/Mushrooms.json b/Mods/Core/Defs/Plants/Mushrooms.json new file mode 100644 index 0000000..60a8b49 --- /dev/null +++ b/Mods/Core/Defs/Plants/Mushrooms.json @@ -0,0 +1,11 @@ +{ + "type": "Plant", + // Грибы: подлесок леса, растут в тени крон. + "defs": [ + { "defName": "GlowstoolA", "parent": "BaseMushroom", "sizeCells": 0.9, "texture": "things/plant/glowstool/GlowstoolA" }, + { "defName": "GlowstoolB", "parent": "BaseMushroom", "sizeCells": 0.9, "texture": "things/plant/glowstool/GlowstoolB" }, + { "defName": "TimbershroomA", "parent": "BaseMushroom", "sizeCells": 1.1, "texture": "things/plant/timbershroom/TimbershroomA" }, + { "defName": "TimbershroomB", "parent": "BaseMushroom", "sizeCells": 1.1, "texture": "things/plant/timbershroom/TimbershroomB" }, + { "defName": "NutrifungusA", "parent": "BaseMushroom", "sizeCells": 0.9, "texture": "things/plant/nutrifungus/NutrifungusA" } + ] +} diff --git a/Mods/Core/Defs/Plants/Trees.json b/Mods/Core/Defs/Plants/Trees.json new file mode 100644 index 0000000..eae24ae --- /dev/null +++ b/Mods/Core/Defs/Plants/Trees.json @@ -0,0 +1,17 @@ +{ + "type": "Plant", + // Деревья: умеренные (BaseTree), тёплые (BaseWarmTree) и холодные (BaseColdTree) ниши. + "defs": [ + { "defName": "TreeOakA", "parent": "BaseTree", "label": "plant.oak", "texture": "things/plant/treeoak/TreeOakA" }, + { "defName": "TreeOakB", "parent": "BaseTree", "label": "plant.oak", "texture": "things/plant/treeoak/TreeOakB" }, + { "defName": "TreeBirchA", "parent": "BaseTree", "label": "plant.birch", "texture": "things/plant/treebirch/TreeBirchA" }, + { "defName": "TreeGrayPineA", "parent": "BaseTree", "label": "plant.pine", "texture": "things/plant/treegraypine/TreeGrayPineA" }, + { "defName": "TreeMapleA", "parent": "BaseTree", "label": "plant.maple", "texture": "things/plant/treemaple/TreeMapleA" }, + { "defName": "TreeMapleB", "parent": "BaseTree", "label": "plant.maple", "texture": "things/plant/treemaple/TreeMapleB" }, + { "defName": "TreePoplarA", "parent": "BaseTree", "label": "plant.poplar", "texture": "things/plant/treepoplar/TreePoplarA" }, + { "defName": "TreeTeakA", "parent": "BaseWarmTree", "label": "plant.teak", "texture": "things/plant/treeteak/TreeTeakA" }, + { "defName": "TreeTeakB", "parent": "BaseWarmTree", "label": "plant.teak", "texture": "things/plant/treeteak/TreeTeakB" }, + { "defName": "TreeCypressA", "parent": "BaseColdTree", "label": "plant.cypress", "texture": "things/plant/treecypress/TreeCypressA" }, + { "defName": "TreeCypressB", "parent": "BaseColdTree", "label": "plant.cypress", "texture": "things/plant/treecypress/TreeCypressB" } + ] +} diff --git a/Mods/Core/Defs/plants.json b/Mods/Core/Defs/Plants/_Bases.json similarity index 53% rename from Mods/Core/Defs/plants.json rename to Mods/Core/Defs/Plants/_Bases.json index 6d078c2..dbbda4c 100644 --- a/Mods/Core/Defs/plants.json +++ b/Mods/Core/Defs/Plants/_Bases.json @@ -1,5 +1,7 @@ { "type": "Plant", + // Общие (абстрактные) растения: базовые геномы по типам ниш. Конкретные виды наследуют их + // через "parent" и лежат рядом в файлах по семействам (Trees, Bushes, Cacti, …). "defs": [ { "defName": "BaseTree", "abstract": true, "sizeCells": 2.0, "trunkRadiusCells": 0.28, "harvestProduct": "ProductWood", "fruitProduct": "ProductAcorn", @@ -14,41 +16,8 @@ { "sizeCells": 1.2, "growDays": 9, "label": "plant.stage.sapling" }, { "sizeCells": 2.0, "label": "plant.stage.mature" } ] }, - { "defName": "TreeOakA", "parent": "BaseTree", "label": "plant.oak", "texture": "things/plant/treeoak/TreeOakA" }, - { "defName": "TreeOakB", "parent": "BaseTree", "label": "plant.oak", "texture": "things/plant/treeoak/TreeOakB" }, - { "defName": "TreeBirchA", "parent": "BaseTree", "label": "plant.birch", "texture": "things/plant/treebirch/TreeBirchA" }, - { "defName": "TreeGrayPineA", "parent": "BaseTree", "label": "plant.pine", "texture": "things/plant/treegraypine/TreeGrayPineA" }, - { "defName": "GrassA", "label": "plant.grass", "texture": "things/plant/grass/grassa", "sizeCells": 1.5, - "harvestProduct": "ProductGrass", - "genome": { "optimalLight": 0.85, "lightTolerance": 0.35, "optimalTemperature": 19, "temperatureTolerance": 8, - "coldHardiness": 9, "heatHardiness": 6, - "optimalFertility": 1.0, "fertilityTolerance": 1.0, "vigor": 1.3, - "lifespan": 22, "dispersalRange": 3, "reproduceInterval": 3, "selfPollination": 0.8, - "mutationRate": 0.06, "variantChance": 0.2, "spread": 0.1, - "harvestAmount": 2, "leafHue": 0.36 }, - "stages": [ - { "texture": "things/plant/seed_default", "sizeCells": 0.5, "growDays": 2, "label": "plant.stage.sprout" }, - { "sizeCells": 1.5, "label": "plant.stage.mature" } - ] }, - - { "defName": "BaseBush", "abstract": true, "label": "plant.bush", "sizeCells": 1.4, - "fruitProduct": "ProductBerry", - "genome": { "optimalLight": 0.6, "lightTolerance": 0.5, "optimalTemperature": 17, "temperatureTolerance": 9, - "coldHardiness": 10, "heatHardiness": 8, - "optimalFertility": 1.1, "fertilityTolerance": 1.0, "vigor": 1.0, - "lifespan": 60, "dispersalRange": 2, "reproduceInterval": 7, "selfPollination": 0.5, - "mutationRate": 0.05, "variantChance": 0.18, "spread": 0.1, - "fruitYield": 3, "fruitSeason": 1, "harvestAmount": 3, "leafHue": 0.32 }, - "stages": [ - { "texture": "things/plant/seed_default", "sizeCells": 0.6, "growDays": 3, "label": "plant.stage.sprout" }, - { "sizeCells": 1.4, "label": "plant.stage.mature" } - ] }, - { "defName": "BushA", "parent": "BaseBush", "texture": "things/plant/bush/BushA" }, - { "defName": "BushB", "parent": "BaseBush", "texture": "things/plant/bush/BushB" }, - { "defName": "BushC", "parent": "BaseBush", "texture": "things/plant/bush/BushC" }, - - // --- Деревья+: тёплая и холодная температурные ниши (showcase температурных генов) --- + // Деревья тёплой и холодной температурных ниш (showcase температурных генов). { "defName": "BaseWarmTree", "abstract": true, "sizeCells": 2.0, "trunkRadiusCells": 0.28, "harvestProduct": "ProductWood", "fruitProduct": "ProductAcorn", "genome": { "optimalLight": 0.65, "lightTolerance": 0.5, "optimalTemperature": 23, "temperatureTolerance": 9, @@ -75,16 +44,21 @@ { "sizeCells": 1.2, "growDays": 9, "label": "plant.stage.sapling" }, { "sizeCells": 2.0, "label": "plant.stage.mature" } ] }, - { "defName": "TreeMapleA", "parent": "BaseTree", "label": "plant.maple", "texture": "things/plant/treemaple/TreeMapleA" }, - { "defName": "TreeMapleB", "parent": "BaseTree", "label": "plant.maple", "texture": "things/plant/treemaple/TreeMapleB" }, - { "defName": "TreePoplarA", "parent": "BaseTree", "label": "plant.poplar", "texture": "things/plant/treepoplar/TreePoplarA" }, - { "defName": "TreeTeakA", "parent": "BaseWarmTree", "label": "plant.teak", "texture": "things/plant/treeteak/TreeTeakA" }, - { "defName": "TreeTeakB", "parent": "BaseWarmTree", "label": "plant.teak", "texture": "things/plant/treeteak/TreeTeakB" }, - { "defName": "TreeCypressA", "parent": "BaseColdTree", "label": "plant.cypress", "texture": "things/plant/treecypress/TreeCypressA" }, - { "defName": "TreeCypressB", "parent": "BaseColdTree", "label": "plant.cypress", "texture": "things/plant/treecypress/TreeCypressB" }, - // --- Пустыня: кактусы и агава на песке. Жаролюбивы, засухоустойчивы (низкий оптимум почвы), - // морозо-нестойки (tMin ≈ -2°C → гибнут в морозы). Большинство без плодов; сагуаро/агава плодоносят. --- + { "defName": "BaseBush", "abstract": true, "label": "plant.bush", "sizeCells": 1.4, + "fruitProduct": "ProductBerry", + "genome": { "optimalLight": 0.6, "lightTolerance": 0.5, "optimalTemperature": 17, "temperatureTolerance": 9, + "coldHardiness": 10, "heatHardiness": 8, + "optimalFertility": 1.1, "fertilityTolerance": 1.0, "vigor": 1.0, + "lifespan": 60, "dispersalRange": 2, "reproduceInterval": 7, "selfPollination": 0.5, + "mutationRate": 0.05, "variantChance": 0.18, "spread": 0.1, + "fruitYield": 3, "fruitSeason": 1, "harvestAmount": 3, "leafHue": 0.32 }, + "stages": [ + { "texture": "things/plant/seed_default", "sizeCells": 0.6, "growDays": 3, "label": "plant.stage.sprout" }, + { "sizeCells": 1.4, "label": "plant.stage.mature" } + ] }, + + // Кактусы: жаролюбивы, засухоустойчивы (низкий оптимум почвы), морозо-нестойки → гибнут в морозы. { "defName": "BaseCactus", "abstract": true, "label": "plant.cactus", "sizeCells": 1.2, "trunkRadiusCells": 0, "harvestProduct": "ProductFiber", "genome": { "optimalLight": 0.95, "lightTolerance": 0.35, "optimalTemperature": 26, "temperatureTolerance": 8, @@ -97,18 +71,9 @@ { "texture": "things/plant/seed_default", "sizeCells": 0.5, "growDays": 5, "label": "plant.stage.sprout" }, { "label": "plant.stage.mature" } ] }, - { "defName": "SaguaroCactusA", "parent": "BaseCactus", "label": "plant.saguaro", "sizeCells": 2.2, "trunkRadiusCells": 0.18, - "fruitProduct": "ProductBerry", "texture": "things/plant/saguarocactus/SaguaroCactusA" }, - { "defName": "SaguaroCactusB", "parent": "BaseCactus", "label": "plant.saguaro", "sizeCells": 2.2, "trunkRadiusCells": 0.18, - "fruitProduct": "ProductBerry", "texture": "things/plant/saguarocactus/SaguaroCactusB" }, - { "defName": "PebbleCactusA", "parent": "BaseCactus", "sizeCells": 1.0, "texture": "things/plant/pebblecactus/PebbleCactusA" }, - { "defName": "PebbleCactusB", "parent": "BaseCactus", "sizeCells": 1.0, "texture": "things/plant/pebblecactus/PebbleCactusB" }, - { "defName": "PincushionCactusA", "parent": "BaseCactus", "sizeCells": 0.9, "texture": "things/plant/pincushioncactus/PincushionCactusA" }, - { "defName": "AgaveA", "parent": "BaseCactus", "label": "plant.agave", "sizeCells": 1.3, "fruitProduct": "ProductBerry", "texture": "things/plant/agave/AgaveA" }, - { "defName": "AgaveB", "parent": "BaseCactus", "label": "plant.agave", "sizeCells": 1.3, "fruitProduct": "ProductBerry", "texture": "things/plant/agave/AgaveB" }, - // --- Грибы: подлесок леса. Низкий оптимум света (0.15) → растут в тени крон, где другим темно - // (showcase световой пригодности). Богатая почва, короткая жизнь, быстрое спороношение. --- + // Грибы: подлесок леса. Низкий оптимум света (0.15) → растут в тени крон, где другим темно + // (showcase световой пригодности). Богатая почва, короткая жизнь, быстрое спороношение. { "defName": "BaseMushroom", "abstract": true, "label": "plant.mushroom", "sizeCells": 0.9, "trunkRadiusCells": 0, "harvestProduct": "ProductMushroom", "genome": { "optimalLight": 0.15, "lightTolerance": 0.22, "optimalTemperature": 14, "temperatureTolerance": 11, @@ -121,13 +86,8 @@ { "texture": "things/plant/seed_default", "sizeCells": 0.4, "growDays": 2, "label": "plant.stage.sprout" }, { "label": "plant.stage.mature" } ] }, - { "defName": "GlowstoolA", "parent": "BaseMushroom", "sizeCells": 0.9, "texture": "things/plant/glowstool/GlowstoolA" }, - { "defName": "GlowstoolB", "parent": "BaseMushroom", "sizeCells": 0.9, "texture": "things/plant/glowstool/GlowstoolB" }, - { "defName": "TimbershroomA", "parent": "BaseMushroom", "sizeCells": 1.1, "texture": "things/plant/timbershroom/TimbershroomA" }, - { "defName": "TimbershroomB", "parent": "BaseMushroom", "sizeCells": 1.1, "texture": "things/plant/timbershroom/TimbershroomB" }, - { "defName": "NutrifungusA", "parent": "BaseMushroom", "sizeCells": 0.9, "texture": "things/plant/nutrifungus/NutrifungusA" }, - // --- Луг: цветы (декоративные, быстрое расселение) и ягодный почвопокров (еда). --- + // Луг: цветы (декоративные, быстрое расселение) и ягодный почвопокров (еда). { "defName": "BaseFlower", "abstract": true, "label": "plant.flower", "sizeCells": 1.0, "trunkRadiusCells": 0, "genome": { "optimalLight": 0.9, "lightTolerance": 0.35, "optimalTemperature": 20, "temperatureTolerance": 9, "coldHardiness": 8, "heatHardiness": 8, @@ -139,12 +99,6 @@ { "texture": "things/plant/seed_default", "sizeCells": 0.4, "growDays": 2, "label": "plant.stage.sprout" }, { "label": "plant.stage.mature" } ] }, - { "defName": "DandelionA", "parent": "BaseFlower", "label": "plant.dandelion", "texture": "things/plant/dandelion/Dandelion" }, - { "defName": "DandelionB", "parent": "BaseFlower", "label": "plant.dandelion", "texture": "things/plant/dandelion/DandelionB" }, - { "defName": "DandelionC", "parent": "BaseFlower", "label": "plant.dandelion", "texture": "things/plant/dandelion/DandelionC" }, - { "defName": "DaylilyA", "parent": "BaseFlower", "label": "plant.daylily", "texture": "things/plant/daylily/DaylilyA" }, - { "defName": "DaylilyB", "parent": "BaseFlower", "label": "plant.daylily", "texture": "things/plant/daylily/DaylilyB" }, - { "defName": "RoseA", "parent": "BaseFlower", "label": "plant.rose", "sizeCells": 1.1, "texture": "things/plant/rose/RoseA" }, { "defName": "BaseBerryBush", "abstract": true, "label": "plant.berrybush", "sizeCells": 1.2, "trunkRadiusCells": 0, "fruitProduct": "ProductBerry", @@ -157,8 +111,6 @@ "stages": [ { "texture": "things/plant/seed_default", "sizeCells": 0.5, "growDays": 3, "label": "plant.stage.sprout" }, { "label": "plant.stage.mature" } - ] }, - { "defName": "Strawberry", "parent": "BaseBerryBush", "label": "plant.strawberry", "sizeCells": 1.0, "texture": "things/plant/strawberryplant/StrawberryPlant" }, - { "defName": "Raspberry", "parent": "BaseBerryBush", "label": "plant.raspberry", "texture": "things/plant/raspberryplant/raspberrybusha" } + ] } ] } diff --git a/Mods/Core/Defs/products.json b/Mods/Core/Defs/Products/Products.json similarity index 100% rename from Mods/Core/Defs/products.json rename to Mods/Core/Defs/Products/Products.json diff --git a/Mods/Core/Defs/terrain.json b/Mods/Core/Defs/Terrain/Terrain.json similarity index 100% rename from Mods/Core/Defs/terrain.json rename to Mods/Core/Defs/Terrain/Terrain.json diff --git a/Mods/Core/Defs/worldpresets.json b/Mods/Core/Defs/WorldPresets/WorldPresets.json similarity index 100% rename from Mods/Core/Defs/worldpresets.json rename to Mods/Core/Defs/WorldPresets/WorldPresets.json diff --git a/Mods/Core/Defs/genes.json b/Mods/Core/Defs/genes.json deleted file mode 100644 index 5610511..0000000 --- a/Mods/Core/Defs/genes.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "type": "Gene", - // Организм-агностичные гены: каждый ген задаёт, как генерируются/мутируют аллели и как ген - // вкладывается в признаки (effects: имя признака → формула; value — выраженное значение гена). - // Этот набор покрывает измерения генома растения (его используют системы роста/жизненного цикла). - "defs": [ - { "defName": "BaseNumericGene", "abstract": true, "kind": "Numeric", - "spread": 0.08, "mutationChance": 0.05, "mutationMagnitude": 0.12 }, - - { "defName": "GeneOptimalLight", "parent": "BaseNumericGene", "label": "gene.optimalLight", - "default": 0.6, "min": 0.0, "max": 1.0, "tags": ["environment", "light"], - "effects": { "optimalLight": "value" } }, - { "defName": "GeneLightTolerance", "parent": "BaseNumericGene", "label": "gene.lightTolerance", - "default": 0.5, "min": 0.05, "max": 1.0, "tags": ["environment", "light"], - "effects": { "lightTolerance": "value" } }, - { "defName": "GeneOptimalTemperature", "parent": "BaseNumericGene", "label": "gene.optimalTemperature", - "default": 14, "min": -20, "max": 45, "tags": ["environment", "temperature"], - "effects": { "optimalTemperature": "value" } }, - { "defName": "GeneTemperatureTolerance", "parent": "BaseNumericGene", "label": "gene.temperatureTolerance", - "default": 16, "min": 2, "max": 40, "tags": ["environment", "temperature"], - "effects": { "temperatureTolerance": "value" } }, - // Жёсткие края диапазона роста (модель RimWorld): на сколько °C ниже/выше плато оптимума рост - // спадает до нуля. Ниже (optimal-tolerance-coldHardiness) или выше (optimal+tolerance+heatHardiness) - // растение дормантно и копит температурный стресс. Асимметрично: вид может терпеть жару лучше холода. - { "defName": "GeneColdHardiness", "parent": "BaseNumericGene", "label": "gene.coldHardiness", - "default": 8, "min": 0, "max": 40, "tags": ["environment", "temperature"], - "effects": { "coldHardiness": "value" } }, - { "defName": "GeneHeatHardiness", "parent": "BaseNumericGene", "label": "gene.heatHardiness", - "default": 10, "min": 0, "max": 40, "tags": ["environment", "temperature"], - "effects": { "heatHardiness": "value" } }, - { "defName": "GeneOptimalFertility", "parent": "BaseNumericGene", "label": "gene.optimalFertility", - "default": 1.4, "min": 0.1, "max": 3.0, "tags": ["environment", "soil"], - "effects": { "optimalFertility": "value" } }, - { "defName": "GeneFertilityTolerance", "parent": "BaseNumericGene", "label": "gene.fertilityTolerance", - "default": 0.9, "min": 0.1, "max": 3.0, "tags": ["environment", "soil"], - "effects": { "fertilityTolerance": "value" } }, - - { "defName": "GeneVigor", "parent": "BaseNumericGene", "label": "gene.vigor", - "default": 1.0, "min": 0.1, "max": 3.0, "tags": ["growth"], - "effects": { "vigor": "value" } }, - { "defName": "GeneLifespan", "parent": "BaseNumericGene", "label": "gene.lifespan", - "default": 160, "min": 5, "max": 500, "tags": ["lifecycle"], - "effects": { "lifespan": "value" } }, - { "defName": "GeneDispersalRange", "parent": "BaseNumericGene", "label": "gene.dispersalRange", - "default": 2, "min": 1, "max": 8, "tags": ["lifecycle", "reproduction"], - "effects": { "dispersalRange": "value" } }, - { "defName": "GeneReproduceInterval", "parent": "BaseNumericGene", "label": "gene.reproduceInterval", - "default": 14, "min": 1, "max": 60, "tags": ["lifecycle", "reproduction"], - "effects": { "reproduceInterval": "value" } }, - { "defName": "GeneSelfPollination", "parent": "BaseNumericGene", "label": "gene.selfPollination", - "default": 0.2, "min": 0.0, "max": 1.0, "tags": ["reproduction"], - "effects": { "selfPollination": "value" } }, - { "defName": "GeneMutationRate", "parent": "BaseNumericGene", "label": "gene.mutationRate", - "default": 0.05, "min": 0.0, "max": 1.0, "tags": ["reproduction"], - "effects": { "mutationRate": "value" } }, - - // --- Контент (фаза G4): плодоношение, добыча, цвет --- - { "defName": "GeneFruitYield", "parent": "BaseNumericGene", "label": "gene.fruitYield", - "default": 0, "min": 0, "max": 12, "tags": ["fruiting"], - "effects": { "fruitYield": "value" } }, - { "defName": "GeneFruitSeason", "parent": "BaseNumericGene", "label": "gene.fruitSeason", - "default": 1, "min": 0, "max": 3, "spread": 0, "mutationChance": 0, "tags": ["fruiting"], - "effects": { "fruitSeason": "value" } }, - { "defName": "GeneHarvestAmount", "parent": "BaseNumericGene", "label": "gene.harvestAmount", - "default": 1, "min": 0, "max": 50, "tags": ["harvest"], - "effects": { "harvestAmount": "value" } }, - { "defName": "GeneLeafHue", "parent": "BaseNumericGene", "label": "gene.leafHue", - "default": 0.33, "min": 0, "max": 1, "spread": 0.04, "tags": ["morphology", "color"], - "effects": { "leafHue": "value" } }, - - // Производный ген: признак собирается группировкой по регэкспу — сумма всех генов-толерантностей - // (демонстрация gsom-функций фазы G5). Собственное значение гена не используется. - { "defName": "GeneHardiness", "parent": "BaseNumericGene", "label": "gene.hardiness", - "default": 0, "min": 0, "max": 1, "spread": 0, "mutationChance": 0, "tags": ["derived"], - "effects": { "hardiness": "gsum('Gene.*Tolerance')" } }, - - // Дискретный ген морфы: вариант 0 доминирует, 1 (рецессивный) виден только в гомозиготе. - { "defName": "GeneMorph", "kind": "Discrete", "label": "gene.morph", - "variants": 2, "variantWeights": [0.82, 0.18], "mutationChance": 0.05, "tags": ["morphology"], - "effects": { "variant": "value" } } - ] -} diff --git a/docs/mods.md b/docs/mods.md index 1239330..cd9b52a 100644 --- a/docs/mods.md +++ b/docs/mods.md @@ -60,6 +60,26 @@ Mods/<Имя>/ вид — `being`/`animal`). CLR-классы — `src/LittleSim/Content/GameDefs.cs`; новый тип дефа = новый класс + `RegisterType` в `GameContent.Load`. +`Defs/` сканируется рекурсивно (`Defs/**/*.json`), и имя файла ни на что не влияет — +важны только `type` и `defName`. Поэтому контент Core разложен по подпапкам для удобства +поиска: одна папка на тип дефа, внутри — общие (абстрактные) дефы в `_Bases.json` и +конкретные, разбитые по семействам: + +``` +Defs/ + Genes/ _Bases.json, Environment.json, Growth.json, Content.json + Plants/ _Bases.json, Trees.json, Bushes.json, Grass.json, Cacti.json, + Mushrooms.json, Flowers.json, Berries.json + Pawns/ _Bases.json, Beings.json, Animals.json + Terrain/ Terrain.json + Products/ Products.json + Patches/ Patches.json + WorldPresets/ WorldPresets.json +``` + +`parent` разрешается после слияния всех файлов, так что ссылка на родителя из другого +файла/папки (`TreeOakA` → `BaseTree`) работает независимо от расположения. + ## Локализация `Languages/<код>/*.json` — плоские словари «ключ → строка»: diff --git a/engine b/engine index 38bdfbb..96e19c7 160000 --- a/engine +++ b/engine @@ -1 +1 @@ -Subproject commit 38bdfbbb81fa7e283d2908e097c94d16853bc0de +Subproject commit 96e19c7c6151152c29c5c5478d365983d3df4069 diff --git a/src/LittleSim/Content/GameDefs.cs b/src/LittleSim/Content/GameDefs.cs index 81b2442..1149a84 100644 --- a/src/LittleSim/Content/GameDefs.cs +++ b/src/LittleSim/Content/GameDefs.cs @@ -14,7 +14,7 @@ public sealed class ScatterEntry public List Options { get; init; } = []; } -/// Тип клетки рельефа (Defs/terrain.json): порог высоты, цвет, поверхность, скаттер растений. +/// Тип клетки рельефа (Defs/Terrain/): порог высоты, цвет, поверхность, скаттер растений. public sealed class TerrainDef : Def { /// Верхняя граница высоты (клетка относится к первому дефу, чей порог выше её высоты). @@ -67,7 +67,7 @@ public sealed class PlantGrowthStage } /// -/// Продукт (Defs/products.json): что растение даёт при сборе (древесина, трава) или плодоношении +/// Продукт (Defs/Products/): что растение даёт при сборе (древесина, трава) или плодоношении /// (ягоды, жёлудь). Источник истины — деф; растения ссылаются на него по имени, а количество /// определяют гены. — ключ локализации (product.*). /// @@ -145,7 +145,7 @@ public sealed class GenomeDef public float LeafHue { get; init; } = 0.33f; } -/// Растение (Defs/plants.json): текстура, размер, опциональный ствол-препятствие, стадии роста, геном. +/// Растение (Defs/Plants/): текстура, размер, опциональный ствол-препятствие, стадии роста, геном. public sealed class PlantDef : Def { /// Ключ текстуры (путь региона в атласах); база для стадий без своей текстуры. @@ -171,7 +171,7 @@ public sealed class PlantDef : Def } /// -/// Пресет размера мира (Defs/worldpresets.json): габариты сетки и население. Меню «Новый +/// Пресет размера мира (Defs/WorldPresets/): габариты сетки и население. Меню «Новый /// мир» строит список размеров из этих дефов — новая механика приходит данными мода, а не /// хардкодом. — ключ локализации (preset.*). /// @@ -190,7 +190,7 @@ public sealed class WorldPresetDef : Def public int Order { get; init; } } -/// Существо (Defs/pawns.json): текстура, размер и вид (житель/животное). +/// Существо (Defs/Pawns/): текстура, размер и вид (житель/животное). public sealed class PawnDef : Def { /// Вид существа: жители ("being") живут в мировой сцене, животные ("animal") — в террейне. diff --git a/src/LittleSim/Content/PlantSet.cs b/src/LittleSim/Content/PlantSet.cs index 0334af7..684b7a1 100644 --- a/src/LittleSim/Content/PlantSet.cs +++ b/src/LittleSim/Content/PlantSet.cs @@ -81,7 +81,7 @@ public sealed class PlantSet /// Индекс вида по дефу. public int IndexOf(PlantDef def) => _index[def]; - // Переводит базовый геном вида (числа из plants.json) в набор генов: каждое число — центр + // Переводит базовый геном вида (числа из Defs/Plants/) в набор генов: каждое число — центр // аллелей соответствующего общего GeneDef; морфа — дискретный ген с долей рецессива из вида. private static GenomeTemplate BuildTemplate( GenomeDef g, @@ -92,7 +92,7 @@ public sealed class PlantSet genes.TryGetValue(id, out var def) ? def : throw new KeyNotFoundException( - $"Gene def '{id}' not found — is Mods/Core/Defs/genes.json loaded?" + $"Gene def '{id}' not found — is Mods/Core/Defs/Genes/ loaded?" ); GenomeTemplate.Entry Numeric(string id, float baseValue) => diff --git a/src/LittleSim/Sim/PlantOrganism.cs b/src/LittleSim/Sim/PlantOrganism.cs index 78aaaca..b6e563b 100644 --- a/src/LittleSim/Sim/PlantOrganism.cs +++ b/src/LittleSim/Sim/PlantOrganism.cs @@ -5,7 +5,7 @@ using MrGameEng.Genetics; namespace LittleSim.Sim; /// -/// Растительные признаки (фенотип), вычисленные из генома формулами генов (см. genes.json): +/// Растительные признаки (фенотип), вычисленные из генома формулами генов (см. Defs/Genes/): /// готовые значения, которые читают системы роста и жизненного цикла, не касаясь генов напрямую. /// Имена полей соответствуют именам признаков в эффектах генов. ///