Added "unwield_slot" script function

Re-fixed obj_art_fid for player's FID (commit 50f4885)
This commit is contained in:
NovaRain
2019-10-08 10:53:47 +08:00
parent 6ede19ceec
commit 1b6d6179a1
8 changed files with 96 additions and 26 deletions
+1
View File
@@ -313,3 +313,4 @@
#define spatial_radius(obj) sfall_func1("spatial_radius", obj) #define spatial_radius(obj) sfall_func1("spatial_radius", obj)
#define tile_refresh_display sfall_func0("tile_refresh_display") #define tile_refresh_display sfall_func0("tile_refresh_display")
#define unjam_lock(obj) sfall_func1("unjam_lock", obj) #define unjam_lock(obj) sfall_func1("unjam_lock", obj)
#define unwield_slot(critter, slot) sfall_func2("unwield_slot", critter, slot)
@@ -622,6 +622,11 @@ optional argument:
- fileNumber: the file ID number for the message_str_game function. The available range is from 0x2000 to 0x2FFF (see ExtraGameMsgFileList setting in ddraw.ini) - fileNumber: the file ID number for the message_str_game function. The available range is from 0x2000 to 0x2FFF (see ExtraGameMsgFileList setting in ddraw.ini)
use fileNumber only if you want to add a message file without editing ddraw.ini or existing scripts to support the old way use fileNumber only if you want to add a message file without editing ddraw.ini or existing scripts to support the old way
> 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 ------- ------ MORE INFO -------
------------------------ ------------------------
+2 -2
View File
@@ -519,8 +519,8 @@ struct Proto {
// for each DamageType // for each DamageType
long damageThreshold[7]; long damageThreshold[7];
long perk; long perk;
long maleFrameNum; long maleFID;
long femaleFrameNum; long femaleFID;
}; };
struct Container { struct Container {
+13 -14
View File
@@ -49,7 +49,7 @@ bool raceButtons = false, styleButtons = false;
int currentRaceVal = 0, currentStyleVal = 0; // holds Appearance values to restore after global reset in NewGame2 function in LoadGameHooks.cpp 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 DWORD critterListSize = 0, critterArraySize = 0; // Critter art list size
fo::PathNode **tempPathPtr = &fo::var::paths; fo::PathNode **heroAppPaths = &fo::var::paths;
// index: 0 - only folder (w/o extension .dat), 1 - file or folder .dat // index: 0 - only folder (w/o extension .dat), 1 - file or folder .dat
fo::PathNode *heroPathPtr[2] = {nullptr, nullptr}; fo::PathNode *heroPathPtr[2] = {nullptr, nullptr};
fo::PathNode *racePathPtr[2] = {nullptr, nullptr}; fo::PathNode *racePathPtr[2] = {nullptr, nullptr};
@@ -219,7 +219,7 @@ static __declspec(noinline) int _stdcall LoadHeroDat(unsigned int race, unsigned
} }
//heroPathPtr[1]->next = nullptr; //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 = &fo::var::paths[0]; // heroPathPtr[] >> foPaths heroPathPtr[0 + heroDatIsExist]->next = &fo::var::paths[0]; // heroPathPtr[] >> foPaths
if (style != 0) { if (style != 0) {
@@ -253,12 +253,12 @@ static __declspec(noinline) int _stdcall LoadHeroDat(unsigned int race, unsigned
static void __declspec(naked) LoadNewHeroArt() { static void __declspec(naked) LoadNewHeroArt() {
__asm { __asm {
cmp byte ptr ds:[esi], 'r'; 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, FO_VAR_paths; mov ecx, FO_VAR_paths;
jmp setPath;
isReading:
mov ecx, tempPathPtr;
setPath:
mov ecx, dword ptr ds:[ecx]; mov ecx, dword ptr ds:[ecx];
retn; retn;
} }
@@ -1278,10 +1278,10 @@ static void __declspec(naked) CharScrnEnd() {
//////////////////////////////////////////////////////////////////////FIX FUNCTIONS////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////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() { static void __declspec(naked) FixPcSFX() {
__asm { __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; jne endFunc;
inc ebx; // shift address to next char inc ebx; // shift address to next char
endFunc: endFunc:
@@ -1325,11 +1325,10 @@ static void __declspec(naked) op_obj_art_fid_hack() {
using namespace Fields; using namespace Fields;
__asm { __asm {
mov esi, [edi + artFid]; mov esi, [edi + artFid];
push ecx; mov eax, esi;
call PartyControl::RealDudeObject; and eax, 0xFFF; // LST index
pop ecx; cmp eax, critterListSize;
cmp eax, edi; // object is dude? jle skip;
jnz skip;
sub esi, critterListSize; // fix hero FrmID sub esi, critterListSize; // fix hero FrmID
skip: skip:
jmp op_obj_art_fid_Ret; jmp op_obj_art_fid_Ret;
+10 -10
View File
@@ -578,26 +578,26 @@ skip:
DWORD __stdcall Inventory::adjust_fid_replacement() { DWORD __stdcall Inventory::adjust_fid_replacement() {
DWORD fid; DWORD fid;
if (fo::var::inven_dude->TypeFid() == fo::OBJ_TYPE_CRITTER) { if (fo::var::inven_dude->TypeFid() == fo::OBJ_TYPE_CRITTER) {
DWORD frameNum; DWORD indexNum;
DWORD weaponAnimCode = 0; DWORD weaponAnimCode = 0;
if (PartyControl::IsNpcControlled()) { if (PartyControl::IsNpcControlled()) {
// if NPC is under control, use current FID of critter // if NPC is under control, use current FID of critter
frameNum = fo::var::inven_dude->artFid & 0xFFF; indexNum = fo::var::inven_dude->artFid & 0xFFF;
} else { } else {
// vanilla logic: // vanilla logic:
frameNum = fo::var::art_vault_guy_num; indexNum = fo::var::art_vault_guy_num;
auto critterPro = fo::GetProto(fo::var::inven_pid); auto critterPro = fo::GetProto(fo::var::inven_pid);
if (critterPro != nullptr) { if (critterPro != nullptr) {
frameNum = critterPro->fid & 0xFFF; indexNum = critterPro->fid & 0xFFF;
} }
if (fo::var::i_worn != nullptr) { if (fo::var::i_worn != nullptr) {
auto armorPro = fo::GetProto(fo::var::i_worn->protoId); auto armorPro = fo::GetProto(fo::var::i_worn->protoId);
DWORD armorFrameNum = fo::func::stat_level(fo::var::inven_dude, fo::STAT_gender) == fo::GENDER_FEMALE DWORD armorFid = fo::func::stat_level(fo::var::inven_dude, fo::STAT_gender) == fo::GENDER_FEMALE
? armorPro->item.armor.femaleFrameNum ? armorPro->item.armor.femaleFID
: armorPro->item.armor.maleFrameNum; : armorPro->item.armor.maleFID;
if (armorFrameNum != -1) { if (armorFid != -1) {
frameNum = armorFrameNum; indexNum = armorFid;
} }
} }
} }
@@ -611,7 +611,7 @@ DWORD __stdcall Inventory::adjust_fid_replacement() {
weaponAnimCode = itemPro->item.weapon.animationCode; weaponAnimCode = itemPro->item.weapon.animationCode;
} }
} }
fid = fo::func::art_id(fo::OBJ_TYPE_CRITTER, frameNum, 0, weaponAnimCode, 0); fid = fo::func::art_id(fo::OBJ_TYPE_CRITTER, indexNum, 0, weaponAnimCode, 0);
} else { } else {
fid = fo::var::inven_dude->artFid; fid = fo::var::inven_dude->artFid;
} }
@@ -23,6 +23,8 @@
#include "..\..\ScriptExtender.h" #include "..\..\ScriptExtender.h"
#include "..\OpcodeContext.h" #include "..\OpcodeContext.h"
#include "..\..\HookScripts\InventoryHs.h"
#include "Interface.h" #include "Interface.h"
namespace sfall namespace sfall
@@ -450,5 +452,65 @@ void sf_draw_image_scaled(OpcodeContext& ctx) {
DrawImage(ctx, true); DrawImage(ctx, true);
} }
void sf_unwield_slot(OpcodeContext& ctx) {
fo::InvenType slot = static_cast<fo::InvenType>(ctx.arg(1).rawValue());
if (slot < fo::INVEN_TYPE_WORN || slot > fo::INVEN_TYPE_LEFT_HAND) {
ctx.printOpcodeError("%s() - incorrect slot number.", ctx.getMetaruleName());
return;
}
fo::GameObject* critter = ctx.arg(0).asObject();
if (critter->Type() != fo::ObjType::OBJ_TYPE_CRITTER) {
ctx.printOpcodeError("%s() - the object is not a critter.", ctx.getMetaruleName());
return;
}
bool isDude = (critter == fo::var::obj_dude);
bool update = false;
if (slot && (GetLoopFlags() && (INVENTORY | INTFACEUSE | INTFACELOOT | BARTER)) == false) {
if (fo::func::inven_unwield(critter, (slot == fo::INVEN_TYPE_LEFT_HAND) ? fo::Left : fo::Right) == 0) {
update = isDude;
}
} else {
// force unwield for opened inventory
bool forceAdd = false;
fo::GameObject* item = nullptr;
if (slot != fo::INVEN_TYPE_WORN) {
if (!isDude) return;
long* itemRef = nullptr;
if (slot == fo::INVEN_TYPE_LEFT_HAND) {
item = fo::var::i_lhand;
itemRef = (long*)FO_VAR_i_lhand;
} else {
item = fo::var::i_rhand;
itemRef = (long*)FO_VAR_i_rhand;
}
if (item) {
if (!CorrectFidForRemovedItem_wHook(critter, item, (slot == fo::INVEN_TYPE_LEFT_HAND) ? fo::ObjectFlag::Left_Hand : fo::ObjectFlag::Right_Hand)) {
return;
}
*itemRef = 0;
forceAdd = true;
update = true;
}
} else {
if (isDude) item = fo::var::i_worn;
if (!item) {
item = fo::func::inven_worn(critter);
} else {
fo::var::i_worn = nullptr;
forceAdd = true;
}
if (item) {
if (!CorrectFidForRemovedItem_wHook(critter, item, fo::ObjectFlag::Worn)) {
if (forceAdd) fo::var::i_worn = item;
return;
}
if (isDude) fo::func::intface_update_ac(0);
}
}
if (forceAdd) fo::func::item_add_force(critter, item, 1);
}
if (update) fo::func::intface_update_items(0, -1, -1);
}
} }
} }
@@ -103,5 +103,7 @@ void sf_draw_image(OpcodeContext&);
void sf_draw_image_scaled(OpcodeContext&); void sf_draw_image_scaled(OpcodeContext&);
void sf_unwield_slot(OpcodeContext&);
} }
} }
@@ -122,6 +122,7 @@ static const SfallMetarule metarules[] = {
{"spatial_radius", sf_spatial_radius, 1, 1, {ARG_OBJECT}}, {"spatial_radius", sf_spatial_radius, 1, 1, {ARG_OBJECT}},
{"tile_refresh_display", sf_tile_refresh_display, 0, 0}, {"tile_refresh_display", sf_tile_refresh_display, 0, 0},
{"unjam_lock", sf_unjam_lock, 1, 1, {ARG_OBJECT}}, {"unjam_lock", sf_unjam_lock, 1, 1, {ARG_OBJECT}},
{"unwield_slot", sf_unwield_slot, 2, 2, {ARG_OBJECT, ARG_INT}},
#ifndef NDEBUG #ifndef NDEBUG
{"validate_test", sf_test, 2, 5, {ARG_INT, ARG_NUMBER, ARG_STRING, ARG_OBJECT, ARG_ANY}}, {"validate_test", sf_test, 2, 5, {ARG_INT, ARG_NUMBER, ARG_STRING, ARG_OBJECT, ARG_ANY}},
#endif #endif