Skip to content

Expose GTA CULL zones to client Lua - #5102

Open
Dryxio wants to merge 4 commits into
multitheftauto:masterfrom
Dryxio:expose-cull-zones
Open

Expose GTA CULL zones to client Lua#5102
Dryxio wants to merge 4 commits into
multitheftauto:masterfrom
Dryxio:expose-cull-zones

Conversation

@Dryxio

@Dryxio Dryxio commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR expose GTA attribute, tunnel and mirror CULL zones to client Lua:

  • engineGetCullZones
  • engineCreateCullZone
  • engineSetCullZone
  • engineSetCullZoneEnabled
  • engineRemoveCullZone
  • engineRestoreCullZone

Original zones can be queried, edited, disabled and restored. Resources can also create custom zones, but cannot edit custom zones created by another resource.
Custom zones are removed and original zones are restored when the resource stops.

The GTA CULL arrays are expanded to support custom zones. Invalid zone sizes, flags and mirror normals are rejected.

Motivation

Allow maps and gamemodes to inspect and manage GTA CULL zones from Lua.

Demo

https://www.youtube.com/watch?v=17QrE21uDgM

Test plan

Test resources: mtasa-cull-zones.zip

CRUD and validation

Server:

refresh
start cull-zone-test

Client:

/cullstats
/cullinvalid
/cullvisual all 200
/culltest attribute 8 40
/culledit 0 60
/cullenable off
/cullenable on
/culldelete
/cullstats

The first /cullstats gives the vanilla counts. /cullinvalid tries invalid geometry and mirror normals on both create and edit; it should return PASS without changing the count.

/cullvisual all 200 displays original and custom zones within 200 units.
/culltest attribute 8 40 creates a 40-unit NO_RAIN zone around the player.
/culledit 0 60 moves it to the current position, resizes it to 60 units and removes the flag.
With rainy weather, rain should be hidden by the first zone and return after the edit. The zone is then disabled, enabled and deleted.
The final /cullstats should match the first one with no custom zone.

Mirrors

Server:

start cull-mirror-floor-test

Client:

/mirrorfloor2
/mirrorfloorinfo
/mirrorfloortoggle off
/mirrorfloortoggle on
/mirrorvanilla
/cullnearest mirror
/cullvanilladisable
/cullvanillarestore
/mirrorfloorleave

/mirrorfloor2 enters the custom mirror showroom and /mirrorfloorinfo prints the nearest mirror definition and plane. The reflection should disappear and return when toggled.

/mirrorvanilla enters the original barbershop. /cullnearest mirror selects its original mirror zone, which should disappear and return when disabled and restored. /mirrorfloorleave returns to the previous position.

Resource cleanup

Server:

stop cull-mirror-floor-test

Client:

/culltest attribute 8 20

Server:

restart cull-zone-test

Client:

/cullstats

Stopping cull-mirror-floor-test removes its custom mirror. The attribute zone is then left active on purpose before restarting cull-zone-test. No custom zone should remain in /cullstats after the restart.

Resource ownership and capacity

Server:

stop cull-mirror-floor-test
stop cull-zone-test
start cull-zone-owner-a
start cull-zone-owner-b

Client:

/cullownera
/cullownerb

Owner A disables and claims one original mirror zone. Owner B checks that it cannot modify this zone, then fills all remaining custom mirror capacity.

Expected with the standard GTA data:

PASS: created=191 expected=191 active=255 custom=191 disabledOriginal=1

Server:

stop cull-zone-owner-a

Client:

/cullownercheck

Stopping owner A should restore its original zone even while the mirror store
is full.

Expected:

PASS: active=256 custom=191 disabledOriginal=0

Server:

stop cull-zone-owner-b
start cull-zone-test

Client:

/cullstats

Stopping owner B should remove all 191 custom zones and return to the vanilla mirror count.

Checklist

  • Your code should follow the coding guidelines.
  • Smaller pull requests are easier to review. If your pull request is beefy, your pull request should be reviewable commit-by-commit.

Dryxio added 3 commits July 30, 2026 19:14
Relocate GTA's fixed attribute, tunnel, and mirror arrays into bounded MTA-owned storage and adopt vanilla entries into an editable catalog.

Reserve native capacity for modified originals so cleanup can always restore them. Centralize mirror enable state and refresh attribute flags before weather processing on MTA's multiplayer path.

Tested with Game SA and full client Release|Win32 builds, 304 passing client tests, and in-game attribute and mirror lifecycle checks.
Register the query and mutation functions with ArgumentParser and bind mutations to the calling resource. Restore original zones and remove custom entries when the resource stops or is destroyed.

Validate IDs, native flag widths, quantized geometry, and unit mirror normals before publishing changes.

Tested with full client Release|Win32 and server Release|x64 builds, 304 passing client tests, invalid-input checks, resource restarts, reconnect cleanup, and custom and vanilla mirror rendering.
Comment thread Client/game_sa/CCullZonesSA.cpp
@FileEX FileEX added the enhancement New feature or request label Jul 30, 2026
@tederis

tederis commented Jul 31, 2026

Copy link
Copy Markdown
Member

What do you think about using elements to represent zones? I mean engineCreateCullZone returns an element so you can manipulate it with functions setElementPosition and destroyElement?

@Dryxio

Dryxio commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

What do you think about using elements to represent zones? I mean engineCreateCullZone returns an element so you can manipulate it with functions setElementPosition and destroyElement?

Why not especially for custom zones, but what about original GTA zones? Should they also be represented as elements, and what should destroyElement do for them?

@FileEX

FileEX commented Aug 1, 2026

Copy link
Copy Markdown
Member

What do you think about using elements to represent zones? I mean engineCreateCullZone returns an element so you can manipulate it with functions setElementPosition and destroyElement?

Why not especially for custom zones, but what about original GTA zones? Should they also be represented as elements, and what should destroyElement do for them?

I think default cull zones shouldn't be elements in MTA. Just like default buildings aren't elements, the default water isn't an element, and default objects aren't elements. Following the same principle, only things created by MTA should be represented as MTA elements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants