From 9c9502414b5aebfd505773cb113fbc921942e476 Mon Sep 17 00:00:00 2001 From: Leonid Pershin Date: Sat, 13 Jun 2026 06:55:43 +0300 Subject: [PATCH] Update plant definitions and localization. Adjusted GrassA sizeCells from 1.2 to 1.5 and added new plant types including BaseWarmTree, BaseColdTree, and various cacti. Enhanced terrain definitions with scatter probabilities for new plants. Updated product definitions to include fiber and mushrooms, and localized new plant and product names in English and Russian. Updated engine subproject commit to 08381703f79377a5bc48fc0745620f8815695b05-dirty. --- Mods/Core/Defs/plants.json | 119 ++++++++++++++++++++++++++++- Mods/Core/Defs/products.json | 4 +- Mods/Core/Defs/terrain.json | 26 +++++-- Mods/Core/Languages/en/ui.json | 17 +++++ Mods/Core/Languages/ru/ui.json | 17 +++++ engine | 2 +- src/LittleSim/Scenes/WorldScene.cs | 18 ++++- 7 files changed, 189 insertions(+), 14 deletions(-) diff --git a/Mods/Core/Defs/plants.json b/Mods/Core/Defs/plants.json index 0791e14..6d078c2 100644 --- a/Mods/Core/Defs/plants.json +++ b/Mods/Core/Defs/plants.json @@ -19,7 +19,7 @@ { "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.2, + { "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, @@ -29,7 +29,7 @@ "harvestAmount": 2, "leafHue": 0.36 }, "stages": [ { "texture": "things/plant/seed_default", "sizeCells": 0.5, "growDays": 2, "label": "plant.stage.sprout" }, - { "sizeCells": 1.2, "label": "plant.stage.mature" } + { "sizeCells": 1.5, "label": "plant.stage.mature" } ] }, { "defName": "BaseBush", "abstract": true, "label": "plant.bush", "sizeCells": 1.4, @@ -46,6 +46,119 @@ ] }, { "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" } + { "defName": "BushC", "parent": "BaseBush", "texture": "things/plant/bush/BushC" }, + + // --- Деревья+: тёплая и холодная температурные ниши (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, + "coldHardiness": 8, "heatHardiness": 16, + "optimalFertility": 1.5, "fertilityTolerance": 0.9, "vigor": 1.1, + "lifespan": 150, "dispersalRange": 2, "reproduceInterval": 14, "selfPollination": 0.2, + "mutationRate": 0.05, "variantChance": 0.15, "spread": 0.08, + "fruitYield": 5, "fruitSeason": 2, "harvestAmount": 10, "leafHue": 0.22 }, + "stages": [ + { "texture": "things/plant/seed_default", "sizeCells": 0.6, "growDays": 4, "label": "plant.stage.seedling" }, + { "sizeCells": 1.2, "growDays": 9, "label": "plant.stage.sapling" }, + { "sizeCells": 2.0, "label": "plant.stage.mature" } + ] }, + { "defName": "BaseColdTree", "abstract": true, "sizeCells": 2.0, "trunkRadiusCells": 0.26, + "harvestProduct": "ProductWood", "fruitProduct": "ProductAcorn", + "genome": { "optimalLight": 0.55, "lightTolerance": 0.5, "optimalTemperature": 8, "temperatureTolerance": 12, + "coldHardiness": 18, "heatHardiness": 8, + "optimalFertility": 1.2, "fertilityTolerance": 1.0, "vigor": 0.9, + "lifespan": 220, "dispersalRange": 2, "reproduceInterval": 16, "selfPollination": 0.2, + "mutationRate": 0.05, "variantChance": 0.12, "spread": 0.08, + "fruitYield": 4, "fruitSeason": 2, "harvestAmount": 12, "leafHue": 0.45 }, + "stages": [ + { "texture": "things/plant/seed_default", "sizeCells": 0.6, "growDays": 4, "label": "plant.stage.seedling" }, + { "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": "BaseCactus", "abstract": true, "label": "plant.cactus", "sizeCells": 1.2, "trunkRadiusCells": 0, + "harvestProduct": "ProductFiber", + "genome": { "optimalLight": 0.95, "lightTolerance": 0.35, "optimalTemperature": 26, "temperatureTolerance": 8, + "coldHardiness": 20, "heatHardiness": 18, + "optimalFertility": 0.4, "fertilityTolerance": 0.5, "vigor": 0.5, + "lifespan": 300, "dispersalRange": 2, "reproduceInterval": 25, "selfPollination": 0.6, + "mutationRate": 0.05, "variantChance": 0.15, "spread": 0.08, + "fruitYield": 3, "fruitSeason": 1, "harvestAmount": 3, "leafHue": 0.5 }, + "stages": [ + { "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 световой пригодности). Богатая почва, короткая жизнь, быстрое спороношение. --- + { "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, + "coldHardiness": 12, "heatHardiness": 8, + "optimalFertility": 1.6, "fertilityTolerance": 1.1, "vigor": 1.2, + "lifespan": 25, "dispersalRange": 3, "reproduceInterval": 4, "selfPollination": 0.9, + "mutationRate": 0.06, "variantChance": 0.2, "spread": 0.1, + "fruitYield": 0, "fruitSeason": 1, "harvestAmount": 3, "leafHue": 0.5 }, + "stages": [ + { "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, + "optimalFertility": 1.0, "fertilityTolerance": 1.1, "vigor": 1.4, + "lifespan": 18, "dispersalRange": 4, "reproduceInterval": 3, "selfPollination": 0.85, + "mutationRate": 0.08, "variantChance": 0.3, "spread": 0.1, + "fruitYield": 0, "fruitSeason": 0, "harvestAmount": 0, "leafHue": 0.2 }, + "stages": [ + { "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", + "genome": { "optimalLight": 0.8, "lightTolerance": 0.4, "optimalTemperature": 18, "temperatureTolerance": 9, + "coldHardiness": 10, "heatHardiness": 7, + "optimalFertility": 1.2, "fertilityTolerance": 1.0, "vigor": 1.1, + "lifespan": 40, "dispersalRange": 2, "reproduceInterval": 6, "selfPollination": 0.6, + "mutationRate": 0.05, "variantChance": 0.18, "spread": 0.1, + "fruitYield": 4, "fruitSeason": 2, "harvestAmount": 0, "leafHue": 0.33 }, + "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.json index f43d352..eec749f 100644 --- a/Mods/Core/Defs/products.json +++ b/Mods/Core/Defs/products.json @@ -5,7 +5,9 @@ "defs": [ { "defName": "ProductWood", "label": "product.wood", "kind": "material" }, { "defName": "ProductGrass", "label": "product.grass", "kind": "material" }, + { "defName": "ProductFiber", "label": "product.fiber", "kind": "material" }, { "defName": "ProductBerry", "label": "product.berry", "kind": "food" }, - { "defName": "ProductAcorn", "label": "product.acorn", "kind": "food" } + { "defName": "ProductAcorn", "label": "product.acorn", "kind": "food" }, + { "defName": "ProductMushroom", "label": "product.mushroom", "kind": "food" } ] } diff --git a/Mods/Core/Defs/terrain.json b/Mods/Core/Defs/terrain.json index d86cb5b..36fb0fb 100644 --- a/Mods/Core/Defs/terrain.json +++ b/Mods/Core/Defs/terrain.json @@ -3,19 +3,31 @@ "defs": [ { "defName": "DeepWater", "label": "terrain.deepwater", "maxHeight": 0.30, "color": [23, 63, 95] }, { "defName": "Water", "label": "terrain.water", "maxHeight": 0.42, "color": [32, 99, 155] }, - { "defName": "Sand", "label": "terrain.sand", "maxHeight": 0.48, "color": [237, 201, 120], - "isLand": true, "surface": "terrain/surfaces/sand", "fertility": 0.4 }, - { "defName": "Grass", "label": "terrain.grass", "maxHeight": 0.68, "color": [90, 160, 70], + { "defName": "Sand", "label": "terrain.sand", "maxHeight": 0.46, "color": [237, 201, 120], + "isLand": true, "surface": "terrain/surfaces/sand", "fertility": 0.4, + "scatter": [ + { "chance": 0.05, "options": ["SaguaroCactusA", "SaguaroCactusB"] }, + { "chance": 0.10, "options": ["PebbleCactusA", "PebbleCactusB", "PincushionCactusA"] }, + { "chance": 0.04, "options": ["AgaveA", "AgaveB"] } + ] }, + { "defName": "Grass", "label": "terrain.grass", "maxHeight": 0.72, "color": [90, 160, 70], "isLand": true, "surface": "terrain/surfaces/mossy", "fertility": 1.0, "scatter": [ - { "chance": 0.6, "options": ["GrassA"] }, - { "chance": 0.07, "options": ["BushA", "BushB", "BushC"] } + { "chance": 1.0, "options": ["GrassA"] }, + { "chance": 0.5, "options": ["GrassA"] }, + { "chance": 0.22, "options": ["BushA", "BushB", "BushC"] }, + { "chance": 0.20, "options": ["Strawberry", "Raspberry"] }, + { "chance": 0.14, "options": ["DandelionA", "DandelionB", "DandelionC", "DaylilyA", "DaylilyB", "RoseA"] } ] }, { "defName": "Forest", "label": "terrain.forest", "maxHeight": 0.85, "color": [44, 110, 50], "isLand": true, "surface": "terrain/surfaces/soil", "fertility": 1.6, "scatter": [ - { "chance": 0.35, "options": ["TreeOakA", "TreeOakB", "TreeBirchA", "TreeGrayPineA"] }, - { "chance": 0.3, "options": ["GrassA"] } + { "chance": 0.35, "options": ["TreeOakA", "TreeOakB", "TreeBirchA", "TreeGrayPineA", + "TreeMapleA", "TreeMapleB", "TreePoplarA", "TreeCypressA", "TreeCypressB", "TreeTeakA", "TreeTeakB"] }, + { "chance": 0.6, "options": ["GrassA"] }, + { "chance": 0.16, "options": ["BushA", "BushB", "BushC"] }, + { "chance": 0.14, "options": ["Strawberry", "Raspberry"] }, + { "chance": 0.16, "options": ["GlowstoolA", "GlowstoolB", "TimbershroomA", "TimbershroomB", "NutrifungusA"] } ] }, { "defName": "Mountain", "label": "terrain.mountain", "maxHeight": 1.01, "color": [136, 132, 128], "surface": "terrain/surfaces/roughhewnrock", "fertility": 0.2, "blocksLight": true } diff --git a/Mods/Core/Languages/en/ui.json b/Mods/Core/Languages/en/ui.json index 916cab9..5c4464f 100644 --- a/Mods/Core/Languages/en/ui.json +++ b/Mods/Core/Languages/en/ui.json @@ -89,14 +89,31 @@ "plant.pine": "pine", "plant.grass": "grass tuft", "plant.bush": "bush", + "plant.maple": "maple", + "plant.poplar": "poplar", + "plant.teak": "teak", + "plant.cypress": "cypress", + "plant.cactus": "cactus", + "plant.saguaro": "saguaro", + "plant.agave": "agave", + "plant.mushroom": "mushroom", + "plant.flower": "flower", + "plant.dandelion": "dandelion", + "plant.daylily": "daylily", + "plant.rose": "rose", + "plant.berrybush": "berry bush", + "plant.strawberry": "strawberry", + "plant.raspberry": "raspberry", "plant.stage.seedling": "seedling", "plant.stage.sprout": "sprout", "plant.stage.sapling": "sapling", "plant.stage.mature": "mature", "product.wood": "wood", "product.grass": "grass", + "product.fiber": "fiber", "product.berry": "berries", "product.acorn": "acorn", + "product.mushroom": "mushrooms", "pawn.being": "being", "pawn.bear": "bear", "pawn.deer": "deer", diff --git a/Mods/Core/Languages/ru/ui.json b/Mods/Core/Languages/ru/ui.json index d41562d..f576f95 100644 --- a/Mods/Core/Languages/ru/ui.json +++ b/Mods/Core/Languages/ru/ui.json @@ -89,14 +89,31 @@ "plant.pine": "сосна", "plant.grass": "пучок травы", "plant.bush": "куст", + "plant.maple": "клён", + "plant.poplar": "тополь", + "plant.teak": "тик", + "plant.cypress": "кипарис", + "plant.cactus": "кактус", + "plant.saguaro": "сагуаро", + "plant.agave": "агава", + "plant.mushroom": "гриб", + "plant.flower": "цветок", + "plant.dandelion": "одуванчик", + "plant.daylily": "лилейник", + "plant.rose": "роза", + "plant.berrybush": "ягодный куст", + "plant.strawberry": "земляника", + "plant.raspberry": "малина", "plant.stage.seedling": "росток", "plant.stage.sprout": "всходы", "plant.stage.sapling": "саженец", "plant.stage.mature": "взрослое", "product.wood": "древесина", "product.grass": "трава", + "product.fiber": "волокно", "product.berry": "ягоды", "product.acorn": "жёлудь", + "product.mushroom": "грибы", "pawn.being": "житель", "pawn.bear": "медведь", "pawn.deer": "олень", diff --git a/engine b/engine index 0838170..38bdfbb 160000 --- a/engine +++ b/engine @@ -1 +1 @@ -Subproject commit 08381703f79377a5bc48fc0745620f8815695b05 +Subproject commit 38bdfbbb81fa7e283d2908e097c94d16853bc0de diff --git a/src/LittleSim/Scenes/WorldScene.cs b/src/LittleSim/Scenes/WorldScene.cs index f5a0dd3..5b56a1b 100644 --- a/src/LittleSim/Scenes/WorldScene.cs +++ b/src/LittleSim/Scenes/WorldScene.cs @@ -45,6 +45,15 @@ public sealed class WorldScene : Scene /// Максимум растений на клетку — потолок плотности для размножения. public const int DensityCap = 4; + /// + /// День года, с которого начинается мир — тёплая весна (~16 °C), а не холодный рубеж года. + /// Сдвигает сезонную фазу климата, давая длинный тёплый сезон роста до первой зимы. + /// + public const int StartDayOfYear = 10; + + /// Час суток на старте мира — утро (07:00), а не полночь. + public const int StartHour = 7; + private readonly WorldConfig _config; private readonly WorldSave? _save; private readonly RectF _bounds; @@ -89,8 +98,13 @@ public sealed class WorldScene : Scene GameLayers.EnsureRegistered(renderer); this.UseTilemaps(); - var calendar = Context.UseCalendar(SecondsPerDay); - var climate = Context.UseClimate(ClimateSettings.Default); + var calendar = Context.UseCalendar(SecondsPerDay, StartHour / 24.0); + var climate = Context.UseClimate( + ClimateSettings.Default with + { + StartDayOfYear = StartDayOfYear, + } + ); var dayNight = new DayNight(calendar, DayNightSettings.Default); // Рельеф детерминирован сидом. Растения: новый мир — скаттер из сида; загрузка — из сейва.