XMODhub Home
Switch language
繁中
SKSE挿件地址庫 Mod Menu

SKSE挿件地址庫

創作者: meh321
已更新:2020-02-24 19:31:54
2.8MB
Verified by McAfee SECURE
驗證
獲得 200,000,000+ 位用戶信任

關於此模組

包含標頭檔和資料庫,使SKSE DLL挿件易於版本獨立。
重要的!現在分為兩個版本:特別版(1.5.x)和週年紀念版(1.6.x)。這兩個版本之間指向地址的ID不一致(遊戲可執行檔差異太大,無法匹配,即使匹配,這些函數中的程式碼也不同)。

描述

對於常規 mod 用戶:從檔案部分下載並安裝「一體化」軟體包。您可以使用模組管理器或手動操作。 .bin 文件應位於此處:
數據/SKSE/插件/
您無需閱讀其餘部分。

對於 SKSE DLL 外掛程式作者:
這是一個模組製作資源(頭檔)。您可以載入一個儲存偏移量的資料庫,這樣您的 DLL 插件就可以獨立於版本,無需重新編譯。頭文件可以從文件的可選部分下載。週年紀念版的頭檔名為 versionlibdb.h,而不是 versiondb.h!如果您使用的是 CommonLib,那麼所有這些都已內置,您無需從這裡下載任何文件。


如何使用

最快的方法:
劇透:
展示


#include "versiondb.h"

void * 我的地址 = NULL;
無符號長整型 MyOffset = 0;

bool 初始化偏移量()
{
// 在堆疊上分配,以便我們退出此函數時它將被卸載。
// 不需要無緣無故地載入整個資料庫並佔用記憶體。
版本資料庫;

// 使用目前可執行版本載入資料庫。
如果(!db.Load())
{
_FATALERROR("無法載入目前可執行檔的版本資料庫!");
返回 false;
}
別的
{
//“SkyrimSE.exe”,“1.5.97.0”
_MESSAGE("已載入 %s 版本 %s 的資料庫。", db.GetModuleName().c_str(), db.GetLoadedVersionString().c_str());
}

// 該位址已經包含模組的基底位址,因此我們可以直接使用該位址。
我的地址 = db.FindAddressById(123);
如果(我的地址 == NULL)
{
_FATALERROR("找不到位址!");
返回 false;
}

// 此偏移量不包含基底址。實際位址為 ModuleBase + MyOffset。
如果(!db.FindOffsetById(123,MyOffset))
{
_FATALERROR("無法找到我的東西的偏移!");
返回 false;
}

// 一切順利。
傳回 true;
}



現在你肯定想知道那個「123」值是什麼。這是一個地址的ID。不同版本的資料庫會為同一個位址分配相同的ID,但它可能指向不同的值。若要取得特定版本的所有ID和值對的列表,請執行下列操作:

劇透:
展示


#include "versiondb.h"

bool DumpSpecificVersion()
{
版本資料庫;

// 無論執行的可執行檔版本為何,都嘗試載入版本 1.5.62.0 的資料庫。
如果(!db.Load(1,5,62,0))
{
_FATALERROR("無法載入 1.5.62.0 資料庫!");
返回 false;
}

// 寫出一個名為 offsets-1.5.62.0.txt 的文件,其中每一行都是 ID 和偏移量。
db.Dump("偏移量-1.5.62.0.txt");
_MESSAGE("轉儲 1.5.62.0 的偏移量");
傳回 true;
}



不要輸入 1, 5, 62, 0,而是輸入你正在逆向且熟悉的版本。你必須先在 /Data/SKSE/Plugins 目錄中擁有對應的資料庫檔案。

呼叫此指令後,Skyrim 主目錄中應該會出現一個名為「offsets-1.5.62.0.txt」的新文件,檔案名稱可以隨意設定。該文件的格式如下:
十進位 ID六角偏移

例如,如果您在 1.5.62.0 中有一個位址 142F4DEF8(玩家角色靜態指標),並且您想要使它與版本無關,您可以這樣做:
1. 在偏移檔案中尋找 2F4DEF8。因為這是沒有基數 140000000 的偏移量
2.看到ID是517014(十進位!)
3. 如果您希望在執行時間將此位址包含在您的 DLL 中,請執行以下操作:


無效* addressOf142F4DEF8 = db.FindAddressById(517014);


就是這樣了。

VersionDb 結構具有以下功能:
劇透:
展示


bool Dump(const std::string& path); // 將目前載入的資料庫轉儲到文件
bool Load(int major, int minor, int revision, int build); // 如果 Data/SKSE/Plugins 目錄中存在 db-major-minor-revision-build.bin,則載入特定版本
bool Load(); // 載入目前應用程式的版本
void Clear(); // 清除目前已載入的資料庫
void GetLoadedVersion(int& major, int& minor, int& revision, int& build) const; // 取得我們現在載入的資料庫檔案的版本
bool GetExecutableVersion(int& major, int& minor, int& revision, int& build) const; // 取得目前正在執行的應用程式的版本
const std::string& GetModuleName() const; // 取得目前載入的資料庫模組的名稱,這應該會顯示“SkyrimSE.exe”
const std::string& GetLoadedVersionString() const; // 取得目前載入的版本作為字串,例如“1.5.62.0”
const std::map& GetOffsetMap() const; // 若需要手動迭代,取得ID到偏移量的映射
void* FindAddressById(unsigned long long id) const; // 透過 ID 尋找位址,該 ID 已包含基底地址且為正確位址。如果未找到,則傳回 NULL!
bool FindOffsetById(unsigned long long id, unsigned long long& result) const; // 透過 ID 找出偏移量,這只是不包含基數的偏移量。
bool FindIdByAddress(void* ptr, unsigned long long& result) const; // 透過位址尋找 ID,這將嘗試反向查找以將位址轉換為 ID
bool FindIdByOffset(unsigned long long offset, unsigned long long& result) const; // 透過偏移量尋找 ID,這將嘗試反向查找以將偏移量轉換為 ID



您應該了解並牢記的事情:

1. 您可以在插件中包含任意(或全部)資料庫文件,但這可能會顯著增加文件大小(約 2.5 MB)。目前,通常將此模組標記為依賴項。

2. 您應該始終在啟動時只載入一次資料庫,初始化/快取所需的位址,然後讓它卸載。卸載僅表示 VersionDb 結構體會被刪除或遺失(如果您在堆疊上分配了記憶體)。這將確保您在遊戲運行時不會使用不必要的記憶體。遊戲過程中無需保持資料庫載入狀態。如果您使用 CommonLib,這一點就毫無意義了,因為它只會載入一次,而不是為每個 DLL 載入一次。

3. 此資料庫包含函數、全域變數、RTTI、vtable 以及任何其他可能引用它的物件的位址。它不包含函數中間或全域變數中間的位址。如果需要函數中間的位址,您應該尋找函數基址並自行新增額外的偏移量。它也不包含無用的內容,例如函數周圍的對齊(在 rdata 中引用),pdata 段會被丟棄,一些編譯器從 rdata 產生的 SEH 資訊也會被丟棄。

4. 您應該始終檢查結果,以確保資料庫已成功載入(bool Load 傳回 true),並且查詢的位址確實傳回了有效結果(非 NULL)。如果載入失敗,則表示檔案缺失或版本錯誤(例如,嘗試在 AE 中使用 SE 標頭)。如果查詢失敗,則表示在該版本中找不到該位址。這可能意味著遊戲程式碼發生了足夠大的更改,導致該地址對該版本不再有效,或者資料庫本身無法檢測到正確的地址。如果發生上述任何一種情況,您應該使插件初始化失敗,以便讓 SKSE 知道您未正確載入。或手動顯示錯誤訊息。

5. 在發布你的 DLL 外掛程式之前,最好檢查一下該位址在所有版本的遊戲中都存在。為此,請加載每個版本的資料庫文件,並在每個版本中查詢相同的地址 ID,以確保它存在:
劇透:
展示


bool LoadAll(std::vector& 全部)
{
靜態 int 版本[] = { 3, 16, 23, 39, 50, 53, 62, 73, 80, 97, -1 };
對於(int i = 0;版本[i]> = 0; i ++)
{
版本資料庫 * db = 新的版本資料庫();
如果(!db->Load(1,5,版本[i],0))
{
刪除資料庫;
返回 false;
}
全部.push_back(db);
}
傳回 true;
}

bool ExistsInAll(std::vector&全部,無符號長整型 id)
{
無符號長整型結果 = 0;
對於(自動資料庫:全部)
{
如果(!db->FindOffsetById(id,結果))
返回 false;
}
傳回 true;
}

無效的FreeAll(std ::向量& 全部)
{
對於(自動資料庫:全部)
刪除資料庫;
全部.清除();
}

bool IsOk()
{
std::vector全部;
如果(!LoadAll(全部))
{
_FATALERROR("無法為目前執行檔載入一個或多個版本資料庫!");
免費全部(全部);
返回 false;
}

如果(!ExistsInAll(全部,517014))
{
_FATALERROR("517014 在所有版本的資料庫中都不存在!");
免費全部(全部);
返回 false;
}

免費全部(全部);
// 好的!
傳回 true;
}



這樣,您可以確保您的 DLL mod 在所有版本中都能工作,或者如果它在某些版本中不起作用,您可以在 mod 頁面上寫明。

6. 有時您需要根據正在執行的遊戲版本執行不同的操作。您可以使用以下程式碼片段來實現:
劇透:
展示


int major = 0,minor = 0,revision = 0,build = 0;
如果(!db.GetExecutableVersion(主要,次要,修訂,建置))
{
_FATALERROR("出現錯誤!");
返回 false;
}

// 正在運行的遊戲是 1.5.x 並且至少是版本 1.5.39.0
if (主 == 1 && 次要 == 5 && 修訂 >= 39)
{
// 東西 ... ?
}



7. 請注意:如果您在偵錯模式下編譯 SKSE DLL,資料庫載入時間可能約為 14 秒!在發布模式下,載入時間約為 0.2 秒。這是因為標準庫容器在該模式下(std map)運作速度非常慢。


權限

做任何你想做的事。

Multiverse Loot Hunter 的熱門模組

探索適用於 Multiverse Loot Hunter 的最佳模組,帶來新功能、升級畫面,以及令人興奮的方式來改變您的遊戲體驗。

使用 XMODhub 解鎖 Multiverse Loot Hunter 的全部潛力 — 今天就探索這些頂級模組!

Verified by McAfee SECURE
驗證
獲得 200,000,000+ 位用戶信任

需要下載或安裝幫助嗎?加入我們的Discord 社群尋求支援。

XMODhub Home
語言
切換語言至 Chinese Traditional
切換語言至 English
切換語言至 German
切換語言至 Korean
切換語言至 Thai
切換語言至 Indonesian
切換語言至 Vietnamese
切換語言至 Turkish
切換語言至 Portuguese
切換語言至 Japanese
切換語言至 Polish
切換語言至 French
切換語言至 Spanish
切換語言至 Italian

遊戲解決方案

資源

合作夥伴

關注我們

造訪 XMODhub Discord造訪 XMODhub Facebook造訪 XMODhub X造訪 XMODhub YouTube
聯絡客服:
support@xmodhub.com
Xmod_Lily
商務洽詢:
dc@xmodhub.com or cathy@business.xmodhub.com
catherine_79237

Larvas Limited

Room 1201, 12/F Tai Sang Bank Building 130-132 Des Voeux Road Central HK