Fixed move_obj_inven_to_obj script function

* it didn't remove the equipped armor properly for the player and party
members, resulting in broken armor stats.

Added a check for valid objects to get/set_object_data functions.

Some code edits to HeroAppearance.cpp.
This commit is contained in:
NovaRain
2019-09-30 07:51:43 +08:00
parent e3a3ff2540
commit 27ec2d24fe
4 changed files with 142 additions and 101 deletions
+1 -1
View File
@@ -149,7 +149,7 @@ void sArrayVar::clearRange( int from, int to /*= -1*/ )
void sArrayVar::clearAll()
{
for (auto it = val.begin(); it != val.end(); ++it) {
for (std::vector<sArrayElement>::iterator it = val.begin(); it != val.end(); ++it) {
it->clearData();
}
}
+81 -39
View File
@@ -378,30 +378,66 @@ static void __declspec(naked) queue_clear_type_mem_free_hook() {
static void __declspec(naked) partyMemberCopyLevelInfo_hook_stat_level() {
__asm {
nextArmor:
mov eax, esi
call inven_worn_
test eax, eax
jz noArmor
and byte ptr [eax+0x27], 0xFB // Unset the flag of equipped armor
jmp nextArmor
mov eax, esi;
call inven_worn_;
test eax, eax;
jz noArmor;
and byte ptr [eax + 0x27], 0xFB; // Unset the flag of equipped armor
jmp nextArmor;
noArmor:
mov eax, esi
jmp stat_level_
mov eax, esi;
jmp stat_level_;
}
}
static void __declspec(naked) correctFidForRemovedItem_hook_adjust_ac() {
__asm {
call adjust_ac_
call adjust_ac_;
nextArmor:
mov eax, esi
call inven_worn_
test eax, eax
jz end
and byte ptr [eax+0x27], 0xFB // Unset flag of equipped armor
jmp nextArmor
mov eax, esi;
call inven_worn_;
test eax, eax;
jz end;
and byte ptr [eax + 0x27], 0xFB; // Unset flag of equipped armor
jmp nextArmor;
end:
retn
retn;
}
}
static void __declspec(naked) op_move_obj_inven_to_obj_hook() {
__asm {
jz skip; // source == dude
mov eax, edx;
call isPartyMember_;
test eax, eax; // is source a party member?
jnz skip;
retn; // must be eax = 0
skip:
mov eax, edx;
call inven_worn_;
cmp edx, ecx; // source(edx) == dude(ecx)
jz dudeFix;
test eax, eax;
jz end;
mov ecx, edx;
xor ebx, ebx; // new armor
xchg eax, edx; // set: eax - source, edx - removed armor
call adjust_ac_; // fix for party member
mov edx, ecx;
xor eax, eax;
end:
retn; // must be eax = 0
dudeFix:
test eax, eax;
jz equipped; // no armor
// additionally check flag of equipped armor for dude
test byte ptr [eax + 0x27], 0x4;
jnz equipped;
xor eax, eax;
equipped:
or cl, 1; // reset ZF
retn;
}
}
@@ -815,7 +851,7 @@ static void __declspec(naked) op_wield_obj_critter_adjust_ac_hook() {
static const DWORD partyMember_init_End = 0x493D16;
static void __declspec(naked) NPCStage6Fix1() {
__asm {
imul eax, edx, 204; // necessary memory = number of NPC records in party.txt * record size
imul eax, edx, 204; // multiply record size 204 bytes by number of NPC records in party.txt
mov ebx, eax; // copy total record size for later memset
call mem_malloc_; // malloc the necessary memory
jmp partyMember_init_End; // call memset to set all malloc'ed memory to 0
@@ -1635,16 +1671,16 @@ end:
static void __declspec(naked) op_obj_can_hear_obj_hack() {
__asm {
mov eax, [esp + 0x28 - 0x28 + 4]; // target
mov edx, [esp + 0x28 - 0x24 + 4]; // source
mov eax, [esp + 0x28 - 0x28 + 4]; // target
mov edx, [esp + 0x28 - 0x24 + 4]; // source
retn;
}
}
static void __declspec(naked) ai_best_weapon_hook() {
__asm {
mov eax, [esp + 0xF4 - 0x10 + 4]; // prev.item
jmp item_w_perk_;
mov eax, [esp + 0xF4 - 0x10 + 4]; // prev.item
jmp item_w_perk_;
}
}
@@ -1665,11 +1701,11 @@ static void __declspec(naked) wmSetupRandomEncounter_hook() {
static void __declspec(naked) inven_obj_examine_func_hack() {
__asm {
mov edx, dword ptr ds:[0x519064]; // inven_display_msg_line
cmp edx, 2; // 2 or more lines
cmp edx, 2; // >2
ja fix;
retn;
fix:
cmp edx, 9; // 8 lines (half of the display window)
cmp edx, 5; // 4 lines
ja limit;
dec edx;
sub eax, 3;
@@ -1677,7 +1713,7 @@ fix:
add eax, 3;
retn;
limit:
mov eax, 57;
mov eax, 30;
retn;
}
}
@@ -1883,9 +1919,9 @@ skip:
static void __declspec(naked) op_attack_hook() {
__asm {
mov esi, dword ptr [esp + 0x3C + 4]; // free_move
mov ebx, dword ptr [esp + 0x40 + 4]; // add amount damage to target
jmp gdialogActive_;
mov esi, dword ptr [esp + 0x3C + 4]; // free_move
mov ebx, dword ptr [esp + 0x40 + 4]; // add amount damage to target
jmp gdialogActive_;
}
}
@@ -1953,8 +1989,8 @@ isLoad:
static void __declspec(naked) JesseContainerFid() {
__asm {
dec edx; // set fid to -1
jmp obj_new_;
dec edx; // set fid to -1
jmp obj_new_;
}
}
@@ -2042,11 +2078,11 @@ static void __declspec(naked) obj_load_dude_hook1() {
static void __declspec(naked) PrintAMList_hook() {
__asm {
cmp ebp, 20; // max line count
jle skip;
mov ebp, 20;
cmp ebp, 20; // max line count
jle skip;
mov ebp, 20;
skip:
jmp qsort_;
jmp qsort_;
}
}
@@ -2308,9 +2344,9 @@ void BugFixesInit()
if (isDebug && (GetPrivateProfileIntA("Debugging", "BugFixes", 1, ".\\ddraw.ini") == 0)) return;
#endif
// fix vanilla negate operator on float values
// Fix vanilla negate operator on float values
MakeCall(0x46AB68, NegateFixHack);
// fix incorrect int-to-float conversion
// Fix incorrect int-to-float conversion
// op_mult:
SafeWrite16(0x46A3F4, 0x04DB); // replace operator to "fild 32bit"
SafeWrite16(0x46A3A8, 0x04DB);
@@ -2382,6 +2418,10 @@ void BugFixesInit()
dlog("Applying fix for armor reducing NPC original stats when removed.", DL_INIT);
HookCall(0x495F3B, partyMemberCopyLevelInfo_hook_stat_level);
HookCall(0x45419B, correctFidForRemovedItem_hook_adjust_ac);
// Fix for move_obj_inven_to_obj function
HookCall(0x45C49A, op_move_obj_inven_to_obj_hook);
SafeWrite16(0x45C496, 0x9090);
SafeWrite8(0x45C4A3, 0x75); // jmp > jnz
dlogr(" Done", DL_INIT);
//}
@@ -2497,19 +2537,21 @@ void BugFixesInit()
// Fix for op_lookup_string_proc_ engine function not searching the last procedure in a script
SafeWrite8(0x46C7AC, 0x76); // jb > jbe
// Update the AC counter
//if (GetPrivateProfileIntA("Misc", "WieldObjCritterFix", 1, ini)) {
dlog("Applying wield_obj_critter fix.", DL_INIT);
SafeWrite8(0x456912, 0x1E);
SafeWrite8(0x456912, 0x1E); // jnz 0x456931
HookCall(0x45697F, op_wield_obj_critter_adjust_ac_hook);
dlogr(" Done", DL_INIT);
//}
// Enable party members with level 6 protos to reach level 6
//if (GetPrivateProfileIntA("Misc", "NPCStage6Fix", 1, ini)) {
dlog("Applying NPC Stage 6 Fix.", DL_INIT);
MakeJump(0x493CE9, NPCStage6Fix1);
SafeWrite8(0x494063, 6); // loop should look for a potential 6th stage
MakeJump(0x493CE9, NPCStage6Fix1); // partyMember_init_
MakeJump(0x494224, NPCStage6Fix2); // partyMemberGetAIOptions_
SafeWrite8(0x494063, 6); // loop should look for a potential 6th stage (partyMember_init_)
SafeWrite8(0x4940BB, 204); // move pointer by 204 bytes instead of 200
MakeJump(0x494224, NPCStage6Fix2);
dlogr(" Done", DL_INIT);
//}
+46 -57
View File
@@ -39,7 +39,7 @@ BYTE *charScrnBackSurface = nullptr;
DWORD charRotTick = 0;
DWORD charRotOri = 0;
bool raceButtions = false, styleButtions = false;
bool raceButtons = false, styleButtons = false;
int currentRaceVal = 0, currentStyleVal = 0; // holds Appearance values to restore after global reset in NewGame2 function in LoadGameHooks.cpp
DWORD critterListSize = 0, critterArraySize = 0; // Critter art list size
@@ -250,11 +250,6 @@ int FWriteDword(void *FileStream, DWORD bVal) {
/////////////////////////////////////////////////////////////////MOUSE FUNCTIONS/////////////////////////////////////////////////////////////////////
// get current mouse pic ref
int GetMousePic() {
return *(DWORD*)_gmouse_current_cursor;
}
// set mouse pic
int SetMousePic(int picNum) {
__asm {
@@ -287,11 +282,6 @@ void HideMouse() {
}
}
// returns 0 if mouse is hidden
int IsMouseHidden() {
return *(DWORD*)_mouse_is_hidden;
}
/////////////////////////////////////////////////////////////////FRM FUNCTIONS///////////////////////////////////////////////////////////////////////
static DWORD BuildFrmId(DWORD lstRef, DWORD lstNum) {
@@ -556,15 +546,15 @@ int check_buttons() {
/////////////////////////////////////////////////////////////////TEXT FUNCTIONS//////////////////////////////////////////////////////////////////////
void SetFont(long ref) {
static void SetFont(long ref) {
__asm {
mov eax, ref;
call text_font_;
}
}
long GetFont() {
return *(DWORD*)_curr_font_num;
static long GetFont() {
return *ptr_curr_font_num;
}
/*
@@ -815,7 +805,7 @@ static __declspec(noinline) int _stdcall LoadHeroDat(unsigned int race, unsigned
}
const char sex = GetSex();
bool folderIsExist = false, datIsExist = false;
bool folderIsExist = false, heroDatIsExist = false;
// check if folder exists for selected appearance
sprintf_s(heroPathPtr[0]->path, 64, appearancePathFmt, sex, race, style, "");
if (GetFileAttributes(heroPathPtr[0]->path) != INVALID_FILE_ATTRIBUTES) {
@@ -830,17 +820,17 @@ static __declspec(noinline) int _stdcall LoadHeroDat(unsigned int race, unsigned
heroPathPtr[1]->isDat = 1;
}
if (folderIsExist) heroPathPtr[0]->next = heroPathPtr[1];
datIsExist = true;
heroDatIsExist = true;
} else if (!folderIsExist) {
return -1; // no .dat files and folder
}
heroPathPtr[1]->next = nullptr;
//heroPathPtr[1]->next = nullptr;
tempPathPtr = &heroPathPtr[1 - folderIsExist]; // set path for selected appearance
heroPathPtr[0 + datIsExist]->next = *(sPath**)_paths; // heroPathPtr[] >> foPaths
heroPathPtr[0 + heroDatIsExist]->next = *(sPath**)_paths; // heroPathPtr[] >> foPaths
if (style != 0) {
datIsExist = false, folderIsExist = false;
bool raceDatIsExist = false, folderIsExist = false;
// check if folder exists for selected race base appearance
sprintf_s(racePathPtr[0]->path, 64, appearancePathFmt, sex, race, 0, "");
if (GetFileAttributes(racePathPtr[0]->path) != INVALID_FILE_ATTRIBUTES) {
@@ -855,14 +845,13 @@ static __declspec(noinline) int _stdcall LoadHeroDat(unsigned int race, unsigned
racePathPtr[1]->isDat = 1;
}
if (folderIsExist) racePathPtr[0]->next = racePathPtr[1];
datIsExist = true;
raceDatIsExist = true;
} else if (!folderIsExist) {
return 0;
}
long i = 0 + (heroPathPtr[1]->next != nullptr);
heroPathPtr[i]->next = racePathPtr[1 - folderIsExist]; // set path for selected race base appearance
racePathPtr[0 + datIsExist]->next = *(sPath**)_paths; // insert racePathPtr in chain path: heroPathPtr[] >> racePathPtr[] >> foPaths
heroPathPtr[0 + heroDatIsExist]->next = racePathPtr[1 - folderIsExist]; // set path for selected race base appearance
racePathPtr[0 + raceDatIsExist]->next = *(sPath**)_paths; // insert racePathPtr in chain path: heroPathPtr[] >> racePathPtr[] >> foPaths
}
return 0;
}
@@ -982,13 +971,13 @@ static void FixCritList() {
critterListSize = (*(DWORD*)0x510774) / 2;
critterArraySize = critterListSize * 13;
char *CritList = (*(char**)0x51076C); // critter list offset
char *HeroList = CritList + critterArraySize; // set start of hero critter list after regular critter list
char *CritList = (*(char**)0x51076C); // critter list offset
char *HeroList = CritList + critterArraySize; // set start of hero critter list after regular critter list
memset(HeroList, 0, critterArraySize);
for (DWORD i = 0; i < critterListSize; i++) { // copy critter name list to hero name list
*HeroList = '_'; // insert a '_' char at the front of new hero critt names. fallout wont load the same name twice
for (DWORD i = 0; i < critterListSize; i++) { // copy critter name list to hero name list
*HeroList = '_'; // insert a '_' char at the front of new hero critt names. fallout wont load the same name twice
memcpy(HeroList + 1, CritList, 11);
HeroList += 13;
CritList += 13;
@@ -1120,11 +1109,11 @@ void _stdcall SetNewCharAppearanceGlobals() {
void _stdcall SetHeroStyle(int newStyleVal) {
if (!appModEnabled || newStyleVal == currentStyleVal) return;
if (LoadHeroDat(currentRaceVal, newStyleVal, true) != 0) { // if new style cannot be set
if (LoadHeroDat(currentRaceVal, newStyleVal, true) != 0) { // if new style cannot be set
if (currentRaceVal == 0 && newStyleVal == 0) {
currentStyleVal = 0; // ignore error if appearance = default
currentStyleVal = 0; // ignore error if appearance = default
} else {
LoadHeroDat(currentRaceVal, currentStyleVal); // reload original style
LoadHeroDat(currentRaceVal, currentStyleVal); // reload original style
}
} else {
currentStyleVal = newStyleVal;
@@ -1137,10 +1126,10 @@ void _stdcall SetHeroStyle(int newStyleVal) {
void _stdcall SetHeroRace(int newRaceVal) {
if (!appModEnabled || newRaceVal == currentRaceVal) return;
if (LoadHeroDat(newRaceVal, 0, true) != 0) { // if new race fails with style at 0
if (LoadHeroDat(newRaceVal, 0, true) != 0) { // if new race fails with style at 0
if (newRaceVal == 0) {
currentRaceVal = 0;
currentStyleVal = 0; // ignore if appearance = default
currentStyleVal = 0; // ignore if appearance = default
} else {
LoadHeroDat(currentRaceVal, currentStyleVal); // reload original race & style
}
@@ -1223,7 +1212,7 @@ static void DrawPCConsole() {
charRotOri = 0;
}
int WinRef = *(DWORD*)_edit_win; // char screen window ref
int WinRef = *ptr_edit_win; // char screen window ref
//BYTE *WinSurface = GetWinSurface(WinRef);
WINinfo *WinInfo = GetWinStruct(WinRef);
@@ -1337,7 +1326,7 @@ static void DrawCharNote(bool style, int winRef, DWORD xPosWin, DWORD yPosWin, B
}
static void _stdcall DrawCharNoteNewChar(bool type) {
DrawCharNote(type, *(DWORD*)_edit_win, 348, 272, charScrnBackSurface, 348, 272, 640, 480);
DrawCharNote(type, *ptr_edit_win, 348, 272, charScrnBackSurface, 348, 272, 640, 480);
}
// op_hero_select_win
@@ -1360,9 +1349,9 @@ void _stdcall HeroSelectWindow(int raceStyleFlag) {
return;
}
int mouseWasHidden = IsMouseHidden();
int mouseWasHidden = *ptr_mouse_is_hidden;
if (mouseWasHidden) ShowMouse();
int oldMouse = GetMousePic();
int oldMouse = *ptr_gmouse_current_cursor;
SetMousePic(1);
BYTE *winSurface = GetWinSurface(winRef);
@@ -1568,16 +1557,16 @@ static int _stdcall CheckCharButtons() {
int drawFlag = -1;
int infoLine = *(DWORD*)_info_line;
int infoLine = *ptr_info_line;
if (infoLine == 0x503 || infoLine == 0x504) {
*(DWORD*)_info_line -= 2;
*ptr_info_line -= 2;
*(DWORD*)_frstc_draw1 = 1;
DrawCharNoteNewChar(infoLine != 0x503);
} else if (infoLine == 0x501 || infoLine == 0x502) {
switch (button) {
case 0x14B: // button left
case 0x14D: // button right
if (*(DWORD*)_glblmode == 1) { //if in char creation scrn
if (*ptr_glblmode == 1) { //if in char creation scrn
if (infoLine == 0x501) {
button = button + 0x3C6;
} else if (infoLine == 0x502) {
@@ -1601,7 +1590,7 @@ static int _stdcall CheckCharButtons() {
case 0x1F6: // button cancel
case 'c': // button cancel
case 'C': // button cancel
*(DWORD*)_info_line += 2; // 0x503/0x504 for redrawing note when reentering char screen
*ptr_info_line += 2; // 0x503/0x504 for redrawing note when reentering char screen
break;
}
}
@@ -1614,13 +1603,13 @@ static int _stdcall CheckCharButtons() {
button = 0x501;
case 0x501: // race title button pushed
if (infoLine != 0x501) {
*(DWORD*)_info_line = 0x501;
*ptr_info_line = 0x501;
drawFlag = 3;
}
break;
case 0x502: // style title button pushed
if (infoLine != 0x502) {
*(DWORD*)_info_line = 0x502;
*ptr_info_line = 0x502;
drawFlag = 2;
}
break;
@@ -1678,11 +1667,11 @@ static int _stdcall CheckCharButtons() {
bool style = false; // Race;
switch (drawFlag) {
case 0:
*(DWORD*)_info_line = 0x502;
*ptr_info_line = 0x502;
style = true;
goto play;
case 1:
*(DWORD*)_info_line = 0x501;
*ptr_info_line = 0x501;
play:
PlayAcm("ib3p1xx1");
break;
@@ -1724,11 +1713,11 @@ static void __fastcall HeroGenderChange(long gender) {
long baseModel = (newGender) // check if male 0
? *(DWORD*)0x5108AC // base female model
: *(DWORD*)_art_vault_person_nums; // base male model
: *ptr_art_vault_person_nums; // base male model
// adjust base hero art
baseModel += critterListSize;
*(DWORD*)_art_vault_guy_num = baseModel;
*ptr_art_vault_guy_num = baseModel;
// reset race and style to defaults
currentRaceVal = 0;
@@ -1738,7 +1727,7 @@ static void __fastcall HeroGenderChange(long gender) {
RefreshHeroBaseArt();
// Check If Race or Style selected to redraw info note
int infoLine = *(DWORD*)_info_line;
int infoLine = *ptr_info_line;
if (infoLine == 0x501 || infoLine == 0x502) {
DrawCharNoteNewChar(infoLine != 0x501);
}
@@ -1775,13 +1764,13 @@ static void __declspec(naked) AddCharScrnButtons() {
}
int WinRef;
WinRef = *(DWORD*)_edit_win; // char screen window ref
WinRef = *ptr_edit_win; // char screen window ref
// race and style title buttons
WinRegisterButton(WinRef, 332, 0, 82, 32, -1, -1, 0x501, -1, 0, 0, 0, 0);
WinRegisterButton(WinRef, 332, 226, 82, 32, -1, -1, 0x502, -1, 0, 0, 0, 0);
if (*(DWORD*)_glblmode == 1 && (styleButtions || raceButtions)) { // equals 1 if new char screen - equals 0 if ingame char screen
if (*ptr_glblmode == 1 && (styleButtons || raceButtons)) { // equals 1 if new char screen - equals 0 if ingame char screen
if (newButtonSurface == nullptr) {
newButtonSurface = new BYTE [20 * 18 * 4];
@@ -1806,11 +1795,11 @@ static void __declspec(naked) AddCharScrnButtons() {
frmSurface = nullptr;
}
if (raceButtions) { // race selection buttons
if (raceButtons) { // race selection buttons
WinRegisterButton(WinRef, 348, 37, 20, 18, -1, -1, -1, 0x511, newButtonSurface, newButtonSurface + (20 * 18), 0, 0x20);
WinRegisterButton(WinRef, 374, 37, 20, 18, -1, -1, -1, 0x513, newButtonSurface + (20 * 18 * 2), newButtonSurface + (20 * 18 * 3), 0, 0x20);
}
if (styleButtions) { // style selection buttons
if (styleButtons) { // style selection buttons
WinRegisterButton(WinRef, 348, 199, 20, 18, -1, -1, -1, 0x512, newButtonSurface, newButtonSurface + (20 * 18), 0, 0x20);
WinRegisterButton(WinRef, 374, 199, 20, 18, -1, -1, -1, 0x514, newButtonSurface + (20 * 18 * 2), newButtonSurface + (20 * 18 * 3), 0, 0x20);
}
@@ -1840,7 +1829,7 @@ static void __declspec(naked) FixCharScrnBack() {
if (charScrnBackSurface == nullptr) {
charScrnBackSurface = new BYTE [640 * 480];
UNLSTDfrm *frm = LoadUnlistedFrm((*(long*)_glblmode) ? "AppChCrt.frm" : "AppChEdt.frm", 6);
UNLSTDfrm *frm = LoadUnlistedFrm((*ptr_glblmode) ? "AppChCrt.frm" : "AppChEdt.frm", 6);
if (frm != nullptr) {
sub_draw(640, 480, 640, 480, 0, 0, frm->frames[0].indexBuff, 640, 480, 0, 0, charScrnBackSurface, 0);
@@ -1899,10 +1888,10 @@ static void __declspec(naked) FixCharScrnBack() {
UnloadFrm(FrmObj);
// frm background for char screen Appearance button
if (*(DWORD*)_glblmode == 1 && (styleButtions || raceButtions)) {
if (*ptr_glblmode && (styleButtons || raceButtons)) {
FrmSurface = GetFrmSurface(BuildFrmId(6, 174), 0, 0, &FrmObj); // Pickchar frm
if (raceButtions) sub_draw(69, 20, 640, 480, 281, 319, FrmSurface, 640, 480, 337, 36, charScrnBackSurface, 0); // button backround top
if (styleButtions) sub_draw(69, 20, 640, 480, 281, 319, FrmSurface, 640, 480, 337, 198, charScrnBackSurface, 0); // button backround bottom
if (raceButtons) sub_draw(69, 20, 640, 480, 281, 319, FrmSurface, 640, 480, 337, 36, charScrnBackSurface, 0); // button backround top
if (styleButtons) sub_draw(69, 20, 640, 480, 281, 319, FrmSurface, 640, 480, 337, 198, charScrnBackSurface, 0); // button backround bottom
UnloadFrm(FrmObj);
}
FrmSurface = nullptr;
@@ -2064,12 +2053,12 @@ static void EnableHeroAppearanceMod() {
// check if Data exists for other races male or female, and if so enable race selection buttons
if (GetFileAttributes("Appearance\\hmR01S00") != INVALID_FILE_ATTRIBUTES || GetFileAttributes("Appearance\\hfR01S00") != INVALID_FILE_ATTRIBUTES ||
GetFileAttributes("Appearance\\hmR01S00.dat") != INVALID_FILE_ATTRIBUTES || GetFileAttributes("Appearance\\hfR01S00.dat") != INVALID_FILE_ATTRIBUTES) {
raceButtions = true;
raceButtons = true;
}
// check if Data exists for other styles male or female, and if so enable style selection buttons
if (GetFileAttributes("Appearance\\hmR00S01") != INVALID_FILE_ATTRIBUTES || GetFileAttributes("Appearance\\hfR00S01") != INVALID_FILE_ATTRIBUTES ||
GetFileAttributes("Appearance\\hmR00S01.dat") != INVALID_FILE_ATTRIBUTES || GetFileAttributes("Appearance\\hfR00S01.dat") != INVALID_FILE_ATTRIBUTES) {
styleButtions = true;
styleButtons = true;
}
// Check if new Appearance char scrn button pushed (editor_design_)
+14 -4
View File
@@ -647,13 +647,23 @@ static void sf_get_loot_object() {
}
static void sf_get_object_data() {
BYTE* object_ptr = (BYTE*)opHandler.arg(0).asObject();
opHandler.setReturn(*(long*)(object_ptr + opHandler.arg(1).asInt()), DATATYPE_INT);
DWORD result = 0;
DWORD* object_ptr = (DWORD*)opHandler.arg(0).rawValue();
if (*(object_ptr - 1) != 0xFEEDFACE) {
opHandler.printOpcodeError("get_object_data() - invalid object pointer.");
} else {
result = *(long*)((BYTE*)object_ptr + opHandler.arg(1).rawValue());
}
opHandler.setReturn(result, DATATYPE_INT);
}
static void sf_set_object_data() {
BYTE* object_ptr = (BYTE*)opHandler.arg(0).asObject();
*(long*)(object_ptr + opHandler.arg(1).asInt()) = opHandler.arg(2).asInt();
DWORD* object_ptr = (DWORD*)opHandler.arg(0).rawValue();
if (*(object_ptr - 1) != 0xFEEDFACE) {
opHandler.printOpcodeError("set_object_data() - invalid object pointer.");
} else {
*(long*)((BYTE*)object_ptr + opHandler.arg(1).rawValue()) = opHandler.arg(2).rawValue();
}
}
static void sf_set_unique_id() {