mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Rewrote the code of force_encounter functions
Added a new flag to force_encounter_with_flags.
This commit is contained in:
@@ -73,7 +73,8 @@
|
||||
#define LIST_ALL (9)
|
||||
|
||||
//Valid flags for force_encounter_with_flags
|
||||
#define ENCOUNTER_FLAG_NO_CAR (1)
|
||||
#define ENCOUNTER_FLAG_NO_CAR (1)
|
||||
#define ENCOUNTER_FLAG_LOCK (2) // block new forced encounter by the next function call until the current specified encounter occurs
|
||||
|
||||
//The attack types returned by get_attack_type
|
||||
#define ATKTYPE_LWEP1 (0)
|
||||
|
||||
@@ -132,6 +132,7 @@
|
||||
#define FO_VAR_max 0x56FB50
|
||||
#define FO_VAR_maxScriptNum 0x51C7CC
|
||||
#define FO_VAR_Meet_Frank_Horrigan 0x672E04
|
||||
#define FO_VAR_Move_on_Car 0x672E64
|
||||
#define FO_VAR_mouse_hotx 0x6AC7D0
|
||||
#define FO_VAR_mouse_hoty 0x6AC7CC
|
||||
#define FO_VAR_mouse_is_hidden 0x6AC790
|
||||
|
||||
@@ -31,77 +31,58 @@ namespace sfall
|
||||
namespace script
|
||||
{
|
||||
|
||||
static DWORD EncounteredHorrigan;
|
||||
static DWORD ForceEnconterMapID;
|
||||
static DWORD ForceEnconterMapID = -1;
|
||||
static DWORD ForceEnconterFlags;
|
||||
|
||||
static void _stdcall ForceEncounterRestore() {
|
||||
*(DWORD*)0x672E04 = EncounteredHorrigan;
|
||||
SafeWrite32(0x4C070E, *(DWORD*)0x4C0718); // map id
|
||||
SafeWrite16(0x4C06D8, 0x5175);
|
||||
SafeWrite32(0x4C071D, 0xFFFC2413);
|
||||
SafeWrite8(0x4C0706, 0x75);
|
||||
DWORD ForceEncounterRestore() {
|
||||
long long data = 0x672E043D83; // cmp ds:_Meet_Frank_Horrigan, 0
|
||||
SafeWriteBytes(0x4C06D1, (BYTE*)&data, 5);
|
||||
ForceEnconterFlags = 0;
|
||||
DWORD mapID = ForceEnconterMapID;
|
||||
ForceEnconterMapID = -1;
|
||||
return mapID;
|
||||
}
|
||||
|
||||
static void __declspec(naked) wmRndEncounterOccurred_hook() {
|
||||
static void __declspec(naked) wmRndEncounterOccurred_hack() {
|
||||
__asm {
|
||||
push ecx;
|
||||
call ForceEncounterRestore;
|
||||
pop ecx;
|
||||
test ForceEnconterFlags, 0x1; // _NoCar flag
|
||||
jnz noCar;
|
||||
cmp ds:[FO_VAR_Move_on_Car], 0;
|
||||
jz noCar;
|
||||
mov edx, FO_VAR_carCurrentArea;
|
||||
mov eax, ForceEnconterMapID;
|
||||
jmp fo::funcoffs::map_load_idx_;
|
||||
call fo::funcoffs::wmMatchAreaContainingMapIdx_;
|
||||
noCar:
|
||||
//push ecx;
|
||||
// TODO: implement a blinking red icon
|
||||
call ForceEncounterRestore;
|
||||
//pop ecx;
|
||||
push 0x4C0721; // return addr
|
||||
jmp fo::funcoffs::map_load_idx_; // eax - mapID
|
||||
}
|
||||
}
|
||||
|
||||
static void __fastcall ForceEncounter(DWORD mapID, DWORD flags) {
|
||||
EncounteredHorrigan = *(DWORD*)0x672E04;
|
||||
void sf_force_encounter(OpcodeContext& cxt) {
|
||||
if (ForceEnconterFlags & (1 << 31)) return; // wait prev. encounter
|
||||
|
||||
DWORD mapID = cxt.arg(0).rawValue();
|
||||
if (mapID < 0) {
|
||||
cxt.printOpcodeError("%s() - invalid map number.", cxt.getOpcodeName());
|
||||
return;
|
||||
}
|
||||
if (ForceEnconterMapID == -1) MakeJump(0x4C06D1, wmRndEncounterOccurred_hack);
|
||||
|
||||
ForceEnconterMapID = mapID;
|
||||
SafeWrite32(0x4C070E, mapID);
|
||||
SafeWrite16(0x4C06D8, 0x13EB); // jmp 0x4C06ED
|
||||
HookCall(0x4C071C, wmRndEncounterOccurred_hook);
|
||||
|
||||
if (flags & 1) SafeWrite8(0x4C0706, 0xEB);
|
||||
}
|
||||
|
||||
void __declspec(naked) op_force_encounter() {
|
||||
__asm {
|
||||
push ecx;
|
||||
push edx;
|
||||
_GET_ARG_INT(end);
|
||||
xor edx, edx; // flags
|
||||
mov ecx, eax; // mapID
|
||||
call ForceEncounter;
|
||||
end:
|
||||
pop edx;
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_force_encounter_with_flags() {
|
||||
__asm {
|
||||
pushad;
|
||||
mov ecx, eax;
|
||||
call fo::funcoffs::interpretPopShort_;
|
||||
mov edx, eax;
|
||||
mov eax, ecx;
|
||||
call fo::funcoffs::interpretPopLong_;
|
||||
mov ebx, eax;
|
||||
mov eax, ecx;
|
||||
call fo::funcoffs::interpretPopShort_;
|
||||
mov edi, eax;
|
||||
mov eax, ecx;
|
||||
call fo::funcoffs::interpretPopLong_;
|
||||
cmp dx, VAR_TYPE_INT;
|
||||
jnz end;
|
||||
cmp di, VAR_TYPE_INT;
|
||||
jnz end;
|
||||
mov edx, ebx; // flags
|
||||
mov ecx, eax; // mapID
|
||||
call ForceEncounter;
|
||||
end:
|
||||
popad;
|
||||
retn;
|
||||
DWORD flags = 0;
|
||||
if (cxt.numArgs() > 1) {
|
||||
flags = cxt.arg(1).rawValue();
|
||||
if (flags & 2) { // _Lock flag
|
||||
flags |= (1 << 31); // set bit 31
|
||||
} else {
|
||||
flags = flags & ~(1 << 31);
|
||||
}
|
||||
}
|
||||
ForceEnconterFlags = flags;
|
||||
}
|
||||
|
||||
// world_map_functions
|
||||
|
||||
@@ -25,9 +25,9 @@ namespace script
|
||||
|
||||
class OpcodeContext;
|
||||
|
||||
void __declspec() op_force_encounter();
|
||||
void sf_force_encounter(OpcodeContext&);
|
||||
|
||||
void __declspec() op_force_encounter_with_flags();
|
||||
DWORD ForceEncounterRestore();
|
||||
|
||||
// world_map_functions
|
||||
void __declspec() op_in_world_map();
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "..\..\FalloutEngine\Fallout2.h"
|
||||
#include "..\KillCounter.h"
|
||||
#include "..\LoadGameHook.h"
|
||||
|
||||
#include "Handlers\Anims.h"
|
||||
#include "Handlers\Arrays.h"
|
||||
@@ -72,6 +73,7 @@ static SfallOpcodeInfo opcodeInfoArray[] = {
|
||||
{0x161, "get_critter_extra_stat", sf_get_critter_extra_stat, 2, true, {ARG_OBJECT, ARG_INT}},
|
||||
{0x163, "get_year", sf_get_year, 0, true},
|
||||
{0x16c, "key_pressed", sf_key_pressed, 1, true, {ARG_INT}},
|
||||
{0x171, "force_encounter", sf_force_encounter, 1, false, {ARG_INT}},
|
||||
|
||||
{0x190, "get_perk_available", sf_get_perk_available, 1, true, {ARG_INT}},
|
||||
{0x195, "set_weapon_knockback", sf_set_object_knockback, 3, false, {ARG_OBJECT, ARG_INT, ARG_NUMBER}},
|
||||
@@ -143,6 +145,7 @@ static SfallOpcodeInfo opcodeInfoArray[] = {
|
||||
|
||||
{0x224, "create_message_window", sf_create_message_window, 1, false, {ARG_STRING}},
|
||||
{0x228, "get_attack_type", sf_get_attack_type, 0, true},
|
||||
{0x229, "force_encounter_with_flags", sf_force_encounter, 2, false, {ARG_INT, ARG_INT}},
|
||||
{0x22d, "create_array", sf_create_array, 2, true, {ARG_INT, ARG_INT}},
|
||||
{0x22e, "set_array", sf_set_array, 3, false, {ARG_OBJECT, ARG_ANY, ARG_ANY}},
|
||||
{0x22f, "get_array", sf_get_array, 2, true, {ARG_ANY, ARG_ANY}}, // can also be used on strings
|
||||
@@ -286,7 +289,6 @@ void InitNewOpcodes() {
|
||||
opcodes[0x16e] = op_set_shader_float;
|
||||
opcodes[0x16f] = op_set_shader_vector;
|
||||
opcodes[0x170] = op_in_world_map;
|
||||
opcodes[0x171] = op_force_encounter;
|
||||
opcodes[0x172] = op_set_world_map_pos;
|
||||
opcodes[0x173] = op_get_world_map_x_pos;
|
||||
opcodes[0x174] = op_get_world_map_y_pos;
|
||||
@@ -384,7 +386,6 @@ void InitNewOpcodes() {
|
||||
opcodes[0x225] = op_remove_trait;
|
||||
opcodes[0x226] = op_get_light_level;
|
||||
opcodes[0x227] = op_refresh_pc_art;
|
||||
opcodes[0x229] = op_force_encounter_with_flags;
|
||||
opcodes[0x22a] = op_set_map_time_multi;
|
||||
opcodes[0x22b] = op_play_sfall_sound;
|
||||
opcodes[0x22c] = op_stop_sfall_sound;
|
||||
@@ -424,6 +425,10 @@ void InitNewOpcodes() {
|
||||
|
||||
InitOpcodeInfoTable();
|
||||
InitMetaruleTable();
|
||||
|
||||
LoadGameHook::OnGameReset() += []() {
|
||||
ForceEncounterRestore(); // restore if the encounter did not happen
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user