Stalker 2 - joric/maps GitHub Wiki
The PDA tileset is from 1.0.3. Markers were updated to 1.1.4.
- Live map (Maptalks-GL version): https://joric.github.io/stalker/
- Source code: https://github.com/joric/stalker/
- https://github.com/maptalks/maptalks.js/issues/2488 Markers depth (closed)
- https://github.com/maptalks/maptalks.js/issues/2493 Vertical lines
- https://github.com/maptalks/maptalks.js/issues/2495 Blurry popups (closed)
- https://github.com/maptalks/maptalks.js/issues/2506 Mobile issues
- https://github.com/maptalks/maptalks.js/issues/2509 Wrong marker
- https://github.com/maptalks/maptalks.js/issues/2510 Altitude option
- Use search to find stuff (searches in currently selected language across all fields).
- Use crosshair icon in the item popup to copy item location and paste it into game console to teleport to the item.
- Click on Wikipedia icon in the popup to jump to the fandom wiki page about the selected item.
- Click on item properties in the list to copy console commands to run quests related to the item.
- Use chain icon to copy map address to clipboard to share backlinks.
- Type
uetools_god
for god mode (needs UETools, https://www.nexusmods.com/stalker2heartofchornobyl/mods/64). - Bind C to noclip in console:
UETools_BindToggle C "XSetNoClipGSC true 1000" "XSetNoClipGSC false"
. - Use
XTeleportTo <x> <y> <z>
to jump to location, e.g.XTeleportTo 446880 654920 -2150
(Rookie Village). - Use quest references to doors to open doors, e.g.
XStartQuestNodeBySID E07_MQ01_SendSignal_HubDoor_Open
. - Start quests with
XStartQuest
(XStartQuest E08_MQ03
), finish withXDKFinishQuest
(XDKFinishQuest E08_MQ01 true
).
More console commands: https://steamcommunity.com/sharedfiles/filedetails/?id=3370986723
- Better search with autocomplete, categories and layers.
- Stash generators UI with player rank selector.
- Quests graph.
- Download FModel, add undetected game, UE5_1 (you have to set the engine to 5.1, later versions are incompatible).
- Add AES key (Directory - AES):
0x33A604DF49A07FFD4A4C919962161F5C35A134D37EFA98DB37A34F6450D7D386
- Add mapping (Settings - General - Local Mapping File): .usmap Mappings file.
- Select all packages (pack, utoc, etc), press "Load". The game directory tree appears in "Folders".
- For binary resources in the object root (e.g. cfg files) select object in the tree, press packages.
- Use "export Raw Data" to save. Exported resources appear in the "Exports" directory by default.
- Half of the items are in umap files rather than in cfg files, see Blueprint items.
The localization asset is Stalker2/Content/_Stalker_2/Localization/LocalizationDB.uasset
it is in pakchunk29-Windows.utoc
. Extract it as raw data in FModel, you get .ubulk file. You may need S2HOC Multi Localization Utility to convert ubulk file to JSON and vice-versa. (To get the pak name for the asset, load everything in FModel and then search by asset name, it shows the pak. The pak name may change in the future as they just use sequential numbering.)
The PDA map is Stalker2/Content/GameLite/FPS_Game/UIRemaster/UITextures/PDA/WorldMap/T_WorldMap_UDIM.uasset
. It's a 65536х65536 virtual texture (the data size is over 3GB). It is not an asset FModel can process, you need to extract raw bitmap data and convert it to typical container/format. You can use ZenTools to extract T_WorldMap_UDIM.ubulk
from pakchunk16-Windows.utoc
. The virtual texture is simply a bunch of tiles (in a lossy 6:1 DXT1 compression format) stiched together (the raw data size would be over 18 GB). I've made a script that can export virtual textures from .ubulk in a custom number of chunks:
- Virtual Texture export script: https://github.com/joric/stalker/blob/main/scripts/vt_simple.py
- Tileset repository wiki (download links): https://github.com/joric/stalker2_tileset/wiki/
There are other maps, see: https://github.com/joric/stalker2_tileset/wiki#extras
- extras/wb:
Stalker2/Content/_Stalker_2/maps/WorldMap/T_GLOBAL_MAP_BASE.uasset
(12951x12951 -> 16384x16384, jpg) - extras/ld:
Stalker2/Content/_Stalker_2/maps/WorldMap/T_WorldMap_LDScheme.uasset
(4096x4096, png) - extras/s1: https://www.nexusmods.com/stalker2heartofchornobyl/images/212 (8599x7452 -> 8192x8192, png)
"LD" in T_WorldMap_LDScheme.uasset possibly means "Low Detail". Or "Longer Days". Or "Last Day". Not sure.
See Stalker2/Content/LevelBitmaps/T_Regions_Map.uasset
, it's a texture that marks regions. Every region is different color. It's not very web friendly because it needs pixel access. The exported 2048x2048 png file is just 20 kb though.
The regions texture was autotraced to SVG (https://joric.github.io/stalker/scripts/T_Regions_Map.svg), scaled into 8192x8192, edited to match T_GLOBAL_MAP_BASE.uasset
and exported to geojson with svg2geojson. It's virtually impossible to edit SVG's in map's native 65536x65536 resolution, so you'd have to scale it up on the client to match the markers.
Stalker 2 uses UE5 blueprints with a proprietary plugin that stores all the metainfo in .cfg files. Most of the marker data is in the .cfg files that are in the Stalker2/Content/GameLite/GameData/SpawnActorPrototypes
folder.
- The base export script is here: https://github.com/joric/stalker/blob/main/scripts/build_markers.py
For the markers you'd have to scan all .cfg files in GameData and extract spawn coordinates and other properties. I personally just use FModel to export all .cfg files as raw data, then read them from the disk.
I got about 60k markers from .cfg files. It does not include desctuctible objects (ESpawnType::DestructibleObject, e.g. pots), because it would be 120k+ markers. Still lacks reference info such as quests and container spawns.
To identify the markers, draw them all in the square CRS (about 812900 units wide) and compare them to what's happening in the game.
The 812900 is the largest landscape allowed in UE5 (8129x8129, NOT 8192) with 100x scaling, see UE5 Techincal Guide.
Some markers appear out of bounds. Markers at the top left corner are partially because they are not filtered by level name and they have their own coordinate system. They should be filtered by WorldMap_WP (except some service markers). Markers at the top right are totally legit, there is a test site on the main map.
If you look at Stalker2/Content/GameLite/GameData/SpawnActorPrototypes
there's plenty of maps: map_P_TeleportHouse_01
, Skif_Home Underground_Base
, StuffTestMap
, etc. Partially they are cutscene footage, partially test maps, some of them must be "interior cells" accessible via triggers.
There are a lot of markers in MarkerPrototypes, SpawnActorPrototypes and other cfg files but quite a few items are still in the standard Unreal Engine maps as blueprints, so there are two sources of items, CFG files and UMAP files.
CFG files do not have all items, about half of the game uses conventional UE map making, looks like it was made in a rush.
They are exported from CFG files (created by a proprietary GSC plugin). It'a pretty straightforward, you just scan all of them and collect coordinates. You can extract them in bulk as raw data (uasset), there is about 300 megs of CFG files.
Exports/Stalker2/Content/GameLite/GameData
Exports/Stalker2/Content/GameLite/DLCGameData
Usually spawned as ESpawnType::Obj. Generally, there is a ton of BP_NPC_*
classes in WorldMap_WP.json
but their references to .cfg files are yet to find. Sidorovich seem to linked via // BP_NPC_Sidorovich
comment in 50D530D64ECEC8C5C8499C95EA5BA59B.cfg
, there's a single reference to a blueprint in WorldMap.uasset.
It also has SpawnedPrototypeSID = Sidorovich
field. It's overlapped with a lot of other markers. The location is precise though, the underground bunker path really goes there and makes an U-turn. If you teleport to his marker's location (XTeleportTo 443589.238372 654426.936737 -3010.04712
) you'll land precisely on his head.
Stashes use generators to generate random items. Some things are completely scripted, e.g. the stash on top of the water tower (with SID 7E0BEBD44F766B65C019A1AF34907893
) does not have a generator, it's is filled in QuestNodePrototypes\SQ01.cfg
.
Comparing generators and real stuff:
{
"sid": "C1EEB89C4D27EE16CAC1A2BC85378947",
"references": [
"Cordon_GD_GiveCache_BP_StashCheap"
],
"type": "ESpawnType::ItemContainer",
"name": "Bag",
"clue": "GDN_22_StashOnMilitaryKPP",
"spawns": [
"StashMedicine_Smart",
"Stash_Ammo_Smart_CommonRare",
"Veteran:Cordon_MilitaryCheckpoint_StashGenerator1_C1EEB89C4D27EE16CAC1A2BC85378947"
]
}
Looks like GrenadeRGD5 only can be obtained by Veteran. Rank in ItemGeneratorSettings
supposed to check for the player rank (which is NOT shown in the game). Game difficulty is given separately in the generator 'Diff' field, it does not affect the player rank. You can switch player rank with XSwitchPlayerRank [Newbie|Veteran|Master|Experienced]
and separately set game difficulty in menu at any time.
Upgrades refer to item prototypes that have their own LocalizationSID
, e.g. Stash_Blueprint_M860_Upgrade_1
generator refers to ItemGeneratorPrototypes.cfg
and Blueprint_M860_Upgrade_1
that refers to the BlueprintPrototypes.cfg
record, and finally in the string table there are two records related to GunM860_Upgrade_Attachment_Mag
.
Hub is basically a building that closes the doors on attack. There are may be multiple hubs per location (e.g. Zalissya has a main building and a side building). Game map seem to deduplicate those hubs (same location hubs have the same MarkerSID
but different SID
), use average coordinates and CloseDoorRadius
for the hub radius (orange color). They are actually "bases" on the game map but the corresponding markers have the ESpawnType::Hub
type.
There's a trigger volume 48716F37408178733ECBE58FB6F4613B
in the basement that has references from other files, e.g. Content/GameLite/GameData/SpawnActorPrototypes/WorldMap_WP/46E399AC4C52E90CC5AA0CA869E16653.cfg
(ESpawnType::Shelter) it's referred as one of 5 "volumes" that are probably a list of shelters, scattered around the village. The "RestrictorVolume" doesn't appear in .cfg files. The trigger next to the player's bed in Zalissya (CD0767DC4762AD400AE9C695678C180C) appears to be a door trigger. It is cross-referenced in a quest Content\GameLite\GameData\QuestNodePrototypes\Zalesie_Hub.cfg
:
A notable thing in the game is "point of not return". It is trigger D02A946045E08A6276CC6FAC8F89CE3F
that references GDTQ02_BP_OnTriggerEnterEvent_Path_*
that is a part of GDTQ02_BP_ShowTutorialWidget_PointOfNoReturn
node. It shows a message with language id sid_tutorial_tutorial_pointofnoreturn_head
.
Use file search (Packages - Search) to find files by name. Most object properties are in the GameLite/GameData directory.
- Item descriptions use
*Prototypes.cfg
, akin to YAML but nested, parse it line by line (scripts). - Base weapon descriptions are in
Content/GameLite/GameData/ItemPrototypes/WeaponPrototypes.cfg
. - Weapon shooting patterns use ordinary JSON files, search for ShootingPatterns. Shotgun uses 8 bullet patterns (apparently randomly selected, see shotgun_pattern.html).
- There is csv about weapon properties
Exports\Stalker2\Content\GameLite\GameData\xls\WeaponPrototypes.csv
- Also a csv about faction relations:
Exports\Stalker2\Content\GameLite\GameData\Relations.csv
- Caliber upgrade, see ChangeCaliber045Effect in UpgradePrototypes.cfg
- Weapon models are mostly in nanite format, there are no hires LODs.
They are exported from Umap files (standard UE5 maps). Extracting items from umap files is a little bit more complicated you export umap binaries as json files (e.g. in FModel). There is about 70 GB of data in json.
Stalker2/Content/_Stalker_2/maps/_Stalker2_WorldMap
Stalker2/Content/_Stalker_2/maps/_Stalker2_WorldMap/WorldMap_WP/_Generated_
You can export individual cells (_Generated_
folder), but you need them all for the complete map anyway.
You can find cell name by Blueprint UAID in Stalker2/Content/_Stalker_2/maps/_Stalker2_WorldMap/WorldMap_WP.json
.
Umap files contain important items such as BP_DoorView
, BP_CodeLock
, and BP_Cardlock
. You need those to complete the map.
I use Blueprint Guid as sid for Blueprint items (without dashes) if Guid exists, otherwise it falls back to Blueprint UAID.
Blueprint UAID looks like BP_PlayerStash_C_UAID_00D861D9738D0AC601_1932023010
, it's unique for every blueprint instance.
Cells only matter for Blueprint items, extracted from UMAP assets. Blueprint items are mapped to cells in WorldMap_WP.json
.
The MainGrid cell may be calculated from latlng of the marker. The global L0 grid is 256x256 cells ranged from -128 to 128.
let latlng = e.target.getLatLng();
let w = getMapSize(mapId); // 8129000
let x = Math.floor((latlng.lng / w - 0.5) * 128);
let y = Math.floor((latlng.lat / w - 0.5) * 128);
console.log(`marker cell: MainGrid_L0_X${x}Y${y}_DL0`)
Levels in grid cells can vary from L0 to L6 (there are just 4 L6 cells), but most items are in L0.
Some personal items are in those strange DLxxx cells, e.g. the Wild Island bed BP_Bed_OnBed_C_UAID_00D861FD685406C601_2144311330
is in MainGrid_L0_X12Y17_DL6ABA6B9
. The nearby locker BP_PlayerStash_C_UAID_00D861FD685406C601_2081831329
is in the ordinary DL0 cell though: MainGrid_L0_X12Y17_DL0
.
Looks L0 is static but DL changes e.g. MainGrid_L0_X12Y17_DL6ABA6B9
. That must be an update or a revision of the cell.
It looks like different item types are located in different cell types. Entity number by cell type (from WorldMap_WP.json
):
Cell Type | Objects |
---|---|
MainGrid | 9370 |
Architecture | 6253 |
Props | 13387 |
Terrain | 1110 |
TreesEnv | 4553 |
NavigationDataChunks | 721 |
RainShadowGrid | 16129 |
BakedFoliageGrid | 1024 |
BakedFoliageGridNonDistantTrees | 1024 |
HLOD | 12918 |
Cell types seem interchangeable, e.g. BP_DoorView may be both in Props and in Terrain, but MOSTLY in Terrain, padlocks, levers and buttons are usually in MainGrid. Apparently there are no strict rules for item placement.
Some scanners are not in MainGrid cells but in NavigationDataChunks that also apparently have different grid size and geometry. Looks like grid offsets for MainGrid and Navigation cells are off by one, probably grid dimensions are wrong (it's rather 147 than 128 for the navigation chunks). The nearby scanner in cell MainGrid_L0_X-8Y8 is calculated correctly with cell size 128 though. Either the cell size is different or the grids may be shifted relative to each other.
CA_lie_bed contextual action determines a usable bed, but not player's. There are no player's beds or chests coordinates in cfg files.
All those items are blueprint classes in .umap files, namely BP_Bed_OnBed_C
and BP_PlayerStash_C
.
There are no references from .cfg files besides "PlayerStash" in ItemContainerPrototypes.cfg
and multiple "AddToPlayerStash" flags.
To find items you look for the partition section in the global map (WorldMap_WP.umap).
Then you look for the skeletal or static mesh component in the MainGrid_L0_X12Y17_DL0
partition in the _Generated_
folder.
See example player bed (BP_Bed_OnBed_C_UAID_00D861D9738D0AC601_1977297011
) and player stash (BP_PlayerStash_C_UAID_00D861D9738D0AC601_1932023010
) in Rookie Village, Cordon region.
Scanners are about the same as personal items, there are no scanner locations in .cfg files, only in .umap. Scanner classes found in maps are: {'BP_TopazScanner_Overworld_C': 10, 'BP_TopazScanner_Prologue_C': 3, 'BP_TopazScanner_Broken_C': 2}
.
There are blueprint classes BP_Teleport_Portal_Bubble_C
(in .umap) that work as teleports.
The teleport blueprint has EndPoint property, that is the target (uses relative coordinates).
There are also BP_TeleportPlaceholder_C
classes, but they don't seem to have any representation in the world tiles. There are references to teleport placeholders, e.g. B29F394A4F431CD6BD7FB7A1D6CBC683
refers to BP_TeleportPointPlaceholder_C_UAID_2CF05D9D9CF6A6E501_1235471597
, but the exact
mechanics is yet unclear.
The teleport target BP_Teleport_Portal_Bubble_C_UAID_30D042F7BCC8A5F901_1538757755
(near the elevator, 927C1F97416A55D00195298B60BBE3B1
) seems off,
it should be on the roof above the pillow anomaly (1E5622954B9C4C06EBAE87882B1EAA92
). Currently there are no placeholders or other markers nearby. Maybe the target translation is relative to something else. Rotation does not fix it.
Similar to personal items, all doors are in umap files, namely BP_DoorView_C
and BP_Stalker2Door_C
classes (the latter is rare).
They have bIsLocked
flag. XUnlockDoor DoorUID
or XOpenDoor DoorUID
don't seem to work on stalker 2 doors.
Stalker 2 doors are controlled through signal components, mostly UnlockDoorReceiver and ReceiverOn (for bunker doors). Each of those signal components have its own guid. GFG files use Guid without dashes, e.g. 106B18EA-46E5BA51-380B878E6-ABB99DC
is mentioned in cfg files as "SignalReceiverGuid": "106B18EA46E5BA51380B878E6ABB99DC"
. Some signals are connected internaly in UMAP files through buttons, levers and destructible padlocks.
There's still an issue with the component that is responsible for the doors that open with grenades. I checked every signal receiver for BP_DoorView_C_UAID_E89C255E1016C20202_2004590303
cell Terrain_L0_X-3Y-6_DL0
(the infamous chimera door in pripyat). I could not find the "explosive" component. It may be ForceOpenDoorReceiver or it may be another blueprint that actually sends the signal akin to levers/keypads.
Another door is at Cordon BP_DoorView_C_UAID_00D861D9738DAEE201_1638133507
, cell Terrain_L0_X0Y5_DL0
. It may be opened with gas tank (it has no blueprint, there should be InstancedStaticMesh entity with mesh SM_gen_gas_cylinder somewhere in prop cells) but there is apparenly no direct connection between gas tanks and doors because you can just roll it away. It looks like they open with any explosion but it's limited to a certain door side (HittableComponent perhaps?)
There are two classes BP_Cardlock and BP_CodeLock that are kind of interchangable, I guess the latter was added later as it sometimes uses Cardlock UAID naming. They send unlock signals to doors using the door unlock guid.
To find the keycode you just search for "CodeComponent" and there's a field "CorrectCode": "1268"
or whatever. E.g. see MainGrid_L0_X2Y39_DL0.json
.
A good keypad door to investigate is BP_DoorView_C_UAID_00D861D9738DACC701_1632770753
in Terrain_L0_X0Y4_DL0
. The key code is 1268
. Teleport to door with XTeleportTo 422465.97 656694.56 874.8045
.
Keypad door to armory opens with code 8506. You get the code from sid_notes_E11_MQ04_Protocol78_Instruction_body
.
It appears to be BP_DoorView_C_UAID_18C04D7E659CAACD01_1306808572
in Props_L0_X-16Y17_DL0
. The unlock receiver there is 6BEF6BCA447D12A3111C5FBD18434A24
it appears in Props_L0_X-16Y17_DL0.json
.
Note sometimes there are two signal senders that use the same guid, do don't deduplicate there.
Quests (in CFG files) usually use UnlockDoorReceiver guid as a reference to a door (via "SignalReceiverGuid" property).
There is a quest section that opens the door with North Checkpoint Key
. If you check string table it refers to E02_MQ03_RihterNorthKey
that's used in quest E02_MQ03. The unlock guid is directly linked to BP_DoorView_C_UAID_D8BBC11C280D10D201_1504827848
in Props_L0_X-2Y16_DL0
via "SignalReceiverGuid": "C151CEF94F982C95F2292FA661D3CC18"
.
You can trace this section back to parent quest to figure out how the keys work. Looks like the door opens the moment you pick up the key.
E.g. the SQ03_SendSignal_OpenHouse
subquest that opens a 2-state object (removes floor debris and opens the cave entrance) is opened by a series of events related to a "Subbota" character, i.e. SQ03_Technical_SubbotaTalked
, SQ03_AddNote_Subbota
when you get MaksSubbotaPDANote
. You can trigger it using XStartQuestNodeBySID SQ03_AddNote_Subbota
or you can spawn the character using XStartQuestNodeBySID SQ03_P_SpawnObjectNPCMonster_MaksSubbota
but he doesn't have the note on him, you get it during Subbota-related quests.
There are more interactive objects, such as BP_Lever, BP_Padlock, BP_Button, BP_Latch, BP_Valve. They use mechanics similar to keypads.
Quest names start from episode name then M for main quests, S for side quests. There are orphaned quests, such as EQ14
.
Examples:
-
E01_MQ01
is the 1st quest ("sid_journal_E01_MQ01_Name": "There and Back Again") -
E02_MQ01
is the 2nd quest ("sid_journal_E02_MQ01_Name": "A Tough Awakening") -
E02_SQ01
is the side quest ("Zhorik" quests, no name in the string list)
There are two folders, QuestPrototypes
contains name definitions, QuestNodePrototypes
contains quest graph.
The Scripts/OnGameLaunch/OnGameLaunchScripts.cfg
file seem to have all the quest sequence but commented out.
- Game launches
Scripts/OnGameLaunch/OnGameLaunchScripts.cfg
that runsOnGameLaunchScripts_E01_MQ01.cfg
. -
OnGameLaunchScripts_E01_MQ01.cfg
runsrootgraph_E01_MQ01
which is listed inQuestNodePrototypes/rootgraph.cfg
. - The output pin of
rootgraph_E01_MQ01
isE01_MQ01_End
which is listed inE01_MQ01.cfg
. -
E01_MQ01_End
runsE01_MQ01_Finish
that hasJournalAction = EJournalAction::Finish
. - The output pin of
rootgraph_E02_MQ01
isE02_MQ01_End
which is listed inE02_MQ01.cfg
.
We cannot pin quests to exact map locations. Mission is related to multiple items scattered across the map. The proper thing to do is to add quest references to items, akin to Fallout-London.
Some items are tied to guests and added to stashes during quests via EQuestNodeType::ItemAdd
nodes.
The EQ110_HermitPDA
is added to Hermit's backpack via quest connector EQ110_P.cfg
. The node name is EQ110_P_ItemAdd_EQ110_HermitPDA
, it has NodeType = EQuestNodeType::ItemAdd
and TargetQuestGuid = 06FA06464829ACE48D0D6CBBD1962021
(backpack sid).
Hints from STALKER G.A.M.M.A discord (https://discord.gg/8qg377vE54) and other sources, added comments.
items on the ground are split into ~80k cfg files, not all of them are items tho, but its still thousands or tens of thousands of individual cfgs that contain the loose items pakchunk0-Windows\Stalker2\Content\GameLite\GameData\SpawnActorPrototypes\WorldMap_WP
Note markers have SpawnType = ESpawnType::Marker, see 44DE8E9A4E838F5C0051AAB546F5A247.cfg
I don't remember exactly, but I think XShowUnitAndSquadUIDs RADIUS might show SIDs of items ingame, including stashes
XShowUnitAndSquadUIDs does not work. But it's an interesting idea to use UE4SS lua scripts to find items with raycasting.
the active WP landscape size is 816000x816000 ue units, UI view scaled size is 32512x32512 the map texture projected on a plane which 32.512x32.512 units and then rendered in sections to UI. I simply measured it with live coordinates. This scale is what my teleport-anywhere-on-the-map-by-click mod uses.
I actually use 812900 and 65536x65536. At 816000 everything will be off (pot/non-pot textures? map/tile borders?).
that world map is from T_WorldMap_UDIM.uasset it's virtual texture and all mips data are in ubulk i did modify fmodel source to extract tiles, cause otherwise it can't handle that texture ... i think i deleted everything, i was just a challenge to get that mip0 texture
All the data is in ubulk packed with oogle. Stock FModel cannot open it: [ERR] System.OverflowException: Array dimensions exceeded supported range. at CUE4Parse.UE4.IO.IoStoreReader.Read(Int64 offset, Int64 length)
. If you rollback and rebuild FModel with patch #127 it opens T_WorldMap_UDIM.uasset but says Value cannot be null. (Parameter 'sourceArray')
. With AlwaysUseChunkedReader = true
and AllowLargeFiles = true
it reads ubulk, but still fails at image saving ([ERR] System.NullReferenceException: Object reference not set to an instance of an object
).
With pyUE4Parse it will be too slow. The data is Oogle compressed, see IoStoreReader.py
: def Read(self, chunkid: FIoChunkId) -> BinaryStream
and the python unpaker stucks. If you stop the ubulk reader early and continue to texture conversion, UE4Parse throws exception "Virtual Textures are not implemented". It needs a virtual texture reader, e.g. backported from CUE4Parse. My take (WIP): https://github.com/joric/pyUE4Parse/blob/vt/vt_example.py.
A simple script to export virtual textures: https://github.com/joric/stalker/blob/main/scripts/vt_simple.py It's still kind of complex though, considering tile borders and Morton code. Read more about it here: https://discourse.threejs.org/t/virtual-textures/53353 (virtual textures), https://devblog.foxworks.cz/post?id=67 (DXT1 compression).
There's bread virtual texture in 4k - Stalker2/Content/_Stalker_2/props/food/Textures/T_foo_bread_01_D.uasset
, 12 Mb in DXT1, raw data is about 72 mb (1:6 compression), multiple mips, mip0 is 64 Mb (4096 * 4096 * 4) RGBA (T_foo_bread_01_D.jpg).
Also see: https://www.nexusmods.com/stalker2heartofchornobyl/articles/138 (How to Override Sections of a Cfg)
- refkey is similar to inheritance in oop. We can both override values from the parent and add new ones.
- refkey to a generator with an ItemGenerator field overwritten rather than appending that field from the parent.
- refkey on structure with refkey works badly and leads to errors and crashes. While it worked inside the original files, it just crashes when you move it to other files. Experiments pointed to the problem in refkey inheritance.
- If you don't need to save fields from the original generator, it's better to completely override it, just using the same sid. If your generator is loaded later, it will completely overwrite the one loaded before it. If they have the same sid. Maybe that's the reason why you sometimes get an error when refkey is used together with the same sid?
- Items with [0], [1], etc. these [0] or [] are not indexes but map keys or variable names. I mean that you can give them clear names and work with them as with fields, getting the possibility to inherit them. Inheritance via refkey of structures that have [0] or [] leads to errors, so it's better to use clear words.
- The ItemGenerator field will be overwritten, not expanded, with either method. The best way I have found is to extend the generator in the original file by adding your generator as a subgenerator. This is the best way to easily resolve mod conflicts afterward. 2 mods that overwrite the same generator, each in their own file, is bad. It's hard to resolve the conflict because it's hard to figure out who added what and who should be referencing who.
- if you add a subgenerator with a non-existing sid to a generator, it will just be ignored! No crash. This means that we can add all the subgenerators we need to the original file in one mod, and add implementations of these generators in other mods, and in an optional order. And it will work! And it's better if different modders have their own calls in the generators, rather than trying to override the same file.
- https://www.reddit.com/r/stalker/comments/1hd6me2/stalker_2_map_in_full_64k_resolution/
- https://www.reddit.com/r/stalker/comments/1ihnm0l/full_map_and_i_mean_full/
- https://rentry.org/TravesS2moddingBible
- https://github.com/Dmgvol/UE_Modding UE4/5 modding guides
- https://www.nexusmods.com/stalker2heartofchornobyl/mods/262 A Monolith's Guide to Replacing Virtual Textures
- https://github.com/CnRJay/Stalker-2-Dump-Files all cfg files from all patches
- S2GUITools Items Creator (invite) (image) a new tool for creating consumables (in progress)
- https://www.nexusmods.com/stalker2heartofchornobyl/mods/1179 Stalker 2 Desolation Mod