Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions nmspy/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@
class GameData:
GcApplication: nms.cGcApplication = None # type: ignore

@property
def environment(self) -> Optional[nms.cGcEnvironment]:
if (sim := self.simulation) is not None:
return sim.mEnvironment

@property
def player_environment(self) -> Optional[nms.cGcPlayerEnvironment]:
if (env := self.environment) is not None:
return env.mPlayerEnvironment

@property
def game_state(self) -> Optional[nms.cGcGameState]:
if self.GcApplication is not None:
Expand Down
1 change: 1 addition & 0 deletions nmspy/data/enums/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
StateEnum,
eStormState,
eLanguageRegion,
EnvironmentLocation,
)

# The following list is auto-generated.
Expand Down
20 changes: 20 additions & 0 deletions nmspy/data/enums/internal_enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,23 @@ class eLanguageRegion(IntEnum):
SimplifiedChinese = 0xE
TencentChinese = 0xF
Korean = 0x10


class EnvironmentLocation:
class Enum(IntEnum):
None_ = 0x0
Default = 0x1
SpaceStation = 0x2
PlanetOnFoot = 0x3
PlanetInShip = 0x4
PlanetInVehicle = 0x5
Underwater = 0x6
Cave = 0x7
IndoorInBase = 0x8
Freighter = 0x9
FreighterInternals = 0xA
AbandonedFreighter = 0xB
InFleet = 0xC
InSpaceObject = 0xD
Nexus = 0xE
Anomaly = 0xF
160 changes: 122 additions & 38 deletions nmspy/data/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ class cGcPlayerState(Structure):
muUnits: Annotated[int, Field(c_uint32, 0x1BC)]
muNanites: Annotated[int, Field(c_uint32, 0x1C0)]
muSpecials: Annotated[int, Field(c_uint32, 0x1C4)]
# Found in cGcPlayerShipOwnership::SpawnNewShip
miPrimaryShip: Annotated[int, Field(c_uint32, 0xC4F0)]

@function_hook(
"48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC ? 44 8B 81 ? ? ? ? 48 8D 2D"
Expand Down Expand Up @@ -274,9 +276,59 @@ def StoreCurrentSystemSpaceStationEndpoint(
): ...


@partial_struct
class cGcPlayerShipOwnership(Structure):
@partial_struct
class sGcShipData(Structure):
_total_size_ = 0x48

mPlayerShipSeed: Annotated[basic.cTkSeed, 0x0]

@function_hook(
"48 89 5C 24 ? 55 56 57 41 54 41 56 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 45"
)
def UpdateMeshRefresh(self, this: "_Pointer[cGcPlayerShipOwnership]"): ...

@function_hook(
"48 8B C4 55 53 56 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 80 B9 ? ? ? ? ? 48 8B F1"
)
def Update(
self,
this: "_Pointer[cGcPlayerShipOwnership]",
lfTimestep: Annotated[float, c_float],
): ...

@function_hook("44 89 44 24 ? 48 89 54 24 ? 55 56 41 54 41 56 41 57 48 8D 6C 24")
def SpawnNewShip(
self,
this: "_Pointer[cGcPlayerShipOwnership]",
lMatrix: _Pointer[basic.cTkMatrix34],
leLandingGearState: c_uint32, # cGcPlayerShipOwnership::ShipSpawnLandingGearState
liShipIndex: c_int32,
lbSpawnShipOverride: c_bool,
) -> c_bool: ...

@function_hook(
"48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 56 48 83 EC ? 48 8B 35 ? ? ? ? 8B DA"
)
def DestroyShip(
self,
this: "_Pointer[cGcPlayerShipOwnership]",
liShipIndex: c_int32,
) -> c_bool: ...

# Not sure about this...
mShips: Annotated[list[sGcShipData], Field(sGcShipData * 12, 0x58)]
# Both these found at the top of cGcPlayerShipOwnership::UpdateMeshRefresh
mbShouldRefreshMesh: Annotated[bool, Field(c_bool, 0xA690)]
mMeshRefreshState: Annotated[int, Field(c_uint32, 0xA694)]


@partial_struct
class cGcGameState(Structure):
mPlayerState: Annotated[cGcPlayerState, 0xA950]
# Found in cGcGameState::Update
mPlayerShipOwnership: Annotated[cGcPlayerShipOwnership, 0xA2BD0]

@function_hook("48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 88 54 24")
def OnSaveProgressCompleted(
Expand All @@ -292,11 +344,18 @@ def OnSaveProgressCompleted(
def LoadFromPersistentStorage(
self,
this: "_Pointer[cGcGameState]",
leSlot: c_uint32,
leSlot: Annotated[int, c_uint32],
a3: c_int32,
lbNetworkClientLoad: Annotated[bool, c_bool],
) -> c_uint64: ...

@function_hook(
"48 8B C4 48 89 58 ? 48 89 70 ? 48 89 78 ? 55 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? F3 0F 10 91"
)
def Update(
self, this: "_Pointer[cGcGameState]", lfTimeStep: Annotated[float, c_float]
): ...


class cTkFSM(Structure):
@function_hook(
Expand Down Expand Up @@ -553,8 +612,59 @@ def Update(
): ...


@partial_struct
class cGcPlayerEnvironment(Structure):
mPlayerTM: Annotated[basic.cTkMatrix34, Field(basic.cTkMatrix34, 0x0)]
mUp: Annotated[basic.Vector3f, Field(basic.Vector3f, 0x40)]

# Found below the call to cTkDynamicGravityControl::GetGravity in cGcPlayerEnvironment::Update
miNearestPlanetIndex: Annotated[int, Field(c_uint32, 0x2BC)]
mfDistanceFromPlanet: Annotated[float, Field(c_float, 0x2C0)]
mfNearestPlanetSealevel: Annotated[float, Field(c_float, 0x2C4)]
mNearestPlanetPos: Annotated[basic.Vector3f, Field(basic.Vector3f, 0x2D0)]
mbInsidePlanetAtmosphere: Annotated[bool, Field(c_bool, 0x2EC)]
meLocation: Annotated[
enums.EnvironmentLocation.Enum,
Field(c_enum32[enums.EnvironmentLocation.Enum], 0x458),
]
meLocationStable: Annotated[
enums.EnvironmentLocation.Enum,
Field(c_enum32[enums.EnvironmentLocation.Enum], 0x464),
]

@function_hook("48 83 EC ? 80 B9 ? ? ? ? ? C6 04 24")
def IsOnboardOwnFreighter(
self, this: "_Pointer[cGcPlayerEnvironment]"
) -> c_bool: ...

@function_hook("8B 81 ? ? ? ? 83 E8 ? 83 F8 ? 0F 96 C0 C3 48 83 EC")
def IsOnPlanet(self, this: "_Pointer[cGcPlayerEnvironment]") -> c_bool: ...

@function_hook("48 8B C4 F3 0F 11 48 ? 55 53 41 54")
def Update(
self,
this: "_Pointer[cGcPlayerEnvironment]",
lfTimeStep: Annotated[float, c_float],
): ...


@partial_struct
class cGcEnvironment(Structure):
# Passed into multiple cGcPlayerEnvironment methods.
mPlayerEnvironment: Annotated[cGcPlayerEnvironment, 0x8A0]

@function_hook(
"48 8B C4 48 89 48 ? 55 53 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 ? 4C 8B E9"
)
def UpdateRender(self, this: "_Pointer[cGcEnvironment]"):
# TODO: There could be a few good functions to get which are called in here...
...


@partial_struct
class cGcSimulation(Structure):
# Found in cGcSimulation::Update. Passed into cGcEnvironment::Update.
mEnvironment: Annotated[cGcEnvironment, 0xAF790]
mPlayer: Annotated[cGcPlayer, 0x24DE40]
# Found in cGcSimulation::Update. Passed into cGcSolarSystem::Update.
mpSolarSystem: Annotated[_Pointer[cGcSolarSystem], 0x24C670]
Expand Down Expand Up @@ -825,34 +935,6 @@ def UpdateGravityPoint(
]


@partial_struct
class cGcPlayerEnvironment(Structure):
mPlayerTM: Annotated[basic.cTkMatrix34, Field(basic.cTkMatrix34, 0x0)]
mUp: Annotated[basic.Vector3f, Field(basic.Vector3f, 0x40)]

# Found below the call to cTkDynamicGravityControl::GetGravity in cGcPlayerEnvironment::Update
miNearestPlanetIndex: Annotated[int, Field(c_uint32, 0x2BC)]
mfDistanceFromPlanet: Annotated[float, Field(c_float, 0x2C0)]
mfNearestPlanetSealevel: Annotated[float, Field(c_float, 0x2C4)]
mNearestPlanetPos: Annotated[basic.Vector3f, Field(basic.Vector3f, 0x2D0)]
mbInsidePlanetAtmosphere: Annotated[bool, Field(c_bool, 0x2EC)]

@function_hook("48 83 EC ? 80 B9 ? ? ? ? ? C6 04 24")
def IsOnboardOwnFreighter(
self, this: "_Pointer[cGcPlayerEnvironment]"
) -> c_bool: ...

@function_hook("8B 81 ? ? ? ? 83 E8 ? 83 F8 ? 0F 96 C0 C3 48 83 EC")
def IsOnPlanet(self, this: "_Pointer[cGcPlayerEnvironment]") -> c_bool: ...

@function_hook("48 8B C4 F3 0F 11 48 ? 55 53 41 54")
def Update(
self,
this: "_Pointer[cGcPlayerEnvironment]",
lfTimeStep: Annotated[float, c_float],
): ...


class Engine:
@static_function_hook("40 53 48 83 EC ? 44 8B D1 44 8B C1")
@staticmethod
Expand Down Expand Up @@ -1096,15 +1178,6 @@ def StateChange(
): ...


class cGcEnvironment(Structure):
@function_hook(
"48 8B C4 48 89 48 ? 55 53 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 ? 4C 8B E9"
)
def UpdateRender(self, this: "_Pointer[cGcEnvironment]"):
# TODO: There could be a few good functions to get which are called in here...
...


class cGcPlayerNotifications(Structure):
@function_hook("48 89 5C 24 ? 48 89 74 24 ? 57 48 81 EC ? ? ? ? 44 8B 81")
def AddTimedMessage(
Expand Down Expand Up @@ -1236,7 +1309,15 @@ def GetPulseDriveFuelFactor(
) -> c_float: ...


@partial_struct
class cGcSpaceshipWeapons(Structure):
# These can be found in cGcSpaceshipWeapons::GetHeatFactor and cGcSpaceshipWeapons::GetOverheatProgress
# This enum corresponds to the element in the following 3 arrays by index.
meWeaponMode: Annotated[c_enum32[enums.cGcShipWeapons], 0xA4]
mafWeaponHeat: Annotated[list[float], Field(c_float * 7, 0x5FA4)]
mafWeaponOverheatTimer: Annotated[list[float], Field(c_float * 7, 0x5FC0)]
mabWeaponOverheated: Annotated[list[bool], Field(c_bool * 7, 0x5FDC)]

@function_hook("48 63 81 ?? ?? 00 00 80 BC 08 ?? ?? 00 00 00 74 12")
def GetOverheatProgress(self, this: "_Pointer[cGcSpaceshipWeapons]") -> c_float: ...

Expand All @@ -1257,6 +1338,9 @@ def GetCurrentShootPoints(
) -> c_uint64: # cGcShootPoint *
...

@function_hook("48 63 81 ? ? ? ? F3 0F 10 84 81")
def GetHeatFactor(self, this: "_Pointer[cGcSpaceshipWeapons]") -> c_float: ...


class cGcPlayerCharacterComponent(Structure):
@function_hook("48 8B C4 55 53 56 57 41 56 48 8D 68 A1 48 81 EC 90 00 00")
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ classifiers = [
dependencies = [
"pymhf[gui]>=0.2.1"
]
version = "155759.0"
version = "155983.0"

[dependency-groups]
dev = [
Expand Down
30 changes: 30 additions & 0 deletions tools/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -743,5 +743,35 @@
"name": "Engine::AddGroupNode",
"signature": "48 89 5C 24 ? 57 48 81 EC ? ? ? ? 44 8B D2 44 8B CA 41 C1 EA ? 41 81 E1 ? ? ? ? 48 8B D9 45 85 D2 0F 84 ? ? ? ? 41 81 F9 ? ? ? ? 0F 84 ? ? ? ? 8B CA 48 8B 15 ? ? ? ? 81 E1 ? ? ? ? 48 8B 82 ? ? ? ? 48 63 0C 88 48 8B 82 ? ? ? ? 48 8B 3C C8 48 85 FF 74 ? 8B 4F ? 8B C1 25 ? ? ? ? 41 3B C1 75 ? C1 E9 ? 41 3B CA 75 ? 4C 8B CF 48 8D 4C 24 ? BA ? ? ? ? E8 ? ? ? ? 48 8B 0D ? ? ? ? 48 8D 05 ? ? ? ? 4C 8D 4C 24 ? 48 89 44 24 ? 41 B8 ? ? ? ? 48 89 7C 24 ? 48 8B D3 E8 ? ? ? ? 48 8D 4C 24 ? E8 ? ? ? ? EB ? C7 03 ? ? ? ? 48 8B C3 48 8B 9C 24 ? ? ? ? 48 81 C4 ? ? ? ? 5F C3 CC CC CC CC CC 48 89 5C 24",
"mangled_name": "?AddGroupNode@Engine@@YA?AVTkHandle@@V2@PEBD@Z"
},
{
"name": "cGcPlayerShipOwnership::UpdateMeshRefresh",
"signature": "48 89 5C 24 ? 55 56 57 41 54 41 56 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 45",
"mangled_name": "?UpdateMeshRefresh@cGcPlayerShipOwnership@@AEAAXXZ"
},
{
"name": "cGcPlayerShipOwnership::Update",
"signature": "48 8B C4 55 53 56 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 80 B9 ? ? ? ? ? 48 8B F1",
"mangled_name": "?Update@cGcPlayerShipOwnership@@QEAAXM@Z"
},
{
"name": "cGcGameState::Update",
"signature": "48 8B C4 48 89 58 ? 48 89 70 ? 48 89 78 ? 55 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? F3 0F 10 91",
"mangled_name": "?Update@cGcGameState@@QEAAXM@Z"
},
{
"name": "cGcPlayerShipOwnership::SpawnNewShip",
"signature": "44 89 44 24 ? 48 89 54 24 ? 55 56 41 54 41 56 41 57 48 8D 6C 24",
"mangled_name": "?SpawnNewShip@cGcPlayerShipOwnership@@QEAA_NAEBVcTkMatrix34@@W4ShipSpawnLandingGearState@1@H_N@Z"
},
{
"name": "cGcPlayerShipOwnership::DestroyShip",
"signature": "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 56 48 83 EC ? 48 8B 35 ? ? ? ? 8B DA",
"mangled_name": "?DestroyShip@cGcPlayerShipOwnership@@QEAA_NH@Z"
},
{
"name": "cGcSpaceshipWeapons::GetHeatFactor",
"signature": "48 63 81 ? ? ? ? F3 0F 10 84 81",
"mangled_name": "?GetHeatFactor@cGcSpaceshipWeapons@@UEBAMXZ"
}
]
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.