Skip to content

Commit 4e62439

Browse files
committed
Allow picking up outlined items behind scenery/walls/misc objects
(ref. fallout2-ce/fallout2-ce#603)
1 parent 9c516e8 commit 4e62439

2 files changed

Lines changed: 130 additions & 1 deletion

File tree

‎sfall/FalloutEngine/Enums.h‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,21 @@ enum ArtType : char
317317
OBJ_TYPE_SKILLDEX = 10
318318
};
319319

320+
enum OutlineType : long
321+
{
322+
OUTLINE_TYPE_NONE = 0x00,
323+
OUTLINE_TYPE_HOSTILE = 0x01,
324+
OUTLINE_TYPE_SAME_TEAM = 0x02,
325+
OUTLINE_TYPE_BODY = 0x04,
326+
OUTLINE_TYPE_FRIENDLY = 0x08,
327+
OUTLINE_TYPE_ITEM = 0x10,
328+
OUTLINE_TYPE_BLOCKED = 0x20,
329+
OUTLINE_TYPE_MAX = 0xFFFFFF
330+
};
331+
332+
#define OUTLINE_PALETTED (0x40000000)
333+
#define OUTLINE_DISABLED (0x80000000)
334+
320335
//XXXXXXXXXXXXXXXXXXXXX
321336
//XX Critter defines XX
322337
//XXXXXXXXXXXXXXXXXXXXX

‎sfall/Modules/Objects.cpp‎

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,116 @@ static __declspec(naked) void obj_insert_hack() {
253253
}
254254
}
255255

256+
// Finds a possible itemObj behind scenery, wall, and misc types of pointedObj
257+
static __declspec(naked) void gmouse_bk_process_hack() {
258+
static const DWORD gmouse_bk_process_Ret = 0x44BA37;
259+
using namespace fo;
260+
using namespace Fields;
261+
using namespace ObjectFlag;
262+
__asm { // edi - pointedObj, eax - objType, ebp - mouse menu primary action
263+
je searchItem; // objType == OBJ_TYPE_WALL
264+
cmp eax, OBJ_TYPE_SCENERY;
265+
je searchItem;
266+
cmp eax, OBJ_TYPE_MISC;
267+
je searchItem;
268+
// overwritten engine code
269+
cmp eax, OBJ_TYPE_WALL;
270+
ja jbreak;
271+
retn; // switch case - OBJ_TYPE_ITEM and OBJ_TYPE_CRITTER
272+
jbreak:
273+
add esp, 4;
274+
jmp gmouse_bk_process_Ret;
275+
searchItem:
276+
mov ecx, eax; // save objType
277+
mov eax, OBJ_TYPE_ITEM;
278+
mov edx, 1;
279+
mov ebx, ds:[FO_VAR_map_elevation];
280+
call fo::funcoffs::object_under_mouse_;
281+
test eax, eax;
282+
jnz chkOutline;
283+
cmp ecx, OBJ_TYPE_MISC;
284+
je jbreak;
285+
chkOutline:
286+
mov ebx, eax; // save itemObj
287+
test ebx, ebx;
288+
jz notOutlined;
289+
mov edx, [ebx + outline];
290+
test edx, OUTLINE_TYPE_MAX;
291+
jz notOutlined;
292+
test edx, OUTLINE_DISABLED;
293+
jnz notOutlined;
294+
itemRet:
295+
mov edi, ebx; // set itemObj as new pointedObj
296+
mov [esp + 0xB4 - 0x1C + 4], ebx; // for obj_look_at_ later
297+
mov eax, OBJ_TYPE_ITEM; // jump to OBJ_TYPE_ITEM case for outlining
298+
retn;
299+
notOutlined: // filter out non-outlined itemObj behind usable scenery
300+
cmp ecx, OBJ_TYPE_SCENERY;
301+
jne cantUse;
302+
mov eax, edi;
303+
call fo::funcoffs::obj_action_can_use_;
304+
test eax, eax;
305+
jz cantUse;
306+
mov ebp, 6; // GAME_MOUSE_ACTION_MENU_ITEM_USE
307+
jmp jbreak;
308+
cantUse: // filter out null or non-outlined itemObj behind blocking walls
309+
test ebx, ebx;
310+
jz lookWall;
311+
cmp ecx, OBJ_TYPE_WALL;
312+
jne itemRet;
313+
mov edx, [edi + flags];
314+
test edx, LightThru or ShootThru;
315+
jnz itemRet;
316+
lookWall:
317+
mov ebp, 3; // GAME_MOUSE_ACTION_MENU_ITEM_LOOK
318+
jmp jbreak;
319+
}
320+
}
321+
322+
// Allows picking up an outlined itemObj behind scenery, wall, and misc types of targetObj
323+
static __declspec(naked) void gmouse_handle_event_hack() {
324+
static const DWORD gmouse_handle_event_Ret = 0x44C835;
325+
using namespace fo;
326+
using namespace Fields;
327+
__asm { // ebx - targetObj, eax - objType
328+
je searchItem; // objType == OBJ_TYPE_WALL
329+
cmp eax, OBJ_TYPE_SCENERY;
330+
je searchItem;
331+
cmp eax, OBJ_TYPE_MISC;
332+
je searchItem;
333+
// overwritten engine code
334+
cmp eax, OBJ_TYPE_WALL;
335+
ja jbreak;
336+
retn; // switch case - OBJ_TYPE_ITEM and OBJ_TYPE_CRITTER
337+
jbreak:
338+
add esp, 4;
339+
jmp gmouse_handle_event_Ret;
340+
searchItem:
341+
push ebx; // save targetObj
342+
mov ecx, eax; // save objType
343+
mov eax, OBJ_TYPE_ITEM;
344+
mov edx, 1;
345+
mov ebx, ds:[FO_VAR_map_elevation];
346+
call fo::funcoffs::object_under_mouse_;
347+
pop ebx; // restore
348+
test eax, eax;
349+
jz skip;
350+
mov edx, [eax + outline];
351+
test edx, OUTLINE_TYPE_MAX;
352+
jz skip;
353+
test edx, OUTLINE_DISABLED;
354+
jnz skip;
355+
mov ebx, eax; // set itemObj as new targetObj
356+
mov eax, OBJ_TYPE_ITEM; // jump to OBJ_TYPE_ITEM case for picking up
357+
retn;
358+
skip: // no outlined itemObj
359+
cmp ecx, OBJ_TYPE_WALL;
360+
ja jbreak;
361+
mov eax, ecx; // restore
362+
retn; // switch case - OBJ_TYPE_SCENERY and OBJ_TYPE_WALL
363+
}
364+
}
365+
256366
static __declspec(naked) void obj_render_pre_roof_hack() {
257367
__asm {
258368
cmp eax, 500;
@@ -288,10 +398,14 @@ void Objects::init() {
288398
// Place some objects on the lower z-layer of the tile
289399
MakeCall(0x48D918, obj_insert_hack, 1);
290400

401+
// Allow outlining and picking up items behind scenery, walls, and misc objects
402+
MakeCall(0x44B98D, gmouse_bk_process_hack, 1); // outlining (walls are limited to non-blocking ones)
403+
MakeCall(0x44C11B, gmouse_handle_event_hack, 1); // pickup
404+
291405
// Increase the maximum number of objects that can be outlined simultaneously (when w/o HRP 4.x by Mash)
292406
if (*(DWORD*)0x48981D == 0x639C00) {
293407
// replace _outlinedObjects array (was 100 objects)
294-
SafeWriteBatch<DWORD>((DWORD)outlinedObjs - 4, {0x4896DF, 0x4897BE}); // obj_render_pre_roof_
408+
SafeWriteBatch<DWORD>((DWORD)(outlinedObjs - 1), {0x4896DF, 0x4897BE}); // obj_render_pre_roof_
295409
SafeWrite32(0x48981D, (DWORD)outlinedObjs); // obj_render_post_roof_
296410
// change the maximum limit to 500
297411
MakeCalls(obj_render_pre_roof_hack, {0x4896D6, 0x4897B5});

0 commit comments

Comments
 (0)