Custom Placement Rules
This guide covers how to author your own placement rules in Grid Building 5.0.7.
For the built-in rule catalog and runtime rule flow, see Placement Rules.
Version note: This guide is validated for Grid Building 5.0.7.
Godot 4.4 Compatibility
Grid Building 5.0.7 is intended to stay compatible with Godot 4.4 workflows.
That means custom rules should not rely on newer GDScript abstract-class syntax for enforcement. Instead, the plugin uses a 4.4-safe virtual-method contract:
PlacementRule.validate_placement()returns a failure by default.- Custom rules must override the methods they actually need.
- Tests enforce the contract for common authoring mistakes.
If you forget to override validate_placement(), the base rule fails with:
This is a virtual condition function and should be implemented in a class that inherits from PlacementRule
Choose the Right Base Class
| Base class | Use it when | Typical examples |
|---|---|---|
PlacementRule | The rule depends on owner state, inventory, economy, or gameplay services | Credit cost, tech unlocks, faction rules |
TileCheckRule | The rule depends on indicator positions, tile coverage, or per-tile validity | Bounds checks, tile data checks, collision checks |
Required Behavior
1. Override validate_placement()
This is the actual pass/fail entry point.
| |
An empty issues array means success.
2. Use get_setup_issues() only for blocking setup problems
Use this when the rule is not usable at all because required data is missing.
| |
These issues are returned from setup(...) and will fail rule setup.
3. Use get_runtime_issues() for non-blocking diagnostics
Use this for notes that are useful to inspect but should not fail setup.
| |
In 5.0.7, these messages remain available for diagnostics, but they do not get appended into setup failures.
4. For TileCheckRule, override get_failing_indicators() only when you need per-indicator precision
If you do not override it, TileCheckRule falls back to validate_placement():
- success returns no failing indicators
- failure marks all provided indicators as failing
That fallback is good enough for many custom rules. Override get_failing_indicators() only if you need some tiles red and others green.
Authoring Patterns
Simple non-tile gameplay rule
| |
Simple tile-based rule with validate-only fallback
| |
Because this extends TileCheckRule, a failed result will also make all supplied indicators invalid unless you override get_failing_indicators() with more specific logic.
Tile-based rule with explicit per-indicator failures
| |
What the Tests Enforce
The focused custom-rule suites currently lock in these behaviors:
| Situation | Expected result |
|---|---|
validate_placement() returns issues | Placement fails with those issues |
TileCheckRule fails and does not override get_failing_indicators() | All provided indicators become invalid |
get_runtime_issues() returns an informational note | The note is visible in runtime diagnostics only |
get_setup_issues() returns a message | setup(...) fails with that message |
setup_rules(...) is called with null targeting state | Setup fails with GridTargetingState is null |
This matters because it keeps setup failures, placement failures, and indicator visuals aligned instead of mixing them together.
Common Mistakes
- Not overriding
validate_placement(). - Putting placement pass/fail logic into
get_runtime_issues(). - Returning setup-breaking messages from diagnostics that should be informational only.
- Overriding
setup(...)and not callingsuper.setup(...)unless you are deliberately reproducing the base behavior yourself. - Extending
PlacementRulewhen the rule really needs tile or indicator data fromTileCheckRule.
Practical Recommendations
- Start with
validate_placement()only. - Add
get_setup_issues()only when the rule truly cannot run. - Add
get_runtime_issues()only for diagnostics you want to inspect without blocking setup. - Stay on the
TileCheckRulefallback unless you need per-indicator coloring. - Keep side effects in
apply()so they happen only after successful validation.