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 เป็นอิสระได้อย่างง่ายดาย
สำคัญ!ตอนนี้แบ่งออกเป็น 2 เวอร์ชัน: Special Edition (1.5.x) และ Anniversary Edition (1.6.x) ID ที่ชี้ไปยังที่อยู่จะไม่ตรงกันระหว่าง 2 เวอร์ชันนี้ (ไฟล์ปฏิบัติการของเกมแตกต่างกันมากจนไม่สามารถจับคู่ได้ และถึงแม้จะตรงกัน แต่โค้ดภายในฟังก์ชันเหล่านั้นก็ยังแตกต่างกันอยู่ดี)

คำอธิบาย

สำหรับผู้ใช้ mod ทั่วไป:ดาวน์โหลดและติดตั้งแพ็กเกจ "all-in-one" จากส่วนไฟล์ คุณสามารถใช้ตัวจัดการ mod หรือติดตั้งด้วยตนเองก็ได้ ไฟล์ .bin ควรอยู่ที่นี่:
ข้อมูล/SKSE/ปลั๊กอิน/
คุณไม่จำเป็นต้องอ่านส่วนที่เหลือของข้อความนี้อีก

สำหรับผู้เขียนปลั๊กอิน SKSE DLL:
นี่คือทรัพยากร modder (ไฟล์ส่วนหัว) คุณสามารถโหลดฐานข้อมูลที่เก็บค่า offset เพื่อให้ปลั๊กอิน DLL ของคุณเป็นอิสระจากเวอร์ชันโดยไม่ต้องคอมไพล์ใหม่ คุณสามารถดาวน์โหลดไฟล์ส่วนหัวได้จากส่วนเสริมของไฟล์ สำหรับ Anniversary Edition ไฟล์ส่วนหัวจะเรียกว่า versionlibdb.h แทนที่จะเป็น versiondb.h! หากคุณใช้ CommonLib อยู่ ไฟล์ทั้งหมดนี้มีอยู่ในตัวแล้ว และคุณไม่จำเป็นต้องใช้ไฟล์ใดๆ จากที่นี่


วิธีการใช้งาน

วิธีที่เร็วที่สุด:
สปอยล์:
แสดง


#รวม "versiondb.h"

void * MyAddress = NULL;
unsigned long long MyOffset = 0;

bool InitializeOffsets()
{
// จัดสรรบนสแต็กเพื่อให้มีการขนถ่ายออกเมื่อเราออกจากฟังก์ชันนี้
ไม่จำเป็นต้องโหลดฐานข้อมูลทั้งหมดและใช้หน่วยความจำโดยไม่จำเป็น
เวอร์ชันDb db;

// โหลดฐานข้อมูลด้วยเวอร์ชันปฏิบัติการปัจจุบัน
ถ้า (!db.Load())
{
_FATALERROR("ไม่สามารถโหลดฐานข้อมูลเวอร์ชันสำหรับไฟล์ปฏิบัติการปัจจุบันได้!");
กลับเป็นเท็จ;
}
อื่น
{
// "SkyrimSE.exe", "1.5.97.0"
_MESSAGE("โหลดฐานข้อมูลสำหรับเวอร์ชัน %s %s แล้ว", db.GetModuleName().c_str(), db.GetLoadedVersionString().c_str());
}

// ที่อยู่นี้รวมที่อยู่ฐานของโมดูลไว้แล้ว ดังนั้นเราจึงสามารถใช้ที่อยู่นี้โดยตรงได้
ที่อยู่ของฉัน = db.FindAddressById(123);
ถ้า (ที่อยู่ของฉัน == NULL)
{
_FATALERROR("ไม่สามารถค้นหาที่อยู่ได้!");
กลับเป็นเท็จ;
}

// ออฟเซ็ตนี้ไม่รวมที่อยู่ฐาน ที่อยู่จริงจะเป็น ModuleBase + MyOffset
หาก (!db.FindOffsetById(123, MyOffset))
{
_FATALERROR("ไม่สามารถค้นหาออฟเซ็ตสำหรับสิ่งของของฉันได้!");
กลับเป็นเท็จ;
}

// ทุกอย่างก็สำเร็จไปได้ด้วยดี
กลับเป็นจริง;
}



ตอนนี้คุณกำลังสงสัยว่าค่า "123" ที่ว่าคืออะไร นี่คือ ID ของที่อยู่ ฐานข้อมูลเวอร์ชันต่างๆ จะมี ID เดียวกันสำหรับที่อยู่ แต่อาจชี้ไปยังค่าที่ต่างกัน หากต้องการดูรายการคู่ ID และค่าทั้งหมดของเวอร์ชันที่ระบุ ให้ทำดังนี้:

สปอยล์:
แสดง


#รวม "versiondb.h"

บูลีน DumpSpecificVersion()
{
เวอร์ชันDb db;

// พยายามโหลดฐานข้อมูลเวอร์ชัน 1.5.62.0 โดยไม่คำนึงถึงเวอร์ชันที่รันอยู่
ถ้า (!db.Load(1, 5, 62, 0))
{
_FATALERROR("ไม่สามารถโหลดฐานข้อมูลสำหรับ 1.5.62.0 ได้!");
กลับเป็นเท็จ;
}

// เขียนไฟล์ชื่อ offsets-1.5.62.0.txt โดยที่แต่ละบรรทัดคือ ID และ offset
db.Dump("offsets-1.5.62.0.txt");
_MESSAGE("ดัมพ์ออฟเซ็ตสำหรับ 1.5.62.0");
กลับเป็นจริง;
}



แทนที่จะใช้ 1, 5, 62, 0 ให้ใส่เวอร์ชันที่คุณกำลังย้อนกลับและคุ้นเคย คุณต้องมีไฟล์ฐานข้อมูลที่เกี่ยวข้องในไดเร็กทอรี /Data/SKSE/Plugins ก่อน

หลังจากเรียกไฟล์นี้แล้ว คุณควรมีไฟล์ใหม่ในไดเรกทอรีหลักของ Skyrim ชื่อ "offsets-1.5.62.0.txt" หรือชื่อไฟล์อะไรก็ได้ที่คุณใส่ไว้ ไฟล์จะอยู่ในฟอร์แมตที่แต่ละบรรทัดเป็นดังนี้:
รหัสทศนิยมออฟเซ็ตหกเหลี่ยม

ตัวอย่างเช่น หากคุณมีที่อยู่ 142F4DEF8 (ตัวชี้คงที่ของตัวละครผู้เล่น) ใน 1.5.62.0 ที่คุณต้องการให้เป็นอิสระจากเวอร์ชัน คุณจะต้องทำสิ่งนี้:
1. ค้นหา 2F4DEF8 ในไฟล์ offsets เนื่องจากนี่คือ offset ที่ไม่มีฐาน 140000000
2. ตรวจสอบว่า ID คือ 517014 (ทศนิยม!)
3. หากคุณต้องการให้ที่อยู่นี้อยู่ใน DLL ของคุณขณะรันไทม์ ให้ทำดังนี้:


void* addressOf142F4DEF8 = db.FindAddressById(517014);


และคุณก็มีมันแล้ว

โครงสร้าง VersionDb มีฟังก์ชันดังต่อไปนี้:
สปอยล์:
แสดง


bool Dump(const std::string& path); // ดัมพ์ฐานข้อมูลที่โหลดในปัจจุบันลงในไฟล์
bool Load(int major, int minor, int revision, int build); // โหลดเวอร์ชันเฉพาะถ้า db-major-minor-revision-build.bin มีอยู่ในไดเร็กทอรี Data/SKSE/Plugins
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 ซึ่งจะรวมฐานไว้แล้วและเป็นที่อยู่ที่ถูกต้อง หากไม่พบจะคืนค่า 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 vtables และสิ่งอื่นใดที่อาจมีการอ้างอิงถึงฐานข้อมูลนี้ ฐานข้อมูลนี้ไม่มีที่อยู่ที่อยู่ตรงกลางฟังก์ชันหรือตรงกลางของตัวแปรโกลบอล หากคุณต้องการที่อยู่ตรงกลางฟังก์ชัน คุณควรค้นหาที่อยู่ฐานของฟังก์ชันและเพิ่มออฟเซ็ตเอง นอกจากนี้ยังไม่มีข้อมูลที่ไม่มีประโยชน์ เช่น การจัดตำแหน่งรอบฟังก์ชัน (ซึ่งอ้างอิงใน rdata) ส่วน pdata จะถูกละทิ้ง และข้อมูล SEH บางส่วนที่สร้างโดยคอมไพเลอร์จาก rdata จะถูกละทิ้ง

4. คุณควรตรวจสอบผลลัพธ์เสมอเพื่อให้แน่ใจว่าฐานข้อมูลโหลดสำเร็จ (ค่าบูลีน Load คืนค่า true) และแอดเดรสที่ค้นหาส่งคืนผลลัพธ์ที่ถูกต้อง (ไม่ใช่ค่า NULL) หากโหลดไม่สำเร็จ แสดงว่าไฟล์หายไปหรือเวอร์ชันไม่ถูกต้อง (เช่น พยายามใช้ส่วนหัว SE ใน AE) หากค้นหาไม่สำเร็จ แสดงว่าไม่พบแอดเดรสในเวอร์ชันนั้น ซึ่งอาจหมายความว่าโค้ดเกมเปลี่ยนแปลงไปมากจนแอดเดรสไม่ถูกต้องสำหรับเวอร์ชันนั้นอีกต่อไป หรือฐานข้อมูลเองไม่สามารถตรวจจับแอดเดรสที่ถูกต้องได้ หากเกิดเหตุการณ์เหล่านี้ขึ้น คุณควรล้มเหลวในการเริ่มต้นปลั๊กอินเพื่อแจ้งให้ SKSE ทราบว่าคุณโหลดไม่ถูกต้อง หรือแสดงข้อความแสดงข้อผิดพลาดด้วยตนเอง

5. นอกจากนี้ ควรตรวจสอบให้แน่ใจว่าที่อยู่นั้นมีอยู่ในเกมทุกเวอร์ชันก่อนที่จะเผยแพร่ปลั๊กอิน DLL ของคุณ โดยให้โหลดไฟล์ฐานข้อมูลแต่ละเวอร์ชันและค้นหา ID ที่อยู่เดียวกันในแต่ละเวอร์ชันเพื่อให้แน่ใจว่ามีอยู่จริง:
สปอยล์:
แสดง


บูลีน LoadAll(std::vector& ทั้งหมด)
{
เวอร์ชันคงที่ int[] = { 3, 16, 23, 39, 50, 53, 62, 73, 80, 97, -1 };
สำหรับ (int i = 0; versions[i] >= 0; i++)
{
VersionDb * db = new VersionDb();
ถ้า (!db->Load(1, 5, versions[i], 0))
{
ลบฐานข้อมูล;
กลับเป็นเท็จ;
}
all.push_back(db);
}
กลับเป็นจริง;
}

bool ExistsInAll(std::vector& ทั้งหมด, unsigned long long id)
{
ผลลัพธ์ unsigned long long = 0;
สำหรับ (ฐานข้อมูลอัตโนมัติ: ทั้งหมด)
{
ถ้า (!db->FindOffsetById(id, ผลลัพธ์))
กลับเป็นเท็จ;
}
กลับเป็นจริง;
}

ว่างเปล่า FreeAll(std::vector& ทั้งหมด)
{
สำหรับ (ฐานข้อมูลอัตโนมัติ: ทั้งหมด)
ลบฐานข้อมูล;
ทั้งหมด.ชัดเจน();
}

bool IsOk()
{
std::vectorทั้งหมด;
ถ้า (!LoadAll(ทั้งหมด))
{
_FATALERROR("ไม่สามารถโหลดฐานข้อมูลเวอร์ชันหนึ่งรายการหรือมากกว่าสำหรับไฟล์ปฏิบัติการปัจจุบันได้!");
ฟรีทั้งหมด(ทั้งหมด);
กลับเป็นเท็จ;
}

ถ้า (!ExistsInAll(ทั้งหมด, 517014))
{
_FATALERROR("517014 ไม่มีอยู่ในฐานข้อมูลทุกเวอร์ชัน!");
ฟรีทั้งหมด(ทั้งหมด);
กลับเป็นเท็จ;
}

ฟรีทั้งหมด(ทั้งหมด);
// ตกลง!
กลับเป็นจริง;
}



วิธีนี้จะทำให้คุณแน่ใจว่า DLL mod ของคุณจะทำงานได้ในทุกเวอร์ชัน หรือหากไม่ทำงานในบางเวอร์ชัน คุณก็สามารถเขียนลงในหน้า mod ของคุณได้

6. บางครั้งคุณอาจต้องทำบางอย่างที่แตกต่างออกไปตามเวอร์ชันเกมที่รันอยู่ คุณสามารถทำได้ด้วยโค้ดสั้นๆ นี้:
สปอยล์:
แสดง


int major = 0, minor = 0, revision = 0, build = 0;
หาก (!db.GetExecutableVersion(หลัก, รอง, การแก้ไข, การสร้าง))
{
_FATALERROR("มีบางอย่างผิดพลาด!");
กลับเป็นเท็จ;
}

// เกมที่รันอยู่คือเวอร์ชัน 1.5.x และอย่างน้อยเวอร์ชัน 1.5.39.0
ถ้า (major == 1 && minor == 5 && revision >= 39)
{
// สิ่งของ ... ?
}



7. โปรดทราบว่า: หากคุณคอมไพล์ SKSE DLL ในโหมดดีบัก เวลาในการโหลดฐานข้อมูลอาจอยู่ที่ประมาณ 14 วินาที! ในโหมดเผยแพร่จะใช้เวลาประมาณ 0.2 วินาที เนื่องจากคอนเทนเนอร์ไลบรารีมาตรฐานทำงานช้ามากในโหมดนี้ (std map)


การอนุญาต

ทำอะไรก็ได้ตามที่คุณต้องการ

ม็อดยอดนิยมสำหรับ Multiverse Loot Hunter

สำรวจม็อดที่ดีที่สุดสำหรับ Multiverse Loot Hunter ที่มาพร้อมฟีเจอร์ใหม่ กราฟิกที่ปรับปรุงแล้ว และวิธีที่น่าตื่นเต้นในการเปลี่ยนประสบการณ์การเล่นเกมของคุณ

ปลดล็อกศักยภาพเต็มของ Multiverse Loot Hunter ด้วย XMODhub — สำรวจม็อดยอดนิยมเหล่านี้วันนี้!

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