mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Moved some script function handlers to new files
Reorganized some script functions.
This commit is contained in:
@@ -69,6 +69,8 @@ static bool CheckRecursiveHooks(DWORD hook) {
|
||||
case HOOK_SETGLOBALVAR:
|
||||
case HOOK_SETLIGHTING:
|
||||
return true;
|
||||
default:
|
||||
if (isDebug) fo::func::debug_printf("\nWARNING: A recursive hook with ID %d was running.", hook);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -269,7 +269,6 @@ static void __declspec(naked) DropIntoContainerHandSlotHack() {
|
||||
}
|
||||
|
||||
static void __declspec(naked) DropAmmoIntoWeaponHook() {
|
||||
//static const DWORD DropAmmoIntoWeaponHack_back = 0x47658D; // proceed with reloading
|
||||
static const DWORD DropAmmoIntoWeaponHack_return = 0x476643;
|
||||
__asm {
|
||||
pushadc;
|
||||
@@ -278,13 +277,11 @@ static void __declspec(naked) DropAmmoIntoWeaponHook() {
|
||||
push 4; // event: weapon reloading
|
||||
call InventoryMoveHook_Script;
|
||||
cmp eax, -1; // ret value
|
||||
popadc;
|
||||
jne donothing;
|
||||
popadc;
|
||||
jmp fo::funcoffs::item_w_can_reload_;
|
||||
//mov ebx, 1; // overwritten code
|
||||
//jmp DropAmmoIntoWeaponHack_back;
|
||||
donothing:
|
||||
add esp, 4; // destroy return address
|
||||
add esp, 4*4; // destroy all pushed values and return address
|
||||
xor eax, eax; // result 0
|
||||
jmp DropAmmoIntoWeaponHack_return;
|
||||
}
|
||||
|
||||
@@ -17,10 +17,8 @@
|
||||
*/
|
||||
|
||||
#include "..\..\..\FalloutEngine\Fallout2.h"
|
||||
#include "..\..\..\SafeWrite.h"
|
||||
#include "..\..\Explosions.h"
|
||||
#include "..\..\ScriptExtender.h"
|
||||
#include "..\OpcodeContext.h"
|
||||
|
||||
#include "Anims.h"
|
||||
|
||||
@@ -143,6 +141,10 @@ void op_explosions_metarule(OpcodeContext& ctx) {
|
||||
ctx.setReturn(result);
|
||||
}
|
||||
|
||||
void op_art_exists(OpcodeContext& ctx) {
|
||||
ctx.setReturn(fo::func::art_exists(ctx.arg(0).rawValue()));
|
||||
}
|
||||
|
||||
void mf_art_cache_flush(OpcodeContext& ctx) {
|
||||
__asm call fo::funcoffs::art_flush_;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "..\OpcodeContext.h"
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
namespace script
|
||||
@@ -40,6 +42,8 @@ void op_reg_anim_callback(OpcodeContext&);
|
||||
|
||||
void op_explosions_metarule(OpcodeContext&);
|
||||
|
||||
void op_art_exists(OpcodeContext&);
|
||||
|
||||
void mf_art_cache_flush(OpcodeContext&);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "..\..\..\FalloutEngine\AsmMacros.h"
|
||||
#include "..\..\..\FalloutEngine\Fallout2.h"
|
||||
#include "..\..\AI.h"
|
||||
#include "..\..\Combat.h"
|
||||
#include "..\..\KillCounter.h"
|
||||
|
||||
#include "..\..\SubModules\CombatBlock.h"
|
||||
|
||||
#include "Combat.h"
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
namespace script
|
||||
{
|
||||
|
||||
// Kill counters
|
||||
static bool extraKillCounter;
|
||||
|
||||
void SetExtraKillCounter(bool value) { extraKillCounter = value; }
|
||||
|
||||
void __declspec(naked) op_get_kill_counter() {
|
||||
__asm {
|
||||
_GET_ARG_INT(fail); // get kill type value
|
||||
cmp extraKillCounter, 1;
|
||||
jne skip;
|
||||
cmp eax, 38;
|
||||
jae fail;
|
||||
movzx edx, word ptr ds:[FO_VAR_pc_kill_counts][eax * 2];
|
||||
jmp end;
|
||||
skip:
|
||||
cmp eax, 19;
|
||||
jae fail;
|
||||
mov edx, ds:[FO_VAR_pc_kill_counts][eax * 4];
|
||||
end:
|
||||
mov eax, ebx; // script
|
||||
_RET_VAL_INT;
|
||||
retn;
|
||||
fail:
|
||||
xor edx, edx; // return 0
|
||||
jmp end;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_mod_kill_counter() {
|
||||
__asm {
|
||||
push ecx;
|
||||
_GET_ARG(ecx, esi); // get mod value
|
||||
mov eax, ebx;
|
||||
_GET_ARG_INT(end); // get kill type value
|
||||
cmp si, VAR_TYPE_INT;
|
||||
jnz end;
|
||||
cmp extraKillCounter, 1;
|
||||
je skip;
|
||||
cmp eax, 19;
|
||||
jae end;
|
||||
add ds:[FO_VAR_pc_kill_counts][eax * 4], ecx;
|
||||
pop ecx;
|
||||
retn;
|
||||
skip:
|
||||
cmp eax, 38;
|
||||
jae end;
|
||||
add word ptr ds:[FO_VAR_pc_kill_counts][eax * 2], cx;
|
||||
end:
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void op_set_object_knockback(OpcodeContext& ctx) {
|
||||
int mode = 0;
|
||||
switch (ctx.opcode()) {
|
||||
case 0x196:
|
||||
mode = 1;
|
||||
break;
|
||||
case 0x197:
|
||||
mode = 2;
|
||||
break;
|
||||
}
|
||||
fo::GameObject* object = ctx.arg(0).object();
|
||||
if (mode) {
|
||||
if (object->IsNotCritter()) {
|
||||
ctx.printOpcodeError("%s() - the object is not a critter.", ctx.getOpcodeName());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (object->IsNotItem()) {
|
||||
ctx.printOpcodeError("%s() - the object is not an item.", ctx.getOpcodeName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
KnockbackSetMod(object, ctx.arg(1).rawValue(), ctx.arg(2).asFloat(), mode);
|
||||
}
|
||||
|
||||
void op_remove_object_knockback(OpcodeContext& ctx) {
|
||||
int mode = 0;
|
||||
switch (ctx.opcode()) {
|
||||
case 0x199:
|
||||
mode = 1;
|
||||
break;
|
||||
case 0x19a:
|
||||
mode = 2;
|
||||
break;
|
||||
}
|
||||
KnockbackRemoveMod(ctx.arg(0).object(), mode);
|
||||
}
|
||||
|
||||
void __declspec(naked) op_get_bodypart_hit_modifier() {
|
||||
__asm {
|
||||
_GET_ARG_INT(fail); // get body value
|
||||
cmp eax, 8; // Body_Head - Body_Uncalled
|
||||
ja fail;
|
||||
mov edx, ds:[FO_VAR_hit_location_penalty][eax * 4];
|
||||
end:
|
||||
mov eax, ebx; // script
|
||||
_J_RET_VAL_TYPE(VAR_TYPE_INT);
|
||||
fail:
|
||||
xor edx, edx; // return 0
|
||||
jmp end;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_set_bodypart_hit_modifier() {
|
||||
__asm {
|
||||
push ecx;
|
||||
_GET_ARG(ecx, esi); // get body value
|
||||
mov eax, ebx;
|
||||
_GET_ARG_INT(end); // get modifier value
|
||||
cmp si, VAR_TYPE_INT;
|
||||
jnz end;
|
||||
cmp eax, 8; // Body_Head - Body_Uncalled
|
||||
ja end;
|
||||
mov ds:[FO_VAR_hit_location_penalty][eax * 4], ecx;
|
||||
end:
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void op_get_attack_type(OpcodeContext& ctx) {
|
||||
ctx.setReturn(fo::GetCurrentAttackMode());
|
||||
}
|
||||
|
||||
void __declspec(naked) op_force_aimed_shots() {
|
||||
__asm {
|
||||
mov esi, ecx;
|
||||
_GET_ARG_INT(end);
|
||||
push eax;
|
||||
call ForceAimedShots;
|
||||
end:
|
||||
mov ecx, esi;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_disable_aimed_shots() {
|
||||
__asm {
|
||||
mov esi, ecx;
|
||||
_GET_ARG_INT(end);
|
||||
push eax;
|
||||
call DisableAimedShots;
|
||||
end:
|
||||
mov ecx, esi;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_get_last_attacker() {
|
||||
__asm {
|
||||
_GET_ARG_INT(fail);
|
||||
mov esi, ecx;
|
||||
push eax;
|
||||
call AI::AIGetLastAttacker;
|
||||
mov edx, eax;
|
||||
mov ecx, esi;
|
||||
end:
|
||||
mov eax, ebx;
|
||||
_J_RET_VAL_TYPE(VAR_TYPE_INT);
|
||||
fail:
|
||||
xor edx, edx; // return 0
|
||||
jmp end;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_get_last_target() {
|
||||
__asm {
|
||||
_GET_ARG_INT(fail);
|
||||
mov esi, ecx;
|
||||
push eax;
|
||||
call AI::AIGetLastTarget;
|
||||
mov edx, eax;
|
||||
mov ecx, esi;
|
||||
end:
|
||||
mov eax, ebx;
|
||||
_J_RET_VAL_TYPE(VAR_TYPE_INT);
|
||||
fail:
|
||||
xor edx, edx; // return 0
|
||||
jmp end;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_block_combat() {
|
||||
__asm {
|
||||
mov esi, ecx;
|
||||
_GET_ARG_INT(end);
|
||||
push eax;
|
||||
call CombatBlock::SetBlockCombat;
|
||||
end:
|
||||
mov ecx, esi;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void mf_attack_is_aimed(OpcodeContext& ctx) {
|
||||
DWORD isAimed, unused;
|
||||
ctx.setReturn(!fo::func::intface_get_attack(&unused, &isAimed) ? isAimed : 0);
|
||||
}
|
||||
|
||||
void mf_combat_data(OpcodeContext& ctx) {
|
||||
fo::ComputeAttackResult* ctd = nullptr;
|
||||
if (fo::var::combat_state & 1) {
|
||||
ctd = &fo::var::main_ctd;
|
||||
}
|
||||
ctx.setReturn((DWORD)ctd, DataType::INT);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "..\OpcodeContext.h"
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
namespace script
|
||||
{
|
||||
|
||||
// Kill counters
|
||||
void SetExtraKillCounter(bool value);
|
||||
|
||||
void __declspec() op_get_kill_counter();
|
||||
|
||||
void __declspec() op_mod_kill_counter();
|
||||
|
||||
void op_set_object_knockback(OpcodeContext&);
|
||||
|
||||
void op_remove_object_knockback(OpcodeContext&);
|
||||
|
||||
void __declspec() op_get_bodypart_hit_modifier();
|
||||
|
||||
void __declspec() op_set_bodypart_hit_modifier();
|
||||
|
||||
void op_get_attack_type(OpcodeContext&);
|
||||
|
||||
void __declspec() op_force_aimed_shots();
|
||||
|
||||
void __declspec() op_disable_aimed_shots();
|
||||
|
||||
void __declspec() op_get_last_attacker();
|
||||
|
||||
void __declspec() op_get_last_target();
|
||||
|
||||
void __declspec() op_block_combat();
|
||||
|
||||
void mf_attack_is_aimed(OpcodeContext&);
|
||||
|
||||
void mf_combat_data(OpcodeContext&);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "..\..\HookScripts\Common.h"
|
||||
#include "..\..\ScriptExtender.h"
|
||||
#include "..\Arrays.h"
|
||||
#include "..\OpcodeContext.h"
|
||||
|
||||
#include "Core.h"
|
||||
|
||||
@@ -155,6 +154,19 @@ end:
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_game_loaded() {
|
||||
__asm {
|
||||
mov esi, ecx;
|
||||
push eax; // script
|
||||
call ScriptExtender::ScriptHasLoaded;
|
||||
mov edx, eax;
|
||||
mov eax, ebx;
|
||||
_RET_VAL_INT;
|
||||
mov ecx, esi;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_init_hook() {
|
||||
__asm {
|
||||
mov edx, HookScripts::initingHookScripts;
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "..\OpcodeContext.h"
|
||||
|
||||
/* Opcodes for core sfall features. */
|
||||
|
||||
namespace sfall
|
||||
@@ -49,6 +51,8 @@ void op_set_sfall_arg(OpcodeContext&);
|
||||
|
||||
void __declspec() op_set_sfall_return();
|
||||
|
||||
void __declspec() op_game_loaded();
|
||||
|
||||
void __declspec() op_init_hook();
|
||||
|
||||
void __declspec() op_set_self();
|
||||
|
||||
@@ -25,9 +25,7 @@
|
||||
#include "..\..\ScriptExtender.h"
|
||||
#include "..\..\Interface.h"
|
||||
#include "..\Arrays.h"
|
||||
#include "..\OpcodeContext.h"
|
||||
|
||||
#include "..\..\..\Game\inventory.h"
|
||||
#include "..\..\..\Game\render.h"
|
||||
|
||||
#include "..\..\SubModules\WindowRender.h"
|
||||
@@ -46,6 +44,19 @@ void __declspec(naked) op_input_funcs_available() {
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_set_pipboy_available() {
|
||||
__asm {
|
||||
_GET_ARG_INT(end);
|
||||
cmp eax, 0;
|
||||
jl end;
|
||||
cmp eax, 1;
|
||||
jg end;
|
||||
mov byte ptr ds:[FO_VAR_gmovie_played_list][0x3], al;
|
||||
end:
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void op_key_pressed(OpcodeContext& ctx) {
|
||||
ctx.setReturn(KeyDown(ctx.arg(0).rawValue()));
|
||||
}
|
||||
@@ -117,18 +128,6 @@ void __declspec(naked) op_get_screen_height() {
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_stop_game() {
|
||||
__asm {
|
||||
jmp fo::funcoffs::map_disable_bk_processes_;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_resume_game() {
|
||||
__asm {
|
||||
jmp fo::funcoffs::map_enable_bk_processes_;
|
||||
}
|
||||
}
|
||||
|
||||
// copy and split
|
||||
static void SplitToBuffer(const char* str, const char** str_ptr, long &lines) {
|
||||
size_t i = 0;
|
||||
@@ -663,68 +662,6 @@ void mf_interface_art_draw(OpcodeContext& ctx) {
|
||||
ctx.setReturn(result);
|
||||
}
|
||||
|
||||
void mf_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());
|
||||
ctx.setReturn(-1);
|
||||
return;
|
||||
}
|
||||
fo::GameObject* critter = ctx.arg(0).object();
|
||||
if (critter->IsNotCritter()) {
|
||||
ctx.printOpcodeError("%s() - the object is not a critter.", ctx.getMetaruleName());
|
||||
ctx.setReturn(-1);
|
||||
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 (!game::Inventory::correctFidForRemovedItem(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 (!game::Inventory::correctFidForRemovedItem(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);
|
||||
}
|
||||
|
||||
void mf_get_window_attribute(OpcodeContext& ctx) {
|
||||
fo::Window* win = Interface::GetWindow(ctx.arg(0).rawValue());
|
||||
if (win == nullptr) {
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "..\OpcodeContext.h"
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
namespace script
|
||||
@@ -28,6 +30,8 @@ class OpcodeContext;
|
||||
// input_functions
|
||||
void __declspec() op_input_funcs_available();
|
||||
|
||||
void __declspec() op_set_pipboy_available();
|
||||
|
||||
void op_key_pressed(OpcodeContext& ctx);
|
||||
|
||||
void __declspec() op_tap_key();
|
||||
@@ -50,12 +54,6 @@ void __declspec() op_get_screen_width();
|
||||
//Return screen height
|
||||
void __declspec() op_get_screen_height();
|
||||
|
||||
//Stop game, the same effect as open charsscreen or inventory
|
||||
void __declspec() op_stop_game();
|
||||
|
||||
//Resume the game when it is stopped
|
||||
void __declspec() op_resume_game();
|
||||
|
||||
//Create a message window with given string
|
||||
void op_create_message_window(OpcodeContext&);
|
||||
|
||||
@@ -113,8 +111,6 @@ void mf_draw_image_scaled(OpcodeContext&);
|
||||
|
||||
void mf_interface_art_draw(OpcodeContext&);
|
||||
|
||||
void mf_unwield_slot(OpcodeContext&);
|
||||
|
||||
void mf_get_window_attribute(OpcodeContext&);
|
||||
|
||||
void mf_interface_print(OpcodeContext&);
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "..\..\..\FalloutEngine\AsmMacros.h"
|
||||
#include "..\..\..\FalloutEngine\Fallout2.h"
|
||||
#include "..\..\LoadGameHook.h"
|
||||
#include "..\..\Inventory.h"
|
||||
|
||||
#include "..\..\..\Game\inventory.h"
|
||||
|
||||
#include "Inventory.h"
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
namespace script
|
||||
{
|
||||
|
||||
void __declspec(naked) op_active_hand() {
|
||||
__asm {
|
||||
mov edx, dword ptr ds:[FO_VAR_itemCurrentItem];
|
||||
_J_RET_VAL_TYPE(VAR_TYPE_INT);
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_toggle_active_hand() {
|
||||
__asm {
|
||||
mov eax, 1;
|
||||
jmp fo::funcoffs::intface_toggle_items_;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_set_inven_ap_cost() {
|
||||
__asm {
|
||||
mov esi, ecx;
|
||||
_GET_ARG_INT(end);
|
||||
mov ecx, eax;
|
||||
call Inventory::SetInvenApCost;
|
||||
end:
|
||||
mov ecx, esi;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void mf_get_inven_ap_cost(OpcodeContext& ctx) {
|
||||
ctx.setReturn(Inventory::GetInvenApCost());
|
||||
}
|
||||
|
||||
void op_obj_is_carrying_obj(OpcodeContext& ctx) {
|
||||
int num = 0;
|
||||
const ScriptValue &invenObjArg = ctx.arg(0),
|
||||
&itemObjArg = ctx.arg(1);
|
||||
|
||||
fo::GameObject *invenObj = invenObjArg.object(),
|
||||
*itemObj = itemObjArg.object();
|
||||
if (invenObj != nullptr && itemObj != nullptr) {
|
||||
for (int i = 0; i < invenObj->invenSize; i++) {
|
||||
if (invenObj->invenTable[i].object == itemObj) {
|
||||
num = invenObj->invenTable[i].count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.setReturn(num);
|
||||
}
|
||||
|
||||
void mf_critter_inven_obj2(OpcodeContext& ctx) {
|
||||
fo::GameObject* critter = ctx.arg(0).object();
|
||||
int slot = ctx.arg(1).rawValue();
|
||||
switch (slot) {
|
||||
case 0:
|
||||
ctx.setReturn(fo::func::inven_worn(critter));
|
||||
break;
|
||||
case 1:
|
||||
ctx.setReturn(fo::func::inven_right_hand(critter));
|
||||
break;
|
||||
case 2:
|
||||
ctx.setReturn(fo::func::inven_left_hand(critter));
|
||||
break;
|
||||
case -2:
|
||||
ctx.setReturn(critter->invenSize);
|
||||
break;
|
||||
default:
|
||||
ctx.printOpcodeError("%s() - invalid type.", ctx.getMetaruleName());
|
||||
}
|
||||
}
|
||||
|
||||
void mf_item_weight(OpcodeContext& ctx) {
|
||||
ctx.setReturn(fo::func::item_weight(ctx.arg(0).object()));
|
||||
}
|
||||
|
||||
void mf_get_current_inven_size(OpcodeContext& ctx) {
|
||||
ctx.setReturn(game::Inventory::item_total_size(ctx.arg(0).object()));
|
||||
}
|
||||
|
||||
void mf_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());
|
||||
ctx.setReturn(-1);
|
||||
return;
|
||||
}
|
||||
fo::GameObject* critter = ctx.arg(0).object();
|
||||
if (critter->IsNotCritter()) {
|
||||
ctx.printOpcodeError("%s() - the object is not a critter.", ctx.getMetaruleName());
|
||||
ctx.setReturn(-1);
|
||||
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 (!game::Inventory::correctFidForRemovedItem(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 (!game::Inventory::correctFidForRemovedItem(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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "..\OpcodeContext.h"
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
namespace script
|
||||
{
|
||||
|
||||
void __declspec() op_active_hand();
|
||||
|
||||
void __declspec() op_toggle_active_hand();
|
||||
|
||||
void __declspec() op_set_inven_ap_cost();
|
||||
|
||||
void mf_get_inven_ap_cost(OpcodeContext&);
|
||||
|
||||
void op_obj_is_carrying_obj(OpcodeContext&);
|
||||
|
||||
void mf_critter_inven_obj2(OpcodeContext&);
|
||||
|
||||
void mf_item_weight(OpcodeContext&);
|
||||
|
||||
void mf_get_current_inven_size(OpcodeContext&);
|
||||
|
||||
void mf_unwield_slot(OpcodeContext&);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,10 @@
|
||||
#include "..\Arrays.h"
|
||||
#include "..\OpcodeContext.h"
|
||||
#include "Anims.h"
|
||||
#include "Combat.h"
|
||||
#include "Core.h"
|
||||
#include "Interface.h"
|
||||
#include "Inventory.h"
|
||||
#include "Math.h"
|
||||
#include "Misc.h"
|
||||
#include "Objects.h"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "..\OpcodeContext.h"
|
||||
|
||||
/*
|
||||
* Misc operators
|
||||
*/
|
||||
@@ -29,6 +31,12 @@ namespace script
|
||||
|
||||
class OpcodeContext;
|
||||
|
||||
//Stop game, the same effect as open charsscreen or inventory
|
||||
void __declspec() op_stop_game();
|
||||
|
||||
//Resume the game when it is stopped
|
||||
void __declspec() op_resume_game();
|
||||
|
||||
void op_set_dm_model(OpcodeContext&);
|
||||
|
||||
void op_set_df_model(OpcodeContext&);
|
||||
@@ -37,31 +45,8 @@ void op_set_movie_path(OpcodeContext&);
|
||||
|
||||
void op_get_year(OpcodeContext&);
|
||||
|
||||
void __declspec() op_game_loaded();
|
||||
|
||||
void __declspec() op_set_pipboy_available();
|
||||
|
||||
// Kill counters
|
||||
void SetExtraKillCounter(bool value);
|
||||
|
||||
void __declspec() op_get_kill_counter();
|
||||
|
||||
void __declspec() op_mod_kill_counter();
|
||||
|
||||
void op_set_object_knockback(OpcodeContext&);
|
||||
|
||||
void op_remove_object_knockback(OpcodeContext&);
|
||||
|
||||
void __declspec() op_active_hand();
|
||||
|
||||
void __declspec() op_toggle_active_hand();
|
||||
|
||||
void __declspec() op_eax_available();
|
||||
|
||||
void op_inc_npc_level(OpcodeContext&);
|
||||
|
||||
void op_get_npc_level(OpcodeContext&);
|
||||
|
||||
void op_get_ini_setting(OpcodeContext&);
|
||||
|
||||
void op_get_ini_string(OpcodeContext&);
|
||||
@@ -70,26 +55,12 @@ void __declspec() op_get_uptime();
|
||||
|
||||
void __declspec() op_set_car_current_town();
|
||||
|
||||
void __declspec() op_set_hp_per_level_mod();
|
||||
|
||||
void __declspec() op_get_bodypart_hit_modifier();
|
||||
|
||||
void __declspec() op_set_bodypart_hit_modifier();
|
||||
|
||||
void op_set_critical_table(OpcodeContext&);
|
||||
|
||||
void op_get_critical_table(OpcodeContext&);
|
||||
|
||||
void op_reset_critical_table(OpcodeContext&);
|
||||
|
||||
void __declspec() op_set_unspent_ap_bonus();
|
||||
|
||||
void __declspec() op_get_unspent_ap_bonus();
|
||||
|
||||
void __declspec() op_set_unspent_ap_perk_bonus();
|
||||
|
||||
void __declspec() op_get_unspent_ap_perk_bonus();
|
||||
|
||||
void op_set_palette(OpcodeContext&);
|
||||
|
||||
//numbers subgame functions
|
||||
@@ -105,8 +76,6 @@ void __declspec() op_get_light_level();
|
||||
|
||||
void __declspec() op_refresh_pc_art();
|
||||
|
||||
void op_get_attack_type(OpcodeContext&);
|
||||
|
||||
void op_play_sfall_sound(OpcodeContext&);
|
||||
|
||||
void __declspec() op_stop_sfall_sound();
|
||||
@@ -115,28 +84,12 @@ void __declspec() op_get_tile_fid();
|
||||
|
||||
void __declspec() op_modified_ini();
|
||||
|
||||
void __declspec() op_force_aimed_shots();
|
||||
|
||||
void __declspec() op_disable_aimed_shots();
|
||||
|
||||
void __declspec() op_mark_movie_played();
|
||||
|
||||
void __declspec() op_get_last_attacker();
|
||||
|
||||
void __declspec() op_get_last_target();
|
||||
|
||||
void __declspec() op_block_combat();
|
||||
|
||||
void __declspec() op_tile_under_cursor();
|
||||
|
||||
void __declspec() op_gdialog_get_barter_mod();
|
||||
|
||||
void __declspec() op_set_inven_ap_cost();
|
||||
|
||||
void mf_get_inven_ap_cost(OpcodeContext&);
|
||||
|
||||
void mf_attack_is_aimed(OpcodeContext&);
|
||||
|
||||
void op_sneak_success(OpcodeContext&);
|
||||
|
||||
void op_tile_light(OpcodeContext&);
|
||||
@@ -149,9 +102,5 @@ void mf_get_ini_sections(OpcodeContext&);
|
||||
|
||||
void mf_get_ini_section(OpcodeContext&);
|
||||
|
||||
void mf_npc_engine_level_up(OpcodeContext&);
|
||||
|
||||
void mf_combat_data(OpcodeContext&);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,15 +21,11 @@
|
||||
#include "..\..\CritterStats.h"
|
||||
#include "..\..\Drugs.h"
|
||||
#include "..\..\Explosions.h"
|
||||
//#include "..\..\Inventory.h"
|
||||
#include "..\..\LoadGameHook.h"
|
||||
#include "..\..\Objects.h"
|
||||
#include "..\..\PartyControl.h"
|
||||
#include "..\..\ScriptExtender.h"
|
||||
#include "..\Arrays.h"
|
||||
#include "..\OpcodeContext.h"
|
||||
|
||||
#include "..\..\..\Game\inventory.h"
|
||||
|
||||
#include "Objects.h"
|
||||
|
||||
@@ -38,10 +34,104 @@ namespace sfall
|
||||
namespace script
|
||||
{
|
||||
|
||||
#define exec_script_proc(script, proc) __asm { \
|
||||
__asm mov eax, script \
|
||||
__asm mov edx, proc \
|
||||
__asm call fo::funcoffs::exec_script_proc_ \
|
||||
static const char* protoFailedLoad = "%s() - failed to load a prototype ID: %d";
|
||||
|
||||
static const char* nameNPCToInc;
|
||||
static long pidNPCToInc;
|
||||
static bool onceNpcLoop;
|
||||
|
||||
static void __cdecl IncNPCLevel(const char* fmt, const char* name) {
|
||||
fo::GameObject* mObj;
|
||||
__asm {
|
||||
push edx;
|
||||
mov eax, [ebp + 0x150 - 0x1C + 16]; // ebp <- esp
|
||||
mov edx, [eax];
|
||||
mov mObj, edx;
|
||||
}
|
||||
|
||||
if ((pidNPCToInc && (mObj && mObj->protoId == pidNPCToInc)) || (!pidNPCToInc && !_stricmp(name, nameNPCToInc))) {
|
||||
fo::func::debug_printf(fmt, name);
|
||||
|
||||
SafeWrite32(0x495C50, 0x01FB840F); // Want to keep this check intact. (restore)
|
||||
|
||||
SafeMemSet(0x495C77, CodeType::Nop, 6); // Check that the player is high enough for the npc to consider this level
|
||||
//SafeMemSet(0x495C8C, CodeType::Nop, 6); // Check that the npc isn't already at its maximum level
|
||||
SafeMemSet(0x495CEC, CodeType::Nop, 6); // Check that the npc hasn't already levelled up recently
|
||||
if (!npcAutoLevelEnabled) {
|
||||
SafeWrite8(0x495CFB, CodeType::JumpShort); // Disable random element
|
||||
}
|
||||
__asm mov [ebp + 0x150 - 0x28 + 16], 255; // set counter for exit loop
|
||||
} else {
|
||||
if (!onceNpcLoop) {
|
||||
SafeWrite32(0x495C50, 0x01FCE9); // set goto next member
|
||||
onceNpcLoop = true;
|
||||
}
|
||||
}
|
||||
__asm pop edx;
|
||||
}
|
||||
|
||||
void op_inc_npc_level(OpcodeContext& ctx) {
|
||||
nameNPCToInc = ctx.arg(0).asString();
|
||||
pidNPCToInc = ctx.arg(0).asInt(); // set to 0 if passing npc name
|
||||
if (pidNPCToInc == 0 && nameNPCToInc[0] == 0) return;
|
||||
|
||||
MakeCall(0x495BF1, IncNPCLevel); // Replace the debug output
|
||||
__asm call fo::funcoffs::partyMemberIncLevels_;
|
||||
onceNpcLoop = false;
|
||||
|
||||
// restore code
|
||||
SafeWrite32(0x495C50, 0x01FB840F);
|
||||
__int64 data = 0x01D48C0F;
|
||||
SafeWriteBytes(0x495C77, (BYTE*)&data, 6);
|
||||
//SafeWrite16(0x495C8C, 0x8D0F);
|
||||
//SafeWrite32(0x495C8E, 0x000001BF);
|
||||
data = 0x0130850F;
|
||||
SafeWriteBytes(0x495CEC, (BYTE*)&data, 6);
|
||||
if (!npcAutoLevelEnabled) {
|
||||
SafeWrite8(0x495CFB, CodeType::JumpZ);
|
||||
}
|
||||
}
|
||||
|
||||
void op_get_npc_level(OpcodeContext& ctx) {
|
||||
int level = -1;
|
||||
DWORD findPid = ctx.arg(0).asInt(); // set to 0 if passing npc name
|
||||
const char *critterName, *name = ctx.arg(0).asString();
|
||||
|
||||
if (findPid || name[0] != 0) {
|
||||
DWORD pid = 0;
|
||||
DWORD* members = fo::var::partyMemberList;
|
||||
for (DWORD i = 0; i < fo::var::partyMemberCount; i++) {
|
||||
if (!findPid) {
|
||||
__asm {
|
||||
mov eax, members;
|
||||
mov eax, [eax];
|
||||
call fo::funcoffs::critter_name_;
|
||||
mov critterName, eax;
|
||||
}
|
||||
if (!_stricmp(name, critterName)) { // found npc
|
||||
pid = ((fo::GameObject*)*members)->protoId;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
DWORD _pid = ((fo::GameObject*)*members)->protoId;
|
||||
if (findPid == _pid) {
|
||||
pid = _pid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
members += 4;
|
||||
}
|
||||
if (pid) {
|
||||
DWORD* pids = fo::var::partyMemberPidList;
|
||||
for (DWORD j = 0; j < fo::var::partyMemberMaxCount; j++) {
|
||||
if (pids[j] == pid) {
|
||||
level = fo::var::partyMemberLevelUpInfoList[j * 3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.setReturn(level);
|
||||
}
|
||||
|
||||
void op_remove_script(OpcodeContext& ctx) {
|
||||
@@ -52,6 +142,12 @@ void op_remove_script(OpcodeContext& ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
#define exec_script_proc(script, proc) __asm { \
|
||||
__asm mov eax, script \
|
||||
__asm mov edx, proc \
|
||||
__asm call fo::funcoffs::exec_script_proc_ \
|
||||
}
|
||||
|
||||
void op_set_script(OpcodeContext& ctx) {
|
||||
using fo::Scripts::start;
|
||||
using fo::Scripts::map_enter_p_proc;
|
||||
@@ -106,6 +202,8 @@ void op_create_spatial(OpcodeContext& ctx) {
|
||||
ctx.setReturn(fo::func::scr_find_obj_from_program(scriptPtr->program));
|
||||
}
|
||||
|
||||
#undef exec_script_proc
|
||||
|
||||
void mf_spatial_radius(OpcodeContext& ctx) {
|
||||
auto spatialObj = ctx.arg(0).object();
|
||||
fo::ScriptInstance* script;
|
||||
@@ -143,7 +241,7 @@ void op_set_weapon_ammo_count(OpcodeContext& ctx) {
|
||||
obj->item.charges = ctx.arg(1).rawValue();
|
||||
}
|
||||
|
||||
enum {
|
||||
enum class BlockType {
|
||||
BLOCKING_TYPE_BLOCK = 0,
|
||||
BLOCKING_TYPE_SHOOT = 1,
|
||||
BLOCKING_TYPE_AI = 2,
|
||||
@@ -151,15 +249,15 @@ enum {
|
||||
BLOCKING_TYPE_SCROLL = 4
|
||||
};
|
||||
|
||||
static DWORD getBlockingFunc(DWORD type) {
|
||||
static DWORD getBlockingFunc(BlockType type) {
|
||||
switch (type) {
|
||||
case BLOCKING_TYPE_BLOCK: default:
|
||||
case BlockType::BLOCKING_TYPE_BLOCK: default:
|
||||
return fo::funcoffs::obj_blocking_at_; // with calling hook
|
||||
case BLOCKING_TYPE_SHOOT:
|
||||
case BlockType::BLOCKING_TYPE_SHOOT:
|
||||
return fo::funcoffs::obj_shoot_blocking_at_; // w/o calling hook
|
||||
case BLOCKING_TYPE_AI:
|
||||
case BlockType::BLOCKING_TYPE_AI:
|
||||
return fo::funcoffs::obj_ai_blocking_at_; // w/o calling hook
|
||||
case BLOCKING_TYPE_SIGHT:
|
||||
case BlockType::BLOCKING_TYPE_SIGHT:
|
||||
return fo::funcoffs::obj_sight_blocking_at_; // w/o calling hook
|
||||
//case 4:
|
||||
// return obj_scroll_blocking_at_;
|
||||
@@ -168,10 +266,10 @@ static DWORD getBlockingFunc(DWORD type) {
|
||||
|
||||
void op_make_straight_path(OpcodeContext& ctx) {
|
||||
auto objFrom = ctx.arg(0).object();
|
||||
DWORD tileTo = ctx.arg(1).rawValue(),
|
||||
type = ctx.arg(2).rawValue();
|
||||
DWORD tileTo = ctx.arg(1).rawValue();
|
||||
BlockType type = (BlockType)ctx.arg(2).rawValue();
|
||||
|
||||
long flag = (type == BLOCKING_TYPE_SHOOT) ? 32 : 0;
|
||||
long flag = (type == BlockType::BLOCKING_TYPE_SHOOT) ? 32 : 0;
|
||||
fo::GameObject* resultObj = nullptr;
|
||||
fo::func::make_straight_path_func(objFrom, objFrom->tile, tileTo, 0, (DWORD*)&resultObj, flag, (void*)getBlockingFunc(type));
|
||||
ctx.setReturn(resultObj);
|
||||
@@ -179,9 +277,8 @@ void op_make_straight_path(OpcodeContext& ctx) {
|
||||
|
||||
void op_make_path(OpcodeContext& ctx) {
|
||||
auto objFrom = ctx.arg(0).object();
|
||||
auto tileTo = ctx.arg(1).rawValue(),
|
||||
type = ctx.arg(2).rawValue();
|
||||
auto func = getBlockingFunc(type);
|
||||
auto tileTo = ctx.arg(1).rawValue();
|
||||
auto func = getBlockingFunc((BlockType)ctx.arg(2).rawValue());
|
||||
|
||||
// if the object is not a critter, then there is no need to check tile (tileTo) for blocking
|
||||
long checkFlag = (objFrom->IsCritter());
|
||||
@@ -197,11 +294,11 @@ void op_make_path(OpcodeContext& ctx) {
|
||||
|
||||
void op_obj_blocking_at(OpcodeContext& ctx) {
|
||||
DWORD tile = ctx.arg(0).rawValue(),
|
||||
elevation = ctx.arg(1).rawValue(),
|
||||
type = ctx.arg(2).rawValue();
|
||||
elevation = ctx.arg(1).rawValue();
|
||||
BlockType type = (BlockType)ctx.arg(2).rawValue();
|
||||
|
||||
fo::GameObject* resultObj = fo::func::obj_blocking_at_wrapper(0, tile, elevation, (void*)getBlockingFunc(type));
|
||||
if (resultObj && type == BLOCKING_TYPE_SHOOT && (resultObj->flags & fo::ObjectFlag::ShootThru)) { // don't know what this flag means, copy-pasted from the engine code
|
||||
if (resultObj && type == BlockType::BLOCKING_TYPE_SHOOT && (resultObj->flags & fo::ObjectFlag::ShootThru)) { // don't know what this flag means, copy-pasted from the engine code
|
||||
// this check was added because the engine always does exactly this when using shoot blocking checks
|
||||
resultObj = nullptr;
|
||||
}
|
||||
@@ -234,49 +331,6 @@ void op_get_party_members(OpcodeContext& ctx) {
|
||||
ctx.setReturn(arrayId);
|
||||
}
|
||||
|
||||
void op_art_exists(OpcodeContext& ctx) {
|
||||
ctx.setReturn(fo::func::art_exists(ctx.arg(0).rawValue()));
|
||||
}
|
||||
|
||||
void op_obj_is_carrying_obj(OpcodeContext& ctx) {
|
||||
int num = 0;
|
||||
const ScriptValue &invenObjArg = ctx.arg(0),
|
||||
&itemObjArg = ctx.arg(1);
|
||||
|
||||
fo::GameObject *invenObj = invenObjArg.object(),
|
||||
*itemObj = itemObjArg.object();
|
||||
if (invenObj != nullptr && itemObj != nullptr) {
|
||||
for (int i = 0; i < invenObj->invenSize; i++) {
|
||||
if (invenObj->invenTable[i].object == itemObj) {
|
||||
num = invenObj->invenTable[i].count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.setReturn(num);
|
||||
}
|
||||
|
||||
void mf_critter_inven_obj2(OpcodeContext& ctx) {
|
||||
fo::GameObject* critter = ctx.arg(0).object();
|
||||
int slot = ctx.arg(1).rawValue();
|
||||
switch (slot) {
|
||||
case 0:
|
||||
ctx.setReturn(fo::func::inven_worn(critter));
|
||||
break;
|
||||
case 1:
|
||||
ctx.setReturn(fo::func::inven_right_hand(critter));
|
||||
break;
|
||||
case 2:
|
||||
ctx.setReturn(fo::func::inven_left_hand(critter));
|
||||
break;
|
||||
case -2:
|
||||
ctx.setReturn(critter->invenSize);
|
||||
break;
|
||||
default:
|
||||
ctx.printOpcodeError("%s() - invalid type.", ctx.getMetaruleName());
|
||||
}
|
||||
}
|
||||
|
||||
void mf_set_outline(OpcodeContext& ctx) {
|
||||
auto obj = ctx.arg(0).object();
|
||||
int color = ctx.arg(1).rawValue();
|
||||
@@ -303,10 +357,6 @@ void mf_outlined_object(OpcodeContext& ctx) {
|
||||
ctx.setReturn(fo::var::outlined_object);
|
||||
}
|
||||
|
||||
void mf_item_weight(OpcodeContext& ctx) {
|
||||
ctx.setReturn(fo::func::item_weight(ctx.arg(0).object()));
|
||||
}
|
||||
|
||||
void mf_set_dude_obj(OpcodeContext& ctx) {
|
||||
auto obj = ctx.arg(0).object();
|
||||
if (obj == nullptr || obj->IsCritter()) {
|
||||
@@ -366,10 +416,6 @@ void mf_item_make_explosive(OpcodeContext& ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
void mf_get_current_inven_size(OpcodeContext& ctx) {
|
||||
ctx.setReturn(game::Inventory::item_total_size(ctx.arg(0).object()));
|
||||
}
|
||||
|
||||
void mf_get_dialog_object(OpcodeContext& ctx) {
|
||||
ctx.setReturn(InDialog() ? fo::var::dialog_target : 0);
|
||||
}
|
||||
@@ -384,7 +430,6 @@ void mf_get_loot_object(OpcodeContext& ctx) {
|
||||
ctx.setReturn((GetLoopFlags() & INTFACELOOT) ? fo::var::target_stack[fo::var::target_curr_stack] : 0);
|
||||
}
|
||||
|
||||
static const char* failedLoad = "%s() - failed to load a prototype ID: %d";
|
||||
static bool protoMaxLimitPatch = false;
|
||||
|
||||
void op_get_proto_data(OpcodeContext& ctx) {
|
||||
@@ -394,7 +439,7 @@ void op_get_proto_data(OpcodeContext& ctx) {
|
||||
if (result != -1) {
|
||||
result = *(long*)((BYTE*)protoPtr + ctx.arg(1).rawValue());
|
||||
} else {
|
||||
ctx.printOpcodeError(failedLoad, ctx.getOpcodeName(), pid);
|
||||
ctx.printOpcodeError(protoFailedLoad, ctx.getOpcodeName(), pid);
|
||||
}
|
||||
ctx.setReturn(result);
|
||||
}
|
||||
@@ -407,7 +452,7 @@ void op_set_proto_data(OpcodeContext& ctx) {
|
||||
protoMaxLimitPatch = true;
|
||||
}
|
||||
} else {
|
||||
ctx.printOpcodeError(failedLoad, ctx.getOpcodeName(), pid);
|
||||
ctx.printOpcodeError(protoFailedLoad, ctx.getOpcodeName(), pid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,5 +577,15 @@ void mf_objects_in_radius(OpcodeContext& ctx) {
|
||||
ctx.setReturn(id);
|
||||
}
|
||||
|
||||
void mf_npc_engine_level_up(OpcodeContext& ctx) {
|
||||
if (ctx.arg(0).asBool()) {
|
||||
if (!npcEngineLevelUp) SafeWrite16(0x4AFC1C, 0x840F); // enable
|
||||
npcEngineLevelUp = true;
|
||||
} else {
|
||||
if (npcEngineLevelUp) SafeWrite16(0x4AFC1C, 0xE990);
|
||||
npcEngineLevelUp = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,15 +18,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "..\..\..\main.h"
|
||||
#include "..\..\Inventory.h"
|
||||
#include "..\..\ScriptExtender.h"
|
||||
#include "..\OpcodeContext.h"
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
namespace script
|
||||
{
|
||||
|
||||
void op_inc_npc_level(OpcodeContext&);
|
||||
|
||||
void op_get_npc_level(OpcodeContext&);
|
||||
|
||||
void op_remove_script(OpcodeContext&);
|
||||
|
||||
void op_set_script(OpcodeContext&);
|
||||
@@ -57,12 +59,6 @@ void op_tile_get_objects(OpcodeContext&);
|
||||
|
||||
void op_get_party_members(OpcodeContext&);
|
||||
|
||||
void op_art_exists(OpcodeContext&);
|
||||
|
||||
void op_obj_is_carrying_obj(OpcodeContext&);
|
||||
|
||||
void mf_critter_inven_obj2(OpcodeContext&);
|
||||
|
||||
void mf_set_outline(OpcodeContext&);
|
||||
|
||||
void mf_get_outline(OpcodeContext&);
|
||||
@@ -73,8 +69,6 @@ void mf_get_flags(OpcodeContext&);
|
||||
|
||||
void mf_outlined_object(OpcodeContext&);
|
||||
|
||||
void mf_item_weight(OpcodeContext&);
|
||||
|
||||
void mf_set_dude_obj(OpcodeContext&);
|
||||
|
||||
void mf_real_dude_obj(OpcodeContext&);
|
||||
@@ -89,8 +83,6 @@ void mf_set_unjam_locks_time(OpcodeContext&);
|
||||
|
||||
void mf_item_make_explosive(OpcodeContext&);
|
||||
|
||||
void mf_get_current_inven_size(OpcodeContext&);
|
||||
|
||||
void mf_get_dialog_object(OpcodeContext&);
|
||||
|
||||
void mf_obj_under_cursor(OpcodeContext&);
|
||||
@@ -113,5 +105,7 @@ void mf_set_unique_id(OpcodeContext&);
|
||||
|
||||
void mf_objects_in_radius(OpcodeContext&);
|
||||
|
||||
void mf_npc_engine_level_up(OpcodeContext&);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,19 @@ namespace script
|
||||
const char* invalidStat = "%s() - stat number out of range.";
|
||||
const char* objNotCritter = "%s() - the object is not a critter.";
|
||||
|
||||
void __declspec(naked) op_set_hp_per_level_mod() {
|
||||
__asm {
|
||||
mov esi, ecx;
|
||||
_GET_ARG_INT(end);
|
||||
push eax; // allowed -/+127
|
||||
push 0x4AFBC1;
|
||||
call SafeWrite8;
|
||||
end:
|
||||
mov ecx, esi;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void op_set_pc_base_stat(OpcodeContext& ctx) {
|
||||
int stat = ctx.arg(0).rawValue();
|
||||
if (stat >= 0 && stat < fo::STAT_max_stat) {
|
||||
@@ -209,6 +222,38 @@ end:
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_set_unspent_ap_bonus() {
|
||||
__asm {
|
||||
_GET_ARG_INT(end);
|
||||
mov Stats::standardApAcBonus, eax;
|
||||
end:
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_get_unspent_ap_bonus() {
|
||||
__asm {
|
||||
mov edx, Stats::standardApAcBonus;
|
||||
_J_RET_VAL_TYPE(VAR_TYPE_INT);
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_set_unspent_ap_perk_bonus() {
|
||||
__asm {
|
||||
_GET_ARG_INT(end);
|
||||
mov Stats::extraApAcBonus, eax;
|
||||
end:
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_get_unspent_ap_perk_bonus() {
|
||||
__asm {
|
||||
mov edx, Stats::extraApAcBonus;
|
||||
_J_RET_VAL_TYPE(VAR_TYPE_INT);
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_get_critter_current_ap() {
|
||||
using namespace fo;
|
||||
using namespace Fields;
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace sfall
|
||||
namespace script
|
||||
{
|
||||
|
||||
void __declspec() op_set_hp_per_level_mod();
|
||||
|
||||
// stat_funcs
|
||||
void op_set_pc_base_stat(OpcodeContext&);
|
||||
|
||||
@@ -50,6 +52,14 @@ void __declspec() op_get_available_skill_points();
|
||||
|
||||
void __declspec() op_mod_skill_points_per_level();
|
||||
|
||||
void __declspec() op_set_unspent_ap_bonus();
|
||||
|
||||
void __declspec() op_get_unspent_ap_bonus();
|
||||
|
||||
void __declspec() op_set_unspent_ap_perk_bonus();
|
||||
|
||||
void __declspec() op_get_unspent_ap_perk_bonus();
|
||||
|
||||
void __declspec() op_get_critter_current_ap();
|
||||
|
||||
void op_set_critter_current_ap(OpcodeContext&);
|
||||
|
||||
@@ -22,10 +22,12 @@
|
||||
|
||||
#include "Handlers\Anims.h"
|
||||
#include "Handlers\Arrays.h"
|
||||
#include "Handlers\Combat.h"
|
||||
#include "Handlers\Core.h"
|
||||
#include "Handlers\FileSystem.h"
|
||||
#include "Handlers\Graphics.h"
|
||||
#include "Handlers\Interface.h"
|
||||
#include "Handlers\Inventory.h"
|
||||
#include "Handlers\Math.h"
|
||||
#include "Handlers\Memory.h"
|
||||
#include "Handlers\Misc.h"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user