-
Notifications
You must be signed in to change notification settings - Fork 0
/
ext_obj.h
278 lines (238 loc) · 7.77 KB
/
ext_obj.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
#ifndef EXT_OBJ_H
#define EXT_OBJ_H
#include "skse/ScaleformCallbacks.h"
#include "skse/ScaleformMovie.h"
#include "skse/GameMenus.h"
#include "skse/GameExtraData.h"
#include "skse/GameRTTI.h"
void ApplyPatches();
void RegisterUpdateControl(GFxMovieView * view, GFxValue * root);
extern UInt8 * bDontUpdate;
void ScheduleInventoryUpdate();
// defined in Hooks_Scaleform.cpp -- no changes
class StandardItemData
{
public:
virtual ~StandardItemData();
virtual const char * GetName(void);
virtual UInt32 GetCount(void);
virtual UInt32 GetEquipState(void);
virtual UInt32 GetFilterFlag(void);
virtual UInt32 GetFavorite(void);
virtual bool GetEnabled(void);
// void ** _vtbl; // 00
PlayerCharacter::ObjDesc * objDesc; // 04
void * unk08; // 08 refr handle? owner id? 00100000 for player, diff for container
UInt32 unk0C; // 0C
GFxValue fxValue; // 10
//MEMBER_FN_PREFIX(StandardItemData);
//DEFINE_MEMBER_FN(ctor_data, StandardItemData *, 0x00842140, GFxMovieView ** movieView, PlayerCharacter::ObjDesc * objDesc, int unk);
//enum { kCtorHookAddress = 0x008433B0 + 0x0049 };
//StandardItemData * ctor_Hook(GFxMovieView ** movieView, PlayerCharacter::ObjDesc * objDesc, int unk);
};
struct ObjDescExt : public PlayerCharacter::ObjDesc {
DEFINE_MEMBER_FN(IsOwned, bool, 0x00477010, TESForm* checkOwner, bool defaultValue);
DEFINE_MEMBER_FN(IsOwnedData, bool, 0x004755D0, TESForm* checkOwner, ExtraOwnership* list, bool defaultValue);
bool IsStolen() {
bool ret = CALL_MEMBER_FN(this, IsOwned)(*g_thePlayer, 1);
return !ret;
}
bool FixStolenCheck(TESForm* checkOwner, ExtraOwnership* owner, bool defaultValue);
UInt32 stolenCount() {
UInt32 count = 0;
tList<BaseExtraList>::Iterator li;
//_MESSAGE("-");
for (li = extraData->Begin(); li.Get(); ++li) {
BaseExtraList * list = li.Get();
if (li->HasType(kExtraData_Ownership)) {
ExtraOwnership * owner = static_cast<ExtraOwnership*>(list->GetByType(kExtraData_Ownership));
bool isOwned = CALL_MEMBER_FN(this, IsOwnedData)(*g_thePlayer, owner, true);
if (!isOwned) {
ExtraCount * extraCount = static_cast<ExtraCount*>(list->GetByType(kExtraData_Count));
if (extraCount) {
count += extraCount->count & 0xffff; // 16 bit value
//_MESSAGE(" sc %d", extraCount->count & 0xffff);
} else {
++count;
//_MESSAGE(" sc 1");
}
}
}
}
return count;
}
};
//struct BaseExtraListExt : public BaseExtraList
//{
//DEFINE_MEMBER_FN(GetExtraData, BSExtraData*, 0x0040A8A0, ExtraDataType type);
//};
// 976580 - constructor?
class ItemMenuData
{
public:
GFxMovieView * view; // 00
UInt32 unk04;
GFxValue listObject; // 08 - List object (gets selectedIndex property, etc)
GFxValue itemList; // 18 - GFxValue array of items
tArray<StandardItemData*> items; // 28
UInt8 updatePending; // 34 - flag checked in GetSelectedItem, returns NULL if set
UInt8 unk31[3];
// grabs StandardItem that corresponds to listObject's selectedIndex
StandardItemData* GetSelectedItem() {
return CALL_MEMBER_FN(this, GetSelectedItem)();
}
MEMBER_FN_PREFIX(ItemMenuData);
// returns null if updatePending above is set
DEFINE_MEMBER_FN(GetSelectedItem, StandardItemData*, 0x00841D90);
// sets updatePending above, then calls 0x00897F90 which adds an InventoryUpdate message to the queue
//DEFINE_MEMBER_FN(ScheduleUpdate, void, 0x00841E70, TESForm* source /*not sure*/);
//DEFINE_MEMBER_FN(InvalidateListData, void, 0x00841D30);
};
//PlayerCharacter ** g_thePlayer = (PlayerCharacter **)0x01B2E8E4;
extern UInt32 * g_playerHandle;
STATIC_ASSERT(sizeof(ItemMenuData) == 0x38);
/*
class IMenu {
...
virtual UInt32 ProcessUnkData1(UnkData1* data);
...
}
ProcessUnkData1 seems to actually be:
virtual UInt32 ProcessMessage(UIMessage* message);
for menus i've looked at, it processes any messages it knows
(when UIMessage::message is 8 its an InventoryUpdateData for item menus for example, 3 is close which generally cleans up some stuff, 1 is open which initializes stuff etc)
when it doesn't it seems to call a common DefaultProcessMessage type function which is at 0x00A64940, and takes the UIMessage as an argument, and returns that value
the DefaultProcessMessage seems to call GFxMovieView::HandleEvent(UIMessage::objData) if objData is not null and UIMessage::message == 6, if it handles the message it returns 0, otherwise 2
for example:
UInt32 ProcessMessage(UIMessage* msg) {
switch (msg->message) {
case 8: // in BarterMenu, InventoryMenu, ContainerMenu, GiftMenu, etc. InventoryUpdateData
InventoryUpdateData * update = static_cast<InventoryUpdateData*>(msg->objData);
// do whatever
break;
case 1: // opening
// initialize
break;
case 3: // closing
// cleanup
break;
default:
return DefaultProcessMessage(msg);
}
return 0;
}
sh r UG
the SKSE default ProcessUnkData1 does the equivalent of that "DefaultProcessMessage" anyway, so whatever
class IUIMessageData
{
public:
virtual ~IUIMessageData();
// void ** _vtbl; // 00
UInt8 unk04; // 04
UInt8 unk05; // 05
UInt8 pad06[2]; // 06
};
*/
class InventoryUpdateData : public IUIMessageData
{
public:
UInt32 refHandle; // 08 ref handle, 0x00100000 for player, properly *0x1B2E8E8, or use container
TESForm * form; // 0C can be null
};
class BarterMenuExt : public IMenu
{
public:
ItemMenuData * itemData; // 1C
UInt32 unk20[(0x4C - 0x20) >> 2]; // 20
tArray<TESForm*> changed; // 4C list of data that changed? tArray<TESForm*> ?, pretty sure its array, branch below taken when length > 0
// added when an item is removed from one list or the other (ex sell/buy all of one type of item), so the list needs to change size
// length > 0 843FF0, == 0 843EE0
UInt32 playerGold; // 58
UInt32 vendorGold; // 5C
UInt32 sortFlag; // 60
MEMBER_FN_PREFIX(BarterMenuExt);
DEFINE_MEMBER_FN(UpdateInventory, void, 0x844450);
};
class InventoryMenu : public IMenu
{
public:
UInt32 unk1C;
UInt32 unk20;
UInt32 unk24;
UInt32 unk28;
UInt32 unk2C;
ItemMenuData * itemData; // 30
UInt32 unk34;
UInt32 unk38;
UInt32 unk3C;
UInt32 unk40;
UInt32 unkFlag; // 44 -- non-zero 86AA50 , zero 86A9F0
UInt32 unk48;
UInt32 sortFlag; // 4C switch on
MEMBER_FN_PREFIX(InventoryMenu);
DEFINE_MEMBER_FN(UpdateInventory, void, 0x86B980);
};
class ContainerMenu : public IMenu
{
public:
UInt32 unk1C;
UInt32 unk20;
UInt32 unk24;
UInt32 unk28;
UInt32 unk2C;
ItemMenuData * itemData; // 30
UInt32 unk34;
UInt32 unk38;
UInt32 unk3C;
UInt32 unk40;
UInt32 unkFlag; // 44 -- non-zero 84A710 , zero 84B020
UInt32 unk48[(0x6C - 0x48) >> 2];
UInt32 sortFlag; // 6C
MEMBER_FN_PREFIX(ContainerMenu);
DEFINE_MEMBER_FN(UpdateInventory, void, 0x84B720);
};
// could be all wrong, haven't double checked
class GiftMenu : IMenu
{
public:
UInt32 unk1C;
UInt32 unk20;
UInt32 unk24;
UInt32 unk28;
UInt32 unk2C;
ItemMenuData * itemData; // 30
UInt32 unk34;
UInt32 unk38;
UInt32 unk3C;
UInt32 unkFlag; // 40
UInt32 unk44;
UInt32 sortFlag; // 48
MEMBER_FN_PREFIX(GiftMenu);
DEFINE_MEMBER_FN(UpdateInventory, void, 0x85DDA0);
};
// Call with T = BarterMenuExt, ContainerMenu, InventoryMenu, GiftMenu
// disables the invalidatelistdata call and updates the item list immediately
extern bool g_disableInvalidate;
template<typename T>
inline void updateInventory(T * menu)
{
g_disableInvalidate = true;
CALL_MEMBER_FN(menu, UpdateInventory)();
g_disableInvalidate = false;
}
// Dumb method to get ItemMenuData, checks open menus then returns if it finds an ItemMenu (oen of the 4 above) open
// todo: less shitty way
ItemMenuData * getItemData();
/*
GFxValue::ObjectInterface
bool RemoveElements(void * data, int at, int count) = 0x00920F40
*/
inline UInt16 GetExtraCount(BaseExtraList * el) {
ExtraCount * count = static_cast<ExtraCount*>(el->GetByType(kExtraData_Count));
if (count) {
return count->count & 0xffff;
} else {
return 1;
}
}
#endif//EXT_OBJ_H