Rewrote the code of force_encounter functions

Added a new flag to force_encounter_with_flags.
This commit is contained in:
NovaRain
2019-08-12 12:06:45 +08:00
parent 50f4885407
commit da864c9789
5 changed files with 54 additions and 66 deletions
+2 -1
View File
@@ -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)
+1
View File
@@ -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
+42 -61
View File
@@ -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
+2 -2
View File
@@ -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();
+7 -2
View File
@@ -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
};
}
}