It is currently 16 Apr 2024, 20:46
   
Text Size

[fixed] Demonic Pact dialog

Moderators: BAgate, drool66, Aswan jaguar, gmzombie, stassy, CCGHQ Admins

Re: [confirmed] Demonic Pact dialog

Postby drool66 » 01 Dec 2021, 15:57

Confirmed. We can fix this in individual cards with DLG_OMIT_ILLEGAL, but that's not exactly copacetic. Fixing that probably involves working with the windows interface, which I don't know a lot about.

Another idiosyncrasy - if a dialog option's ai_priority <= 0, AI can just run through the options without actually choosing that one, like if it has a Demonic Pact with the first three options already chosen. Changing the fourth option's ai_priority to 1 disallows this behavior. I can speculate on how to get dialog_ai() to handle non-positive values for ai_priority.

Fixed both issues for Demonic Pact, unpushed, but leaving this open for the sake of the two issues above.
User avatar
drool66
Programmer
 
Posts: 1163
Joined: 25 Nov 2010, 22:38
Has thanked: 186 times
Been thanked: 267 times

Re: [confirmed] Demonic Pact dialog

Postby Korath » 01 Dec 2021, 16:15

See the WM_INITDIALOG handler in Shandalar's hook_dlgproc_do_dialog() for how I fixed the first issue over there. (Basically, if the first option is grayed out when the dialog is created, send it a "home" keypress. And, on reflection, it's probably not even necessary to check if the first option is grayed out, either - just always send the key.)

Having at least one option with positive ai_priority, or being cancellable, is part of DIALOG()'s documented preconditions. I suppose you could add a popup to complain if that's untrue, though whether that's more irritating for end-users than the current wrong behavior would vary from card to card. Or you could just give each legal option an even weighting.
User avatar
Korath
DEVELOPER
 
Posts: 3707
Joined: 02 Jun 2013, 05:57
Has thanked: 496 times
Been thanked: 1106 times

Re: [confirmed] Demonic Pact dialog

Postby drool66 » 03 Dec 2021, 06:35

See the WM_INITDIALOG handler in Shandalar's hook_dlgproc_do_dialog() for how I fixed the first issue over there. (Basically, if the first option is grayed out when the dialog is created, send it a "home" keypress. And, on reflection, it's probably not even necessary to check if the first option is grayed out, either - just always send the key.)
Done,unpushed, though I just made it dependent on "(who_sees = EXE_DWORD(0x736ad8)) == HUMAN"; I don't see a separate param in ML for "who_chooses." Does it even need to do that?
User avatar
drool66
Programmer
 
Posts: 1163
Joined: 25 Nov 2010, 22:38
Has thanked: 186 times
Been thanked: 267 times

Re: [fixed] Demonic Pact dialog

Postby Korath » 03 Dec 2021, 16:34

It's harmless to send it regardless of who_sees - wndproc_BigCardChoiceClass(), which eventually gets the message, ignores WM_KEYDOWN unless player 0 is choosing.

do_dialog()@0x471EB0 sends !who_chooses as the last parameter to raw_do_dialog()@0x471B60, which sets it in one of the fields of the struct dialog_args_t { int bigcard_player; int bigcard_card; int smallcard_player; int smallcard_card; char* prompt; int human_chooses; } it passes as the dialog's dwInitParam, becoming lparam in dlgproc_do_dialog()'s WM_INITDIALOG handler. A pointer to the struct gets stored in static_dlg_args, which is at 0x607490 in Manalink. What leads you to think 0x736ad8 is relevant?
User avatar
Korath
DEVELOPER
 
Posts: 3707
Joined: 02 Jun 2013, 05:57
Has thanked: 496 times
Been thanked: 1106 times

Re: [fixed] Demonic Pact dialog

Postby drool66 » 03 Dec 2021, 21:37

What leads you to think 0x736ad8 is relevant?
Not having everything mapped properly. I deduced (wrongly) from the lines in do_dialog():
Code: Select all
      v10 = a2 == dword_736AD8;
      v13 = sub_471B60(a1, HIDWORD(a2), a3, a4, HIDWORD(a4), (int)&byte_60A690, v10);   //raw_do_dialog()
Thank you for the address, but I can't get it to work properly. Here's what I have:
Code: Select all
typedef struct
{
  int bigcard_player;
  int bigcard_card;
  int smallcard_player;
  int smallcard_card;
  const char* prompt;
  int human_chooses;
} dialog_args_t;

#define option_Layout      EXE_DWORD(0x787260)
#define hwnd_FullCardClass   EXE_PTR_VOID(0x715ca0)
#define static_dlg_args      EXE_TYP_PTR(dialog_args_t, 0x607490)

INT_PTR __stdcall dlgproc_do_dialog_hook(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
  if (msg == (option_Layout == 2 ? WM_RBUTTONDBLCLK : WM_RBUTTONDOWN))
   {
     SendMessageA(hwnd_FullCardClass, WM_COMMAND, 1, 0);
     return 0;
   }

  // move to first legal choice by sending a home key press
  if( static_dlg_args->human_chooses ){
     int num_choices = SendDlgItemMessage(hwnd, 1021, WM_USER, 0, 0);
     if (num_choices > 0)
         SendDlgItemMessage(hwnd, 1021, WM_KEYDOWN, VK_HOME, 0);
  }

  return EXE_STDCALL_FN(INT_PTR, 0x4aa090, HWND, UINT, WPARAM, LPARAM)(hwnd, msg, wparam, lparam);   // dlgproc_do_dialog()
}
I've also tried this kind of thing:
Code: Select all
typedef struct
{
  int bigcard_player;
  int bigcard_card;
  int smallcard_player;
  int smallcard_card;
  const char* prompt;
  int human_chooses;
} dialog_args_t;

#define option_Layout      EXE_DWORD(0x787260)
#define hwnd_FullCardClass   EXE_PTR_VOID(0x715ca0)
#define static_dlg_args      EXE_TYP_PTR(dialog_args_t, 0x607490)

INT_PTR __stdcall dlgproc_do_dialog_hook(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
  if (msg == (option_Layout == 2 ? WM_RBUTTONDBLCLK : WM_RBUTTONDOWN))
   {
     SendMessageA(hwnd_FullCardClass, WM_COMMAND, 1, 0);
     return 0;
   }

  if( msg == WM_INITDIALOG ){
     INT_PTR rv = EXE_STDCALL_FN(INT_PTR, 0x4aa090, HWND, UINT, WPARAM, LPARAM)(hwnd, msg, wparam, lparam);   // dlgproc_do_dialog()
     // move to first legal choice by sending a home key press
     if( static_dlg_args->human_chooses ){
        int num_choices = SendDlgItemMessage(hwnd, 1021, WM_USER, 0, 0);
        if (num_choices > 0)
         SendDlgItemMessage(hwnd, 1021, WM_KEYDOWN, VK_HOME, 0);
     }
     return rv;
   }

  return EXE_STDCALL_FN(INT_PTR, 0x4aa090, HWND, UINT, WPARAM, LPARAM)(hwnd, msg, wparam, lparam);   // dlgproc_do_dialog()
}
On the other hand, like you say simply unconditionally firing "SendDlgItemMessage(hwnd, 1021, WM_KEYDOWN, VK_HOME, 0)" works and doesn't seem to have any repercussions as far as I can tell.
User avatar
drool66
Programmer
 
Posts: 1163
Joined: 25 Nov 2010, 22:38
Has thanked: 186 times
Been thanked: 267 times

Re: [fixed] Demonic Pact dialog

Postby Korath » 03 Dec 2021, 22:09

Second kind of thing is almost right. (The first isn't. A DLGPROC gets all kinds of messages; you only want to respond to WM_INITDIALOG, and only after what the original does - including setting up static_dlg_args in the first place - is complete.)

The problem is that you haven't defined static_dlg_args correctly. What you have is saying that there's a dialog_args_t stored starting at address 0x607490, and that your symbol static_dlg_args is a pointer to it. It's actually stored on the stack, as one of the local variables in raw_do_dialog(), and what's stored at 0x607490 is its address. (That's why I can get away with tacking extra data members onto the end of the structure in Shandalar just by replacing raw_do_dialog().) So you want to make static_dlg_args to be an alias of the pointer at 0x607490, and the way you do that is by #defining it as EXE_TYP(dialog_args_t*, 0x607490).

Omitting the check against dialog_args_t::human_chooses is harmless. Omitting the one against num_choices might not be; it's not completely clear what would happen with an unchoiced popup without it.

The value at 0x736ad8 looks like the equivalent of our HUMAN. It's set once to zero and then never changed again.
User avatar
Korath
DEVELOPER
 
Posts: 3707
Joined: 02 Jun 2013, 05:57
Has thanked: 496 times
Been thanked: 1106 times

Re: [fixed] Demonic Pact dialog

Postby drool66 » 04 Dec 2021, 01:46

Oh wow, thanks! That explains an awful lot.

EDIT: fixed in c4d64b4 & 41e1a37
User avatar
drool66
Programmer
 
Posts: 1163
Joined: 25 Nov 2010, 22:38
Has thanked: 186 times
Been thanked: 267 times


Return to Archived Reports

Who is online

Users browsing this forum: No registered users and 58 guests


Who is online

In total there are 58 users online :: 0 registered, 0 hidden and 58 guests (based on users active over the past 10 minutes)
Most users ever online was 4143 on 23 Jan 2024, 08:21

Users browsing this forum: No registered users and 58 guests

Login Form