Jump to content

Modding XCOM under Linux


wghost81

Recommended Posts

  • Replies 77
  • Created
  • Last Reply

Top Posters In This Topic

Wghost81 is there a way to read upk files or onveret them to something that makes sense? I tried reading xcomstrategygame.upk.unpacked however if you don't know exactly which bit you are searching for it's imposible to make sense out of it.

 

I would like to mod starting base layout a bit. I managed to move starting sat-uplink to utmost left position of first level. However I would like to do few things more - restrict termal vents to level 4 exclusively and change probabiliy for right corridor of level one to revert back to non-excavated state.

Edited by Amphibious
Link to comment
Share on other sites

Amphibious, you can extract object lists with ExtractNameLists and find and partially deserialize any export object with FindObjectEntry. FindObjectEntry can also copy object's serial data to separate binary file.

 

But if you need to decompile object's script, you'll need UE Explorer. I tried running it under wine with no success. It wants some libraries I can't install because of the 32-64 bit wine libraries conflict on my system. May be you'll have more luck with it.

Link to comment
Share on other sites

 

FindObjectEntry

Name to find: XGBase

Found Export Object:

0x00002992 (10642): Class'XGBase'

TypeRef: 0x00000000 ->

ParentClassRef: 0x000001BF -> XGStrategyActor

OwnerRef: 0x00000000 ->

NameIdx: 0x00003587 (Index) 0x00000000 (Numeric) -> XGBase

ArchetypeRef: 0x00000000 ->

ObjectFlagsH: 0x00000000

ObjectFlagsL: 0x000F0004

0x00000004: Public

0x00010000: LoadForClient

0x00020000: LoadForServer

0x00040000: LoadForEdit

0x00080000: Standalone

SerialSize: 0x000002B2 (690)

SerialOffset: 0x00326182

ExportFlags: 0x00000000

NetObjectCount: 0

GUID: 00000000000000000000000000000000

Unknown1: 0x00000000

Attempting deserialization:

UObject:

PrevObjRef = 0x00002991 -> OnInterrogationCinematicComplete

UField:

NextRef = 0x00000000 ->

ParentRef = 0x000001BF -> XGStrategyActor

UStruct:

ScriptTextRef = 0x00000000 ->

FirstChildRef = 0x00002991 -> OnInterrogationCinematicComplete

CppTextRef = 0x00000000 ->

Line = 0xFFFFFFFF

TextPos = 0xFFFFFFFF

ScriptMemorySize = 0x00000000

ScriptSerialSize = 0x00000000

Script decompiler is not implemented!

UState:

ProbeMask = 0x10000008

LabelTableOffset = 0xFFFF

StateFlags = 0x00000002

0x00000002: Auto

StateMapSize = 0x0000002F (47)

StateMap[0]:

0x000026C4 (Index) 0x00000000 (Numeric) -> OnInterrogationCinematicComplete

0x00002991 -> OnInterrogationCinematicComplete

StateMap[1]:

0x000016BE (Index) 0x00000000 (Numeric) -> InterrogateContainedAlien

0x00002990 -> InterrogateContainedAlien

StateMap[2]:

0x0000095B (Index) 0x00000000 (Numeric) -> DoAlienInterrogation

0x0000298E -> DoAlienInterrogation

StateMap[3]:

0x000003E3 (Index) 0x00000000 (Numeric) -> BeginAlienContainment

0x0000298C -> BeginAlienContainment

StateMap[4]:

0x00002632 (Index) 0x00000000 (Numeric) -> OnAlienContainmentStreamed

0x00002989 -> OnAlienContainmentStreamed

StateMap[5]:

0x000005F2 (Index) 0x00000000 (Numeric) -> CaptureAlienMapStreamFinished

0x00002985 -> CaptureAlienMapStreamFinished

StateMap[6]:

0x000013AD (Index) 0x00000000 (Numeric) -> GetXComMapManager

0x00002983 -> GetXComMapManager

StateMap[7]:

0x00001178 (Index) 0x00000000 (Numeric) -> GetCineDummy

0x0000297E -> GetCineDummy

StateMap[8]:

0x0000298D (Index) 0x00000000 (Numeric) -> RemoveRoom

0x0000297A -> RemoveRoom

StateMap[9]:

0x000026A6 (Index) 0x00000000 (Numeric) -> OnFaciltyStreamed_OTS

0x00002976 -> OnFaciltyStreamed_OTS

StateMap[10]:

0x000026A5 (Index) 0x00000000 (Numeric) -> OnFaciltyStreamed_AlienContainment

0x00002974 -> OnFaciltyStreamed_AlienContainment

StateMap[11]:

0x00001418 (Index) 0x00000000 (Numeric) -> HandleFacilitySpecificFuncitionality

0x00002971 -> HandleFacilitySpecificFuncitionality

StateMap[12]:

0x00002F34 (Index) 0x00000000 (Numeric) -> StreamInRoom

0x0000296E -> StreamInRoom

StateMap[13]:

0x000033F1 (Index) 0x00000000 (Numeric) -> UnstreamRooms

0x00002965 -> UnstreamRooms

StateMap[14]:

0x00002F33 (Index) 0x00000000 (Numeric) -> StreamInBaseRooms

0x00002962 -> StreamInBaseRooms

StateMap[15]:

0x00001272 (Index) 0x00000000 (Numeric) -> GetMapName

0x0000295E -> GetMapName

StateMap[16]:

0x0000132B (Index) 0x00000000 (Numeric) -> GetRoomLocation

0x0000295A -> GetRoomLocation

StateMap[17]:

0x00000522 (Index) 0x00000000 (Numeric) -> BuildHQAnimChar

0x00002954 -> BuildHQAnimChar

StateMap[18]:

0x00000521 (Index) 0x00000000 (Numeric) -> BuildHQAnim

0x0000294F -> BuildHQAnim

StateMap[19]:

0x00001233 (Index) 0x00000000 (Numeric) -> GetHQAnims

0x00002947 -> GetHQAnims

StateMap[20]:

0x000017D8 (Index) 0x00000000 (Numeric) -> IsEngineeringFacility

0x00002942 -> IsEngineeringFacility

StateMap[21]:

0x00001866 (Index) 0x00000000 (Numeric) -> IsScienceFacility

0x0000293F -> IsScienceFacility

StateMap[22]:

0x00001863 (Index) 0x00000000 (Numeric) -> IsSatelliteFacility

0x0000293C -> IsSatelliteFacility

StateMap[23]:

0x0000184C (Index) 0x00000000 (Numeric) -> IsPowerFacility

0x00002939 -> IsPowerFacility

StateMap[24]:

0x00001374 (Index) 0x00000000 (Numeric) -> GetSurroundingAdjacencies

0x00002936 -> GetSurroundingAdjacencies

StateMap[25]:

0x0000113A (Index) 0x00000000 (Numeric) -> GetAdjacency

0x00002930 -> GetAdjacency

StateMap[26]:

0x00001139 (Index) 0x00000000 (Numeric) -> GetAdjacencies

0x00002928 -> GetAdjacencies

StateMap[27]:

0x00001B00 (Index) 0x00000000 (Numeric) -> LookAtFacility

0x00002920 -> LookAtFacility

StateMap[28]:

0x000005C0 (Index) 0x00000000 (Numeric) -> CanAfford

0x0000291B -> CanAfford

StateMap[29]:

0x0000177B (Index) 0x00000000 (Numeric) -> IsAccessLocation

0x00002915 -> IsAccessLocation

StateMap[30]:

0x0000142E (Index) 0x00000000 (Numeric) -> HasExcavation

0x00002911 -> HasExcavation

StateMap[31]:

0x00001135 (Index) 0x00000000 (Numeric) -> GetAccessX

0x0000290B -> GetAccessX

StateMap[32]:

0x0000141F (Index) 0x00000000 (Numeric) -> HasAccess

0x00002909 -> HasAccess

StateMap[33]:

0x000034A2 (Index) 0x00000000 (Numeric) -> UpdateTiles

0x00002905 -> UpdateTiles

StateMap[34]:

0x000030E9 (Index) 0x00000000 (Numeric) -> TileIndex

0x00002902 -> TileIndex

StateMap[35]:

0x00002ADB (Index) 0x00000000 (Numeric) -> SetFacility

0x000028FE -> SetFacility

StateMap[36]:

0x00001127 (Index) 0x00000000 (Numeric) -> GenerateTiles

0x000028FA -> GenerateTiles

StateMap[37]:

0x0000184E (Index) 0x00000000 (Numeric) -> IsPrimaryTile

0x000028F2 -> IsPrimaryTile

StateMap[38]:

0x000011E8 (Index) 0x00000000 (Numeric) -> GetFacilityAt

0x000028EE -> GetFacilityAt

StateMap[39]:

0x000017E0 (Index) 0x00000000 (Numeric) -> IsFacilityAt

0x000028EA -> IsFacilityAt

StateMap[40]:

0x00001380 (Index) 0x00000000 (Numeric) -> GetTileAt

0x000028E6 -> GetTileAt

StateMap[41]:

0x000018A3 (Index) 0x00000000 (Numeric) -> IsValidTile

0x000028E2 -> IsValidTile

StateMap[42]:

0x00002819 (Index) 0x00000000 (Numeric) -> PerformAction

0x000028DE -> PerformAction

StateMap[43]:

0x000011E7 (Index) 0x00000000 (Numeric) -> GetFacility3DLocation

0x000028D8 -> GetFacility3DLocation

StateMap[44]:

0x000011EF (Index) 0x00000000 (Numeric) -> GetFacilityLocation

0x000028D4 -> GetFacilityLocation

StateMap[45]:

0x00001664 (Index) 0x00000000 (Numeric) -> Init

0x000028CF -> Init

StateMap[46]:

0x000011A8 (Index) 0x00000000 (Numeric) -> GetCurrentCaptive

0x000028CE -> GetCurrentCaptive

UClass:

ClassFlags = 0x00800036

0x00000002: Compiled

0x00000004: Config

0x00000010: Parsed

0x00000020: Localized

0x00800000: CacheExempt

0x00800000: Hidden

WithinRef = 0xFFFFFEDD -> Object

ConfigNameIdx = 0x000010F6 (Index) 0x00000000 (Numeric) -> GameData

NumComponents = 0x00000000 (0)

NumInterfaces = 0x00000000 (0)

NumDontSortCategories = 0x00000000 (0)

NumHideCategories = 0x00000001 (1)

HideCategories[0]:

0x000025A6 (Index) 0x00000000 (Numeric) -> Navigation

NumAutoExpandCategories = 0x00000000 (0)

NumAutoCollapseCategories = 0x00000000 (0)

ForceScriptOrder = 0x00000000

NumClassGroups = 0x00000000 (0)

NativeClassNameLength = 0x00000000

DLLBindName = 0x000025E0 (Index) 0x00000000 (Numeric) -> None

DefaultRef = 0x00002993 -> Default__XGBase

 

Ok I found an object of my interest. What I can I do next? ... the part I wish to alter is under GenerateTIles. Can I cut out that particular part of the code somehow to take a closer look in Hex editor?

 

What do these numbers mean?

 

StateMap[36]:

0x00001127 (Index) 0x00000000 (Numeric) -> GenerateTiles

0x000028FA -> GenerateTiles

Link to comment
Share on other sites

./FindObjectEntry xcomstrategygame.upk XGBase.GenerateTiles /d
This will create XGBase.GenerateTiles.Function binary file. Serial data format can be found here: http://www.nexusmods.com/xcom/download/1000003820 Some information on Unreal Script bytecode can be found here: http://wiki.tesnexus.com/index.php/Hex_editing_UPK_files

 

Have you tried to run UE Explorer under wine?

 

BTW, there is another script decompiler for UE: http://code.google.com/p/unhood/ It's open-source and written in C#. I haven't yet tried to compile it under linux. I don't even know if C# compilers exist under linux. :smile: I'm not a programmer, believe it or not. :smile:

 

StateMap is a map (Unreal Script data type), which maps state names to corresponding object indexes. It's related to UState objects, I don't know how it is used internally. Since XGBase is a class and UClass type inherits from UState type, XGBase also has state properties inside. Along with other properties from other types it inherits from. Serialization format is partially explained in the document I linked. But there are a lot of things we still don't know.

Edited by wghost81
Link to comment
Share on other sites

Thanks fragmenting the file helped a lot, it is a lot easier to find wanted values in smaller fragments.

 

Anyway to change starting free radar position you have to alter the hex sequence 2C-09-2C-02-26. It's unique for xcomstrategygame.upk so simply search it up (Its offset for EW is 322D0E btw). The following sequence shows type of facilty and coordinated in base grid (f,x,y).

 

If there is 2C before the value it's real value is calucaletd by converting hex to decimal number. If there is no 2C before the value then 25 represents 0, 26 represents 1 and so on. SO that means we have facility type 9, located on x-position 2 and on y-position 1.

 

To learn more on x and y poitions look first post here: http://forums.nexusmods.com/index.php?/topic/811577-base-generation/

 

SO to move free radar to utmost left position of first level change hex code to 2C-09-2C-00-26. Theoretically you could change the type of facility by fiddling with the first value so changing the code to 2C-0E-2C-02-26 should give you large radar instead of the small one (I didn't test it). And changing the code to 2C-09-2C-02-27 should move the small radar to second level. Easy, right?

 

Next I managed to change probabilty of getting the right part of the tunnel excavated. Default chance is 75% to be solid rock. YOu have to search for 2C-4B-16-16-0F unique hex sequence (it's offset is 322AD7). 4B decimal value is 75%. Simply change that value to any hex value you would like it to be. I.e. if you want to guarantee that all right coridors will be excavated change it to 00, and if you would like 25% chance to be slid rock change it to 19.

 

That's it so far... I just need to figure out how to restrict steam vents to lvl 4 if it's possible.

Edited by Amphibious
Link to comment
Share on other sites

I don't recommend to use global offsets, as those can change with the patch. Download UPKUtils from Nexus, there is a readme file on how to use PatchUPK "language" and write your own mods. Use relative references and find/replace sequences inside an object. This will help you to keep compatibility between different game versions (most mods can be made compatible with both EU and EW) and between different patches.
Link to comment
Share on other sites

I don't recommend to use global offsets, as those can change with the patch. Download UPKUtils from Nexus, there is a readme file on how to use PatchUPK "language" and write your own mods. Use relative references and find/replace sequences inside an object. This will help you to keep compatibility between different game versions (most mods can be made compatible with both EU and EW) and between different patches.

True (that's why I mentioned them in brackets, my choice is to search those unique hex sequences with hex editor), and I don't plan to release mods and have disabled auto'updates on Steam. In any case if anyone wishes to change starting base layout a bit now they will know how.

Edited by Amphibious
Link to comment
Share on other sites

Disabling auto-updates does not prevent Steam from downloading a patch. It prevents silent downloads only. Once patch is released, you won't be able to play the game until you've downloaded it. Switching to offline mode after new patch was released and scheduled for download by Steam isn't helping too: if Steam "knows" about patch it will prevent the game from launching.
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...