Teleportationstrank: the running campaign's portal list
In the Underworld the potion opens the Underworld portals (busy dialog mode 6, as the teleporters there do); g_campaign moved to game/addresses.h. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
0ef3cf4bbd
commit
3978060954
4 files changed
+26
-5
No files matched your search
@@ -32,3 +32,11 @@ one of them.
|
||||
- The potion is used up (flag, RemoveItem, DestroyObject as UseItem does; a
|
||||
stack loses one) only when cCreature::Teleport is called from the portal
|
||||
case while it is pending; closing the window keeps it.
|
||||
|
||||
## Campaign (2026-10-21)
|
||||
|
||||
The potion showed Ancaria's portals in the Underworld. cInterpretSQW::Teleporter
|
||||
(0x4ae330) chooses the busy dialog's mode by the portal touched: index > 0xd
|
||||
(Underworld) mode 6, else mode 5, both with the hero's known-portal mask
|
||||
(+0x578). The potion now chooses by the running campaign, g_campaign
|
||||
(0x182cdc8, u16: 0 Ancaria, 1 Underworld): mode 6 in the Underworld.
|
||||
@@ -28,6 +28,7 @@ constexpr uint32_t WorldToScreen = 0x00623c40;
|
||||
// --- globals -----------------------------------------------------------------
|
||||
constexpr uint32_t g_dxDriver = 0x00cda99c; // DxDriver7*
|
||||
constexpr uint32_t g_appFlags = 0x0182cdb8; // uint32_t, 0x20000 = inactive
|
||||
constexpr uint32_t g_campaign = 0x0182cdc8; // uint16_t, the running game's campaign: 0 Ancaria, 1 Underworld
|
||||
constexpr uint32_t g_mouseCursor = 0x00cdbadc; // mouse cursor object*: x +4, y +8 (render pixels)
|
||||
|
||||
// --- read-only constants -----------------------------------------------------
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "game/addresses.h"
|
||||
#include "game/engine/events.h"
|
||||
#include "game/engine/objects.h"
|
||||
#include "game/ui/draw.h"
|
||||
@@ -102,7 +103,7 @@ constexpr uintptr_t kGameLevel = 0x0182cdc4; // g_gameLevel: the difficulty of
|
||||
// g_campaign (u16): the campaign of the game to start / running. The main menu
|
||||
// sets it by entry (0x712180..), cEngine::Load from the save header; the load
|
||||
// window lists only saves of it (0x71e2b9).
|
||||
constexpr uintptr_t kCampaign = 0x0182cdc8;
|
||||
constexpr uintptr_t kCampaign = game::addr::g_campaign;
|
||||
constexpr size_t kSessionSinglePlayer = 0x14; // set to 1 by both
|
||||
constexpr size_t kSessionHeroClass = 0x44; // the start hero's class (Session::SetHeroClass 0x7d7cf0)
|
||||
// cCommand_armaPlay (vtable 0x894ff4): execute (0x755ac0) posts 0x8002 (mode,
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
// whose tooltip names the potion too). Touching a teleporter runs
|
||||
// cInterpretSQW::Teleporter (0x4ae330): it adds the portal to the hero's known ones (bit mask at hero +0x578) and posts
|
||||
// a UI event (type 0x39) to DEFAULT_BUSYDLG with +8 = 2, +0xc = 5 (portal
|
||||
// mode; 6 for the underworld portals above 0xd) and +0x10 = the mask;
|
||||
// mode; 6 for the underworld portals above 0xd, the same mask) and +0x10 =
|
||||
// the mask;
|
||||
// cUI_BusyDlg::HandleEvent (0x720c10) then calls SetMode (0x720180, (mode, a,
|
||||
// b), ret 0xc). Choosing a portal sends the engine an event whose case
|
||||
// (0x619671, "EE_USEPORTAL") teleports the hero with cCreature::Teleport
|
||||
@@ -26,11 +27,13 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "game/addresses.h"
|
||||
#include "game/engine/events.h"
|
||||
#include "game/engine/items.h"
|
||||
#include "game/engine/objects.h"
|
||||
#include "game/engine/orders.h"
|
||||
#include "game/ui/texts.h"
|
||||
#include "mods/charfile.h"
|
||||
#include "mods/skillslots.h"
|
||||
#include "re/hook.h"
|
||||
#include "re/log.h"
|
||||
@@ -55,7 +58,8 @@ constexpr uint32_t kUiEventBusyDialog = 0x39;
|
||||
constexpr uintptr_t kBusyDialogName = 0x0094d700; // "DEFAULT_BUSYDLG"
|
||||
constexpr uintptr_t kNoSender = 0x00aa24bc; // the game's empty name
|
||||
constexpr uint32_t kBusyDialogSetMode = 2;
|
||||
constexpr uint32_t kBusyModePortals = 5;
|
||||
constexpr uint32_t kBusyModePortals = 5; // Ancaria's portals
|
||||
constexpr uint32_t kBusyModeUnderworldPortals = 6;
|
||||
constexpr size_t kUiEventSize = 0x80;
|
||||
constexpr size_t kUiEventString = 0x68;
|
||||
|
||||
@@ -65,6 +69,13 @@ constexpr uintptr_t kPortalTeleportReturn = 0x006197c8;
|
||||
constexpr size_t kControlFlags = 0x10;
|
||||
constexpr uint32_t kControlVisible = 1;
|
||||
|
||||
// The portal list of the running campaign (user, 2026-10-21: the potion
|
||||
// showed Ancaria's portals in the Underworld), as the teleporters choose it.
|
||||
uint32_t PortalMode() {
|
||||
const uint16_t campaign = *reinterpret_cast<const uint16_t*>(game::addr::g_campaign);
|
||||
return campaign == characters::kCampaignUnderworld ? kBusyModeUnderworldPortals : kBusyModePortals;
|
||||
}
|
||||
|
||||
// The potion that opened the portal window, until it is used or the window
|
||||
// closes; and the dialog, once it showed for it.
|
||||
uint32_t g_pending = 0;
|
||||
@@ -77,7 +88,7 @@ void OpenPortalWindow(uint32_t knownPortals) {
|
||||
uint32_t, uint32_t, uint32_t);
|
||||
reinterpret_cast<CtorFn>(0x00553080)(event, nullptr, kUiEventBusyDialog, reinterpret_cast<const char*>(kBusyDialogName),
|
||||
reinterpret_cast<const char*>(kNoSender),
|
||||
kBusyDialogSetMode, kBusyModePortals, knownPortals, 0, 0, 0);
|
||||
kBusyDialogSetMode, PortalMode(), knownPortals, 0, 0, 0);
|
||||
game::PostEvent(event);
|
||||
using FreeFn = void(__fastcall*)(void*, void*);
|
||||
reinterpret_cast<FreeFn>(0x006e85d0)(event + kUiEventString, nullptr);
|
||||
@@ -162,7 +173,7 @@ void __fastcall BusyDlg_SetMode(void* self, void* edx, uint32_t mode, uint32_t a
|
||||
using namespace mods::teleportpotion;
|
||||
if (g_pending) {
|
||||
g_dialog = static_cast<uint8_t*>(self);
|
||||
if (mode != kBusyModePortals) {
|
||||
if (mode != kBusyModePortals && mode != kBusyModeUnderworldPortals) {
|
||||
g_pending = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user