@@ -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+
256366static __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