Changed the implementation of HOOK_FINDTARGET so you don't have to specify all 4 targets to override normal sorting (from Mr.Stalin)

Added "loot_obj" script function.
This commit is contained in:
NovaRain
2018-11-06 11:11:44 +08:00
parent 4ae4d6dff0
commit de055cd8ec
10 changed files with 31 additions and 20 deletions
+1
View File
@@ -255,6 +255,7 @@
#define item_make_explosive(pid, aPid, min, max) sfall_func4("item_make_explosive", pid, aPid, min, max)
#define item_weight(obj) sfall_func1("item_weight", obj)
#define lock_is_jammed(obj) sfall_func1("lock_is_jammed", obj)
#define loot_obj sfall_func0("loot_obj")
#define obj_under_cursor(crSwitch, inclDude) sfall_func2("obj_under_cursor", crSwitch, inclDude)
#define outlined_object sfall_func0("outlined_object")
#define real_dude_obj sfall_func0("real_dude_obj")
+1 -1
View File
@@ -189,7 +189,7 @@ Critter arg1 - The critter that just died
HOOK_FINDTARGET (hs_findtarget.int)
Runs when the ai is trying to pick a target in combat. Fallout first chooses a list of 4 likely suspects, then normally sorts them in order of weakness/distance/etc depending on the ai caps of the attacker. This hook replaces that sorting function, allowing you to sort the targets in some arbitrary way. Use sfall_return to give the 4 targets, in order of preference. All 4 must be given if you want to override normal sorting; if you want to specify less than 4 targets fill in the extra spaces with 0's. If you do not give 4 targets, the NPCs normal sorting mechanism will be used.
Runs when the ai is trying to pick a target in combat. Fallout first chooses a list of 4 likely suspects, then normally sorts them in order of weakness/distance/etc depending on the ai caps of the attacker. This hook replaces that sorting function, allowing you to sort the targets in some arbitrary way. Use sfall_return to give the 4 targets, in order of preference. If you want to specify less than 4 targets, fill in the extra spaces with 0's. Pass -1 to skip the return value.
The return values can include critters that weren't in the list of possible targets, but the additional targets may still be discarded later on in the combat turn if they are out of the attackers perception or the chance of a successful hit is too low. The list of possible targets often includes duplicated entries.
+4 -1
View File
@@ -540,13 +540,16 @@ Some utility/math functions are available:
- the can_rest_here values in maps.txt are ignored
> object sfall_func0("dialog_obj")
- returns the object (critter) the player is having a conversation or bartering with
- returns a pointer to the object (critter) the player is having a conversation or bartering with
> object sfall_func2("obj_under_cursor", bool crSwitch, bool inclDude)
- returns the object under the cursor on the main game screen
- crSwitch: True - only checks critters and ignores their cover (roof tiles, walls, scenery, etc.), False - checks all objects (can't check critters under objects)
- passing False to the inclDude argument will ignore dude_obj
> object sfall_func0("loot_obj")
- returns a pointer to the target object (container or critter) of the loot screen
------------------------
------ MORE INFO -------
------------------------
+9 -14
View File
@@ -185,27 +185,22 @@ static void __fastcall FindTargetHook_Script(DWORD* target, DWORD attacker) {
RunHookScript(HOOK_FINDTARGET);
if (cRet >= 4) {
target[0] = rets[0];
target[1] = rets[1];
target[2] = rets[2];
target[3] = rets[3];
if (cRet > 0) {
if (rets[0] != -1) target[0] = rets[0];
if (cRet > 1 && rets[1] != -1) target[1] = rets[1];
if (cRet > 2 && rets[2] != -1) target[2] = rets[2];
if (cRet > 3 && rets[3] != -1) target[3] = rets[3];
}
EndHook();
}
static void __declspec(naked) FindTargetHook() {
__asm {
pushad;
mov ecx, eax; // targets (base)
mov edx, esi; // attacker
call FindTargetHook_Script;
popad;
cmp cRet, 4;
jge skip;
push eax;
call fo::funcoffs::qsort_;
skip:
retn;
pop ecx; // targets (base)
mov edx, esi; // attacker
jmp FindTargetHook_Script;
}
}
+3
View File
@@ -60,6 +60,8 @@ static Delegate<> onAfterNewGame;
static Delegate<DWORD> onGameModeChange;
static Delegate<> onBeforeGameClose;
DWORD LoadGameHook::LootTarget = 0;
static DWORD inLoop = 0;
static DWORD saveInCombatFix;
static bool disableHorrigan = false;
@@ -528,6 +530,7 @@ static void __declspec(naked) UseInventoryOnHook() {
static void __declspec(naked) LootContainerHook() {
__asm {
mov LoadGameHook::LootTarget, edx;
_InLoop(1, INTFACELOOT);
call fo::funcoffs::loot_container_;
_InLoop(0, INTFACELOOT);
+2
View File
@@ -52,6 +52,8 @@ public:
// Invoked before the game exits to windows
static Delegate<>& OnBeforeGameClose();
static DWORD LootTarget;
};
// True if some map was loaded, false when on the main menu
@@ -104,6 +104,7 @@ static const SfallMetarule metarules[] = {
{"item_make_explosive", sf_item_make_explosive, 3, 4, {ARG_INT, ARG_INT, ARG_INT, ARG_INT}},
{"item_weight", sf_item_weight, 1, 1, {ARG_OBJECT}},
{"lock_is_jammed", sf_lock_is_jammed, 1, 1, {ARG_OBJECT}},
{"loot_obj", sf_get_loot_object, 0, 0},
{"obj_under_cursor", sf_obj_under_cursor, 2, 2, {ARG_INT, ARG_INT}},
{"outlined_object", sf_outlined_object, 0, 0},
{"real_dude_obj", sf_real_dude_obj, 0, 0},
@@ -456,5 +456,9 @@ void sf_get_dialog_object(OpcodeContext& ctx) {
ctx.setReturn(InDialog() ? fo::var::dialog_target : 0);
}
void sf_get_loot_object(OpcodeContext& ctx) {
ctx.setReturn((GetLoopFlags() & INTFACELOOT) ? LoadGameHook::LootTarget : 0);
}
}
}
@@ -97,5 +97,7 @@ void sf_get_current_inven_size(OpcodeContext&);
void sf_get_dialog_object(OpcodeContext&);
void sf_get_loot_object(OpcodeContext&);
}
}
+4 -4
View File
@@ -47,19 +47,19 @@ void _stdcall SafeWrite32(DWORD addr, DWORD data) {
void _stdcall SafeWriteStr(DWORD addr, const char* data) {
DWORD oldProtect;
VirtualProtect((void *)addr, strlen(data)+1, PAGE_EXECUTE_READWRITE, &oldProtect);
VirtualProtect((void *)addr, strlen(data) + 1, PAGE_EXECUTE_READWRITE, &oldProtect);
strcpy((char *)addr, data);
VirtualProtect((void *)addr, strlen(data)+1, oldProtect, &oldProtect);
VirtualProtect((void *)addr, strlen(data) + 1, oldProtect, &oldProtect);
}
void HookCall(DWORD addr, void* func) {
SafeWrite32(addr+1, (DWORD)func - (addr+5));
SafeWrite32(addr + 1, (DWORD)func - (addr + 5));
#ifndef NDEBUG
bool exist = false;
for (const auto &wa : writeAddress) {
if (addr == wa) {
exist = true;
char buf[512];
char buf[256];
sprintf_s(buf, "Memory writing conflict at address 0x%x. The address has already been overwritten by other code.", addr);
MessageBoxA(0, buf, "Conflict Detected", MB_TASKMODAL);
}