Skip to content

Instantly share code, notes, and snippets.

@emoose
Last active October 15, 2021 18:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emoose/3feb2cadd0a6a53374c6a49c98edcede to your computer and use it in GitHub Desktop.
Save emoose/3feb2cadd0a6a53374c6a49c98edcede to your computer and use it in GitHub Desktop.
New Vegas structs
#pragma once
#include <nvse/NiNodes.h>
// Most definitions here taken from JIP LN NVSE:
// https://github.com/jazzisparis/JIP-LN-NVSE/blob/master/internal/netimmerse.h
// Though most lighting-related structs have had some extra things mapped out here
template <typename T_Data> struct DListNode
{
DListNode* next;
DListNode* prev;
T_Data* data;
DListNode* Advance(UInt32 times)
{
DListNode* result = this;
while (result && times)
{
times--;
result = result->next;
}
return result;
}
DListNode* Regress(UInt32 times)
{
DListNode* result = this;
while (result && times)
{
times--;
result = result->prev;
}
return result;
}
};
STATIC_ASSERT(sizeof(DListNode<void>) == 0xC);
template <class Item> class DList
{
public:
typedef DListNode<Item> Node;
public:
Node* first;
Node* last;
UInt32 count;
};
STATIC_ASSERT(sizeof(DList<void>) == 0xC);
class NiPoint3 : public NiMemObject
{
public:
float x, y, z;
};
STATIC_ASSERT(sizeof(NiPoint3) == 0xC);
class NiBound : public NiMemObject
{
public:
NiBound();
~NiBound();
NiPoint3 m_kCenter;
float m_fRadius;
};
//TODO: STATIC_ASSERT(sizeof(NiBound) == 0x14);
class NiProperty : public NiObjectNET
{
public:
NiProperty();
};
STATIC_ASSERT(sizeof(NiProperty) == 0x18);
typedef NiPointer<NiProperty> NiPropertyPtr;
typedef DList<NiPropertyPtr> NiPropertyList;
class NiCollisionObject : public NiObject
{
public:
NiCollisionObject(NiAVObject* pkSceneObject);
virtual ~NiCollisionObject() = 0;
NiAVObject* m_pkSceneObject;
};
STATIC_ASSERT(sizeof(NiCollisionObject) == 0xC);
typedef NiPointer<NiCollisionObject> NiCollisionObjectPtr;
// 04
class hkBaseObject
{
public:
virtual void Destroy(bool doFree);
};
// 08
class hkReferencedObject : public hkBaseObject
{
public:
hkReferencedObject();
~hkReferencedObject();
virtual void CalcStatistics(void* /* hkStatisticsCollector* */ collector);
virtual void Unk_02(void);
UInt16 sizeAndFlags; // 04
UInt16 refCount; // 06
};
// 0C
class bhkRefObject : public NiObject
{
public:
bhkRefObject();
~bhkRefObject();
virtual void SetObject(hkReferencedObject* object);
virtual void UpdateRefCount(bool incRef); // inc/dec ref, depending on arg
hkReferencedObject* refObject; // 08
};
// 10
class bhkSerializable : public bhkRefObject
{
public:
bhkSerializable();
~bhkSerializable();
virtual void Unk_25(UInt32 arg);
virtual void* /* hkpWorld* */ GetWorld(void);
virtual bool Unk_27(UInt32 arg);
virtual bool Unk_28(void);
virtual void FreeData(bool del); // free hkData
virtual UInt32 Unk_2A(void);
virtual void LoadHavokData(NiStream* stream); // called from bhkSerializable::Load after primary load is done
virtual void Unk_2C(void); // create object
virtual void* CreateHavokData(UInt8* arg); // create Cinfo, return hkData
virtual void Unk_2E(void); // destroy object
virtual void Unk_2F(void);
virtual void Unk_30(void);
void* hkData; // 0C - stores hkConstraintData (descriptor used to build hkObj)
};
// 14
class bhkWorldObject : public bhkSerializable
{
public:
bhkWorldObject();
~bhkWorldObject();
virtual void Unk_31(void);
virtual void Unk_32(void);
virtual void Unk_33(void);
virtual void Unk_34(void);
UInt32 bodyFlags; // 10
void ApplyForce(void* /* hkVector4* */ forceVector);
};
class bhkNiCollisionObject : public NiCollisionObject
{
public:
bhkNiCollisionObject();
~bhkNiCollisionObject();
virtual void Unk_28(void);
virtual void Unk_29(void);
virtual void Unk_2A(void);
virtual void Unk_2B(void);
virtual void Unk_2C(void);
virtual void Unk_2D(void);
virtual void Unk_2E(void);
virtual void Unk_2F(void);
virtual void Unk_30(void);
UInt32 flags; // 0C
bhkWorldObject* worldObj; // 10
};
class NiAVObject : public NiObjectNET
{
public:
NiAVObject();
~NiAVObject();
NiNode* m_pkParent;
NiCollisionObjectPtr m_spCollisionObject;
NiBound* m_kWorldBound;
NiPropertyList m_kPropertyList;
unsigned int m_uFlags;
NiTransform m_kLocal;
NiTransform m_kWorld;
};
STATIC_ASSERT(sizeof(NiAVObject) == 0x9C);
class NiDynamicEffect : public NiAVObject
{
public:
NiDynamicEffect();
~NiDynamicEffect();
bool m_bOn;
char m_ucEffectType;
int m_iIndex;
unsigned int m_uiPushCount;
unsigned int m_uiRevID;
DList<NiNode*> m_kAffectedNodeList;
DList<NiNode*> m_kUnaffectedNodeList;
};
STATIC_ASSERT(sizeof(NiDynamicEffect) == 0xC4);
class NiLight : public NiDynamicEffect
{
public:
NiLight();
~NiLight();
/* 0xC4 */ float m_fDimmer;
/* 0xC8 */ NiColor m_kAmb;
/* 0xD4 */ NiColor m_kDiff;
/* 0xE0 */ NiColor m_kSpec;
/* 0xEC */ void* m_pvRendererData;
};
STATIC_ASSERT(sizeof(NiLight) == 0xF0);
class NiPointLight : public NiLight
{
public:
NiPointLight();
~NiPointLight();
float m_fAtten0;
float m_fAtten1;
float m_fAtten2;
};
STATIC_ASSERT(sizeof(NiPointLight) == 0xFC);
// Name taken from Oblivion.exe
//
// https://github.com/jazzisparis/JIP-LN-NVSE/blob/master/internal/netimmerse.h#L1016
// (thanks to TrueCourierSix for letting me know!)
class ShadowSceneLight : public NiRefObject
{
public:
ShadowSceneLight();
~ShadowSceneLight();
/* 0x08 */ UInt32 unk8;
/* 0x0C */ float unkC[49];
/* 0xD0 */ float unkD0;
/* 0xD0 */ float unkD4;
/* 0xD0 */ float unkD8;
/* 0xD0 */ float unkDC;
/* 0xE0 */ DList<void> kLightStrips; // NiTriStrips
/* 0xEC */ BYTE bFlagUnkEC;
/* 0xED */ BYTE unkED;
/* 0xEE */ BYTE unkEE[2]; // pad
/* 0xF0 */ void* unkF0;
/* 0xF4 */ BYTE unkF4;
/* 0xF5 */ BYTE unkF5;
/* 0xF8 */ NiPointLight* spBaseLight; // base obj?
/* 0xFC */ BYTE unkFC; // 1 = pip light? (don't believe its lies)
/* 0x100 */ float fPosition[3]; // only set in pip light?
/* 0x10C */ void* unk10C;
/* 0x110 */ WORD bIsEnabled; // 0xFF = disabled (distance too far), anything else = enabled
/* 0x112 */ WORD unk112;
/* 0x114 */ void* unk114;
/* 0x118 */ BYTE unk118;
/* 0x119 */ BYTE unk119[3]; // pad
/* 0x11C */ float unk11C;
/* 0x120 */ float unk120;
/* 0x124 */ BYTE unk124;
/* 0x125 */ BYTE unk125[3]; // pad
/* 0x128 */ void* unk128; // float**?
/* 0x12C */ DList<NiAVObject> unk12C; // "NiTPointerList<NiPointer<NiAVObject>>" in Oblivion, maybe all NiTPointerLists are NVSE DList now?
/* 0x138 */ DWORD unk138;
/* 0x13C */ void* unk13C; // NiTriShape*
/* 0x140 */ void* unk140;
/* 0x12C */ DWORD unk144[24];
/* 0x1A4 */ DWORD unk1A4;
/* 0x1A8 */ BYTE unk1A8[0x60];
/* 0x208 */ BYTE unk208;
/* 0x20C */ void* unk20C;
/* 0x210 */ void* unk210; //vftable? non-RTTI ver of BSSimpleArray ?
/* 0x214 */ DWORD unk214;
/* 0x218 */ DWORD unk218;
/* 0x21C */ DWORD unk21C;
/* 0x220 */ void* unk220; //vftable? non-RTTI ver of BSSimpleArray ?
/* 0x224 */ DWORD unk224;
/* 0x228 */ DWORD unk228;
/* 0x22C */ DWORD unk22C;
/* 0x230 */ BSSimpleArray<NiNode> array230;
/* 0x240 */ BSPortalGraph* portalGraph;
/* 0x244 */ DWORD unk244[3];
bool active_light() const // game checks this stuff at 0xB70790
{
return spBaseLight != 0 && bIsEnabled != 0xFF && (spBaseLight->m_uFlags & 1) != 1;
// & 1 = & APP_CULLED_MASK
}
bool active_light_2() const // game checks this stuff at 0xB707D0
{
return active_light() && bFlagUnkEC == 0;
}
float distance(ShadowSceneLight* other) const
{
float delta_x = spBaseLight->m_kWorld.translate.x - other->spBaseLight->m_kWorld.translate.x;
float delta_y = spBaseLight->m_kWorld.translate.y - other->spBaseLight->m_kWorld.translate.y;
float delta_z = spBaseLight->m_kWorld.translate.z - other->spBaseLight->m_kWorld.translate.z;
float delta = delta_x * delta_x + delta_y * delta_y + delta_z * delta_z;
delta = sqrtf(delta);
return delta - spBaseLight->m_kSpec.r;
}
bool is_pip_light() const
{
if (!active_light_2())
return false;
if (spBaseLight->m_pcName != 0)
return false;
if (unkFC != 1)
return false;
if (fPosition[0] == 0 && fPosition[1] == 0 && fPosition[2] == 0)
return false;
return true;
//return unk4 == 2 && unkFC == 1 && (object != 0 && *(BYTE**)(object + 8) == 0);
//split the above up to allow breakpoint tests...
}
// light-cell size seems to be 1024, actual cell size is 4096 though?
bool crosses_cells() const
{
int cellX_r = (int)spBaseLight->m_kWorld.translate.x % 1024;
int cellY_r = (int)spBaseLight->m_kWorld.translate.y % 1024;
if (cellX_r + spBaseLight->m_kSpec.r > 1024 || cellX_r - spBaseLight->m_kSpec.r < 0)
return true;
if (cellY_r + spBaseLight->m_kSpec.r > 1024 || cellY_r - spBaseLight->m_kSpec.r < 0)
return true;
return false;
}
};
STATIC_ASSERT(sizeof(ShadowSceneLight) == 0x250);
typedef DListNode<ShadowSceneLight> LightingDataNode;
typedef DList<ShadowSceneLight> LightingDataList;
// 30 - NiTexture
class NiTexture2 : public NiObjectNET
{
public:
NiTexture2();
~NiTexture2();
virtual void Unk_23(void);
virtual void Unk_24(void);
virtual void Unk_25(void);
virtual void Unk_26(void);
virtual void Unk_27(void);
virtual void Unk_28(void);
enum
{
kPxlLayout_Palette8BPP = 0,
kPxlLayout_Raw16BPP,
kPxlLayout_Raw32BPP,
kPxlLayout_Compressed,
kPxlLayout_Bumpmap,
kPxlLayout_Palette4BPP,
kPxlLayout_Default,
kAlphaFmt_None = 0,
kAlphaFmt_Binary1BPP,
kAlphaFmt_Smooth8BPP,
kAlphaFmt_Default,
kMipMapFmt_Disabled = 0,
kMipMapFmt_Enabled,
kMipMapFmt_Default,
};
UInt32 pixelLayout; // 18
UInt32 alphaFormat; // 1C
UInt32 mipmapFormat; // 20
void *textureData; // 24 NiDX9TextureData
NiTexture *prev; // 28
NiTexture *next; // 2C
};
// 48 - NiSourceTexture
class NiSourceTexture2 : public NiTexture2
{
public:
NiSourceTexture2();
~NiSourceTexture2();
virtual void Unk_29(void);
virtual void Unk_2A(void);
virtual void Unk_2B(void);
char *ddsPath1; // 30
char *ddsPath2; // 34
UInt32 unk38; // 38
UInt32 unk3C; // 3C
UInt8 byte40; // 40
UInt8 byte41; // 41
UInt8 byte42; // 42
UInt8 byte43; // 43
UInt32 unk44; // 44
};
class NiShadeProperty : public NiProperty
{
public:
NiShadeProperty();
~NiShadeProperty();
};
class BSShaderProperty : public NiShadeProperty
{
public:
// names from oblivion eboot.bin
class RenderPass
{
public:
void* spTriStrips; // NiTriStrips*
WORD iPassNum;
BYTE unk6;
BYTE bEnabled; // if set pass becomes "Fpass" instead of "pass" ?
BYTE unk8;
BYTE unk9;
BYTE unkA;
BYTE unkB;
void* unkC;
};
STATIC_ASSERT(sizeof(RenderPass) == 0x10); // no idea if size is correct, probably not
// NiTArray<RenderPass> but with an extra int at the end for some reason
class RenderPassList
{
public:
virtual void Destroy(bool doFree);
RenderPass** m_pBase;
WORD m_usMaxSize;
WORD m_usSize;
WORD m_usESize;
WORD m_usGrowBy;
DWORD iNumPasses; // doesn't equal m_usSize, weird
};
STATIC_ASSERT(sizeof(RenderPassList) == 0x14);
BSShaderProperty();
~BSShaderProperty();
WORD unk18;
DWORD unk1C;
DWORD unk20;
DWORD unk24;
float fAlpha;
float fFadeAlpha;
float fEnvmapScale; // "Envmap Scale"
float unk34;
DWORD iLastRenderPassState;
RenderPassList* pRenderPassList;
void* unk40;
DWORD unk44;
DWORD unk48;
DWORD unk4C;
DWORD unk50;
DWORD unk54; // pad?
DWORD iShaderIndex; // "Shader Index"
float fDepthBias;
};
STATIC_ASSERT(sizeof(BSShaderProperty) == 0x60);
class BSShaderLightingProperty : public BSShaderProperty
{
public:
BSShaderLightingProperty();
~BSShaderLightingProperty();
DList<ShadowSceneLight> lights;
float unk6C;
DWORD iReferenceID; // "Reference ID"
BYTE unk74;
DWORD unk78;
};
STATIC_ASSERT(sizeof(BSShaderLightingProperty) == 0x7C);
class BSShaderPPLightingProperty : public BSShaderLightingProperty
{
public:
// names from oblivion, fields unknown...
class TangentSpaceData : NiRefObject
{
public:
BYTE unk8;
void* unkC;
void* unk10;
};
STATIC_ASSERT(sizeof(TangentSpaceData) == 0x14);
class TextureEffectData : NiRefObject
{
public:
void* unk8;
float fFillColorR;
float fFillColorG;
float fFillColorB;
float fFillColorA;
float fEdgeColorR;
float fEdgeColorG;
float fEdgeColorB;
float fEdgeColorA;
float unk2C[10];
float fEdgeFalloff;
float unk58;
DWORD unk5C;
DWORD unk60;
DWORD unk64;
DWORD unk68;
void* unk6C;
DWORD unk70;
};
STATIC_ASSERT(sizeof(TextureEffectData) == 0x74);
BSShaderPPLightingProperty();
~BSShaderPPLightingProperty();
DWORD unk7C; // unused?
DWORD unk80; // unused?
float unk84;
float unk88;
float unk8C;
float unk90;
float unk94;
float unk98;
float unk9C;
float unkA0;
DWORD unkA4;
WORD iNumLandscapeTextures; // "landscape textures"
NiSourceTexture2** spTextureBase; // "base tex" / "base diff" / "multi diff"
NiSourceTexture2** spTextureNormal; // "normal map" / "base normal" / "multi normal"
NiSourceTexture2** spTextureGlow; // "glow map" / "glow/skin sst/hair layer texture"
NiSourceTexture2** spTextureHeightmap; // "heightmap texture"
NiSourceTexture2** spTextureEnvmap; // "envmap texture"
NiSourceTexture2** spTextureEnvmapMask; // "envmap mask texture"
void* unkC4;
DWORD unkC8; // pad?
bool* pbTextureIsSpecular; // "specular"
TangentSpaceData* spTangentSpaceData; // unsure if TangentSpaceData*, definitely NiRefObject
void* unkD4;
DWORD unkD8;
TextureEffectData* spTexEffectData; // "spTexEffectData"
float fRefractionPower; // "refraction power"
DWORD iRefractionPeriod; // "refraction period"
float unkE8;
float unkEC;
DWORD unkF0[4]; // unused?
float* unk100;
};
STATIC_ASSERT(sizeof(BSShaderPPLightingProperty) == 0x104);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment