diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..cda2bf02 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,3 @@ +[*.cs] +dotnet_style_require_accessibility_modifiers = omit_if_default:warning +dotnet_diagnostic.IDE0040.severity = warning \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..378e40c2 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,15 @@ +# These are supported funding model platforms + +github: datvm +patreon: # Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +polar: # Replace with a single Polar username +buy_me_a_coffee: # Replace with a single Buy Me a Coffee username +thanks_dev: # Replace with a single thanks.dev username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/copilot-instructions.MD b/.github/copilot-instructions.MD new file mode 100644 index 00000000..ecfeca5f --- /dev/null +++ b/.github/copilot-instructions.MD @@ -0,0 +1,31 @@ +# Copilot Instructions + +## General Guidelines +- When validating changes, build only the projects containing modified files instead of building the whole solution. +- Do not run `dotnet build` when changes are limited to JavaScript and CSS files only. + +## Code Style +- Always use code blocks even for single conditional or loop statements. For example: +```cs +if (condition) { return; } + +// NOT: +if (condition) return; +``` +- Always use the latest C# features like pattern matching, switch expressions, and collection initializers. For example: +```cs +List numbers = []; +MyType variable = new(); + +// NOT: +List numbers = new(); +MyType variable = new MyType(); +``` +- Prefer no access modifier for lowest visibility. Do not use _ to prefix fields. For example: +```cs +int field; +class MyClass {} + +// NOT: +private int _field; +internal class MyClass {} diff --git a/.github/workflows/build-benchmark-v11port.yml b/.github/workflows/build-benchmark-v11port.yml new file mode 100644 index 00000000..10702c70 --- /dev/null +++ b/.github/workflows/build-benchmark-v11port.yml @@ -0,0 +1,39 @@ +name: Build BenchmarkAndOptimizerV11Port +on: + push: + branches: + - pr/benchmark-optimizer-v11-port + paths: + - 'BenchmarkAndOptimizerV11Port/**' + - '.github/workflows/build-benchmark-v11port.yml' + pull_request: + paths: + - 'BenchmarkAndOptimizerV11Port/**' + - '.github/workflows/build-benchmark-v11port.yml' + workflow_dispatch: +permissions: + contents: read +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + - name: Build CSV profiler + run: dotnet build BenchmarkAndOptimizerV11Port/BenchmarkAndOptimizerV11Port.csproj -c Release + - name: Stage ready-to-install mod + shell: bash + run: | + set -euxo pipefail + ROOT="${RUNNER_TEMP}/timberborn-artifact/BenchmarkAndOptimizerV11Port" + mkdir -p "$ROOT/version-1.1/Scripts" + cp BenchmarkAndOptimizerV11Port/manifest.json "$ROOT/version-1.1/manifest.json" + cp BenchmarkAndOptimizerV11Port/bin/Release/netstandard2.1/BenchmarkAndOptimizerV11.dll "$ROOT/version-1.1/Scripts/" + test -s "$ROOT/version-1.1/Scripts/BenchmarkAndOptimizerV11.dll" + - uses: actions/upload-artifact@v4 + with: + name: BenchmarkAndOptimizerV11Port_1.1.103 + path: ${{ runner.temp }}/timberborn-artifact/ + if-no-files-found: error diff --git a/.github/workflows/publish-timberlive.yml b/.github/workflows/publish-timberlive.yml new file mode 100644 index 00000000..14549aaa --- /dev/null +++ b/.github/workflows/publish-timberlive.yml @@ -0,0 +1,76 @@ +name: Publish TimberLive + +on: + workflow_dispatch: + +permissions: + contents: write + +concurrency: + group: publish-timberlive + cancel-in-progress: false + +jobs: + build-and-publish: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '10.0.x' + + - name: Restore dependencies + run: dotnet restore TimberLive/TimberLive.csproj + + - name: Publish TimberLive + run: dotnet publish TimberLive/TimberLive.csproj --configuration Release --output /tmp/TimberLive-publish + + - name: Verify fingerprint placeholders were replaced + run: | + if grep -R "#\[.{fingerprint}\]" /tmp/TimberLive-publish/wwwroot/index.html; then + echo "Fingerprint placeholder was not replaced in published index.html" + exit 1 + fi + + - name: Deploy to Cloudflare Pages + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + command: pages deploy /tmp/TimberLive-publish/wwwroot --project-name=timberlive + + - name: Checkout or create publish branch + run: | + git config user.name "GitHub Actions" + git config user.email "actions@github.com" + + if git ls-remote --exit-code --heads origin TimberLive-publish; then + git fetch origin TimberLive-publish + git switch TimberLive-publish + git reset --hard origin/TimberLive-publish + else + git switch --orphan TimberLive-publish + git rm -rf . || true + fi + + - name: Copy published files + run: | + rm -rf TimberLive + mkdir -p TimberLive + cp -a /tmp/TimberLive-publish/wwwroot/. TimberLive/ + + - name: Commit and push changes + run: | + git add TimberLive + if git diff --cached --quiet; then + echo "No changes to commit" + else + git commit -m "chore: publish TimberLive from ${{ github.sha }}" + git push origin TimberLive-publish + fi \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9491a2fd..d712965f 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,10 @@ bld/ [Ll]og/ [Ll]ogs/ +# Restore the actual buildings +!ConveyorBelt/Root/Buildings/Conveyors/Log/ +!ConveyorBelt/Root/Buildings/Conveyors/Log/** + # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..6587b251 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "grok.mentionIndexLimit": 500000 +} \ No newline at end of file diff --git a/Agents.MD b/Agents.MD new file mode 100644 index 00000000..6e5afc6a --- /dev/null +++ b/Agents.MD @@ -0,0 +1,176 @@ +# ModDesc.txt + +Do not write or update `ModDesc.txt` or `ChangeLog.txt` unless the user explicitly asks. The notes below apply only then. + +When asked to write a `ModDesc.txt`, write a Steam Workshop description in Steam BBCode (not Markdown). Match the recent mods (Crane, Fourpillars, ConstructionSiteHauler, BuildingRenovations): player-facing, practical, and compact. + +Voice: second person, what the player gets. Colleague tone: explain the mod to another player, not ad copy. No marketing fluff. Mix sentence length. A short sentence is fine when the next one carries the detail. Do not stack fragments. That includes "Not X. Not Y. Just Z." and any run of same-beat punches ("No queue. No repeat. Just science."). + +Light humor only in `[i]` flavor lines. Bold names, UI labels, and caveats with `[b]`. + +For a new building, keep the three parts separate. Do not fold them into one sentence: + +- Lore name: the name on the building. +- Mechanical description: what the player can do with it. +- Flavor: one `[i]` line, and not inside the mechanical description. + +BBCode only (Steam tags, not Markdown): `[b]`, `[i]`, `[h1]`/`[h2]`, `[img]url[/img]`, `[url=...]text[/url]`, `[list][*] item[/list]`, `[table]`/`[tr]`/`[th]`/`[td]`, `[spoiler]` only when needed. Place a screenshot soon after the intro and after major sections (Steam UGC URL when available). + +End every description with the GitHub footer below. Do not paraphrase it. + +Typical order (omit unused sections): + +1. 1–2 sentences of what the mod does. Optional `[i]` flavor line. +2. Screenshot. +3. `[h1]`/`[h2]` for buildings, features, settings, how-to, tips, FAQs, extending. +4. If configurable: `Main Menu -> Mods -> Settings button next to the mod name`. Say when defaults leave vanilla unchanged. +5. Stats as dashes (`Unlock`, `Cost`, `Workers`, `Range`, …). Related mods as Steam `[url]`. +6. Footer exactly: + +``` +=== +Mod source code and donation: https://github.com/datvm/TimberbornMods (feel free to use the code for anything). +``` + +# Versioning + +Do not bump a mod's `manifest.json` version, `ChangeLog.txt` version heading, or `IModUpdateNotifier2` version / loc key unless the user explicitly asks to bump the version. Fold new notes into the current version entry. Do not write or update `ChangeLog.txt` itself unless the user explicitly asks. + +# Code Style + +Always use code block even for single conditional or loop statements. For example: +```cs +if (condition) { return; } + +// NOT: +if (condition) return; +``` + +Always use latest C# features like pattern matching, switch expressions, and collection initializers. For example: +```cs +List numbers = []; +MyType variable = new(); + +// NOT: +List numbers = new(); +MyType variable = new MyType(); +``` + +Prefer no access modifier for lowest visibility. Do not use `_` to prefix fields. For example: +```cs +int field; +class MyClass {} + +// NOT: +private int _field; +internal class MyClass {} +``` + +Info-only types (DTOs, checks, list entries, bags of data with no behavior) should be `readonly record struct`, or `record` if they need reference identity. For example: +```cs +readonly record struct Shot(Vector3Int Dest, GameObject Box, float Started); + +// NOT: +sealed class Shot +{ + public Vector3Int Dest { get; } + public GameObject Box { get; } + public float Started { get; } +} +``` + +When a `BaseComponent` needs more than one or two injected services, put those dependencies on a `[BindSingleton]` service instead and inject only that service into the component. Put calculation / orchestration methods on the service. For simple shared deps like `ILoc`, expose a readonly field: + +```cs +[BindSingleton] +public class DischargePipeService(IWaterService waterService, IThreadSafeWaterMap waterMap, ILoc t) +{ + public readonly ILoc t = t; + // … +} + +[AddTemplateModule2(typeof(DischargePipeSpec))] +public class DischargePipe(DischargePipeService service) : BaseComponent // … +``` + +// NOT: inject IWaterService + IThreadSafeWaterMap + ILoc directly into the component. + +# Component lifecycle + +On a `BaseComponent`, `Awake` only grabs references (`GetComponent`, injected services already on the constructor). Do computation in `InitializeEntity`: reading specs, asking services for rates, building status toggles, filling ports. + +A placement preview runs `Awake` and does not run `InitializeEntity`. That `Awake` can run before other services' `Load`. Work done there can crash the preview. `BeltCarrier` is the pattern: `Awake` stores `BlockObject` and `MechanicalNode`; `InitializeEntity` reads `BeltCarrierSpec`, registers the stuck status, and asks `BeltCarrierService` for items per hour. + +# Singleton lifecycle + +`ILoadableSingleton.Load` and `IPostLoadableSingleton.PostLoad` run in **dependency order**. If B's constructor injects A, `A.Load` always runs before `B.Load` (same for `PostLoad`). Do not add `EnsureLoaded` / lazy-init sequences to force that order. + +# Tests + +Keep test method names short and descriptive. Prefer names like `InitializeWithCorrectCharacterType`, `IgnoreWrongCharacterType`, or `ComputeSegments` over long Given/When/Then-style names. + +Prefer focused tests with clear arrange/act/assert spacing. Use helpers or factories for repeated setup when Unity or Timberborn types require reflection or publicized DLL setup. + +# Tools + +Timberborn game source should be read from `ModdingAssetUpdater/out`, which contains decompiled game DLLs. When investigating game behavior, search and read that folder instead of decompiling assemblies on demand. + +More exported Timberborn game data is stored at `D:\Personal\Mods\Timberborn\V1Data\ExportedProject\Assets\Resources`. For example, the `Buildings` folder there contains game building blueprints that may be useful when comparing mod blueprints to vanilla behavior. + +If `ModdingAssetUpdater/out` does not exist or is empty, ask the user to decompile the game source there first. + +Leave `BackwardCompatibleTemplateNames` as `[]`. Do not add old template names unless the user explicitly asks. We are developing; save migration is not needed unless requested. + +Game assemblies are publicized for mod projects. It is okay to reference publicized Timberborn types and members directly in code and Harmony patches instead of avoiding `internal` or private members with reflection-only approaches. + +Timberborn grid coordinates use **X/Y for the horizontal plane and Z for vertical**. Unity is the opposite: **Y is up**, with X/Z as the horizontal plane. When converting grid coordinates or directions into Unity/world vectors, check `CoordinateSystem` and its namespace code first (`GridToWorld`, `GridToWorldCentered`, and the reverse). It likely already has the conversion needed, so avoid adding local helpers like `ToUnityDirection` unless the built-in conversion does not fit. + +## Timbermesh models (read / edit) + +When you need to **read or edit** a `.timbermesh` model (node hierarchy, materials, meshes, doors/props, etc.), use the `tmesh2glb` tool from `Timbermesh2Blender` — do **not** try to parse the binary by hand. + +Working directory for dumps/packs: **`D:\Temp\TimbermeshModel`**. + +```powershell +# From repo root. -c Release is required: the Debug build replaces args with a hardcoded Forester path. +dotnet run -c Release --project Timbermesh2Blender -- dump -i -o D:\Temp\TimbermeshModel -f +# Edit the produced *.timbermesh.json +dotnet run -c Release --project Timbermesh2Blender -- pack -i D:\Temp\TimbermeshModel\.timbermesh.json -o D:\Temp\TimbermeshModel -f +``` + +The installed `tmesh2glb` tool is fine too. It does not have that Debug override. + +Notes: + +- Default dump keeps vertex attributes as **base64** (lossless). Use `--decode-vertices` only when you need numeric position/normal/uv arrays. +- Prefer structural edits in JSON (delete/rename/reparent nodes, swap material names). Use **glb** export + Blender for real mesh sculpting. +- After packing, you can preview with `tmesh2glb glb -i ... -r -o D:\Temp\TimbermeshModel -f`. +- Game Resources path: `D:\Personal\Mods\Timberborn\V1Data\ExportedProject\Assets\Resources`. +- **Folktails first.** Unless the user explicitly asks for Iron Teeth (or both factions), only dump / edit / pack **Folktails** models. Do the Iron Teeth pass later, after the Folktails model is approved. + +### UV mapping + +A generated building that looks clipped has a bad `uv0` rectangle. The face shows a chopped mix: part of a board, a blank pale patch, a hole, a metal trim cut in half. A pale or white face is the same bug. It is the empty corner of the picture, or another material left on a made-up rectangle. Fix every material on the model, not only the one that looked worst. + +The material's picture is a collage of many separate pictures in one square. `uv0` picks a spot in that square. `(0,0)` is one corner of the whole square. `(1,1)` is the opposite corner. A face set to `(0,0)`–`(1,1)` stretches the entire collage across that one face. + +Two fixes that still look clipped: + +- Any rectangle you invent, even one that sits inside the square. On the belt, a wide patch of the wood picture removed the hole and still cut the grain off at the edge of the face. The metal bar was left on a homemade patch and stayed a pale clipped plate. +- Shrinking the coordinates yourself for the faction atlas. The game already does `uv * UVScale + UVOffset` in `AutoAtlasingPrefabOptimizer`. Write coordinates against the original picture. + +What works is one vanilla face's rectangle, copied unchanged, per face: + +- Dump a vanilla mesh that uses the same material, with `--decode-vertices`. Read one face's `uv0` and use that exact box. +- Wood (`BaseWood_*`, both factions): `Platform.Full.Folktails` on `BaseWood_Brown.Folktails`. One board is `u 0.7504–0.8128`, `v 0.5001–0.8753`. The next boards on that platform are the same height, stepped across in `u` (`0.8129–0.8753`, `0.8754–0.9378`, `0.9379–0.998`). +- Metal (`BaseMetal.Folktails`): `MetalPlatform3x3.Full.Folktails`. The repeated small plate is `u 0.595–0.656`, `v 0.008–0.242`. +- One face, one rectangle. A wider surface is several faces, each with the next vanilla rectangle. The platform top is a row of boards, not one face covering many boards. +- Stay on the copied numbers. `0.5001` instead of `0.5000` is already in them so the face does not pick up the neighbor. + +Before packing, dump with `--decode-vertices` and check every material. A triangle whose `uv0` runs `0–1`, or whose box is larger than the vanilla face you copied, is still clipped. + +## Buildings (Folktails first) + +Unless the user explicitly asks for Iron Teeth (or both factions), only create and edit **Folktails** buildings. Do not create `.IronTeeth.blueprint.json` or an Iron Teeth collection until they say they are ready for the IT pass. + +When adding a building, copy a placeholder icon **into that building's own folder** (for example `Buildings/Water/Pipes/NewPipe/NewPipeIcon.png`) and point `LabeledEntitySpec.Icon` at that local file. Do not reuse another building's icon path. diff --git a/AirlockChamber/AirlockChamber.csproj b/AirlockChamber/AirlockChamber.csproj new file mode 100644 index 00000000..88dce4e5 --- /dev/null +++ b/AirlockChamber/AirlockChamber.csproj @@ -0,0 +1,7 @@ + + + AirlockChamber + + + + diff --git a/AirlockChamber/ModDesc.txt b/AirlockChamber/ModDesc.txt new file mode 100644 index 00000000..1bdb0998 --- /dev/null +++ b/AirlockChamber/ModDesc.txt @@ -0,0 +1,33 @@ +This mod adds the Airlock Chamber, a "high-tech" structure that blocks water and allows beavers to walk through it. + +[h1]Airlock Chamber[/h1] + +[i]Reverse-engineered from a submerged vault labeled 'Do Not Open When Wet'.[/i] + +- Block water but allow two-way passage. +- Solid (other buildings can be built on its top). +- Cost 1500 Science to unlock, 15 Planks, 15 Resin and 5 Metal Blocks to build. + +[h1]6-way Airlock Chamber[/h1] + +[i]Schröbeaver principle: path and puddle states collapse only when you peek.[/i] + +- Same as Airlock Chamber but allows passage in all 6 directions. You need to build one extra to exit on the same level if you want to go up. +- Cost 2000 Science to unlock, 30 Planks, 30 Resin and 10 Metal Blocks to build. + +Both can be built by both the Folktails and Iron Teeths. GreedyBuilders and Emberpelts are supported but not tested, please tell me if it does not work. + +=== +Mod source code and donation: https://github.com/datvm/TimberbornMods + +v10.0.2: Should work with Update 1.0.7 (Jan 12) +v10.0.1: Should work with Update 1.0.5 (Dec 03) +v10.0.0: should work with game v1.0 + +v7.1.1: +- 4-way Airlock Chamber is now 6-way Airlock Chamber. Internally it keeps [i]AirlockChamber4[/i] name to prevent problems. +v7.1.0: +- Now need Resin to build (already built structures are not affected). +- You can now build multiple Airlock Chambers in a line. +- Added 4-way Airlock Chamber. +- Added Emberpelts support. \ No newline at end of file diff --git a/AirlockChamber/version-0.7/AssetBundles/airlockchamberassets_mac b/AirlockChamber/version-0.7/AssetBundles/airlockchamberassets_mac new file mode 100644 index 00000000..aebded4d Binary files /dev/null and b/AirlockChamber/version-0.7/AssetBundles/airlockchamberassets_mac differ diff --git a/AirlockChamber/version-0.7/AssetBundles/airlockchamberassets_mac.manifest b/AirlockChamber/version-0.7/AssetBundles/airlockchamberassets_mac.manifest new file mode 100644 index 00000000..2996a1ac --- /dev/null +++ b/AirlockChamber/version-0.7/AssetBundles/airlockchamberassets_mac.manifest @@ -0,0 +1,72 @@ +ManifestFileVersion: 0 +UnityVersion: 6000.1.4f1 +CRC: 401082871 +Hashes: + AssetFileHash: + serializedVersion: 2 + Hash: 40cbbdad1e6e3bb388d68aa0ac94f8a9 + TypeTreeHash: + serializedVersion: 2 + Hash: aa9da36ac0d3890c556a5ba9d7a6f5f5 + IncrementalBuildHash: + serializedVersion: 2 + Hash: be1f2dc89891191feef0c9e41a91fff6 +HashAppended: 0 +ClassTypes: +- Class: 1 + Script: {instanceID: 0} +- Class: 4 + Script: {instanceID: 0} +- Class: 65 + Script: {instanceID: 0} +- Class: 114 + Script: {fileID: 437054131, guid: 644c1295076bbdbb604b7f96aa6be9c2, type: 3} +- Class: 114 + Script: {fileID: 1566945626, guid: b5f268a4cb31a93ed707a95d3a502b0e, type: 3} +- Class: 114 + Script: {fileID: 652365310, guid: b6b9d4cc3090b6fceb2eb6438dd271f1, type: 3} +- Class: 114 + Script: {fileID: 59574725, guid: 4ed0189b1e1d234e361262ab78b6f74b, type: 3} +- Class: 114 + Script: {fileID: -1146001497, guid: 4ed0189b1e1d234e361262ab78b6f74b, type: 3} +- Class: 114 + Script: {fileID: 1596376676, guid: 1bd6ccb667024f9c2b77daf7f62a4eed, type: 3} +- Class: 114 + Script: {fileID: -579399493, guid: 1bd6ccb667024f9c2b77daf7f62a4eed, type: 3} +- Class: 114 + Script: {fileID: 447443988, guid: c1ff95bb5ae0e8b420075ec58add6f36, type: 3} +- Class: 114 + Script: {fileID: -1706396145, guid: c1ff95bb5ae0e8b420075ec58add6f36, type: 3} +- Class: 114 + Script: {fileID: -1925074215, guid: 79523a2b71f4fae881a60ad2e723d456, type: 3} +- Class: 114 + Script: {fileID: -923837550, guid: 79523a2b71f4fae881a60ad2e723d456, type: 3} +- Class: 114 + Script: {fileID: -1942782917, guid: 40833514e55bcf2135fbcf9411078554, type: 3} +- Class: 114 + Script: {fileID: 1412436833, guid: 915d565361ffc0071cb972b12ad62c80, type: 3} +- Class: 114 + Script: {fileID: -1668926802, guid: 915d565361ffc0071cb972b12ad62c80, type: 3} +- Class: 115 + Script: {instanceID: 0} +SerializeReferenceClassIdentifiers: +- AssemblyName: Timberborn.BlockSystemNavigation + ClassName: Timberborn.BlockSystemNavigation.BlockObjectNavMeshEdgeGroupSpec +- AssemblyName: Timberborn.BlockSystemNavigation + ClassName: Timberborn.BlockSystemNavigation.BlockObjectNavMeshEdgeSpec +- AssemblyName: Timberborn.BlockSystemNavigation + ClassName: Timberborn.BlockSystemNavigation.BlockObjectNavMeshGroup +- AssemblyName: Timberborn.BlockSystem + ClassName: Timberborn.BlockSystem.BlockSpec +- AssemblyName: Timberborn.BlockSystem + ClassName: Timberborn.BlockSystem.BlocksSpec +- AssemblyName: Timberborn.BlockSystem + ClassName: Timberborn.BlockSystem.CustomPivotSpec +- AssemblyName: Timberborn.BlockSystem + ClassName: Timberborn.BlockSystem.EntranceBlockSpec +- AssemblyName: Timberborn.Goods + ClassName: Timberborn.Goods.GoodAmountSpec +Assets: +- Assets/Mods/AirlockChamberAssets/AssetBundles/Resources/Buildings/Paths/AirlockChamber4.prefab +- Assets/Mods/AirlockChamberAssets/AssetBundles/Resources/Buildings/Paths/AirlockChamber.prefab +Dependencies: [] diff --git a/AirlockChamber/version-0.7/AssetBundles/airlockchamberassets_win b/AirlockChamber/version-0.7/AssetBundles/airlockchamberassets_win new file mode 100644 index 00000000..8a2607d5 Binary files /dev/null and b/AirlockChamber/version-0.7/AssetBundles/airlockchamberassets_win differ diff --git a/AirlockChamber/version-0.7/AssetBundles/airlockchamberassets_win.manifest b/AirlockChamber/version-0.7/AssetBundles/airlockchamberassets_win.manifest new file mode 100644 index 00000000..271afb04 --- /dev/null +++ b/AirlockChamber/version-0.7/AssetBundles/airlockchamberassets_win.manifest @@ -0,0 +1,72 @@ +ManifestFileVersion: 0 +UnityVersion: 6000.1.4f1 +CRC: 3707483020 +Hashes: + AssetFileHash: + serializedVersion: 2 + Hash: 4c8a14043e1dfeff8cdf4624a253a1e0 + TypeTreeHash: + serializedVersion: 2 + Hash: aa9da36ac0d3890c556a5ba9d7a6f5f5 + IncrementalBuildHash: + serializedVersion: 2 + Hash: 48c25523b03bd5ec03b63246f878dba5 +HashAppended: 0 +ClassTypes: +- Class: 1 + Script: {instanceID: 0} +- Class: 4 + Script: {instanceID: 0} +- Class: 65 + Script: {instanceID: 0} +- Class: 114 + Script: {fileID: 437054131, guid: 644c1295076bbdbb604b7f96aa6be9c2, type: 3} +- Class: 114 + Script: {fileID: 1566945626, guid: b5f268a4cb31a93ed707a95d3a502b0e, type: 3} +- Class: 114 + Script: {fileID: 652365310, guid: b6b9d4cc3090b6fceb2eb6438dd271f1, type: 3} +- Class: 114 + Script: {fileID: 59574725, guid: 4ed0189b1e1d234e361262ab78b6f74b, type: 3} +- Class: 114 + Script: {fileID: -1146001497, guid: 4ed0189b1e1d234e361262ab78b6f74b, type: 3} +- Class: 114 + Script: {fileID: 1596376676, guid: 1bd6ccb667024f9c2b77daf7f62a4eed, type: 3} +- Class: 114 + Script: {fileID: -579399493, guid: 1bd6ccb667024f9c2b77daf7f62a4eed, type: 3} +- Class: 114 + Script: {fileID: 447443988, guid: c1ff95bb5ae0e8b420075ec58add6f36, type: 3} +- Class: 114 + Script: {fileID: -1706396145, guid: c1ff95bb5ae0e8b420075ec58add6f36, type: 3} +- Class: 114 + Script: {fileID: -1925074215, guid: 79523a2b71f4fae881a60ad2e723d456, type: 3} +- Class: 114 + Script: {fileID: -923837550, guid: 79523a2b71f4fae881a60ad2e723d456, type: 3} +- Class: 114 + Script: {fileID: -1942782917, guid: 40833514e55bcf2135fbcf9411078554, type: 3} +- Class: 114 + Script: {fileID: 1412436833, guid: 915d565361ffc0071cb972b12ad62c80, type: 3} +- Class: 114 + Script: {fileID: -1668926802, guid: 915d565361ffc0071cb972b12ad62c80, type: 3} +- Class: 115 + Script: {instanceID: 0} +SerializeReferenceClassIdentifiers: +- AssemblyName: Timberborn.BlockSystemNavigation + ClassName: Timberborn.BlockSystemNavigation.BlockObjectNavMeshEdgeGroupSpec +- AssemblyName: Timberborn.BlockSystemNavigation + ClassName: Timberborn.BlockSystemNavigation.BlockObjectNavMeshEdgeSpec +- AssemblyName: Timberborn.BlockSystemNavigation + ClassName: Timberborn.BlockSystemNavigation.BlockObjectNavMeshGroup +- AssemblyName: Timberborn.BlockSystem + ClassName: Timberborn.BlockSystem.BlockSpec +- AssemblyName: Timberborn.BlockSystem + ClassName: Timberborn.BlockSystem.BlocksSpec +- AssemblyName: Timberborn.BlockSystem + ClassName: Timberborn.BlockSystem.CustomPivotSpec +- AssemblyName: Timberborn.BlockSystem + ClassName: Timberborn.BlockSystem.EntranceBlockSpec +- AssemblyName: Timberborn.Goods + ClassName: Timberborn.Goods.GoodAmountSpec +Assets: +- Assets/Mods/AirlockChamberAssets/AssetBundles/Resources/Buildings/Paths/AirlockChamber4.prefab +- Assets/Mods/AirlockChamberAssets/AssetBundles/Resources/Buildings/Paths/AirlockChamber.prefab +Dependencies: [] diff --git a/AirlockChamber/version-0.7/AssetsBuilding/AssetBundles/Resources/Buildings/Paths/AirlockChamber.prefab b/AirlockChamber/version-0.7/AssetsBuilding/AssetBundles/Resources/Buildings/Paths/AirlockChamber.prefab new file mode 100644 index 00000000..f424fcd4 --- /dev/null +++ b/AirlockChamber/version-0.7/AssetsBuilding/AssetBundles/Resources/Buildings/Paths/AirlockChamber.prefab @@ -0,0 +1,652 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1027312957033359 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4145870286760774} + - component: {fileID: 65161242882772090} + - component: {fileID: 114749206421087040} + m_Layer: 0 + m_Name: '#Platform' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4145870286760774 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1027312957033359} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4609505999293618} + m_LocalEulerAnglesHint: {x: 0, y: -0, z: -0} +--- !u!65 &65161242882772090 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1027312957033359} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 0.1, z: 1} + m_Center: {x: 0.5, y: 0.95, z: 0.5} +--- !u!114 &114749206421087040 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1027312957033359} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1942782917, guid: 40833514e55bcf2135fbcf9411078554, type: 3} + m_Name: + m_EditorClassIdentifier: + _modelName: Buildings\Paths\VerticalTubeway\VerticalTubewayCover.IronTeeth.Model +--- !u!1 &1294685043706720 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4928603305276287} + m_Layer: 0 + m_Name: '#Unfinished' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4928603305276287 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1294685043706720} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 4853944874330179} + - {fileID: 4949659688046282} + m_Father: {fileID: 4347414775528117} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1297530000548179 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4949659688046282} + - component: {fileID: 65721840009953000} + - component: {fileID: 114320076570388322} + m_Layer: 0 + m_Name: ConstructionStage0 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4949659688046282 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297530000548179} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4928603305276287} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &65721840009953000 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297530000548179} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 0.1, z: 1} + m_Center: {x: 0.5, y: 0.05, z: 0.5} +--- !u!114 &114320076570388322 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297530000548179} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1942782917, guid: 40833514e55bcf2135fbcf9411078554, type: 3} + m_Name: + m_EditorClassIdentifier: + _modelName: Buildings\Paths\VerticalTubeway\VerticalTubeway.IronTeeth.ConstructionStage0.Model +--- !u!1 &1424989490097325 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4609505999293618} + m_Layer: 0 + m_Name: '#Finished' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4609505999293618 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1424989490097325} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 4145870286760774} + - {fileID: 4536798673540851} + m_Father: {fileID: 4347414775528117} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1846583253462335 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4853944874330179} + - component: {fileID: 65453043453152181} + - component: {fileID: 114986452790445055} + m_Layer: 0 + m_Name: ConstructionBase1x1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4853944874330179 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1846583253462335} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4928603305276287} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &65453043453152181 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1846583253462335} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 0.1, z: 1} + m_Center: {x: 0.5, y: 0.05, z: 0.5} +--- !u!114 &114986452790445055 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1846583253462335} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1942782917, guid: 40833514e55bcf2135fbcf9411078554, type: 3} + m_Name: + m_EditorClassIdentifier: + _modelName: ConstructionBases\ConstructionBase1x1\ConstructionBase1x1.Model +--- !u!1 &1873099707921874 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4536798673540851} + - component: {fileID: 65989017850012235} + - component: {fileID: 65245692924686067} + - component: {fileID: 114308890445178238} + m_Layer: 0 + m_Name: Variant_001000 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4536798673540851 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1873099707921874} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4609505999293618} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &65989017850012235 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1873099707921874} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 0.04, z: 1} + m_Center: {x: 0.5, y: 0.02, z: 0.5} +--- !u!65 &65245692924686067 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1873099707921874} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 0.36129043, y: 0.7358919, z: 0.99799085} + m_Center: {x: 0.5, y: 0.36794594, z: 0.5} +--- !u!114 &114308890445178238 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1873099707921874} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1942782917, guid: 40833514e55bcf2135fbcf9411078554, type: 3} + m_Name: + m_EditorClassIdentifier: + _modelName: Buildings\Paths\VerticalTubeway\VerticalTubeway001000.IronTeeth.Model +--- !u!1 &1914886916114091 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4347414775528117} + - component: {fileID: 114619145766908011} + - component: {fileID: 114646530240802421} + - component: {fileID: 114119986661874792} + - component: {fileID: 114526941125596721} + - component: {fileID: 114076411417914655} + - component: {fileID: 114831120187134361} + - component: {fileID: 114607580025657821} + - component: {fileID: 114230826247343656} + - component: {fileID: 114428801838767372} + - component: {fileID: 114871275619388575} + - component: {fileID: -7128729733825823795} + - component: {fileID: 1018640434098314929} + - component: {fileID: 4393196155429996104} + m_Layer: 0 + m_Name: AirlockChamber + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4347414775528117 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 4609505999293618} + - {fileID: 4928603305276287} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: -0, z: -0} +--- !u!114 &114619145766908011 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -579399493, guid: 1bd6ccb667024f9c2b77daf7f62a4eed, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _selectionSoundName: Tubeway + _loopingSoundName: + _buildingCost: + - _goodId: Plank + _amount: 15 + - _goodId: MetalBlock + _amount: 5 + - _goodId: PineResin + _amount: 15 + _scienceCost: 1500 + _placeFinished: 0 + _finishableWithBeaversOnSite: 0 + _drawRangeBoundsOnIt: 0 +--- !u!114 &114646530240802421 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1596376676, guid: 1bd6ccb667024f9c2b77daf7f62a4eed, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _finishedModelName: '#Finished' + _unfinishedModelName: '#Unfinished' + _finishedUncoveredModelName: + _undergroundModelName: + _constructionModeModel: 0 + _undergroundModelDepth: 0 +--- !u!114 &114119986661874792 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1566945626, guid: b5f268a4cb31a93ed707a95d3a502b0e, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _prefabName: AirlockChamber + _backwardCompatiblePrefabNames: [] + _requiredFeatureToggle: + _disablingFeatureToggle: +--- !u!114 &114526941125596721 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1925074215, guid: 79523a2b71f4fae881a60ad2e723d456, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _noAutoWalls: 0 + _generateFloorsOnStackable: 1 + _edgeGroups: + - _cost: 1 + _group: + _useGroup: 0 + _groupName: + _isPath: 1 + _addedEdges: + - _start: {x: 0, y: 0, z: 0} + _end: {x: 0, y: -1, z: 0} + _isTwoWay: 0 + - _start: {x: 0, y: 0, z: 0} + _end: {x: 0, y: 1, z: 0} + _isTwoWay: 0 + _unblockedCoordinates: [] +--- !u!114 &114076411417914655 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 447443988, guid: c1ff95bb5ae0e8b420075ec58add6f36, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _blocksSpec: + _size: {x: 1, y: 1, z: 1} + _blockSpecs: + - _matterBelow: 1 + _legacyOccupation: 0 + _useNewOccupation: 1 + _occupations: 62 + _stackable: 1 + _occupyAllBelow: 0 + _underground: 0 + _entrance: + _hasEntrance: 0 + _coordinates: {x: 0, y: 0, z: 0} + _baseZ: 0 + _overridable: 0 + _flippable: 0 +--- !u!114 &114831120187134361 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1706396145, guid: c1ff95bb5ae0e8b420075ec58add6f36, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _toolGroupId: Paths + _toolOrder: 15 + _toolShape: 0 + _layout: 2 + _customPivot: + _hasCustomPivot: 0 + _coordinates: {x: 0, y: 0, z: 0} + _canBeAttachedToTerrainSide: 0 + _devModeTool: 0 +--- !u!114 &114607580025657821 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 652365310, guid: b6b9d4cc3090b6fceb2eb6438dd271f1, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _displayNameLocKey: LV.AC.AirlockChamber + _descriptionLocKey: LV.AC.AirlockChamberDesc + _flavorDescriptionLocKey: LV.AC.AirlockChamberFlavor + _imagePath: Sprites/Buildings/Paths/AirlockChamber +--- !u!114 &114230826247343656 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -923837550, guid: 79523a2b71f4fae881a60ad2e723d456, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} +--- !u!114 &114428801838767372 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1146001497, guid: 4ed0189b1e1d234e361262ab78b6f74b, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _mainPathCoordinates: {x: 0, y: 0, z: 0} +--- !u!114 &114871275619388575 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 437054131, guid: 644c1295076bbdbb604b7f96aa6be9c2, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _progressThresholds: + - 0 +--- !u!114 &-7128729733825823795 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 59574725, guid: 4ed0189b1e1d234e361262ab78b6f74b, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _driveway: 6 + _hasCustomCoordinates: 1 + _customCoordinates: {x: 0, y: -1, z: 0} + _customDirection: 0 + _drivewayMode: 0 +--- !u!114 &1018640434098314929 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1668926802, guid: 915d565361ffc0071cb972b12ad62c80, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _coordinates: + - {x: 0, y: 0} +--- !u!114 &4393196155429996104 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1412436833, guid: 915d565361ffc0071cb972b12ad62c80, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _height: 1 diff --git a/AirlockChamber/version-0.7/AssetsBuilding/AssetBundles/Resources/Buildings/Paths/AirlockChamber4.prefab b/AirlockChamber/version-0.7/AssetsBuilding/AssetBundles/Resources/Buildings/Paths/AirlockChamber4.prefab new file mode 100644 index 00000000..04be58aa --- /dev/null +++ b/AirlockChamber/version-0.7/AssetsBuilding/AssetBundles/Resources/Buildings/Paths/AirlockChamber4.prefab @@ -0,0 +1,686 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1027312957033359 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4145870286760774} + - component: {fileID: 65161242882772090} + - component: {fileID: 114749206421087040} + m_Layer: 0 + m_Name: '#Platform' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4145870286760774 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1027312957033359} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4609505999293618} + m_LocalEulerAnglesHint: {x: 0, y: -0, z: -0} +--- !u!65 &65161242882772090 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1027312957033359} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 0.1, z: 1} + m_Center: {x: 0.5, y: 0.95, z: 0.5} +--- !u!114 &114749206421087040 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1027312957033359} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1942782917, guid: 40833514e55bcf2135fbcf9411078554, type: 3} + m_Name: + m_EditorClassIdentifier: + _modelName: Buildings\Paths\VerticalTubeway\VerticalTubewayCover.IronTeeth.Model +--- !u!1 &1294685043706720 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4928603305276287} + m_Layer: 0 + m_Name: '#Unfinished' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4928603305276287 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1294685043706720} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 4853944874330179} + - {fileID: 4949659688046282} + m_Father: {fileID: 4347414775528117} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1297530000548179 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4949659688046282} + - component: {fileID: 65721840009953000} + - component: {fileID: 114320076570388322} + m_Layer: 0 + m_Name: ConstructionStage0 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4949659688046282 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297530000548179} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4928603305276287} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &65721840009953000 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297530000548179} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 0.1, z: 1} + m_Center: {x: 0.5, y: 0.05, z: 0.5} +--- !u!114 &114320076570388322 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297530000548179} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1942782917, guid: 40833514e55bcf2135fbcf9411078554, type: 3} + m_Name: + m_EditorClassIdentifier: + _modelName: Buildings\Paths\VerticalTubeway\VerticalTubeway.IronTeeth.ConstructionStage0.Model +--- !u!1 &1424989490097325 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4609505999293618} + m_Layer: 0 + m_Name: '#Finished' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4609505999293618 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1424989490097325} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 4145870286760774} + - {fileID: 9184579485941725398} + m_Father: {fileID: 4347414775528117} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1846583253462335 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4853944874330179} + - component: {fileID: 65453043453152181} + - component: {fileID: 114986452790445055} + m_Layer: 0 + m_Name: ConstructionBase1x1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4853944874330179 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1846583253462335} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4928603305276287} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &65453043453152181 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1846583253462335} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 0.1, z: 1} + m_Center: {x: 0.5, y: 0.05, z: 0.5} +--- !u!114 &114986452790445055 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1846583253462335} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1942782917, guid: 40833514e55bcf2135fbcf9411078554, type: 3} + m_Name: + m_EditorClassIdentifier: + _modelName: ConstructionBases\ConstructionBase1x1\ConstructionBase1x1.Model +--- !u!1 &1914886916114091 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4347414775528117} + - component: {fileID: 114619145766908011} + - component: {fileID: 114646530240802421} + - component: {fileID: 114119986661874792} + - component: {fileID: 114526941125596721} + - component: {fileID: 114076411417914655} + - component: {fileID: 114831120187134361} + - component: {fileID: 114607580025657821} + - component: {fileID: 114230826247343656} + - component: {fileID: 114428801838767372} + - component: {fileID: 114871275619388575} + - component: {fileID: -7128729733825823795} + - component: {fileID: 1018640434098314929} + - component: {fileID: 4393196155429996104} + m_Layer: 0 + m_Name: AirlockChamber4 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4347414775528117 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 4609505999293618} + - {fileID: 4928603305276287} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: -0, z: -0} +--- !u!114 &114619145766908011 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -579399493, guid: 1bd6ccb667024f9c2b77daf7f62a4eed, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _selectionSoundName: Tubeway + _loopingSoundName: + _buildingCost: + - _goodId: Plank + _amount: 30 + - _goodId: MetalBlock + _amount: 10 + - _goodId: PineResin + _amount: 30 + _scienceCost: 2000 + _placeFinished: 0 + _finishableWithBeaversOnSite: 0 + _drawRangeBoundsOnIt: 0 +--- !u!114 &114646530240802421 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1596376676, guid: 1bd6ccb667024f9c2b77daf7f62a4eed, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _finishedModelName: '#Finished' + _unfinishedModelName: '#Unfinished' + _finishedUncoveredModelName: + _undergroundModelName: + _constructionModeModel: 0 + _undergroundModelDepth: 0 +--- !u!114 &114119986661874792 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1566945626, guid: b5f268a4cb31a93ed707a95d3a502b0e, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _prefabName: AirlockChamber4 + _backwardCompatiblePrefabNames: [] + _requiredFeatureToggle: + _disablingFeatureToggle: +--- !u!114 &114526941125596721 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1925074215, guid: 79523a2b71f4fae881a60ad2e723d456, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _noAutoWalls: 0 + _generateFloorsOnStackable: 1 + _edgeGroups: + - _cost: 1 + _group: + _useGroup: 0 + _groupName: + _isPath: 1 + _addedEdges: + - _start: {x: 0, y: 0, z: 0} + _end: {x: 0, y: -1, z: 0} + _isTwoWay: 0 + - _start: {x: 0, y: 0, z: 0} + _end: {x: 0, y: 1, z: 0} + _isTwoWay: 0 + - _start: {x: 0, y: 0, z: 0} + _end: {x: -1, y: 0, z: 0} + _isTwoWay: 0 + - _start: {x: 0, y: 0, z: 0} + _end: {x: 1, y: 0, z: 0} + _isTwoWay: 0 + - _start: {x: 0, y: 0, z: 0} + _end: {x: 0, y: 0, z: 1} + _isTwoWay: 0 + - _start: {x: 0, y: 0, z: 0} + _end: {x: 0, y: 0, z: -1} + _isTwoWay: 0 + _unblockedCoordinates: [] +--- !u!114 &114076411417914655 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 447443988, guid: c1ff95bb5ae0e8b420075ec58add6f36, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _blocksSpec: + _size: {x: 1, y: 1, z: 1} + _blockSpecs: + - _matterBelow: 1 + _legacyOccupation: 0 + _useNewOccupation: 1 + _occupations: 62 + _stackable: 1 + _occupyAllBelow: 0 + _underground: 0 + _entrance: + _hasEntrance: 0 + _coordinates: {x: 0, y: 0, z: 0} + _baseZ: 0 + _overridable: 0 + _flippable: 0 +--- !u!114 &114831120187134361 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1706396145, guid: c1ff95bb5ae0e8b420075ec58add6f36, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _toolGroupId: Paths + _toolOrder: 16 + _toolShape: 0 + _layout: 2 + _customPivot: + _hasCustomPivot: 0 + _coordinates: {x: 0, y: 0, z: 0} + _canBeAttachedToTerrainSide: 0 + _devModeTool: 0 +--- !u!114 &114607580025657821 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 652365310, guid: b6b9d4cc3090b6fceb2eb6438dd271f1, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _displayNameLocKey: LV.AC.AirlockChamber4 + _descriptionLocKey: LV.AC.AirlockChamber4Desc + _flavorDescriptionLocKey: LV.AC.AirlockChamber4Flavor + _imagePath: Sprites/Buildings/Paths/AirlockChamber4 +--- !u!114 &114230826247343656 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -923837550, guid: 79523a2b71f4fae881a60ad2e723d456, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} +--- !u!114 &114428801838767372 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1146001497, guid: 4ed0189b1e1d234e361262ab78b6f74b, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _mainPathCoordinates: {x: 0, y: 0, z: 0} +--- !u!114 &114871275619388575 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 437054131, guid: 644c1295076bbdbb604b7f96aa6be9c2, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _progressThresholds: + - 0 +--- !u!114 &-7128729733825823795 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 59574725, guid: 4ed0189b1e1d234e361262ab78b6f74b, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _driveway: 6 + _hasCustomCoordinates: 1 + _customCoordinates: {x: 0, y: -1, z: 0} + _customDirection: 0 + _drivewayMode: 0 +--- !u!114 &1018640434098314929 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1668926802, guid: 915d565361ffc0071cb972b12ad62c80, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _coordinates: + - {x: 0, y: 0} +--- !u!114 &4393196155429996104 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1914886916114091} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1412436833, guid: 915d565361ffc0071cb972b12ad62c80, type: 3} + m_Name: + m_EditorClassIdentifier: + _componentCache: {fileID: 0} + _height: 1 +--- !u!1 &2261874247302169788 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 9184579485941725398} + - component: {fileID: 7445198145564227894} + - component: {fileID: 1300293351087892662} + - component: {fileID: 3244821090120760841} + - component: {fileID: 4187711808490521246} + m_Layer: 0 + m_Name: Variant_111100 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &9184579485941725398 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2261874247302169788} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4609505999293618} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &7445198145564227894 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2261874247302169788} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 0.04, z: 1} + m_Center: {x: 0.5, y: 0.02, z: 0.5} +--- !u!65 &1300293351087892662 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2261874247302169788} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1.0030464, y: 0.7358919, z: 0.32637167} + m_Center: {x: 0.50274616, y: 0.36794594, z: 0.5101131} +--- !u!65 &3244821090120760841 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2261874247302169788} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 0.36129045, y: 0.7358919, z: 0.9996898} + m_Center: {x: 0.5, y: 0.36794594, z: 0.4991505} +--- !u!114 &4187711808490521246 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2261874247302169788} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1942782917, guid: 40833514e55bcf2135fbcf9411078554, type: 3} + m_Name: + m_EditorClassIdentifier: + _modelName: Buildings\Paths\VerticalTubeway\VerticalTubeway111100.IronTeeth.Model diff --git a/AirlockChamber/version-0.7/AssetsBuilding/manifest.json b/AirlockChamber/version-0.7/AssetsBuilding/manifest.json new file mode 100644 index 00000000..a6d15335 --- /dev/null +++ b/AirlockChamber/version-0.7/AssetsBuilding/manifest.json @@ -0,0 +1,7 @@ +{ + "Name": "AssetBundles Compiler", + "Version": "0.0.0", + "MinimumGameVersion": "0.0.0", + "Id": "AssetBundlesCompiler", + "Description": "Just for compiling" +} \ No newline at end of file diff --git a/AirlockChamber/version-0.7/Localizations/enUS.csv b/AirlockChamber/version-0.7/Localizations/enUS.csv new file mode 100644 index 00000000..2315509f --- /dev/null +++ b/AirlockChamber/version-0.7/Localizations/enUS.csv @@ -0,0 +1,7 @@ +ID,Text,Comment +LV.AC.AirlockChamber,"Airlock Chamber", +LV.AC.AirlockChamberDesc,"Block water but allow two-way passage.", +LV.AC.AirlockChamberFlavor,"Reverse-engineered from a submerged vault labeled 'Do Not Open When Wet'", +LV.AC.AirlockChamber4,"6-way Airlock Chamber", +LV.AC.AirlockChamber4Desc,"Block water but allow six-way passage.", +LV.AC.AirlockChamber4Flavor,"Schröbeaver principle: path and puddle states collapse only when you peek.", \ No newline at end of file diff --git a/AirlockChamber/version-0.7/blueprints/Factions/Faction.Emberpelts.optional.json b/AirlockChamber/version-0.7/blueprints/Factions/Faction.Emberpelts.optional.json new file mode 100644 index 00000000..586d8e48 --- /dev/null +++ b/AirlockChamber/version-0.7/blueprints/Factions/Faction.Emberpelts.optional.json @@ -0,0 +1,7 @@ +{ + "FactionSpec": { + "PrefabGroups#append": [ + "AirlockChamber" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-0.7/blueprints/Factions/Faction.Folktails.json b/AirlockChamber/version-0.7/blueprints/Factions/Faction.Folktails.json new file mode 100644 index 00000000..b5e1745b --- /dev/null +++ b/AirlockChamber/version-0.7/blueprints/Factions/Faction.Folktails.json @@ -0,0 +1,10 @@ +{ + "FactionSpec": { + "MaterialGroups#append": [ + "IronTeeth" + ], + "PrefabGroups#append": [ + "AirlockChamber" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-0.7/blueprints/Factions/Faction.GreedyBuilders.optional.json b/AirlockChamber/version-0.7/blueprints/Factions/Faction.GreedyBuilders.optional.json new file mode 100644 index 00000000..586d8e48 --- /dev/null +++ b/AirlockChamber/version-0.7/blueprints/Factions/Faction.GreedyBuilders.optional.json @@ -0,0 +1,7 @@ +{ + "FactionSpec": { + "PrefabGroups#append": [ + "AirlockChamber" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-0.7/blueprints/Factions/Faction.IronTeeth.json b/AirlockChamber/version-0.7/blueprints/Factions/Faction.IronTeeth.json new file mode 100644 index 00000000..586d8e48 --- /dev/null +++ b/AirlockChamber/version-0.7/blueprints/Factions/Faction.IronTeeth.json @@ -0,0 +1,7 @@ +{ + "FactionSpec": { + "PrefabGroups#append": [ + "AirlockChamber" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-0.7/blueprints/PrefabGroups/PrefabGroup.AirlockChamber.json b/AirlockChamber/version-0.7/blueprints/PrefabGroups/PrefabGroup.AirlockChamber.json new file mode 100644 index 00000000..007d0ceb --- /dev/null +++ b/AirlockChamber/version-0.7/blueprints/PrefabGroups/PrefabGroup.AirlockChamber.json @@ -0,0 +1,9 @@ +{ + "PrefabGroupSpec": { + "Id": "AirlockChamber", + "Paths": [ + "Buildings/Paths/AirlockChamber", + "Buildings/Paths/AirlockChamber4" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-0.7/manifest.json b/AirlockChamber/version-0.7/manifest.json new file mode 100644 index 00000000..9fe997aa --- /dev/null +++ b/AirlockChamber/version-0.7/manifest.json @@ -0,0 +1,7 @@ +{ + "Name": "Airlock Chamber", + "Version": "7.1.1", + "Id": "AirlockChamber", + "MinimumGameVersion": "0.7.0.0", + "Description": "An airlock chamber that block water but your beavers can walk through" +} \ No newline at end of file diff --git a/AirlockChamber/version-0.7/sprites/Buildings/Paths/AirlockChamber.png b/AirlockChamber/version-0.7/sprites/Buildings/Paths/AirlockChamber.png new file mode 100644 index 00000000..01f8d8d7 Binary files /dev/null and b/AirlockChamber/version-0.7/sprites/Buildings/Paths/AirlockChamber.png differ diff --git a/AirlockChamber/version-0.7/sprites/Buildings/Paths/AirlockChamber4.png b/AirlockChamber/version-0.7/sprites/Buildings/Paths/AirlockChamber4.png new file mode 100644 index 00000000..1230be3e Binary files /dev/null and b/AirlockChamber/version-0.7/sprites/Buildings/Paths/AirlockChamber4.png differ diff --git a/AirlockChamber/version-1.0/Factions/Faction.Emberpelts.optional.blueprint.json b/AirlockChamber/version-1.0/Factions/Faction.Emberpelts.optional.blueprint.json new file mode 100644 index 00000000..cb60226e --- /dev/null +++ b/AirlockChamber/version-1.0/Factions/Faction.Emberpelts.optional.blueprint.json @@ -0,0 +1,7 @@ +{ + "FactionSpec": { + "MaterialCollectionIds#append": [ + "IronTeeth" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-1.0/Factions/Faction.Folktails.blueprint.json b/AirlockChamber/version-1.0/Factions/Faction.Folktails.blueprint.json new file mode 100644 index 00000000..cb60226e --- /dev/null +++ b/AirlockChamber/version-1.0/Factions/Faction.Folktails.blueprint.json @@ -0,0 +1,7 @@ +{ + "FactionSpec": { + "MaterialCollectionIds#append": [ + "IronTeeth" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-1.0/Factions/Faction.GreedyBuilders.optional.blueprint.json b/AirlockChamber/version-1.0/Factions/Faction.GreedyBuilders.optional.blueprint.json new file mode 100644 index 00000000..cb60226e --- /dev/null +++ b/AirlockChamber/version-1.0/Factions/Faction.GreedyBuilders.optional.blueprint.json @@ -0,0 +1,7 @@ +{ + "FactionSpec": { + "MaterialCollectionIds#append": [ + "IronTeeth" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-1.0/Factions/Faction.IronTeeth.blueprint.json b/AirlockChamber/version-1.0/Factions/Faction.IronTeeth.blueprint.json new file mode 100644 index 00000000..cb60226e --- /dev/null +++ b/AirlockChamber/version-1.0/Factions/Faction.IronTeeth.blueprint.json @@ -0,0 +1,7 @@ +{ + "FactionSpec": { + "MaterialCollectionIds#append": [ + "IronTeeth" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-1.0/Localizations/enUS.csv b/AirlockChamber/version-1.0/Localizations/enUS.csv new file mode 100644 index 00000000..2315509f --- /dev/null +++ b/AirlockChamber/version-1.0/Localizations/enUS.csv @@ -0,0 +1,7 @@ +ID,Text,Comment +LV.AC.AirlockChamber,"Airlock Chamber", +LV.AC.AirlockChamberDesc,"Block water but allow two-way passage.", +LV.AC.AirlockChamberFlavor,"Reverse-engineered from a submerged vault labeled 'Do Not Open When Wet'", +LV.AC.AirlockChamber4,"6-way Airlock Chamber", +LV.AC.AirlockChamber4Desc,"Block water but allow six-way passage.", +LV.AC.AirlockChamber4Flavor,"Schröbeaver principle: path and puddle states collapse only when you peek.", \ No newline at end of file diff --git a/AirlockChamber/version-1.0/Resources/Buildings/Paths/AirlockChamber/AirlockChamber.blueprint.json b/AirlockChamber/version-1.0/Resources/Buildings/Paths/AirlockChamber/AirlockChamber.blueprint.json new file mode 100644 index 00000000..80525682 --- /dev/null +++ b/AirlockChamber/version-1.0/Resources/Buildings/Paths/AirlockChamber/AirlockChamber.blueprint.json @@ -0,0 +1,248 @@ +{ + "BuildingSpec": { + "SelectionSoundName": "Tubeway", + "LoopingSoundName": "", + "BuildingCost": [ + { + "Id": "Plank", + "Amount": 15 + }, + { + "Id": "MetalBlock", + "Amount": 5 + }, + { + "Id": "PineResin", + "Amount": 15 + } + ], + "ScienceCost": 1500, + "PlaceFinished": false, + "FinishableWithBeaversOnSite": false, + "DrawRangeBoundsOnIt": false + }, + "BuildingModelSpec": { + "FinishedModelName": "#Finished", + "UnfinishedModelName": "#Unfinished", + "FinishedUncoveredModelName": "", + "UndergroundModelName": "", + "ConstructionModeModel": "Finished", + "UndergroundModelDepth": 0 + }, + "TemplateSpec": { + "TemplateName": "AirlockChamber", + "BackwardCompatibleTemplateNames": [], + "RequiredFeatureToggle": "", + "DisablingFeatureToggle": "" + }, + "BlockObjectNavMeshSettingsSpec": { + "NoAutoWalls": false, + "GenerateFloorsOnStackable": true, + "EdgeGroups": [ + { + "Cost": 1, + "Group": { + "UseGroup": 0, + "GroupName": "" + }, + "IsPath": true, + "AddedEdges": [ + { + "Start": { + "X": 0, + "Y": 0, + "Z": 0 + }, + "End": { + "X": 0, + "Y": -1, + "Z": 0 + }, + "IsTwoWay": false + }, + { + "Start": { + "X": 0, + "Y": 0, + "Z": 0 + }, + "End": { + "X": 0, + "Y": 1, + "Z": 0 + }, + "IsTwoWay": false + } + ] + } + ], + "UnblockedCoordinates": [] + }, + "BlockObjectSpec": { + "Size": { + "X": 1, + "Y": 1, + "Z": 1 + }, + "Blocks": [ + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom, Top, Corners, Path, Middle", + "Stackable": "BlockObject", + "OccupyAllBelow": false, + "Underground": false + } + ], + "Entrance": { + "HasEntrance": false, + "Coordinates": { + "X": 0, + "Y": 0, + "Z": 0 + } + }, + "BaseZ": 0, + "Overridable": false, + "Flippable": false + }, + "PlaceableBlockObjectSpec": { + "ToolGroupId": "Paths", + "ToolOrder": 15, + "ToolShape": "Square", + "Layout": "Line", + "CustomPivot": { + "HasCustomPivot": false, + "Coordinates": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0 + } + }, + "CanBeAttachedToTerrainSide": false, + "DevModeTool": false + }, + "LabeledEntitySpec": { + "DisplayNameLocKey": "LV.AC.AirlockChamber", + "DescriptionLocKey": "LV.AC.AirlockChamberDesc", + "FlavorDescriptionLocKey": "LV.AC.AirlockChamberFlavor", + "Icon": "Sprites/Buildings/Paths/AirlockChamber" + }, + "WaterObstacleSpec": { + "Coordinates": [ + { + "X": 0, + "Y": 0 + } + ] + }, + "FinishableWaterObstacleSpec": { + "Height": 1.0 + }, + "BlockObjectWithPathRangeSpec": {}, + "PathSpec": { + "MainPathCoordinates": { + "X": 0, + "Y": 0, + "Z": 0 + } + }, + "ConstructionSiteProgressVisualizerSpec": { + "ProgressThresholds": [ + 0.0 + ] + }, + "Children": { + "#Finished": { + "Children": { + "#Platform": { + "TimbermeshSpec": { + "Model": "Buildings/Paths/VerticalTubeway/VerticalTubewayCover.IronTeeth.Model" + }, + "CollidersSpec": { + "BoxColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.95, + "Z": 0.5 + }, + "Size": { + "X": 1.0, + "Y": 0.1, + "Z": 1.0 + } + } + ], + "SphereColliders": [], + "CapsuleColliders": [] + } + }, + "Variant_001000": { + "TimbermeshSpec": { + "Model": "Buildings/Paths/VerticalTubeway/VerticalTubeway001000.IronTeeth.Model" + }, + "CollidersSpec": { + "BoxColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.02, + "Z": 0.5 + }, + "Size": { + "X": 1.0, + "Y": 0.04, + "Z": 1.0 + } + }, + { + "Center": { + "X": 0.5, + "Y": 0.367945939, + "Z": 0.5 + }, + "Size": { + "X": 0.361290425, + "Y": 0.7358919, + "Z": 0.997990847 + } + } + ], + "SphereColliders": [], + "CapsuleColliders": [] + } + } + } + }, + "#Unfinished": { + "Children": { + "ConstructionBase1x1#nested": { + "BlueprintPath": "ConstructionBases/ConstructionBase1x1/ConstructionBase1x1.blueprint" + }, + "ConstructionStage0": { + "TimbermeshSpec": { + "Model": "Buildings/Paths/VerticalTubeway/VerticalTubeway.IronTeeth.ConstructionStage0.Model" + }, + "CollidersSpec": { + "BoxColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.05, + "Z": 0.5 + }, + "Size": { + "X": 1.0, + "Y": 0.1, + "Z": 1.0 + } + } + ], + "SphereColliders": [], + "CapsuleColliders": [] + } + } + } + } + } +} \ No newline at end of file diff --git a/AirlockChamber/version-1.0/Resources/Buildings/Paths/AirlockChamber/AirlockChamber4.blueprint.json b/AirlockChamber/version-1.0/Resources/Buildings/Paths/AirlockChamber/AirlockChamber4.blueprint.json new file mode 100644 index 00000000..66668420 --- /dev/null +++ b/AirlockChamber/version-1.0/Resources/Buildings/Paths/AirlockChamber/AirlockChamber4.blueprint.json @@ -0,0 +1,324 @@ +{ + "BuildingSpec": { + "SelectionSoundName": "Tubeway", + "LoopingSoundName": "", + "BuildingCost": [ + { + "Id": "Plank", + "Amount": 30 + }, + { + "Id": "MetalBlock", + "Amount": 10 + }, + { + "Id": "PineResin", + "Amount": 20 + } + ], + "ScienceCost": 2000, + "PlaceFinished": false, + "FinishableWithBeaversOnSite": false, + "DrawRangeBoundsOnIt": false + }, + "BuildingModelSpec": { + "FinishedModelName": "#Finished", + "UnfinishedModelName": "#Unfinished", + "FinishedUncoveredModelName": "", + "UndergroundModelName": "", + "ConstructionModeModel": "Finished", + "UndergroundModelDepth": 0 + }, + "TemplateSpec": { + "TemplateName": "AirlockChamber4", + "BackwardCompatibleTemplateNames": [], + "RequiredFeatureToggle": "", + "DisablingFeatureToggle": "" + }, + "BlockObjectNavMeshSettingsSpec": { + "NoAutoWalls": false, + "GenerateFloorsOnStackable": true, + "EdgeGroups": [ + { + "Cost": 1, + "Group": { + "UseGroup": 0, + "GroupName": "" + }, + "IsPath": true, + "AddedEdges": [ + { + "Start": { + "X": 0, + "Y": 0, + "Z": 0 + }, + "End": { + "X": 0, + "Y": -1, + "Z": 0 + }, + "IsTwoWay": false + }, + { + "Start": { + "X": 0, + "Y": 0, + "Z": 0 + }, + "End": { + "X": 0, + "Y": 1, + "Z": 0 + }, + "IsTwoWay": false + }, + { + "Start": { + "X": 0, + "Y": 0, + "Z": 0 + }, + "End": { + "X": -1, + "Y": 0, + "Z": 0 + }, + "IsTwoWay": false + }, + { + "Start": { + "X": 0, + "Y": 0, + "Z": 0 + }, + "End": { + "X": 1, + "Y": 0, + "Z": 0 + }, + "IsTwoWay": false + }, + { + "Start": { + "X": 0, + "Y": 0, + "Z": 0 + }, + "End": { + "X": 0, + "Y": 0, + "Z": -1 + }, + "IsTwoWay": false + }, + { + "Start": { + "X": 0, + "Y": 0, + "Z": 0 + }, + "End": { + "X": 0, + "Y": 0, + "Z": 1 + }, + "IsTwoWay": false + } + ] + } + ], + "UnblockedCoordinates": [] + }, + "BlockObjectSpec": { + "Size": { + "X": 1, + "Y": 1, + "Z": 1 + }, + "Blocks": [ + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom, Top, Corners, Path, Middle", + "Stackable": "BlockObject", + "OccupyAllBelow": false, + "Underground": false + } + ], + "Entrance": { + "HasEntrance": false, + "Coordinates": { + "X": 0, + "Y": 0, + "Z": 0 + } + }, + "BaseZ": 0, + "Overridable": false, + "Flippable": false + }, + "PlaceableBlockObjectSpec": { + "ToolGroupId": "Paths", + "ToolOrder": 16, + "ToolShape": "Square", + "Layout": "Line", + "CustomPivot": { + "HasCustomPivot": false, + "Coordinates": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0 + } + }, + "CanBeAttachedToTerrainSide": false, + "DevModeTool": false + }, + "LabeledEntitySpec": { + "DisplayNameLocKey": "LV.AC.AirlockChamber4", + "DescriptionLocKey": "LV.AC.AirlockChamber4Desc", + "FlavorDescriptionLocKey": "LV.AC.AirlockChamber4Flavor", + "Icon": "Sprites/Buildings/Paths/AirlockChamber4" + }, + "WaterObstacleSpec": { + "Coordinates": [ + { + "X": 0, + "Y": 0 + } + ] + }, + "FinishableWaterObstacleSpec": { + "Height": 1.0 + }, + "BlockObjectWithPathRangeSpec": {}, + "PathSpec": { + "MainPathCoordinates": { + "X": 0, + "Y": 0, + "Z": 0 + } + }, + "ConstructionSiteProgressVisualizerSpec": { + "ProgressThresholds": [ + 0.0 + ] + }, + "Children": { + "#Finished": { + "Children": { + "#Platform": { + "TimbermeshSpec": { + "Model": "Buildings/Paths/VerticalTubeway/VerticalTubewayCover.IronTeeth.Model" + }, + "CollidersSpec": { + "BoxColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.95, + "Z": 0.5 + }, + "Size": { + "X": 1.0, + "Y": 0.1, + "Z": 1.0 + } + } + ], + "SphereColliders": [], + "CapsuleColliders": [] + } + }, + "Variant_111111": { + "TimbermeshSpec": { + "Model": "Buildings/Paths/VerticalTubeway/VerticalTubeway111111.IronTeeth.Model" + }, + "CollidersSpec": { + "BoxColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.02, + "Z": 0.5 + }, + "Size": { + "X": 1.0, + "Y": 0.04, + "Z": 1.0 + } + }, + { + "Center": { + "X": 0.502746165, + "Y": 0.367945939, + "Z": 0.5101131 + }, + "Size": { + "X": 1.00304639, + "Y": 0.7358919, + "Z": 0.32637167 + } + }, + { + "Center": { + "X": 0.5, + "Y": 0.367945939, + "Z": 0.4991505 + }, + "Size": { + "X": 0.361290455, + "Y": 0.7358919, + "Z": 0.9996898 + } + }, + { + "Center": { + "X": 0.5, + "Y": 0.5636263, + "Z": 0.5026854 + }, + "Size": { + "X": 0.361290455, + "Y": 0.863144636, + "Z": 0.3704958 + } + } + ], + "SphereColliders": [], + "CapsuleColliders": [] + } + } + } + }, + "#Unfinished": { + "Children": { + "ConstructionBase1x1#nested": { + "BlueprintPath": "ConstructionBases/ConstructionBase1x1/ConstructionBase1x1.blueprint" + }, + "ConstructionStage0": { + "TimbermeshSpec": { + "Model": "Buildings/Paths/VerticalTubeway/VerticalTubeway.IronTeeth.ConstructionStage0.Model" + }, + "CollidersSpec": { + "BoxColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.05, + "Z": 0.5 + }, + "Size": { + "X": 1.0, + "Y": 0.1, + "Z": 1.0 + } + } + ], + "SphereColliders": [], + "CapsuleColliders": [] + } + } + } + } + } +} \ No newline at end of file diff --git a/AirlockChamber/version-1.0/TemplateCollectionSpecs/AirlockChamber.TemplateCollectionSpec.blueprint.json b/AirlockChamber/version-1.0/TemplateCollectionSpecs/AirlockChamber.TemplateCollectionSpec.blueprint.json new file mode 100644 index 00000000..01681f71 --- /dev/null +++ b/AirlockChamber/version-1.0/TemplateCollectionSpecs/AirlockChamber.TemplateCollectionSpec.blueprint.json @@ -0,0 +1,9 @@ +{ + "TemplateCollectionSpec": { + "CollectionId": "Common", + "Blueprints": [ + "Resources/Buildings/Paths/AirlockChamber/AirlockChamber.blueprint", + "Resources/Buildings/Paths/AirlockChamber/AirlockChamber4.blueprint" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-1.0/blueprints/Factions/Faction.Emberpelts.optional.blueprint.json b/AirlockChamber/version-1.0/blueprints/Factions/Faction.Emberpelts.optional.blueprint.json new file mode 100644 index 00000000..7d0cc229 --- /dev/null +++ b/AirlockChamber/version-1.0/blueprints/Factions/Faction.Emberpelts.optional.blueprint.json @@ -0,0 +1,10 @@ +{ + "FactionSpec": { + "MaterialCollectionIds#append": [ + "IronTeeth" + ], + "TemplateCollectionIds#append": [ + "AirlockChamber" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-1.0/blueprints/Factions/Faction.Folktails.blueprint.json b/AirlockChamber/version-1.0/blueprints/Factions/Faction.Folktails.blueprint.json new file mode 100644 index 00000000..7d0cc229 --- /dev/null +++ b/AirlockChamber/version-1.0/blueprints/Factions/Faction.Folktails.blueprint.json @@ -0,0 +1,10 @@ +{ + "FactionSpec": { + "MaterialCollectionIds#append": [ + "IronTeeth" + ], + "TemplateCollectionIds#append": [ + "AirlockChamber" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-1.0/blueprints/Factions/Faction.GreedyBuilders.optional.blueprint.json b/AirlockChamber/version-1.0/blueprints/Factions/Faction.GreedyBuilders.optional.blueprint.json new file mode 100644 index 00000000..7d0cc229 --- /dev/null +++ b/AirlockChamber/version-1.0/blueprints/Factions/Faction.GreedyBuilders.optional.blueprint.json @@ -0,0 +1,10 @@ +{ + "FactionSpec": { + "MaterialCollectionIds#append": [ + "IronTeeth" + ], + "TemplateCollectionIds#append": [ + "AirlockChamber" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-1.0/blueprints/Factions/Faction.IronTeeth.blueprint.json b/AirlockChamber/version-1.0/blueprints/Factions/Faction.IronTeeth.blueprint.json new file mode 100644 index 00000000..7d0cc229 --- /dev/null +++ b/AirlockChamber/version-1.0/blueprints/Factions/Faction.IronTeeth.blueprint.json @@ -0,0 +1,10 @@ +{ + "FactionSpec": { + "MaterialCollectionIds#append": [ + "IronTeeth" + ], + "TemplateCollectionIds#append": [ + "AirlockChamber" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-1.0/blueprints/TemplateCollectionSpecs/AirlockChamber.TemplateCollectionSpec.blueprint.json b/AirlockChamber/version-1.0/blueprints/TemplateCollectionSpecs/AirlockChamber.TemplateCollectionSpec.blueprint.json new file mode 100644 index 00000000..a4d78d9e --- /dev/null +++ b/AirlockChamber/version-1.0/blueprints/TemplateCollectionSpecs/AirlockChamber.TemplateCollectionSpec.blueprint.json @@ -0,0 +1,9 @@ +{ + "TemplateCollectionSpec": { + "CollectionId": "AirlockChamber", + "Blueprints": [ + "Resources/Buildings/Paths/AirlockChamber/AirlockChamber.blueprint", + "Resources/Buildings/Paths/AirlockChamber/AirlockChamber4.blueprint" + ] + } +} \ No newline at end of file diff --git a/AirlockChamber/version-1.0/manifest.json b/AirlockChamber/version-1.0/manifest.json new file mode 100644 index 00000000..a51c8148 --- /dev/null +++ b/AirlockChamber/version-1.0/manifest.json @@ -0,0 +1,7 @@ +{ + "Name": "Airlock Chamber", + "Version": "10.0.2", + "Id": "AirlockChamber", + "MinimumGameVersion": "1.0.0", + "Description": "An airlock chamber that block water but your beavers can walk through" +} \ No newline at end of file diff --git a/AirlockChamber/version-1.0/sprites/Buildings/Paths/AirlockChamber.png b/AirlockChamber/version-1.0/sprites/Buildings/Paths/AirlockChamber.png new file mode 100644 index 00000000..01f8d8d7 Binary files /dev/null and b/AirlockChamber/version-1.0/sprites/Buildings/Paths/AirlockChamber.png differ diff --git a/AirlockChamber/version-1.0/sprites/Buildings/Paths/AirlockChamber4.png b/AirlockChamber/version-1.0/sprites/Buildings/Paths/AirlockChamber4.png new file mode 100644 index 00000000..1230be3e Binary files /dev/null and b/AirlockChamber/version-1.0/sprites/Buildings/Paths/AirlockChamber4.png differ diff --git a/AirlockChamber/workshop_data.json b/AirlockChamber/workshop_data.json new file mode 100644 index 00000000..f435f6ed --- /dev/null +++ b/AirlockChamber/workshop_data.json @@ -0,0 +1,14 @@ +{ + "ItemId": "3543201946", + "Name": "Airlock Chamber", + "Visibility": "Public", + "UpdateDescription": false, + "UpdateVisibility": false, + "UpdatePreview": false, + "Tags": [ + "Update 1.0", + "Update 0.7", + "New content", + "Buildings" + ] +} \ No newline at end of file diff --git a/AllBuildingsTransferPower/AllBuildingsTransferPower.csproj b/AllBuildingsTransferPower/AllBuildingsTransferPower.csproj new file mode 100644 index 00000000..9aa8f225 --- /dev/null +++ b/AllBuildingsTransferPower/AllBuildingsTransferPower.csproj @@ -0,0 +1,10 @@ + + + + AllBuildingsTransferPower + + + + + + diff --git a/AllBuildingsTransferPower/BuildingModifier.cs b/AllBuildingsTransferPower/BuildingModifier.cs new file mode 100644 index 00000000..4b0ed81f --- /dev/null +++ b/AllBuildingsTransferPower/BuildingModifier.cs @@ -0,0 +1,176 @@ +using ModdableTimberborn.DependencyInjection; + +namespace AllBuildingsTransferPower; + +[MultiBind(typeof(ITemplateModifier))] +public class BuildingModifier : ITemplateModifier +{ + public EditableBlueprint? Modify(EditableBlueprint template, TemplateSpec originalTemplateSpec, Blueprint original) + { + var bo = template.GetSpec(); + if (bo is null) { return null; } + + var blocks = GetBuildingBlocks(bo).ToDictionary(b => b.Coords, b => b.IsBorder); + + var originalIndex = template.Specs.FindIndex(spec => spec is TransputProviderSpec); + var ignoreRotation = false; + HashSet<(Vector3Int Coordinates, Direction3D Direction)> reverseRotations = []; + if (originalIndex >= 0) + { + var tps = (TransputProviderSpec)template.Specs[originalIndex]; + ignoreRotation = tps.IgnoreRotation; + + foreach (var transput in tps.Transputs) + { + if (!transput.ReverseRotation) { continue; } + + foreach (var direction in GetDirections(transput.Directions)) + { + reverseRotations.Add((transput.Coordinates, direction)); + } + } + + template.Specs.RemoveAt(originalIndex); + } + + if (!template.Specs.Any(s => s is MechanicalConnectorTargetSpec)) + { + template.Specs.Add(new MechanicalConnectorTargetSpec()); + } + + List transputs = []; + foreach (var (coords, isBorder) in blocks) + { + if (!isBorder) { continue; } + + var directions = FindDirections(coords, blocks); + var normalDirections = Directions3D.None; + var reversedDirections = Directions3D.None; + + foreach (var direction in GetDirections(directions)) + { + if (reverseRotations.Contains((coords, direction))) + { + reversedDirections |= direction.ToDirections3D(); + } + else + { + normalDirections |= direction.ToDirections3D(); + } + } + + AddTransput(transputs, coords, normalDirections, reverseRotation: false); + AddTransput(transputs, coords, reversedDirections, reverseRotation: true); + } + + template.Specs.Add(new TransputProviderSpec() + { + Transputs = [.. transputs], + IgnoreRotation = ignoreRotation, + }); + + return template; + } + + public bool ShouldModify(string blueprintName, string templateName, TemplateSpec originalTemplateSpec) + { + if (!originalTemplateSpec.HasSpec() + || originalTemplateSpec.HasSpec()) // The Power Shaft, will crash if modified + { + return false; + } + + if (originalTemplateSpec.GetSpec() is not { } bld) { return false; } + if (bld.PlaceFinished) // Free buildings are skipped unless they are district centers + { + return bld.HasSpec(); + } + + return true; + } + + static void AddTransput(List transputs, Vector3Int coords, Directions3D directions, bool reverseRotation) + { + if (directions == Directions3D.None) { return; } + + transputs.Add(new() + { + Coordinates = coords, + ReverseRotation = reverseRotation, + Directions = directions, + }); + } + + static Directions3D FindDirections(Vector3Int coords, Dictionary blocks) + { + Directions3D result = Directions3D.None; + + foreach (var n in Deltas.Neighbors6Vector3Int) + { + var target = coords + n; + if (!blocks.ContainsKey(target)) + { + var d = Direction3DExtensions.FromOffset(n); + result |= d.ToDirections3D(); + } + } + + return result; + } + + static IEnumerable GetDirections(Directions3D directions) + { + foreach (var n in Deltas.Neighbors6Vector3Int) + { + var direction = Direction3DExtensions.FromOffset(n); + if ((directions & direction.ToDirections3D()) != 0) + { + yield return direction; + } + } + } + + IEnumerable GetBuildingBlocks(BlockObjectSpec bo) + { + var (sx, sy, sz) = bo.Size; + + var occupiedBlocks = bo.GetBlocks().GetOccupiedBlocks() + .Select(b => b.Coordinates) + .ToHashSet(); + + for (int x = 0; x < sx; x++) + { + var isXBorder = x == 0 || x == sx - 1; + + for (int y = 0; y < sy; y++) + { + var isYBorder = y == 0 || y == sy - 1; + + for (int z = 0; z < sz; z++) + { + var coords = new Vector3Int(x, y, z); + + if (!occupiedBlocks.Contains(coords)) { continue; } + + var isBorder = isXBorder || isYBorder || z == 0 || z == sz - 1; + if (!isBorder) // Check for empty surrouding blocks + { + foreach (var n in Deltas.Neighbors6Vector3Int) + { + var target = coords + n; + if (!occupiedBlocks.Contains(target)) + { + isBorder = true; + break; + } + } + } + + yield return new BuildingBlock(coords, isBorder); + } + } + } + } + + readonly record struct BuildingBlock(Vector3Int Coords, bool IsBorder); +} diff --git a/AllBuildingsTransferPower/MConfigs.cs b/AllBuildingsTransferPower/MConfigs.cs new file mode 100644 index 00000000..7502cd1b --- /dev/null +++ b/AllBuildingsTransferPower/MConfigs.cs @@ -0,0 +1,6 @@ +namespace AllBuildingsTransferPower; + +public class MConfigs : BaseModdableTimberbornAttributeConfiguration, IWithDIConfig +{ + public override ConfigurationContext AvailableContexts => ConfigurationContext.Game; +} diff --git a/AllBuildingsTransferPower/ModDesc.txt b/AllBuildingsTransferPower/ModDesc.txt new file mode 100644 index 00000000..54ecccdf --- /dev/null +++ b/AllBuildingsTransferPower/ModDesc.txt @@ -0,0 +1,10 @@ +This mod simply makes all buildings, and all parts of a building, be able to transfer power. + +Instant buildings (like Roads) are excluded, except the District Center. Power Shafts are also excluded because they are special buildings that would crash if modified. + +[img]https://files.catbox.moe/o9cwm9.jpg[/img] + +Intended to be for my Conveyor Belts mod to make power transfer less of a chore but it is not required. + +=== +Mod source code and donation: https://github.com/datvm/TimberbornMods (feel free to use the code for anything). \ No newline at end of file diff --git a/AllBuildingsTransferPower/manifest.json b/AllBuildingsTransferPower/manifest.json new file mode 100644 index 00000000..bd8dd0a5 --- /dev/null +++ b/AllBuildingsTransferPower/manifest.json @@ -0,0 +1,10 @@ +{ + "Name": "All Buildings Transfer Power", + "Version": "11.0.1", + "Id": "AllBuildingsTransferPower", + "MinimumGameVersion": "1.1.0", + "Description": "All parts of buildings can transfer power.", + "RequiredMods": [ + { "Id": "ModdableTimberborn" } + ] +} \ No newline at end of file diff --git a/AllGoodsInWarehouses/AllGoodsInWarehouses.csproj b/AllGoodsInWarehouses/AllGoodsInWarehouses.csproj new file mode 100644 index 00000000..7ebad00f --- /dev/null +++ b/AllGoodsInWarehouses/AllGoodsInWarehouses.csproj @@ -0,0 +1,20 @@ + + + + AllGoodsInWarehouses + + + + + + + + + + + + + + + + diff --git a/AllGoodsInWarehouses/MConfigs.U7.cs b/AllGoodsInWarehouses/MConfigs.U7.cs new file mode 100644 index 00000000..4d69fa8c --- /dev/null +++ b/AllGoodsInWarehouses/MConfigs.U7.cs @@ -0,0 +1,25 @@ +global using ModdableTimberborn.DependencyInjection; +global using AllGoodsInWarehouses.Services; + +namespace AllGoodsInWarehouses; + +public class AllGoodsInWarehousesConfigs : BaseModdableTimberbornConfiguration +{ + + public override void StartMod(IModEnvironment modEnvironment) + { + base.StartMod(modEnvironment); + + ModdableTimberbornRegistry.Instance + .UseDependencyInjection(); + } + + public override void Configure(Configurator configurator, ConfigurationContext context) + { + if (!context.IsGameContext()) { return; } + + configurator + .BindSpecModifier() + ; + } +} diff --git a/AllGoodsInWarehouses/MConfigs.V1.cs b/AllGoodsInWarehouses/MConfigs.V1.cs new file mode 100644 index 00000000..63192d6f --- /dev/null +++ b/AllGoodsInWarehouses/MConfigs.V1.cs @@ -0,0 +1,15 @@ +global using ModdableTimberborn.DependencyInjection; +global using AllGoodsInWarehouses.Services; + +namespace AllGoodsInWarehouses; +public class AllGoodsInWarehousesConfigs : BaseModdableTimberbornConfiguration, IWithDIConfig +{ + public override ConfigurationContext AvailableContexts { get; } = ConfigurationContext.Game; + + public override void Configure(Configurator configurator, ConfigurationContext context) + { + configurator + .BindSpecModifier() + ; + } +} diff --git a/AllGoodsInWarehouses/ModDesc.txt b/AllGoodsInWarehouses/ModDesc.txt new file mode 100644 index 00000000..2cea7de6 --- /dev/null +++ b/AllGoodsInWarehouses/ModDesc.txt @@ -0,0 +1,10 @@ +All Goods In Warehouses lets every resource previously restricted to Piles and Tanks be stored directly in Warehouses. + +After enabling the mod and loading your save, you can freely move existing goods out of Piles and Tanks into Warehouses. Once transferred, you can safely remove the old storage buildings. + +[b]Important: do not open the Good selection panel on any existing Pile or Tank. The game will crash.[/b] Only use them to evacuate their contents, then demolish them. + +To prevent accidental new build, Piles and Tanks also become [spoiler]Dev Tool buildings[/spoiler] which should be hidden unless you enable certain mode. Idea by kathysgeek. + +=== +Mod source code and donation: https://github.com/datvm/TimberbornMods (feel free to use the code for anything). \ No newline at end of file diff --git a/AllGoodsInWarehouses/Root/Buildings/Storage/LargeIndustrialPile/LargeIndustrialPile.IronTeeth.blueprint.json b/AllGoodsInWarehouses/Root/Buildings/Storage/LargeIndustrialPile/LargeIndustrialPile.IronTeeth.blueprint.json new file mode 100644 index 00000000..829747ef --- /dev/null +++ b/AllGoodsInWarehouses/Root/Buildings/Storage/LargeIndustrialPile/LargeIndustrialPile.IronTeeth.blueprint.json @@ -0,0 +1,5 @@ +{ + "PlaceableBlockObjectSpec": { + "DevModeTool": true + } +} \ No newline at end of file diff --git a/AllGoodsInWarehouses/Root/Buildings/Storage/LargePile/LargePile.Folktails.blueprint.json b/AllGoodsInWarehouses/Root/Buildings/Storage/LargePile/LargePile.Folktails.blueprint.json new file mode 100644 index 00000000..829747ef --- /dev/null +++ b/AllGoodsInWarehouses/Root/Buildings/Storage/LargePile/LargePile.Folktails.blueprint.json @@ -0,0 +1,5 @@ +{ + "PlaceableBlockObjectSpec": { + "DevModeTool": true + } +} \ No newline at end of file diff --git a/AllGoodsInWarehouses/Root/Buildings/Storage/LargeTank/LargeTank.Folktails.blueprint.json b/AllGoodsInWarehouses/Root/Buildings/Storage/LargeTank/LargeTank.Folktails.blueprint.json new file mode 100644 index 00000000..829747ef --- /dev/null +++ b/AllGoodsInWarehouses/Root/Buildings/Storage/LargeTank/LargeTank.Folktails.blueprint.json @@ -0,0 +1,5 @@ +{ + "PlaceableBlockObjectSpec": { + "DevModeTool": true + } +} \ No newline at end of file diff --git a/AllGoodsInWarehouses/Root/Buildings/Storage/LargeTank/LargeTank.IronTeeth.blueprint.json b/AllGoodsInWarehouses/Root/Buildings/Storage/LargeTank/LargeTank.IronTeeth.blueprint.json new file mode 100644 index 00000000..829747ef --- /dev/null +++ b/AllGoodsInWarehouses/Root/Buildings/Storage/LargeTank/LargeTank.IronTeeth.blueprint.json @@ -0,0 +1,5 @@ +{ + "PlaceableBlockObjectSpec": { + "DevModeTool": true + } +} \ No newline at end of file diff --git a/AllGoodsInWarehouses/Root/Buildings/Storage/MediumTank/MediumTank.Folktails.blueprint.json b/AllGoodsInWarehouses/Root/Buildings/Storage/MediumTank/MediumTank.Folktails.blueprint.json new file mode 100644 index 00000000..829747ef --- /dev/null +++ b/AllGoodsInWarehouses/Root/Buildings/Storage/MediumTank/MediumTank.Folktails.blueprint.json @@ -0,0 +1,5 @@ +{ + "PlaceableBlockObjectSpec": { + "DevModeTool": true + } +} \ No newline at end of file diff --git a/AllGoodsInWarehouses/Root/Buildings/Storage/MediumTank/MediumTank.IronTeeth.blueprint.json b/AllGoodsInWarehouses/Root/Buildings/Storage/MediumTank/MediumTank.IronTeeth.blueprint.json new file mode 100644 index 00000000..829747ef --- /dev/null +++ b/AllGoodsInWarehouses/Root/Buildings/Storage/MediumTank/MediumTank.IronTeeth.blueprint.json @@ -0,0 +1,5 @@ +{ + "PlaceableBlockObjectSpec": { + "DevModeTool": true + } +} \ No newline at end of file diff --git a/AllGoodsInWarehouses/Root/Buildings/Storage/SmallPile/SmallPile.Folktails.blueprint.json b/AllGoodsInWarehouses/Root/Buildings/Storage/SmallPile/SmallPile.Folktails.blueprint.json new file mode 100644 index 00000000..829747ef --- /dev/null +++ b/AllGoodsInWarehouses/Root/Buildings/Storage/SmallPile/SmallPile.Folktails.blueprint.json @@ -0,0 +1,5 @@ +{ + "PlaceableBlockObjectSpec": { + "DevModeTool": true + } +} \ No newline at end of file diff --git a/AllGoodsInWarehouses/Root/Buildings/Storage/SmallTank/SmallTank.Folktails.blueprint.json b/AllGoodsInWarehouses/Root/Buildings/Storage/SmallTank/SmallTank.Folktails.blueprint.json new file mode 100644 index 00000000..829747ef --- /dev/null +++ b/AllGoodsInWarehouses/Root/Buildings/Storage/SmallTank/SmallTank.Folktails.blueprint.json @@ -0,0 +1,5 @@ +{ + "PlaceableBlockObjectSpec": { + "DevModeTool": true + } +} \ No newline at end of file diff --git a/AllGoodsInWarehouses/Root/Buildings/Storage/SmallTank/SmallTank.IronTeeth.blueprint.json b/AllGoodsInWarehouses/Root/Buildings/Storage/SmallTank/SmallTank.IronTeeth.blueprint.json new file mode 100644 index 00000000..829747ef --- /dev/null +++ b/AllGoodsInWarehouses/Root/Buildings/Storage/SmallTank/SmallTank.IronTeeth.blueprint.json @@ -0,0 +1,5 @@ +{ + "PlaceableBlockObjectSpec": { + "DevModeTool": true + } +} \ No newline at end of file diff --git a/AllGoodsInWarehouses/Root/Buildings/Storage/UndergroundPile/UndergroundPile.Folktails.blueprint.json b/AllGoodsInWarehouses/Root/Buildings/Storage/UndergroundPile/UndergroundPile.Folktails.blueprint.json new file mode 100644 index 00000000..829747ef --- /dev/null +++ b/AllGoodsInWarehouses/Root/Buildings/Storage/UndergroundPile/UndergroundPile.Folktails.blueprint.json @@ -0,0 +1,5 @@ +{ + "PlaceableBlockObjectSpec": { + "DevModeTool": true + } +} \ No newline at end of file diff --git a/AllGoodsInWarehouses/Services/GoodSpecModifier.U7.cs b/AllGoodsInWarehouses/Services/GoodSpecModifier.U7.cs new file mode 100644 index 00000000..40ae9433 --- /dev/null +++ b/AllGoodsInWarehouses/Services/GoodSpecModifier.U7.cs @@ -0,0 +1,29 @@ +namespace AllGoodsInWarehouses.Services; + +public class GoodSpecModifier : BaseSpecModifier +{ + public override int Order { get; } = 100; + + public const string WarehouseGoodType = "Box"; + + public GoodSpec? Transform(GoodSpec spec) + { + if (spec.GoodType == WarehouseGoodType) { return null; } + + return spec with + { + GoodType = WarehouseGoodType, + ContainerColor = spec.ContainerColor == "" ? "#FFFFFF" : spec.ContainerColor, + StockpileVisualization = WarehouseGoodType, + }; + } + + protected override IEnumerable Modify(IEnumerable specs) + { + foreach (var spec in specs) + { + var transformed = Transform(spec); + yield return transformed is null ? spec : transformed; + } + } +} diff --git a/AllGoodsInWarehouses/Services/GoodSpecModifier.V1.cs b/AllGoodsInWarehouses/Services/GoodSpecModifier.V1.cs new file mode 100644 index 00000000..5c02d8ec --- /dev/null +++ b/AllGoodsInWarehouses/Services/GoodSpecModifier.V1.cs @@ -0,0 +1,20 @@ + +namespace AllGoodsInWarehouses.Services; + +public class GoodSpecModifier : BaseSpecTransformer +{ + public const string WarehouseGoodType = "Box"; + + public override GoodSpec? Transform(GoodSpec spec) + { + if (spec.GoodType == WarehouseGoodType) { return null; } + + return spec with + { + GoodType = WarehouseGoodType, + ContainerColor = spec.ContainerColor with { a = 1, }, + StockpileVisualization = WarehouseGoodType, + }; + } + +} diff --git a/AllGoodsInWarehouses/manifest.json b/AllGoodsInWarehouses/manifest.json new file mode 100644 index 00000000..fd528055 --- /dev/null +++ b/AllGoodsInWarehouses/manifest.json @@ -0,0 +1,10 @@ +{ + "Name": "All Goods In Warehouses", + "Version": "10.1.0", + "Id": "AllGoodsInWarehouses", + "MinimumGameVersion": "0.7.0", + "Description": "All goods are stored in warehouses.", + "RequiredMods": [ + { "Id": "ModdableTimberborn" } + ] +} \ No newline at end of file diff --git a/AllGoodsInWarehouses/workshop_data.json b/AllGoodsInWarehouses/workshop_data.json new file mode 100644 index 00000000..3781a102 --- /dev/null +++ b/AllGoodsInWarehouses/workshop_data.json @@ -0,0 +1,14 @@ +{ + "ItemId": "3608113524", + "Name": "All Goods In Warehouses", + "Visibility": "Public", + "UpdateDescription": false, + "UpdateVisibility": false, + "UpdatePreview": false, + "Tags": [ + "Update 1.0", + "Update 0.7", + "Cheats", + "Goods" + ] +} \ No newline at end of file diff --git a/AlwaysConnected/AlwaysConnected.csproj b/AlwaysConnected/AlwaysConnected.csproj new file mode 100644 index 00000000..b687b593 --- /dev/null +++ b/AlwaysConnected/AlwaysConnected.csproj @@ -0,0 +1,7 @@ + + + AlwaysConnected + + + + \ No newline at end of file diff --git a/AlwaysConnected/MechanicalGraphManagerPatch.cs b/AlwaysConnected/MechanicalGraphManagerPatch.cs new file mode 100644 index 00000000..0b8e9321 --- /dev/null +++ b/AlwaysConnected/MechanicalGraphManagerPatch.cs @@ -0,0 +1,43 @@ +using Timberborn.MechanicalSystem; +using Timberborn.MechanicalSystemUI; + +namespace AlwaysConnected; + +[HarmonyPatch(typeof(MechanicalGraphManager))] +public static class MechanicalGraphManagerPatch +{ + static readonly FieldInfo mechanicalGraphRegistryField = typeof(MechanicalGraphFactory).GetField("_mechanicalGraphRegistry", BindingFlags.NonPublic | BindingFlags.Instance); + + [HarmonyPatch(nameof(MechanicalGraphManager.AddNode)), HarmonyPostfix] + public static void PostfixAddNode(MechanicalGraphFactory ____mechanicalGraphFactory) + { + Patch(____mechanicalGraphFactory); + } + + [HarmonyPatch(nameof(MechanicalGraphManager.RemoveNode)), HarmonyPostfix] + public static void PostfixRemoveNode(MechanicalGraphFactory ____mechanicalGraphFactory) + { + Patch(____mechanicalGraphFactory); + } + + static void Patch(MechanicalGraphFactory ____mechanicalGraphFactory) + { + var registry = (MechanicalGraphRegistry)mechanicalGraphRegistryField.GetValue(____mechanicalGraphFactory); + + ____mechanicalGraphFactory.Join([.. registry.MechanicalGraphs]); + } + + // Fixing Forester crashing + [HarmonyPrefix, HarmonyPatch(typeof(MechanicalModel), nameof(MechanicalModel.UpdateModel))] + public static bool PrefixUpdateModel(MechanicalModel __instance) + { + if (__instance._mechanicalNode?.Transputs.Any() != true) + { + Debug.Log("Skipping UpdateModel to prevent crash"); + return false; + } + + return true; + } + +} diff --git a/AlwaysConnected/ModStarter.cs b/AlwaysConnected/ModStarter.cs new file mode 100644 index 00000000..190f2c67 --- /dev/null +++ b/AlwaysConnected/ModStarter.cs @@ -0,0 +1,13 @@ +using HarmonyLib; +using Timberborn.ModManagerScene; + +namespace AlwaysConnected; +public class ModStarter : IModStarter +{ + + public void StartMod(IModEnvironment modEnvironment) + { + new Harmony(nameof(AlwaysConnected)).PatchAll(); + } + +} diff --git a/AlwaysConnected/manifest.json b/AlwaysConnected/manifest.json new file mode 100644 index 00000000..f209df39 --- /dev/null +++ b/AlwaysConnected/manifest.json @@ -0,0 +1,13 @@ +{ + "Name": "Always Connected (Power)", + "Version": "7.0.0", + "Id": "AlwaysConnected", + "MinimumGameVersion": "0.6.0.0", + "Description": "Connecting and organizing power shaft maybe fun for a few games. If you are tired of it, this mod is for you. All power buildings in the game will always be connected, no shaft needed anymore.", + "RequiredMods": [ + { + "Id": "Harmony", + "MinimumVersion": "0.6.0.0" + } + ] +} \ No newline at end of file diff --git a/AlwaysConnected/workshop_data.json b/AlwaysConnected/workshop_data.json new file mode 100644 index 00000000..40d05ff1 --- /dev/null +++ b/AlwaysConnected/workshop_data.json @@ -0,0 +1,16 @@ +{ + "ItemId": "3414359638", + "Name": "Always Connected (Power)", + "Visibility": "Public", + "UpdateDescription": false, + "UpdateVisibility": false, + "UpdatePreview": false, + "Tags": [ + "Update 1.0", + "Update 0.7", + "Update 0.6", + "Cheats", + "Buildings", + "Miscellaneous" + ] +} \ No newline at end of file diff --git a/AlwaysFlexibleStart/AlwaysFlexibleStart.csproj b/AlwaysFlexibleStart/AlwaysFlexibleStart.csproj new file mode 100644 index 00000000..97856de4 --- /dev/null +++ b/AlwaysFlexibleStart/AlwaysFlexibleStart.csproj @@ -0,0 +1,13 @@ + + + AlwaysFlexibleStart + + + + + + E:\SteamLibrary\steamapps\common\Timberborn\Timberborn_Data\Managed\Timberborn.GameWonderCompletion.dll + False + + + \ No newline at end of file diff --git a/AlwaysFlexibleStart/GameWonderCompletionServicePatch.cs b/AlwaysFlexibleStart/GameWonderCompletionServicePatch.cs new file mode 100644 index 00000000..f48aed8b --- /dev/null +++ b/AlwaysFlexibleStart/GameWonderCompletionServicePatch.cs @@ -0,0 +1,16 @@ +using HarmonyLib; +using Timberborn.GameWonderCompletion; + +namespace AlwaysFlexibleStart; + +[HarmonyPatch(typeof(GameWonderCompletionService), nameof(GameWonderCompletionService.IsWonderCompletedWithAnyFaction))] +public static class GameWonderCompletionServicePatch +{ + + public static bool Prefix(ref bool __result) + { + __result = true; + return false; + } + +} diff --git a/AlwaysFlexibleStart/ModStarter.cs b/AlwaysFlexibleStart/ModStarter.cs new file mode 100644 index 00000000..fb036cc4 --- /dev/null +++ b/AlwaysFlexibleStart/ModStarter.cs @@ -0,0 +1,13 @@ +using HarmonyLib; +using Timberborn.ModManagerScene; + +namespace AlwaysFlexibleStart; +public class ModStarter : IModStarter +{ + + public void StartMod(IModEnvironment modEnvironment) + { + new Harmony(nameof(AlwaysFlexibleStart)).PatchAll(); + } + +} diff --git a/AlwaysFlexibleStart/manifest.json b/AlwaysFlexibleStart/manifest.json new file mode 100644 index 00000000..f56b08a7 --- /dev/null +++ b/AlwaysFlexibleStart/manifest.json @@ -0,0 +1,13 @@ +{ + "Name": "Always Flexible Start", + "Version": "1.0.0", + "Id": "AlwaysFlexibleStart", + "MinimumGameVersion": "0.6.0.0", + "Description": "You can always move your starting settlement as if you have flexible start enabled by building a wonder on this map once.", + "RequiredMods": [ + { + "Id": "Harmony", + "MinimumVersion": "0.6.0.0" + } + ] +} \ No newline at end of file diff --git a/AlwaysFlexibleStart/workshop_data.json b/AlwaysFlexibleStart/workshop_data.json new file mode 100644 index 00000000..fadf6a9e --- /dev/null +++ b/AlwaysFlexibleStart/workshop_data.json @@ -0,0 +1,15 @@ +{ + "ItemId": "3393736557", + "Name": "Always Flexible Start", + "Visibility": "Public", + "UpdateDescription": false, + "UpdateVisibility": false, + "UpdatePreview": false, + "Tags": [ + "Update 1.0", + "Update 0.7", + "Update 0.6", + "Cheats", + "Miscellaneous" + ] +} \ No newline at end of file diff --git a/AutomationArrays/AutomationArrays.csproj b/AutomationArrays/AutomationArrays.csproj new file mode 100644 index 00000000..1ab32f8c --- /dev/null +++ b/AutomationArrays/AutomationArrays.csproj @@ -0,0 +1,11 @@ + + + AutomationArrays + + + + + + + + \ No newline at end of file diff --git a/AutomationArrays/Components/IArrayTransmitter.cs b/AutomationArrays/Components/IArrayTransmitter.cs new file mode 100644 index 00000000..8649ac62 --- /dev/null +++ b/AutomationArrays/Components/IArrayTransmitter.cs @@ -0,0 +1,9 @@ +namespace AutomationArrays.Components; + +public interface IArrayTransmitter : ITransmitter +{ + + IReadOnlyList States { get; } + + +} diff --git a/AutomationArrays/Components/RelayHub.cs b/AutomationArrays/Components/RelayHub.cs new file mode 100644 index 00000000..b4f0a6b1 --- /dev/null +++ b/AutomationArrays/Components/RelayHub.cs @@ -0,0 +1,70 @@ +namespace AutomationArrays.Components; + +[AddTemplateModule2(typeof(RelayHubSpec))] +public class RelayHub() : BaseComponent, IAwakableComponent, IArrayTransmitter, ICombinationalTransmitter, IPersistentEntity +{ + static readonly ComponentKey SaveKey = new(nameof(RelayHub)); + static readonly ListKey InputsKey = new("Inputs"); + static readonly ListKey SingleParametersKey = new("SingleParameters"); + static readonly ListKey ArrayParametersKey = new("ArrayParameters"); + static readonly PropertyKey SingleModeNotKey = new("SingleModeNot"); + static readonly PropertyKey ArrayModeNotKey = new("ArrayModeNot"); + +#nullable disable + SegmentedIlluminator illuminator; + Automator automator; +#nullable enable + + public RelayHubSingleMode SingleMode { get; private set; } + public bool SingleModeNot { get; private set; } + public RelayHubArrayMode ArrayMode { get; private set; } + public bool ArrayModeNot { get; private set; } + public int[] SingleParameters { get; private set; } = []; + public int[] ArrayParameters { get; private set; } = []; + + readonly List connections = []; + readonly List states = []; + + public IEnumerable Connections => connections; + public IReadOnlyList States => states; + + public void Awake() + { + illuminator = GetComponent(); + automator = GetComponent(); + } + + public void Add() + { + var connection = automator.AddInput(); + connections.Add(connection); + + Evaluate(); + } + + public void Remove(int index) + { + var conn = connections[index]; + connections.RemoveAt(index); + conn.Remove(); + + Evaluate(); + } + + readonly List inputCache = []; + public void Evaluate() + { + var newState = RelayHubEvaluator.Evaluate(this, inputCache, states); + automator.SetState(newState); + } + + public void Load(IEntityLoader entityLoader) + { + + } + + public void Save(IEntitySaver entitySaver) + { + + } +} diff --git a/AutomationArrays/Components/RelayHubModel.cs b/AutomationArrays/Components/RelayHubModel.cs new file mode 100644 index 00000000..17db543b --- /dev/null +++ b/AutomationArrays/Components/RelayHubModel.cs @@ -0,0 +1,45 @@ +namespace AutomationArrays.Components; + +[AddTemplateModule2(typeof(RelayHubSpec))] +public class RelayHubModel : BaseComponent, IAwakableComponent +{ + const int SizeX = 3; + const int SizeY = 3; + +#nullable disable + GameObject template; +#nullable enable + + readonly GameObject[] entries = new GameObject[SizeX * SizeY]; + + public void Awake() + { + InitializeModels(); + } + + void InitializeModels() + { + var go = GameObject; + + template = go.FindChild("#Template"); + var container = go.FindChild("#Actual"); + + var i = 0; + for (int x = 0; x < SizeX; x++) + { + for (int y = 0; y < SizeY; y++) + { + var entry = GameObject.Instantiate(template, container.transform); + entries[i] = entry; + entry.transform.Translate(new(x, 0, y)); + + i++; + } + } + + template.SetActive(false); + + GetComponent().InitializeSegments(entries); + } + +} diff --git a/AutomationArrays/Components/RelayHubModes.cs b/AutomationArrays/Components/RelayHubModes.cs new file mode 100644 index 00000000..3740becd --- /dev/null +++ b/AutomationArrays/Components/RelayHubModes.cs @@ -0,0 +1,26 @@ +namespace AutomationArrays.Components; + +public enum RelayHubSingleMode +{ + And, + Or, + Index, + Eq, + Gt, + Gte, + Lt, + Lte, +} + +public enum RelayHubArrayMode +{ + Passthrough, + Reverse, + Repeat, + Slice, + Shift, + + And, + Or, + Xor, +} \ No newline at end of file diff --git a/AutomationArrays/Components/SegmentedIlluminator.cs b/AutomationArrays/Components/SegmentedIlluminator.cs new file mode 100644 index 00000000..4d40d495 --- /dev/null +++ b/AutomationArrays/Components/SegmentedIlluminator.cs @@ -0,0 +1,87 @@ +namespace AutomationArrays.Components; + +[AddTemplateModule2(typeof(RelayHubSpec))] +public class SegmentedIlluminator(IlluminationService illuminationService) : BaseComponent, IPreviewStateListener +{ + public const float DefaultStrength = 1f; + + class SegmentInfo(GameObject go, MeshRenderer[] renderers, Material[] materials, Color color) + { + public GameObject GameObject { get; } = go; + public Material[] Materials { get; } = materials; + public MeshRenderer[] Renderers { get; } = renderers; + public Color Color { get; set; } = color; + public float Strength { get; set; } = DefaultStrength; + public bool On { get; set; } + } + + SegmentInfo[] segments = null!; + + public void InitializeSegments(GameObject[] segmentRoots) + { + var c = illuminationService.DefaultColor; + + segments = [.. segmentRoots.Select(go => { + var renderers = go.GetComponentsInChildren(); + List materials = []; + + foreach (var r in renderers) + { + materials.AddRange(r.materials); + } + + return new SegmentInfo(go, renderers, [..materials], c); + })]; + } + + public void OnEnterPreviewState() => SetAllSegments(on: false); + + public void SetAllSegments(Color? color = null, float? strength = null, bool? on = null) + { + for (int i = 0; i < segments.Length; i++) + { + SetSegment(i, color, strength, on); + } + } + + public void SetSegment(int index, Color? color = null, float? strength = null, bool? on = null) + { + var seg = segments[index]; + + if (color.HasValue) + { + var c = color.Value; + + if (c != seg.Color) + { + seg.Color = c; + ColorMaterials(seg.Materials, c); + } + } + + var changed = false; + if (strength.HasValue && seg.Strength != strength.Value) + { + seg.Strength = strength.Value; + changed = true; + } + + if (on.HasValue && seg.On != on.Value) + { + seg.On = on.Value; + changed = true; + } + + if (!changed) { return; } + MaterialLightingEnabler.SetStrengthInRenderers(seg.Renderers, seg.On ? seg.Strength : 0); + } + + void ColorMaterials(Material[] materials, Color c) + { + foreach (var m in materials) + { + m.SetColor(MaterialColorer.LightingColorProperty, c); + } + } + +} diff --git a/AutomationArrays/Helpers/AutomationHelpers.cs b/AutomationArrays/Helpers/AutomationHelpers.cs new file mode 100644 index 00000000..16a5f777 --- /dev/null +++ b/AutomationArrays/Helpers/AutomationHelpers.cs @@ -0,0 +1,22 @@ +namespace AutomationArrays.Helpers; + +public static class AutomationHelpers +{ + + extension(Automator automator) + { + public bool IsArrayTransmitter([NotNullWhen(true)] out IArrayTransmitter? transmitter) + => (transmitter = automator as IArrayTransmitter) is not null; + } + + extension(T value) where T : Enum + { + + public ArgumentOutOfRangeException ThrowInvalid() + { + throw new ArgumentOutOfRangeException($"Value {value} is not valid for enum type {typeof(T).Name}"); + } + + } + +} diff --git a/AutomationArrays/Localizations/enUS.csv b/AutomationArrays/Localizations/enUS.csv new file mode 100644 index 00000000..9ded4ff2 --- /dev/null +++ b/AutomationArrays/Localizations/enUS.csv @@ -0,0 +1,11 @@ +ID,Text,Comment +LV.AA.RelayHub.Name,"Relay Hub", +LV.AA.RelayHub.Desc,"Receive, relay and perform logical operations on infinite amount of input signals.", +LV.AA.RelayHub.Parameter.Index,"Index", +LV.AA.RelayHub.Parameter.Start,"Start Index", +LV.AA.RelayHub.Parameter.Length,"Length", +LV.AA.RelayHub.Parameter.ShiftDirection,"Shift Direction", +LV.AA.RelayHub.Parameter.ShiftAmount,"Shift Amount", +LV.AA.RelayHub.Parameter.RepeatCount,"Repeat Count", +LV.AA.Left,"Left", +LV.AA.Right,"Right", \ No newline at end of file diff --git a/AutomationArrays/MConfigs.cs b/AutomationArrays/MConfigs.cs new file mode 100644 index 00000000..aef2f0c0 --- /dev/null +++ b/AutomationArrays/MConfigs.cs @@ -0,0 +1,7 @@ +namespace AutomationArrays; + +public class AutomationArraysConfigs : BaseModdableTimberbornAttributeConfiguration +{ + public override ConfigurationContext AvailableContexts { get; } = ConfigurationContext.Game; + +} diff --git a/AutomationArrays/Root/Blueprints/TemplateCollectionSpecs/AutomationArrays.Folktail.blueprint.json b/AutomationArrays/Root/Blueprints/TemplateCollectionSpecs/AutomationArrays.Folktail.blueprint.json new file mode 100644 index 00000000..ef06e830 --- /dev/null +++ b/AutomationArrays/Root/Blueprints/TemplateCollectionSpecs/AutomationArrays.Folktail.blueprint.json @@ -0,0 +1,8 @@ +{ + "TemplateCollectionSpec": { + "CollectionId": "Buildings.Folktails", + "Blueprints": [ + "Buildings/Automation/RelayHub/RelayHub.Folktails.blueprint" + ] + } +} \ No newline at end of file diff --git a/AutomationArrays/Root/Buildings/Automation/RelayHub/RelayHub.Folktails.blueprint.json b/AutomationArrays/Root/Buildings/Automation/RelayHub/RelayHub.Folktails.blueprint.json new file mode 100644 index 00000000..93c2ba35 --- /dev/null +++ b/AutomationArrays/Root/Buildings/Automation/RelayHub/RelayHub.Folktails.blueprint.json @@ -0,0 +1,298 @@ +{ + "BuildingSpec": { + "SelectionSoundName": "Automation", + "LoopingSoundName": "", + "BuildingCost": [ + { + "Id": "Plank", + "Amount": 5 + }, + { + "Id": "Gear", + "Amount": 5 + } + ], + "ScienceCost": 300, + "PlaceFinished": false, + "FinishableWithBeaversOnSite": false, + "DrawRangeBoundsOnIt": false + }, + "TemplateSpec": { + "TemplateName": "RelayHub.Folktails", + "BackwardCompatibleTemplateNames": [], + "RequiredFeatureToggle": "", + "DisablingFeatureToggle": "" + }, + "NamedEntitySpec": { + "IsEditable": true + }, + "BuildingModelSpec": { + "FinishedModelName": "#Finished", + "UnfinishedModelName": "#Unfinished", + "FinishedUncoveredModelName": "", + "UndergroundModelName": "", + "ConstructionModeModel": "Finished", + "UndergroundModelDepth": 0 + }, + "BlockObjectSpec": { + "Size": { + "X": 3, + "Y": 3, + "Z": 2 + }, + "Blocks": [ + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom, Top, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom, Top, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom, Top, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom, Top, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom, Top, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom, Top, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom, Top, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom, Top, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom, Top, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "Any", + "Occupations": "Floor, Bottom, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "Any", + "Occupations": "Floor, Bottom, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "Any", + "Occupations": "Floor, Bottom, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "Any", + "Occupations": "Floor, Bottom, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "Any", + "Occupations": "Floor, Bottom, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "Any", + "Occupations": "Floor, Bottom, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "Any", + "Occupations": "Floor, Bottom, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "Any", + "Occupations": "Floor, Bottom, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + }, + { + "MatterBelow": "Any", + "Occupations": "Floor, Bottom, Path, Middle", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + } + ], + "Entrance": { + "HasEntrance": false, + "Coordinates": { + "X": 0, + "Y": 0, + "Z": 0 + } + }, + "BaseZ": 0, + "Overridable": false, + "Flippable": false + }, + "PlaceableBlockObjectSpec": { + "ToolGroupId": "Automation", + "ToolOrder": 15, + "ToolShape": "Square", + "Layout": "Single", + "CustomPivot": { + "HasCustomPivot": false, + "Coordinates": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0 + } + }, + "CanBeAttachedToTerrainSide": false, + "DevModeTool": false + }, + "LabeledEntitySpec": { + "DisplayNameLocKey": "LV.AA.RelayHub.Name", + "DescriptionLocKey": "LV.AA.RelayHub.Desc", + "FlavorDescriptionLocKey": "", + "Icon": "Buildings/Automation/RelayHub/RelayHubIcon" + }, + "ConstructionSiteProgressVisualizerSpec": { + "ProgressThresholds": [ + 0.0 + ] + }, + "RelayHubSpec": {}, + "CustomizableIlluminatorSpec": {}, + "Children": { + "#Finished": { + "Children": { + "#Actual": { + + }, + "#Template": { + "TimbermeshSpec": { + "Model": "Buildings/Automation/Relay/Relay.Folktails.Model" + }, + "CollidersSpec": { + "BoxColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.0439901724, + "Z": 0.5 + }, + "Size": { + "X": 0.8103639, + "Y": 0.09253374, + "Z": 0.805315733 + } + }, + { + "Center": { + "X": 0.5, + "Y": 0.872119546, + "Z": 0.498978674 + }, + "Size": { + "X": 0.365354538, + "Y": 1.55569243, + "Z": 0.356008559 + } + } + ], + "SphereColliders": [], + "CapsuleColliders": [] + } + } + } + }, + "#Unfinished": { + "Children": { + "ConstructionBase1x1#nested": { + "BlueprintPath": "ConstructionBases/ConstructionBase3x3/ConstructionBase3x3.blueprint" + }, + "ConstructionStage0": { + "TimbermeshSpec": { + "Model": "Buildings/Automation/Relay/Relay.Folktails.ConstructionStage0.Model" + }, + "CollidersSpec": { + "BoxColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.05, + "Z": 0.5 + }, + "Size": { + "X": 0.807948053, + "Y": 0.1, + "Z": 0.807948351 + } + }, + { + "Center": { + "X": 0.501479864, + "Y": 0.633312, + "Z": 0.505613565 + }, + "Size": { + "X": 0.1750803, + "Y": 1.08803964, + "Z": 0.169145823 + } + } + ], + "SphereColliders": [], + "CapsuleColliders": [] + } + } + } + } + } +} \ No newline at end of file diff --git a/AutomationArrays/Root/Buildings/Automation/RelayHub/RelayHubIcon.png b/AutomationArrays/Root/Buildings/Automation/RelayHub/RelayHubIcon.png new file mode 100644 index 00000000..01f8a06d Binary files /dev/null and b/AutomationArrays/Root/Buildings/Automation/RelayHub/RelayHubIcon.png differ diff --git a/AutomationArrays/Services/RelayHubEvaluator.cs b/AutomationArrays/Services/RelayHubEvaluator.cs new file mode 100644 index 00000000..0311cae5 --- /dev/null +++ b/AutomationArrays/Services/RelayHubEvaluator.cs @@ -0,0 +1,291 @@ +namespace AutomationArrays.Services; + +public static class RelayHubEvaluator +{ + + public static bool Evaluate(RelayHub hub, List reuseInput, List arrayOutput) + { + GatherInputs(hub, reuseInput); + EvaluateArrayMode(hub, reuseInput, arrayOutput); + var singleResult = EvaluateSingleMode(hub, reuseInput); + + reuseInput.Clear(); + + return singleResult; + } + + static void GatherInputs(RelayHub hub, List inputs) + { + inputs.Clear(); + + foreach (var conn in hub.Connections) + { + if (conn.State == ConnectionState.Disconnected) + { + inputs.Add(false); + continue; + } + + var trans = conn.Transmitter; + + if (trans.IsArrayTransmitter(out var arrTrans)) + { + inputs.AddRange(arrTrans.States); + } + else + { + inputs.Add(conn.BooleanState); + } + } + } + + static bool EvaluateSingleMode(RelayHub hub, List input) + { + var len = input.Count; + var notMode = hub.SingleModeNot; + if (len == 0) { return notMode; } + + var result = EvaluateWithoutNot(); + return notMode ? !result : result; + + bool EvaluateWithoutNot() + { + var parameters = hub.SingleParameters; + var mode = hub.SingleMode; + + switch (mode) + { + case RelayHubSingleMode.And: + for (int i = 0; i < len; i++) + { + if (!input[i]) + { + return false; + } + } + return true; + case RelayHubSingleMode.Or: + for (int i = 0; i < len; i++) + { + if (input[i]) + { + return true; + } + } + return false; + case RelayHubSingleMode.Index: + var index = parameters[0]; + return index >= 0 && index < len && input[index]; + default: // Compare modes, MSB = index 0 + var firstBit = GetFirstDifferentBit(); + var eq = firstBit == null; + var a = firstBit?.Item1 ?? default; + + return mode switch + { + RelayHubSingleMode.Eq => eq, + RelayHubSingleMode.Gt => !eq && a, + RelayHubSingleMode.Gte => eq || a, + RelayHubSingleMode.Lt => !eq && !a, + RelayHubSingleMode.Lte => eq || !a, + _ => throw mode.ThrowInvalid(), + }; + } + + (bool, bool)? GetFirstDifferentBit() // Assume working on two unsigned bytes, split and pad if odd: [a0, a1, a2, b0, b1, 0] + { + var mid = (len + 1) / 2; + for (int i = mid - 1; i >= 0; i--) + { + var a = input[i]; + var b = mid + i < len && input[mid + i]; + + if (a != b) { return (a, b); } + } + + return null; + } + } + } + + static void EvaluateArrayMode(RelayHub hub, List input, List arrayOutput) + { + var parameters = hub.ArrayParameters; + var mode = hub.ArrayMode; + var inputLen = input.Count; + + EnsureOutputLength(inputLen, mode, parameters, arrayOutput); + var outputLen = arrayOutput.Count; + + switch (mode) + { + case RelayHubArrayMode.Passthrough: + FillExact(); + break; + case RelayHubArrayMode.Reverse: + for (int i = 0; i < inputLen; i++) + { + arrayOutput[i] = input[inputLen - 1 - i]; + } + break; + case RelayHubArrayMode.Repeat: + var index = 0; + var repeatCount = parameters[0]; + for (int i = 0; i < repeatCount; i++) + { + for (int j = 0; j < inputLen; j++) + { + arrayOutput[index++] = input[j]; + } + } + break; + case RelayHubArrayMode.Slice: + var from = Math.Max(0, parameters[0]); + var to = Math.Min(from + parameters[1], inputLen); + + for (int i = from; i < to; i++) + { + arrayOutput[i - from] = input[i]; + } + + if (to - from < outputLen) + { + for (int i = Math.Max(0, to - from); i < outputLen; i++) + { + arrayOutput[i] = false; + } + } + + break; + case RelayHubArrayMode.Shift: + var shiftAmount = parameters[1]; + if (shiftAmount == 0) + { + FillExact(); + } + else if (shiftAmount >= inputLen) + { + FillEmpty(); + } + else + { + var direction = parameters[0] == 0 ? 1 : -1; // 0 for left, 1 for right + for (int i = 0; i < outputLen; i++) + { + var fromIndex = i + direction * shiftAmount; + arrayOutput[i] = fromIndex >= 0 && fromIndex < inputLen && input[fromIndex]; + } + } + + break; + case RelayHubArrayMode.And: + SplitAndFill((a, b) => a && b); + break; + case RelayHubArrayMode.Or: + SplitAndFill((a, b) => a || b); + break; + case RelayHubArrayMode.Xor: + SplitAndFill((a, b) => a ^ b); + break; + default: + throw hub.ArrayMode.ThrowInvalid(); + } + + if (hub.ArrayModeNot) + { + for (int i = 0; i < outputLen; i++) + { + arrayOutput[i] = !arrayOutput[i]; + } + } + + // Split at middle and pad zero if non-even ([a0, a1, a2, b0, b1, 0]) + void SplitAndFill(Func operation) + { + var mid = (inputLen + 1) / 2; + for (int i = 0; i < mid; i++) + { + var a = input[i]; + var b = mid + i < inputLen && input[mid + i]; + arrayOutput[i] = operation(a, b); + } + } + + void FillExact() + { + for (int i = 0; i < outputLen; i++) + { + arrayOutput[i] = input[i]; + } + } + + void FillEmpty() + { + for (int i = 0; i < outputLen; i++) + { + arrayOutput[i] = false; + } + } + } + + static void EnsureOutputLength(int inputLength, RelayHubArrayMode mode, int[] parameters, List arrayOutput) + { + var expectingLength = GetArrayOutputLength(inputLength, mode, parameters); + if (arrayOutput.Count != expectingLength) + { + if (arrayOutput.Count > expectingLength) + { + arrayOutput.RemoveRange(expectingLength, arrayOutput.Count - expectingLength); + } + else + { + arrayOutput.Capacity = expectingLength; + var adding = expectingLength - arrayOutput.Count; + for (int i = 0; i < adding; i++) + { + arrayOutput.Add(default); + } + } + } + } + + static int GetArrayOutputLength(int inputLength, RelayHubArrayMode mode, int[] parameters) => mode switch + { + RelayHubArrayMode.Passthrough or + RelayHubArrayMode.Reverse or + RelayHubArrayMode.Shift => inputLength, + RelayHubArrayMode.Repeat => inputLength * parameters[0], + RelayHubArrayMode.Slice => parameters[1], + RelayHubArrayMode.And or + RelayHubArrayMode.Or or + RelayHubArrayMode.Xor => (inputLength + 1) / 2, + _ => throw mode.ThrowInvalid(), + }; + + public static string[] GetParameters(RelayHubSingleMode mode) => mode switch + { + RelayHubSingleMode.Index => ["LV.AA.RelayHub.Parameter.Index"], + RelayHubSingleMode.And or + RelayHubSingleMode.Or or + RelayHubSingleMode.Eq or + RelayHubSingleMode.Gt or + RelayHubSingleMode.Gte or + RelayHubSingleMode.Lt or + RelayHubSingleMode.Lte => [], + _ => throw mode.ThrowInvalid(), + }; + + public static string[] GetParameters(RelayHubArrayMode mode) => mode switch + { + RelayHubArrayMode.Slice => ["LV.AA.RelayHub.Parameter.Start", "LV.AA.RelayHub.Parameter.Length"], + RelayHubArrayMode.Shift => ["LV.AA.RelayHub.Parameter.ShiftDirection", "LV.AA.RelayHub.Parameter.ShiftAmount"], + RelayHubArrayMode.Repeat => ["LV.AA.RelayHub.Parameter.RepeatCount"], + RelayHubArrayMode.And or + RelayHubArrayMode.Or or + RelayHubArrayMode.Xor or + RelayHubArrayMode.Passthrough or + RelayHubArrayMode.Reverse => [], + _ => throw mode.ThrowInvalid(), + }; + +} diff --git a/AutomationArrays/Specs/RelayHubSpec.cs b/AutomationArrays/Specs/RelayHubSpec.cs new file mode 100644 index 00000000..60577bb0 --- /dev/null +++ b/AutomationArrays/Specs/RelayHubSpec.cs @@ -0,0 +1,3 @@ +namespace AutomationArrays.Specs; + +public record RelayHubSpec : ComponentSpec; diff --git a/AutomationArrays/ZGlobalUsings.cs b/AutomationArrays/ZGlobalUsings.cs new file mode 100644 index 00000000..5e1e508c --- /dev/null +++ b/AutomationArrays/ZGlobalUsings.cs @@ -0,0 +1,4 @@ +global using AutomationArrays.Components; +global using AutomationArrays.Specs; +global using AutomationArrays.Services; +global using AutomationArrays.Helpers; \ No newline at end of file diff --git a/AutomationArrays/manifest.json b/AutomationArrays/manifest.json new file mode 100644 index 00000000..3f7ec9c9 --- /dev/null +++ b/AutomationArrays/manifest.json @@ -0,0 +1,10 @@ +{ + "Name": "Automation Arrays", + "Version": "10.0.0", + "Id": "AutomationArrays", + "MinimumGameVersion": "1.0.0", + "Description": "", + "RequiredMods": [ + { "Id": "ModdableTimberborn" } + ] +} \ No newline at end of file diff --git a/AutomationGraph/AutomationGraph.csproj b/AutomationGraph/AutomationGraph.csproj new file mode 100644 index 00000000..b4b43f4c --- /dev/null +++ b/AutomationGraph/AutomationGraph.csproj @@ -0,0 +1,8 @@ + + + + netstandard2.1 + enable + + + diff --git a/BathBombs/BathBombs.csproj b/BathBombs/BathBombs.csproj new file mode 100644 index 00000000..10f17979 --- /dev/null +++ b/BathBombs/BathBombs.csproj @@ -0,0 +1,7 @@ + + + BathBombs + + + + \ No newline at end of file diff --git a/BathBombs/Components/BathBombComponent.cs b/BathBombs/Components/BathBombComponent.cs new file mode 100644 index 00000000..aef3cf6f --- /dev/null +++ b/BathBombs/Components/BathBombComponent.cs @@ -0,0 +1,74 @@ +namespace BathBombs.Components; + +public readonly record struct BathBombWater(float Amount, bool Contaminated); + +public class BathBombComponent(BathBombService service) : TickableComponent, IAwakableComponent, IPersistentEntity, IEntityDescriber +{ + static readonly ComponentKey SaveKey = new(nameof(BathBombComponent)); + static readonly PropertyKey TicksToDetonationKey = new("TicksToDetonation"); + +#nullable disable + public BathBombSpec spec; +#nullable enable + + public BathBombWater Water => new(spec.Amount, spec.Contaminated); + public Vector3Int Coordinates => GetComponent().Coordinates; + public string ExplosionPrefabPath => spec.ExplosionPrefabPath; + + int ticksToDetonation = -1; + public bool Triggered => Enabled && ticksToDetonation >= 0; + + public void Awake() + { + spec = GetComponent(); + + if (ticksToDetonation < 0) + { + DisableComponent(); + } + } + + public void Trigger() + { + ticksToDetonation = spec.DetonationTicks; + EnableComponent(); + } + + void Detonate() + { + service.Detonate(this); + } + + public void Load(IEntityLoader entityLoader) + { + if (!entityLoader.TryGetComponent(SaveKey, out var s)) { return; } + + if (s.Has(TicksToDetonationKey)) + { + ticksToDetonation = s.Get(TicksToDetonationKey); + } + } + + public void Save(IEntitySaver entitySaver) + { + if (ticksToDetonation < 0) { return; } + + var s = entitySaver.GetComponent(SaveKey); + s.Set(TicksToDetonationKey, ticksToDetonation); + } + + public override void Tick() + { + ticksToDetonation--; + + if (ticksToDetonation <= 0) + { + DisableComponent(); + Detonate(); + } + } + + public IEnumerable DescribeEntity() => [ + EntityDescription.CreateTextSection(service.GetDescription(spec.Amount), 100), + ]; +} diff --git a/BathBombs/Components/BathBombIndicator.cs b/BathBombs/Components/BathBombIndicator.cs new file mode 100644 index 00000000..27abe8e6 --- /dev/null +++ b/BathBombs/Components/BathBombIndicator.cs @@ -0,0 +1,23 @@ +namespace BathBombs.Components; + +public class BathBombIndicator : BaseComponent, IAwakableComponent +{ + static readonly Vector3 LocalPosition = new(.5f, .01f, .5f); + static readonly Vector3 LocalScale = new(.7f, .7f, 1); + + public void Awake() + { + var icon = GetComponent().Icon.Asset; + + var go = new GameObject("BathBombIndicator"); + var t = go.transform; + t.parent = Transform; + t.Rotate(Vector3.right, 90); + t.localScale = LocalScale; + t.localPosition = LocalPosition; + + var renderer = go.AddComponent(); + renderer.sprite = icon; + } + +} diff --git a/BathBombs/Components/BathBombSpec.cs b/BathBombs/Components/BathBombSpec.cs new file mode 100644 index 00000000..9bc047ed --- /dev/null +++ b/BathBombs/Components/BathBombSpec.cs @@ -0,0 +1,17 @@ +namespace BathBombs.Components; + +public record BathBombSpec : ComponentSpec +{ + + [Serialize] + public float Amount { get; init; } + + [Serialize] + public bool Contaminated { get; init; } + + [Serialize] + public int DetonationTicks { get; init; } + + [Serialize] + public string ExplosionPrefabPath { get; init; } = null!; +} diff --git a/BathBombs/Localizations/enUS.csv b/BathBombs/Localizations/enUS.csv new file mode 100644 index 00000000..2b27f648 --- /dev/null +++ b/BathBombs/Localizations/enUS.csv @@ -0,0 +1,13 @@ +ID,Text,Comment +LV.BBb.BathBomb.GoodName,"Bath Bomb", +LV.BBb.BathBomb.GoodNamePlural,"Bath Bombs", +LV.BBb.BathBomb.Name,"Bath Bomb", +LV.BBb.BathBomb.Description,"A dynamite that releases a burst of water when it explodes. Does not affect terrain or beavers.", +LV.BBb.BathBomb.Flavor,"Inspired by the name recovered from a hooman \"bathroom manual\". Apparently explosions were part of proper hygiene.", +LV.BBb.DirtyBathBomb.GoodName,"Dirty Bath Bomb", +LV.BBb.DirtyBathBomb.GoodNamePlural,"Dirty Bath Bombs", +LV.BBb.DirtyBathBomb.Name,"Dirty Bath Bomb", +LV.BBb.DirtyBathBomb.Description,"A dynamite that releases a burst of badwater when it explodes. Does not affect terrain or beavers.", +LV.BBb.DirtyBathBomb.Flavor,"In the same manual, apparently this explosive discharge is sure to follow after the use of an interesting artifact called taco.", +LV.BBb.BurstAmount,"Burst Amount: {0:0.#}m³", +Name_BathBombFragment,"[DO_NOT_COLLAPSE]", \ No newline at end of file diff --git a/BathBombs/MConfigs.cs b/BathBombs/MConfigs.cs new file mode 100644 index 00000000..727ad8b2 --- /dev/null +++ b/BathBombs/MConfigs.cs @@ -0,0 +1,40 @@ +global using BathBombs.Components; +global using BathBombs.Services; +global using BathBombs.UI; + +namespace BathBombs; + +[Context("Game")] +public class MGameConfig : Configurator +{ + + public override void Configure() + { + Bind().AsSingleton(); + Bind().AsSingleton(); + + Bind().AsTransient(); + Bind().AsTransient(); + + MultiBind().ToProvider(() => + { + var b = new TemplateModule.Builder(); + b.AddDecorator(); + b.AddDecorator(); + return b.Build(); + }).AsSingleton(); + + MultiBind().ToProvider().AsSingleton(); + } + + class FragmentProvider(BathBombFragment f) : IProvider + { + public EntityPanelModule Get() + { + var b = new EntityPanelModule.Builder(); + b.AddTopFragment(f); + return b.Build(); + } + } + +} diff --git a/BathBombs/ModDesc.txt b/BathBombs/ModDesc.txt new file mode 100644 index 00000000..da994bcd --- /dev/null +++ b/BathBombs/ModDesc.txt @@ -0,0 +1,36 @@ +You're gonna have a splash. The beavers have just recovered a hooman's genius invention: Bath bombs! This mod adds two new buildings: Bath Bomb and Dirty Bath Bomb that release a burst of water on detonation. + +[h1]New buildings[/h1] +[h2]Bath Bombs[/h2] +A dynamite that releases a burst of water when it explodes. Does not affect terrain or beavers. +[i]Inspired by the name recovered from a hooman "bathroom manual". Apparently explosions were part of proper hygiene.[/i] +Need 2 Bath Bombs items to build, 600 Science to unlock. + +[img]https://files.catbox.moe/p1i62b.jpg[/img] + +[h2]Dirty Bath Bombs[/h2] +A dynamite that releases a burst of badwater when it explodes. Does not affect terrain or beavers. +[i]In the same manual, apparently this explosive discharge is sure to follow after the use of an interesting artifact called taco.[/i] +Need 2 Dirty Bath Bombs items to build, 600 Science to unlock. + +[h2]Note and Effects[/h2] +Both buildings are located in the Water group, near the end of the category. + +[img]https://files.catbox.moe/cispyy.jpg[/img] + +On detonation, each bath bomb releases a burst of [b]2m³[/b] of water or badwater (the same amount of liquid used to build them). + +Unlike Dynamites, these explosives do not affect terrain or beavers. They do trigger neighboring bath bombs, including the other type. However, they won't trigger Dynamite or be triggered by it. Since terrain is unaffected, placement of bath bombs is more flexible, you can place them almost anywhere. + +[h1]New items[/h1] +To build the new buildings, you need to craft Bath Bomb and Dirty Bath Bomb items. +- Crafted in the Explosives Factory. +- Same base cost as the Dynamite (5 Badwater), plus 5 Water for Bath Bomb or 5 Badwater for Dirty Bath Bomb (that is, 1m³ of water or badwater). +- Take 5 hours to craft one. +- Weigh 11kg (same as Dynamite 1kg + 10kg of liquid). +Fun fact: 1m³ of water weighs 1000kg in real life. The correct unit for a game tile would actually be closer to 1L (dm³). + +[img]https://files.catbox.moe/nry5n9.jpg[/img] + +=== +Mod source code and donation: https://github.com/datvm/TimberbornMods (feel free to use the code for anything). \ No newline at end of file diff --git a/BathBombs/Root/Blueprints/Buildings/Water/BathBomb/BathBomb.Folktails.blueprint.json b/BathBombs/Root/Blueprints/Buildings/Water/BathBomb/BathBomb.Folktails.blueprint.json new file mode 100644 index 00000000..c94db5ed --- /dev/null +++ b/BathBombs/Root/Blueprints/Buildings/Water/BathBomb/BathBomb.Folktails.blueprint.json @@ -0,0 +1,151 @@ +{ + "BuildingSpec": { + "SelectionSoundName": "Dynamite", + "LoopingSoundName": "", + "BuildingCost": [ + { + "Id": "BathBomb", + "Amount": 2 + } + ], + "ScienceCost": 600, + "PlaceFinished": false, + "FinishableWithBeaversOnSite": true, + "DrawRangeBoundsOnIt": true + }, + "BuildingModelSpec": { + "FinishedModelName": "#Finished", + "UnfinishedModelName": "#Unfinished", + "FinishedUncoveredModelName": "", + "UndergroundModelName": "#Underground", + "ConstructionModeModel": "Finished", + "UndergroundModelDepth": 1 + }, + "TemplateSpec": { + "TemplateName": "BathBomb.Folktails", + "BackwardCompatibleTemplateNames": [], + "RequiredFeatureToggle": "", + "DisablingFeatureToggle": "" + }, + "BlockObjectSpec": { + "Size": { + "X": 1, + "Y": 1, + "Z": 1 + }, + "Blocks": [ + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + } + ], + "Entrance": { + "HasEntrance": false, + "Coordinates": { + "X": 0, + "Y": 0, + "Z": 0 + } + }, + "BaseZ": 0, + "Overridable": false, + "Flippable": false + }, + "BlockObjectNavMeshSettingsSpec": { + "NoAutoWalls": true, + "GenerateFloorsOnStackable": false, + "EdgeGroups": [], + "UnblockedCoordinates": [], + "BlockedEdges": [] + }, + "PlaceableBlockObjectSpec": { + "ToolGroupId": "Water", + "ToolOrder": 110, + "ToolShape": "Square", + "Layout": "Rectangle", + "CustomPivot": { + "HasCustomPivot": false, + "Coordinates": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0 + } + }, + "CanBeAttachedToTerrainSide": false, + "DevModeTool": false + }, + "BathBombSpec": { + "Amount": 2, + "Contaminated": false, + "DetonationTicks": 2, + "ExplosionPrefabPath": "Buildings/Landscaping/Dynamite/DynamiteExplosion" + }, + "LabeledEntitySpec": { + "DisplayNameLocKey": "LV.BBb.BathBomb.Name", + "DescriptionLocKey": "LV.BBb.BathBomb.Description", + "FlavorDescriptionLocKey": "LV.BBb.BathBomb.Flavor", + "Icon": "Blueprints/Buildings/Water/BathBomb/BathBombIcon" + }, + "ConstructionSiteProgressVisualizerSpec": { + "ProgressThresholds": [ + 0.0 + ] + }, + "Children": { + "#Finished": { + "TimbermeshSpec": { + "Model": "Buildings/Landscaping/Dynamite/Dynamite.Folktails.Model" + }, + "CollidersSpec": { + "BoxColliders": [], + "SphereColliders": [], + "CapsuleColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.15, + "Z": 0.5 + }, + "Radius": 0.2, + "Height": 0.61, + "Axis": "Y" + } + ] + } + }, + "#Unfinished": { + "Children": { + "ConstructionBase1x1Dynamite#nested": { + "BlueprintPath": "ConstructionBases/ConstructionBase1x1Dynamite/ConstructionBase1x1Dynamite.blueprint" + }, + "ConstructionStage0": { + "TimbermeshSpec": { + "Model": "Buildings/Landscaping/Dynamite/Dynamite.Folktails.ConstructionStage0.Model" + }, + "CollidersSpec": { + "BoxColliders": [], + "SphereColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.07, + "Z": 0.5 + }, + "Radius": 0.32 + } + ], + "CapsuleColliders": [] + } + } + } + }, + "#Underground": { + "TimbermeshSpec": { + "Model": "Buildings/Landscaping/Dynamite/Dynamite.Underground" + } + } + } +} \ No newline at end of file diff --git a/BathBombs/Root/Blueprints/Buildings/Water/BathBomb/BathBomb.IronTeeth.blueprint.json b/BathBombs/Root/Blueprints/Buildings/Water/BathBomb/BathBomb.IronTeeth.blueprint.json new file mode 100644 index 00000000..2da4f4c2 --- /dev/null +++ b/BathBombs/Root/Blueprints/Buildings/Water/BathBomb/BathBomb.IronTeeth.blueprint.json @@ -0,0 +1,151 @@ +{ + "BuildingSpec": { + "SelectionSoundName": "Dynamite", + "LoopingSoundName": "", + "BuildingCost": [ + { + "Id": "BathBomb", + "Amount": 2 + } + ], + "ScienceCost": 600, + "PlaceFinished": false, + "FinishableWithBeaversOnSite": true, + "DrawRangeBoundsOnIt": true + }, + "BuildingModelSpec": { + "FinishedModelName": "#Finished", + "UnfinishedModelName": "#Unfinished", + "FinishedUncoveredModelName": "", + "UndergroundModelName": "#Underground", + "ConstructionModeModel": "Finished", + "UndergroundModelDepth": 1 + }, + "TemplateSpec": { + "TemplateName": "BathBomb.IronTeeth", + "BackwardCompatibleTemplateNames": [], + "RequiredFeatureToggle": "", + "DisablingFeatureToggle": "" + }, + "BlockObjectSpec": { + "Size": { + "X": 1, + "Y": 1, + "Z": 1 + }, + "Blocks": [ + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + } + ], + "Entrance": { + "HasEntrance": false, + "Coordinates": { + "X": 0, + "Y": 0, + "Z": 0 + } + }, + "BaseZ": 0, + "Overridable": false, + "Flippable": false + }, + "BlockObjectNavMeshSettingsSpec": { + "NoAutoWalls": true, + "GenerateFloorsOnStackable": false, + "EdgeGroups": [], + "UnblockedCoordinates": [], + "BlockedEdges": [] + }, + "PlaceableBlockObjectSpec": { + "ToolGroupId": "Water", + "ToolOrder": 110, + "ToolShape": "Square", + "Layout": "Rectangle", + "CustomPivot": { + "HasCustomPivot": false, + "Coordinates": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0 + } + }, + "CanBeAttachedToTerrainSide": false, + "DevModeTool": false + }, + "BathBombSpec": { + "Amount": 2, + "Contaminated": false, + "DetonationTicks": 2, + "ExplosionPrefabPath": "Buildings/Landscaping/Dynamite/DynamiteExplosion" + }, + "LabeledEntitySpec": { + "DisplayNameLocKey": "LV.BBb.BathBomb.Name", + "DescriptionLocKey": "LV.BBb.BathBomb.Description", + "FlavorDescriptionLocKey": "LV.BBb.BathBomb.Flavor", + "Icon": "Blueprints/Buildings/Water/BathBomb/BathBombIcon" + }, + "ConstructionSiteProgressVisualizerSpec": { + "ProgressThresholds": [ + 0.0 + ] + }, + "Children": { + "#Finished": { + "TimbermeshSpec": { + "Model": "Buildings/Landscaping/Dynamite/Dynamite.IronTeeth.Model" + }, + "CollidersSpec": { + "BoxColliders": [], + "SphereColliders": [], + "CapsuleColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.15, + "Z": 0.5 + }, + "Radius": 0.2, + "Height": 0.61, + "Axis": "Y" + } + ] + } + }, + "#Unfinished": { + "Children": { + "ConstructionBase1x1Dynamite#nested": { + "BlueprintPath": "ConstructionBases/ConstructionBase1x1Dynamite/ConstructionBase1x1Dynamite.blueprint" + }, + "ConstructionStage0": { + "TimbermeshSpec": { + "Model": "Buildings/Landscaping/Dynamite/Dynamite.IronTeeth.ConstructionStage0.Model" + }, + "CollidersSpec": { + "BoxColliders": [], + "SphereColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.07, + "Z": 0.5 + }, + "Radius": 0.32 + } + ], + "CapsuleColliders": [] + } + } + } + }, + "#Underground": { + "TimbermeshSpec": { + "Model": "Buildings/Landscaping/Dynamite/Dynamite.Underground" + } + } + } +} \ No newline at end of file diff --git a/BathBombs/Root/Blueprints/Buildings/Water/BathBomb/BathBombIcon.png b/BathBombs/Root/Blueprints/Buildings/Water/BathBomb/BathBombIcon.png new file mode 100644 index 00000000..018255f2 Binary files /dev/null and b/BathBombs/Root/Blueprints/Buildings/Water/BathBomb/BathBombIcon.png differ diff --git a/BathBombs/Root/Blueprints/Buildings/Water/DirtyBathBomb/DirtyBathBomb.Folktails.blueprint.json b/BathBombs/Root/Blueprints/Buildings/Water/DirtyBathBomb/DirtyBathBomb.Folktails.blueprint.json new file mode 100644 index 00000000..4bdda395 --- /dev/null +++ b/BathBombs/Root/Blueprints/Buildings/Water/DirtyBathBomb/DirtyBathBomb.Folktails.blueprint.json @@ -0,0 +1,151 @@ +{ + "BuildingSpec": { + "SelectionSoundName": "Dynamite", + "LoopingSoundName": "", + "BuildingCost": [ + { + "Id": "DirtyBathBomb", + "Amount": 2 + } + ], + "ScienceCost": 600, + "PlaceFinished": false, + "FinishableWithBeaversOnSite": true, + "DrawRangeBoundsOnIt": true + }, + "BuildingModelSpec": { + "FinishedModelName": "#Finished", + "UnfinishedModelName": "#Unfinished", + "FinishedUncoveredModelName": "", + "UndergroundModelName": "#Underground", + "ConstructionModeModel": "Finished", + "UndergroundModelDepth": 1 + }, + "TemplateSpec": { + "TemplateName": "DirtyBathBomb.Folktails", + "BackwardCompatibleTemplateNames": [], + "RequiredFeatureToggle": "", + "DisablingFeatureToggle": "" + }, + "BlockObjectSpec": { + "Size": { + "X": 1, + "Y": 1, + "Z": 1 + }, + "Blocks": [ + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + } + ], + "Entrance": { + "HasEntrance": false, + "Coordinates": { + "X": 0, + "Y": 0, + "Z": 0 + } + }, + "BaseZ": 0, + "Overridable": false, + "Flippable": false + }, + "BlockObjectNavMeshSettingsSpec": { + "NoAutoWalls": true, + "GenerateFloorsOnStackable": false, + "EdgeGroups": [], + "UnblockedCoordinates": [], + "BlockedEdges": [] + }, + "PlaceableBlockObjectSpec": { + "ToolGroupId": "Water", + "ToolOrder": 115, + "ToolShape": "Square", + "Layout": "Rectangle", + "CustomPivot": { + "HasCustomPivot": false, + "Coordinates": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0 + } + }, + "CanBeAttachedToTerrainSide": false, + "DevModeTool": false + }, + "BathBombSpec": { + "Amount": 2, + "Contaminated": true, + "DetonationTicks": 2, + "ExplosionPrefabPath": "Buildings/Landscaping/Dynamite/DynamiteExplosion" + }, + "LabeledEntitySpec": { + "DisplayNameLocKey": "LV.BBb.DirtyBathBomb.Name", + "DescriptionLocKey": "LV.BBb.DirtyBathBomb.Description", + "FlavorDescriptionLocKey": "LV.BBb.DirtyBathBomb.Flavor", + "Icon": "Blueprints/Buildings/Water/DirtyBathBomb/DirtyBathBombIcon" + }, + "ConstructionSiteProgressVisualizerSpec": { + "ProgressThresholds": [ + 0.0 + ] + }, + "Children": { + "#Finished": { + "TimbermeshSpec": { + "Model": "Buildings/Landscaping/Dynamite/Dynamite.Folktails.Model" + }, + "CollidersSpec": { + "BoxColliders": [], + "SphereColliders": [], + "CapsuleColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.15, + "Z": 0.5 + }, + "Radius": 0.2, + "Height": 0.61, + "Axis": "Y" + } + ] + } + }, + "#Unfinished": { + "Children": { + "ConstructionBase1x1Dynamite#nested": { + "BlueprintPath": "ConstructionBases/ConstructionBase1x1Dynamite/ConstructionBase1x1Dynamite.blueprint" + }, + "ConstructionStage0": { + "TimbermeshSpec": { + "Model": "Buildings/Landscaping/Dynamite/Dynamite.Folktails.ConstructionStage0.Model" + }, + "CollidersSpec": { + "BoxColliders": [], + "SphereColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.07, + "Z": 0.5 + }, + "Radius": 0.32 + } + ], + "CapsuleColliders": [] + } + } + } + }, + "#Underground": { + "TimbermeshSpec": { + "Model": "Buildings/Landscaping/Dynamite/Dynamite.Underground" + } + } + } +} \ No newline at end of file diff --git a/BathBombs/Root/Blueprints/Buildings/Water/DirtyBathBomb/DirtyBathBomb.IronTeeth.blueprint.json b/BathBombs/Root/Blueprints/Buildings/Water/DirtyBathBomb/DirtyBathBomb.IronTeeth.blueprint.json new file mode 100644 index 00000000..ca47e1eb --- /dev/null +++ b/BathBombs/Root/Blueprints/Buildings/Water/DirtyBathBomb/DirtyBathBomb.IronTeeth.blueprint.json @@ -0,0 +1,151 @@ +{ + "BuildingSpec": { + "SelectionSoundName": "Dynamite", + "LoopingSoundName": "", + "BuildingCost": [ + { + "Id": "DirtyBathBomb", + "Amount": 2 + } + ], + "ScienceCost": 600, + "PlaceFinished": false, + "FinishableWithBeaversOnSite": true, + "DrawRangeBoundsOnIt": true + }, + "BuildingModelSpec": { + "FinishedModelName": "#Finished", + "UnfinishedModelName": "#Unfinished", + "FinishedUncoveredModelName": "", + "UndergroundModelName": "#Underground", + "ConstructionModeModel": "Finished", + "UndergroundModelDepth": 1 + }, + "TemplateSpec": { + "TemplateName": "DirtyBathBomb.IronTeeth", + "BackwardCompatibleTemplateNames": [], + "RequiredFeatureToggle": "", + "DisablingFeatureToggle": "" + }, + "BlockObjectSpec": { + "Size": { + "X": 1, + "Y": 1, + "Z": 1 + }, + "Blocks": [ + { + "MatterBelow": "GroundOrStackable", + "Occupations": "Bottom", + "Stackable": "None", + "OccupyAllBelow": false, + "Underground": false + } + ], + "Entrance": { + "HasEntrance": false, + "Coordinates": { + "X": 0, + "Y": 0, + "Z": 0 + } + }, + "BaseZ": 0, + "Overridable": false, + "Flippable": false + }, + "BlockObjectNavMeshSettingsSpec": { + "NoAutoWalls": true, + "GenerateFloorsOnStackable": false, + "EdgeGroups": [], + "UnblockedCoordinates": [], + "BlockedEdges": [] + }, + "PlaceableBlockObjectSpec": { + "ToolGroupId": "Water", + "ToolOrder": 115, + "ToolShape": "Square", + "Layout": "Rectangle", + "CustomPivot": { + "HasCustomPivot": false, + "Coordinates": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0 + } + }, + "CanBeAttachedToTerrainSide": false, + "DevModeTool": false + }, + "BathBombSpec": { + "Amount": 2, + "Contaminated": true, + "DetonationTicks": 2, + "ExplosionPrefabPath": "Buildings/Landscaping/Dynamite/DynamiteExplosion" + }, + "LabeledEntitySpec": { + "DisplayNameLocKey": "LV.BBb.DirtyBathBomb.Name", + "DescriptionLocKey": "LV.BBb.DirtyBathBomb.Description", + "FlavorDescriptionLocKey": "LV.BBb.DirtyBathBomb.Flavor", + "Icon": "Blueprints/Buildings/Water/DirtyBathBomb/DirtyBathBombIcon" + }, + "ConstructionSiteProgressVisualizerSpec": { + "ProgressThresholds": [ + 0.0 + ] + }, + "Children": { + "#Finished": { + "TimbermeshSpec": { + "Model": "Buildings/Landscaping/Dynamite/Dynamite.IronTeeth.Model" + }, + "CollidersSpec": { + "BoxColliders": [], + "SphereColliders": [], + "CapsuleColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.15, + "Z": 0.5 + }, + "Radius": 0.2, + "Height": 0.61, + "Axis": "Y" + } + ] + } + }, + "#Unfinished": { + "Children": { + "ConstructionBase1x1Dynamite#nested": { + "BlueprintPath": "ConstructionBases/ConstructionBase1x1Dynamite/ConstructionBase1x1Dynamite.blueprint" + }, + "ConstructionStage0": { + "TimbermeshSpec": { + "Model": "Buildings/Landscaping/Dynamite/Dynamite.IronTeeth.ConstructionStage0.Model" + }, + "CollidersSpec": { + "BoxColliders": [], + "SphereColliders": [ + { + "Center": { + "X": 0.5, + "Y": 0.07, + "Z": 0.5 + }, + "Radius": 0.32 + } + ], + "CapsuleColliders": [] + } + } + } + }, + "#Underground": { + "TimbermeshSpec": { + "Model": "Buildings/Landscaping/Dynamite/Dynamite.Underground" + } + } + } +} \ No newline at end of file diff --git a/BathBombs/Root/Blueprints/Buildings/Water/DirtyBathBomb/DirtyBathBombIcon.png b/BathBombs/Root/Blueprints/Buildings/Water/DirtyBathBomb/DirtyBathBombIcon.png new file mode 100644 index 00000000..24673e4d Binary files /dev/null and b/BathBombs/Root/Blueprints/Buildings/Water/DirtyBathBomb/DirtyBathBombIcon.png differ diff --git a/BathBombs/Root/Blueprints/GoodCollectionSpec/BathBomb.Common.blueprint.json b/BathBombs/Root/Blueprints/GoodCollectionSpec/BathBomb.Common.blueprint.json new file mode 100644 index 00000000..856bf09e --- /dev/null +++ b/BathBombs/Root/Blueprints/GoodCollectionSpec/BathBomb.Common.blueprint.json @@ -0,0 +1,9 @@ +{ + "GoodCollectionSpec": { + "CollectionId": "Common", + "Goods": [ + "BathBomb", + "DirtyBathBomb" + ] + } +} \ No newline at end of file diff --git a/BathBombs/Root/Blueprints/GoodSpecs/BathBomb.blueprint.json b/BathBombs/Root/Blueprints/GoodSpecs/BathBomb.blueprint.json new file mode 100644 index 00000000..bb074fce --- /dev/null +++ b/BathBombs/Root/Blueprints/GoodSpecs/BathBomb.blueprint.json @@ -0,0 +1,25 @@ +{ + "GoodSpec": { + "Id": "BathBomb", + "BackwardCompatibleIds": [], + "ConsumptionEffects": [], + "GoodType": "Box", + "StockpileVisualization": "Box", + "VisibleContainer": "Box", + "ContainerColor": { + "r": 0.6509804, + "g": 0.0627451, + "b": 0.105882354, + "a": 1.0 + }, + "ContainerMaterial": "", + "CarryingAnimation": "CarryInHands", + "Weight": 11, + "GoodGroupId": "Materials", + "GoodOrder": 4010, + "Icon": "Sprites/Goods/BathBombIcon", + "ForceImport": false, + "DisplayNameLocKey": "LV.BBb.BathBomb.GoodName", + "PluralDisplayNameLocKey": "LV.BBb.BathBomb.GoodNamePlural" + } +} \ No newline at end of file diff --git a/BathBombs/Root/Blueprints/GoodSpecs/DirtyBathBomb.blueprint.json b/BathBombs/Root/Blueprints/GoodSpecs/DirtyBathBomb.blueprint.json new file mode 100644 index 00000000..928db32c --- /dev/null +++ b/BathBombs/Root/Blueprints/GoodSpecs/DirtyBathBomb.blueprint.json @@ -0,0 +1,25 @@ +{ + "GoodSpec": { + "Id": "DirtyBathBomb", + "BackwardCompatibleIds": [], + "ConsumptionEffects": [], + "GoodType": "Box", + "StockpileVisualization": "Box", + "VisibleContainer": "Box", + "ContainerColor": { + "r": 0.6509804, + "g": 0.0627451, + "b": 0.105882354, + "a": 1.0 + }, + "ContainerMaterial": "", + "CarryingAnimation": "CarryInHands", + "Weight": 11, + "GoodGroupId": "Materials", + "GoodOrder": 4020, + "Icon": "Sprites/Goods/DirtyBathBombIcon", + "ForceImport": false, + "DisplayNameLocKey": "LV.BBb.DirtyBathBomb.GoodName", + "PluralDisplayNameLocKey": "LV.BBb.DirtyBathBomb.GoodNamePlural" + } +} \ No newline at end of file diff --git a/BathBombs/Root/Blueprints/RecipeSpecs/BathBomb.blueprint.json b/BathBombs/Root/Blueprints/RecipeSpecs/BathBomb.blueprint.json new file mode 100644 index 00000000..112d12c5 --- /dev/null +++ b/BathBombs/Root/Blueprints/RecipeSpecs/BathBomb.blueprint.json @@ -0,0 +1,30 @@ +{ + "RecipeSpec": { + "Id": "BathBomb", + "BackwardCompatibleIds": [], + "DisplayLocKey": "LV.BBb.BathBomb.GoodNamePlural", + "CycleDurationInHours": 5.0, + "Ingredients": [ + { + "Id": "Badwater", + "Amount": 5 + }, + { + "Id": "Water", + "Amount": 5 + } + ], + "Products": [ + { + "Id": "BathBomb", + "Amount": 1 + } + ], + "ProducedSciencePoints": 0, + "Fuel": "", + "CyclesFuelLasts": 0, + "FuelCapacity": 0, + "CyclesCapacity": 5, + "Icon": "Sprites/Goods/BathBombIcon" + } +} \ No newline at end of file diff --git a/BathBombs/Root/Blueprints/RecipeSpecs/DirtyBathBomb.blueprint.json b/BathBombs/Root/Blueprints/RecipeSpecs/DirtyBathBomb.blueprint.json new file mode 100644 index 00000000..daa9cdb2 --- /dev/null +++ b/BathBombs/Root/Blueprints/RecipeSpecs/DirtyBathBomb.blueprint.json @@ -0,0 +1,26 @@ +{ + "RecipeSpec": { + "Id": "DirtyBathBomb", + "BackwardCompatibleIds": [], + "DisplayLocKey": "LV.BBb.DirtyBathBomb.GoodNamePlural", + "CycleDurationInHours": 5.0, + "Ingredients": [ + { + "Id": "Badwater", + "Amount": 10 + } + ], + "Products": [ + { + "Id": "DirtyBathBomb", + "Amount": 1 + } + ], + "ProducedSciencePoints": 0, + "Fuel": "", + "CyclesFuelLasts": 0, + "FuelCapacity": 0, + "CyclesCapacity": 5, + "Icon": "Sprites/Goods/DirtyBathBombIcon" + } +} \ No newline at end of file diff --git a/BathBombs/Root/Blueprints/TemplateCollectionSpecs/BathBomb.Buildings.Folktails.blueprint.json b/BathBombs/Root/Blueprints/TemplateCollectionSpecs/BathBomb.Buildings.Folktails.blueprint.json new file mode 100644 index 00000000..ea83e868 --- /dev/null +++ b/BathBombs/Root/Blueprints/TemplateCollectionSpecs/BathBomb.Buildings.Folktails.blueprint.json @@ -0,0 +1,9 @@ +{ + "TemplateCollectionSpec": { + "CollectionId": "Buildings.Folktails", + "Blueprints": [ + "Blueprints/Buildings/Water/BathBomb/BathBomb.Folktails.blueprint", + "Blueprints/Buildings/Water/DirtyBathBomb/DirtyBathBomb.Folktails.blueprint" + ] + } +} \ No newline at end of file diff --git a/BathBombs/Root/Blueprints/TemplateCollectionSpecs/BathBomb.Buildings.IronTeeth.blueprint.json b/BathBombs/Root/Blueprints/TemplateCollectionSpecs/BathBomb.Buildings.IronTeeth.blueprint.json new file mode 100644 index 00000000..bc74ecfd --- /dev/null +++ b/BathBombs/Root/Blueprints/TemplateCollectionSpecs/BathBomb.Buildings.IronTeeth.blueprint.json @@ -0,0 +1,9 @@ +{ + "TemplateCollectionSpec": { + "CollectionId": "Buildings.IronTeeth", + "Blueprints": [ + "Blueprints/Buildings/Water/BathBomb/BathBomb.IronTeeth.blueprint", + "Blueprints/Buildings/Water/DirtyBathBomb/DirtyBathBomb.IronTeeth.blueprint" + ] + } +} \ No newline at end of file diff --git a/BathBombs/Root/Buildings/Landscaping/ExplosivesFactory/ExplosivesFactory.Folktails.blueprint.json b/BathBombs/Root/Buildings/Landscaping/ExplosivesFactory/ExplosivesFactory.Folktails.blueprint.json new file mode 100644 index 00000000..4f0bc9b1 --- /dev/null +++ b/BathBombs/Root/Buildings/Landscaping/ExplosivesFactory/ExplosivesFactory.Folktails.blueprint.json @@ -0,0 +1,8 @@ +{ + "ManufactorySpec": { + "ProductionRecipeIds#append": [ + "BathBomb", + "DirtyBathBomb" + ] + } +} \ No newline at end of file diff --git a/BathBombs/Root/Buildings/Landscaping/ExplosivesFactory/ExplosivesFactory.IronTeeth.blueprint.json b/BathBombs/Root/Buildings/Landscaping/ExplosivesFactory/ExplosivesFactory.IronTeeth.blueprint.json new file mode 100644 index 00000000..4f0bc9b1 --- /dev/null +++ b/BathBombs/Root/Buildings/Landscaping/ExplosivesFactory/ExplosivesFactory.IronTeeth.blueprint.json @@ -0,0 +1,8 @@ +{ + "ManufactorySpec": { + "ProductionRecipeIds#append": [ + "BathBomb", + "DirtyBathBomb" + ] + } +} \ No newline at end of file diff --git a/BathBombs/Services/BathBombService.cs b/BathBombs/Services/BathBombService.cs new file mode 100644 index 00000000..8fe0cae5 --- /dev/null +++ b/BathBombs/Services/BathBombService.cs @@ -0,0 +1,103 @@ +namespace BathBombs.Services; + +public class BathBombService( + EntityService entities, + IBlockService blocks, + IWaterService waterService, + ExplosionSoundPlayer explosionSoundPlayer, + IInstantiator instantiator, + IAssetLoader assets, + ILoc t +) : ITickableSingleton +{ + const int SoundEffectTicks = 10; + readonly LinkedList soundEffects = []; + + public string GetDescription(float amount) => t.T("LV.BBb.BurstAmount", amount); + + public void Detonate(BathBombComponent comp) + { + var coords = comp.Coordinates; + var water = comp.Water; + var prefabPath = comp.ExplosionPrefabPath; + + var effCoords = comp.GetComponent().WorldCenter; + + RemoveBathBomb(comp); + TriggerNeighbors(coords); + PlayEffect(effCoords, prefabPath); + AddWater(coords, water); + } + + void PlayEffect(Vector3 coords, string prefabPath) + { + var prefab = assets.Load(prefabPath); + var go = instantiator.Instantiate(prefab, null); + go.transform.position = coords; + + var obj = new SoundEffectObject(go); + explosionSoundPlayer.Play(go); + soundEffects.AddLast(obj); + } + + public void Tick() + { + if (soundEffects.Count == 0) { return; } + + var curr = soundEffects.First; + while (curr is not null) + { + var next = curr.Next; + + if (curr.Value.TickPassed >= SoundEffectTicks) + { + curr.Value.Remove(); + soundEffects.Remove(curr); + } + + curr = next; + } + } + + void AddWater(Vector3Int coords, BathBombWater water) + { + var (amount, contaminated) = water; + + Action addWater = contaminated ? waterService.AddContaminatedWater : waterService.AddCleanWater; + addWater(coords, amount); + } + + void RemoveBathBomb(BathBombComponent comp) + { + comp.GetComponent().DisableDeconstruction(); + entities.Delete(comp); + } + + void TriggerNeighbors(Vector3Int src) + { + foreach (var n in Deltas.Neighbors4Vector3Int) + { + var coord = src + n; + + var bo = blocks.GetFirstObjectWithComponentAt(coord); + if (bo) + { + bo.Trigger(); + } + } + } + + class SoundEffectObject(GameObject go) + { + + public GameObject GameObject { get; } = go; + public int TickPassed { get; set; } + + public void Remove() + { + UnityEngine.Object.Destroy(GameObject); + } + + } + +} diff --git a/BathBombs/Sprites/Goods/BathBombIcon.png b/BathBombs/Sprites/Goods/BathBombIcon.png new file mode 100644 index 00000000..018255f2 Binary files /dev/null and b/BathBombs/Sprites/Goods/BathBombIcon.png differ diff --git a/BathBombs/Sprites/Goods/DirtyBathBombIcon.png b/BathBombs/Sprites/Goods/DirtyBathBombIcon.png new file mode 100644 index 00000000..24673e4d Binary files /dev/null and b/BathBombs/Sprites/Goods/DirtyBathBombIcon.png differ diff --git a/BathBombs/UI/BathBombFragment.cs b/BathBombs/UI/BathBombFragment.cs new file mode 100644 index 00000000..b5c9e1a7 --- /dev/null +++ b/BathBombs/UI/BathBombFragment.cs @@ -0,0 +1,76 @@ +namespace BathBombs.UI; + +public class BathBombFragment( + VisualElementLoader visualElementLoader, + ILoc t, + InputService inputService, + ITooltipRegistrar tooltipRegistrar +) : IEntityPanelFragment, IInputProcessor +{ +#nullable disable + VisualElement panel; + Button btnDetonate; +#nullable enable + + BathBombComponent? comp; + + public void ClearFragment() + { + inputService.RemoveInputProcessor(this); + panel.ToggleDisplayStyle(false); + comp = null; + } + + public VisualElement InitializeFragment() + { + panel = visualElementLoader.LoadVisualElement("Game/EntityPanel/DynamiteFragment"); + btnDetonate = panel.Q