Added "unwield_slot" script function

Re-fixed obj_art_fid for player's FID (commit 36523d8)
This commit is contained in:
NovaRain
2019-10-08 10:56:49 +08:00
parent f6ec543f40
commit 37acec7115
6 changed files with 81 additions and 14 deletions
+1
View File
@@ -265,3 +265,4 @@
#define spatial_radius(obj) sfall_func1("spatial_radius", obj)
#define tile_refresh_display sfall_func0("tile_refresh_display")
#define unjam_lock(obj) sfall_func1("unjam_lock", obj)
#define unwield_slot(critter, slot) sfall_func2("unwield_slot", critter, slot)
@@ -507,6 +507,11 @@ Some utility/math functions are available:
- there is also a unique ID number range for the player and party members from 18000 to 83535
- to assign a new ID number generated by the engine to the object (i.e. unassign a unique ID), call the function with two arguments and pass -1 for the flag argument
> void sfall_func2("unwield_slot", object critter, int slot)
- unequips an item from the specified slot for a critter or the player
- can take off player's equipped item when the inventory is opened, or the player is in the barter screen
- slot: 0 - armor slot, 1 - right slot, 2 - left slot (see INVEN_TYPE_* in define.h)
------------------------
------ MORE INFO -------
------------------------
+13 -14
View File
@@ -51,7 +51,7 @@ struct sPath {
sPath* next;
};
sPath **tempPathPtr = (sPath**)_paths;
sPath **heroAppPaths = (sPath**)_paths;
// index: 0 - only folder (w/o extension .dat), 1 - file or folder .dat
sPath *heroPathPtr[2] = {nullptr, nullptr};
sPath *racePathPtr[2] = {nullptr, nullptr};
@@ -826,7 +826,7 @@ static __declspec(noinline) int _stdcall LoadHeroDat(unsigned int race, unsigned
}
//heroPathPtr[1]->next = nullptr;
tempPathPtr = &heroPathPtr[1 - folderIsExist]; // set path for selected appearance
heroAppPaths = &heroPathPtr[1 - folderIsExist]; // set path for selected appearance
heroPathPtr[0 + heroDatIsExist]->next = *(sPath**)_paths; // heroPathPtr[] >> foPaths
if (style != 0) {
@@ -860,12 +860,12 @@ static __declspec(noinline) int _stdcall LoadHeroDat(unsigned int race, unsigned
static void __declspec(naked) LoadNewHeroArt() {
__asm {
cmp byte ptr ds:[esi], 'r';
je isReading;
jne isNotReading;
mov ecx, heroAppPaths;
mov ecx, dword ptr ds:[ecx]; // set app path
retn;
isNotReading:
mov ecx, _paths;
jmp setPath;
isReading:
mov ecx, tempPathPtr;
setPath:
mov ecx, dword ptr ds:[ecx];
retn;
}
@@ -1945,10 +1945,10 @@ static void __declspec(naked) CharScrnEnd() {
//////////////////////////////////////////////////////////////////////FIX FUNCTIONS//////////////////////////////////////////////////////////////////
// Adjust PC SFX acm name. Skip Underscore char at the start of PC App Name
// Adjust PC SFX acm name. Skip Underscore char at the start of PC frm file name
static void __declspec(naked) FixPcSFX() {
__asm {
cmp byte ptr ds:[ebx], 0x5F; // check if Name begins with an '_' character
cmp byte ptr ds:[ebx], '_'; // check if Name begins with an 0x5F character
jne endFunc;
inc ebx; // shift address to next char
endFunc:
@@ -1991,11 +1991,10 @@ static const DWORD op_obj_art_fid_Ret = 0x45C5D9;
static void __declspec(naked) op_obj_art_fid_hack() {
__asm {
mov esi, [edi + 0x20]; // artFid
push ecx;
call RealDudeObject;
pop ecx;
cmp eax, edi; // object is dude?
jnz skip;
mov eax, esi;
and eax, 0xFFF; // LST index
cmp eax, critterListSize;
jle skip;
sub esi, critterListSize; // fix hero FrmID
skip:
jmp op_obj_art_fid_Ret;
+1
View File
@@ -410,6 +410,7 @@ static const SfallOpcodeMetadata opcodeMetaArray[] = {
{sf_set_unjam_locks_time, "set_unjam_locks_time", {DATATYPE_MASK_INT}},
{sf_spatial_radius, "spatial_radius", {DATATYPE_MASK_VALID_OBJ}},
{sf_unjam_lock, "unjam_lock", {DATATYPE_MASK_VALID_OBJ}},
{sf_unwield_slot, "unwield_slot", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
#ifndef NDEBUG
{sf_test, "validate_test", {DATATYPE_MASK_INT, DATATYPE_MASK_INT | DATATYPE_MASK_FLOAT, DATATYPE_MASK_STR, DATATYPE_NONE}},
#endif
+60
View File
@@ -429,3 +429,63 @@ static void sf_create_win() {
opHandler.printOpcodeError("create_win() - couldn't create window.");
}
}
static void sf_unwield_slot() {
long slot = static_cast<long>(opHandler.arg(1).rawValue());
if (slot < INVEN_TYPE_WORN || slot > INVEN_TYPE_LEFT_HAND) {
opHandler.printOpcodeError("unwield_slot() - incorrect slot number.");
return;
}
TGameObj* critter = opHandler.arg(0).asObject();
if (critter->pid >> 24 != OBJ_TYPE_CRITTER) {
opHandler.printOpcodeError("unwield_slot() - the object is not a critter.");
return;
}
bool isDude = (critter == *ptr_obj_dude);
bool update = false;
if (slot && (GetLoopFlags() && (INVENTORY | INTFACEUSE | INTFACELOOT | BARTER)) == false) {
if (InvenUnwield(critter, (slot == INVEN_TYPE_LEFT_HAND) ? 0 : 1) == 0) {
update = isDude;
}
} else {
// force unwield for opened inventory
bool forceAdd = false;
TGameObj* item = nullptr;
if (slot != INVEN_TYPE_WORN) {
if (!isDude) return;
long* itemRef = nullptr;
if (slot == INVEN_TYPE_LEFT_HAND) {
item = *ptr_i_lhand;
itemRef = (long*)_i_lhand;
} else {
item = *ptr_i_rhand;
itemRef = (long*)_i_rhand;
}
if (item) {
if (!CorrectFidForRemovedItem_wHook(critter, item, (slot == INVEN_TYPE_LEFT_HAND) ? 0x1000000 : 0x2000000)) {
return;
}
*itemRef = 0;
forceAdd = true;
update = true;
}
} else {
if (isDude) item = *ptr_i_worn;
if (!item) {
item = InvenWorn(critter);
} else {
*ptr_i_worn = nullptr;
forceAdd = true;
}
if (item) {
if (!CorrectFidForRemovedItem_wHook(critter, item, 0x4000000)) {
if (forceAdd) *ptr_i_worn = item;
return;
}
if (isDude) IntfaceUpdateAc(0);
}
}
if (forceAdd) ItemAddForce(critter, item, 1);
}
if (update) IntfaceUpdateItems(0, -1, -1);
}
+1
View File
@@ -157,6 +157,7 @@ static const SfallMetarule metaruleArray[] = {
{"spatial_radius", sf_spatial_radius, 1, 1},
{"tile_refresh_display", sf_tile_refresh_display, 0, 0},
{"unjam_lock", sf_unjam_lock, 1, 1},
{"unwield_slot", sf_unwield_slot, 2, 2},
#ifndef NDEBUG
{"validate_test", sf_test, 2, 5},
#endif