mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Added "unwield_slot" script function
Re-fixed obj_art_fid for player's FID (commit 50f4885)
This commit is contained in:
@@ -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 -------
|
||||||
------------------------
|
------------------------
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user