VIRUXE/samp-house-shells
SA-MP's enterable house shells (lshouse/sfhouse/lvhouse, ids 19489-19512) reworked to fit San Andreas: baked lighting, windows, textures, LODs. Drop-in for SA-MP and MTA:SA.
README.md
samp-house-shells
Making SA-MP's enterable house shells look like they belong in San Andreas.
The SA-MP client ships a set of house models in SAMP\SAMP.img: an exterior that reuses a vanilla house's
textures plus a separate interior, for LS, SF and LV.
| ids | exteriors | interiors |
|---|---|---|
| 19489–19496 | sfhouse1–sfhouse4 | sfhouse1int–sfhouse4int |
| 19497–19504 | lvhouse1–lvhouse4 | lvhouse1int–lvhouse4int |
| 19505–19512 | lshouse1–lshouse4 | lshouse1int–lshouse4int |
Servers use them in place of the solid vanilla houses so that players can walk in. Next to the vanilla city they look out of place. This repo holds the tooling, the reworked models and before/after screenshots. The goal is replacement DFF files that any SA-MP or MTA:SA server can use as a drop-in.
Status
| problem | state | |
|---|---|---|
| #2 | interiors have no baked lighting, stay day-bright at night | done: all 12 interiors baked (models/baked/), checked in MTA:SA |
| #3 | windows are flat panes, glow white at night | in progress: every shell has built-in windows (reveal, sill, reflective glass, per-house frames, curtains and blinds), so maps can drop window001, which no longer glows either; to do: check in the MTA:SA client |
| #4 | no ceiling from inside | open; in-game the roof underside does show from inside, but sky shows through the gap between the interior walls and the roof (LS); several SF/LV interiors have their own ceiling |
| #5 | every interior uses the generic all_walls textures | open |
| #6 | no LOD models | open |
| #7 | drop-in package for SA-MP and MTA:SA | open |
Before and after
All 12 houses, original next to reworked, rendered in Blender →
Baked interior lighting (#2)
The original *int models have no prelight at all (geometry flags 0x10036, no prelit bit 0x08, no night
colours), so the game lights them uniformly and they glow at midnight. They now carry day and night vertex
colours baked from Cycles ambient occlusion, with the exterior loaded as an occluder. Each model's material colour
goes from grey 127 to white, because SA multiplies texture × prelight × material colour.
In game (MTA:SA client, same house, the baked model loaded via engineReplaceModel):
| noon | midnight |
|---|---|
Glazed windows (#3)
The shells ship with open window holes. Maps fill each one with SA-MP's 19466 window001: 1,643 objects in the
Scavenge & Survive houses alone. That model has no prelight and a grey 127 material, so every pane glowed white
at night, and its texture was a flat 16×16 grey at 85% alpha.
- Each exterior now has its own windows. Every opening gets a lined reveal, a sill, glass set into the wall, a
frame that stands out of it and, behind it, curtains, a blind or nothing. The frame follows the window texture in
the house's vanilla TXD: white sashes in SF, weathered wood in Ganton, louvres, security bars, and so on (see
the houses). Everything else in the DFF is left exactly as SA-MP shipped it. With these models
a server can stop placing
window001in the houses. - The look follows vanilla's see-through glass. In the Wang Cars showroom (
carshowwin_SFSX) and the SF Ammu-Nation (ammuwindows_SFS), glass is a white-material alpha texture with dark prelight (about 35 by day). It reads as glass with the room behind it, never as a grey board; light, lit-from-inside windows come only from bright night colours. The exteriors use vanilla TXDs, which have no glass texture, so the panes are untextured: alpha 170, prelight graded from about 30 at the bottom to 60 at the top like a sky reflection, a diagonal reflection band, and dark at night.
window001is fixed as well, for maps that keep it. It gets day/night prelight and a white material, andlsmall_window01inlsmall_shops.txdbecomes a 64×64 glass texture: a sky-to-street gradient with two reflection streaks, at 59% alpha so the room shows through. 19325lsmall_window01(shop glass) shares that texture.
How the openings are found:
tools/window_seeds.pytakes everywindow001near a shell into that shell's frame, plus every door object. Offsets that recur in at least half of the instances become seeds (data/window_seeds.json).tools/glaze_shells.pyadds seeds of its own. Maps glaze only some holes: lshouse3 gets one, and lvhouse4's seeds sit outside the model. The script sweeps each exterior with horizontal rays from 8 directions, groups the hits into wall planes, and takes every enclosed gap in a plane as a seed.- Each seed is fitted: rays are cast through the wall on a 4 cm grid around it, and the open region connected to the
seed is the opening. Openings that leak past ±3 m are dropped. Scanned openings are also dropped when they:
- hold a map door object (an entrance),
- are not fully rectangular (an arched doorway), or
- are over 2.4 m tall (a garage).
- The fitted openings go to
data/windows.json(each taggedmaporscan), andtools/add_panes.pywrites the panes.
ariane/tour.py flies the editor round one instance of each shell and captures it from two corners, which is how
the missing panes were spotted.
The "after" shots hide every window001 (apply-removals.ps1 -WithoutPanes), so the glass you see is the
shells' own.
All shots are viewport captures from Ariane at weather 1, taken by
ariane/shots.ps1 from fixed cameras, so before and after line up exactly. The placements are a real server's: the
house maps of Scavenge & Survive (CC BY-SA 4.0), which also remove
the vanilla houses underneath.
Layout
| path | what |
|---|---|
models/original/ | the 24 shell DFFs and all_walls.txd, extracted from SA-MP's SAMP.img |
models/original/window001.dff, lsmall_shops.txd | SA-MP's window pane and its TXD, extracted from SAMP.img |
models/baked/ | reworked models (drop-in replacements, same names): baked interiors, glazed exteriors, window001, lsmall_shops.txd |
data/window_seeds.json, data/windows.json | where maps put window panes and doors per shell, and the openings fitted from them |
screenshots/before, after, compare | Ariane captures and the generated before/after grids |
screenshots/houses, docs/houses.md | Blender renders of every house, original next to reworked, and the window close-ups |
screenshots/ingame | MTA:SA client captures |
tools/img.py | IMG v2 extract/build |
tools/bake_interiors.py | headless Blender bake of the interiors |
tools/window_seeds.py | window001 placements → per-shell seeds |
tools/glaze_shells.py | headless Blender: scans each exterior for openings, fits them by ray casting, turns them to face out and measures the wall depth |
tools/add_panes.py | builds the windows into the exteriors: reveal, sill, glass, frame, curtains (gtaLib, rest of the DFF untouched) |
tools/rework_window.py | prelight for window001, new glass texture in lsmall_shops.txd |
tools/view_house.py | opens a house in Blender: original interior left, baked right, game-style shading, night slider |
tools/compare.py | builds screenshots/compare/*.png |
tools/render_houses.py, tools/gallery.py | Blender renders of every house, original and reworked, and the docs/houses.md grids |
tools/make_ipl.py | server placements → IPL for Ariane |
tools/blender_call.py | sends one command to a running Blender's blender-mcp socket (screenshots, scripted edits) |
ariane/*.ps1, ariane/removals.py, ariane/look_at.py, ariane/tour.py | start/drive Ariane, swap original/baked models, replay removals over one connection, aim the camera at a placed model (vanilla references), tour every shell, take the named shots |
Workflow
# bake (headless, ~1 min for all 12)
& 'C:\Program Files\Blender Foundation\Blender 5.2\blender.exe' --background --factory-startup --python tools/bake_interiors.py -- models/original models/baked
# glaze the exteriors and rework window001 (DragonFF checkout for gtaLib)
python -I tools/window_seeds.py <game copy>\scavenge\scavenge.ipl data/window_seeds.json
& 'C:\Program Files\Blender Foundation\Blender 5.2\blender.exe' --background --factory-startup --python tools/glaze_shells.py -- models/original data/window_seeds.json data/windows.json
python -I tools/add_panes.py <DragonFF> models/original data/windows.json models/baked
python -I tools/rework_window.py <DragonFF> models/original models/baked
# render every house for docs/houses.md (renders in work/renders)
& 'C:\Program Files\Blender Foundation\Blender 5.2\blender.exe' --background --factory-startup --python tools/render_houses.py
python -I tools/gallery.py
# look at one in Blender (original left, baked right; Scene properties > Custom Properties > night)
& 'C:\Program Files\Blender Foundation\Blender 5.2\blender.exe' --python tools/view_house.py -- lshouse1
# see it in the world, then capture and compare
pwsh ariane/use-shells.ps1 baked # or: original; baked also hides the maps' window001
pwsh ariane/shots.ps1 after # or: before; optional name filter, e.g. '*-interior'
python -I tools/compare.py
DragonFF notes. gtaLib reads the BinMesh into a plain list (extensions["mat_split"]) that its writer cannot
serialise. The gtaLib tools move those triangles, which carry the real material ids, into geometry.triangles
and let the writer rebuild the BinMesh. SA-MP's shells keep their material ids only in the BinMesh PLG; the triangle list says material 0
everywhere. Import with read_mat_split=True, or every face gets the first texture. Import with
remove_doubles=False, or overlapping faces are merged away. The bake checks that each output's BinMesh matches
the original's.
Tools
- Ariane Agent Alpha 1 (map editor with a CLI/MCP agent interface), on a dedicated copy of the game so it never writes to the install you play on.
- GTA Scout to find vanilla textures and props that fit.
- Blender 5.2 with DragonFF (latest
master; DFF/TXD import and export, day/night vertex colours) and blender-mcp.
Setup
-
Copy the game (with its
SAMPfolder) somewhere else, e.g.D:\Games\GTA San Andreas\ariane-sa, and putariane.exeandfonts\from the Agent Alpha bundle next togta_sa.exe. -
In the copy's
data\gta.dat, add the following lines. Put theIMGlines after the existingIMGlines, theIDElines after the lastIDEline, and theIPLline at the end. Later IMG lines override entries of the same name, which is howSHELLS.IMGswaps in the reworked models;ariane/use-shells.ps1manages that line.IMG SAMP\SAMP.IMG IMG SAMP\SAMPCOL.IMG IMG SAMP\CUSTOM.IMG IMG SHELLS\SHELLS.IMG IDE SAMP\SAMP.IDE IDE SAMP\CUSTOM.IDE IPL SCAVENGE\SCAVENGE.IPL -
Generate the placements and run the editor:
python -I tools/make_ipl.py <scavengesurvive-mta checkout> <game copy> <game copy>\scavenge pwsh ariane/start.ps1 # editor on port 48731, token in %LOCALAPPDATA%\ariane-agent\token pwsh ariane/apply-removals.ps1 # replays the maps' RemoveBuildingForPlayer list as a scratch session # (-WithoutPanes also hides window001; takes seconds)make_ipl.pyreads the map data that scavengesurvive-mta generates from the upstream.mapfiles. It writes a text IPL plus the removal list. Map-wide removals are expanded into one entry per vanilla instance, because Ariane capssuppress-world-modelsat a 250 m radius. -
For
tools/view_house.py, extract the vanilla TXDs it shows into the ignoredwork/txd/folder:python -I tools/img.py extract <game copy>\models\gta3.img work/txd ganghouse1_lax.txd comedhos1_la.txd glenphouse_lax.txd boxhses_sfsx.txd vegashse2.txd vegashse3.txd vegashse4.txd vegashse6.txd, pluscopy models\original\all_walls.txd work\txd\.
Licence
The scripts, screenshots and our edits are released into the public domain under the Unlicense. The
model files come from the SA-MP client. Vanilla GTA San Andreas files are never committed (work/ is ignored).
arianeblenderdffgta-moddinggta-san-andreasgtasamtasamulti-theft-autorenderwaresa-mpsamp
Esta página se genera con lo que GitHub publica sobre el repositorio. samp.directory no aloja el código. Informar de un problema con esta ficha