logo
th
ภาษาไทย

ห้องสมุดที่อยู่สําหรับปลั๊กอิน SKSE

ผู้สร้าง: meh321
อัปเดตแล้ว:2020-02-24 19:31:54
2.8MB
mcafee
การยืนยันตัวตน
ได้รับความไว้วางใจจากผู้ใช้ 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 ด้วย Xmod — สำรวจม็อดยอดนิยมเหล่านี้วันนี้!

mcafee
การยืนยันตัวตน
ได้รับความไว้วางใจจากผู้ใช้ 200,000,000+ คน

ต้องการความช่วยเหลือเกี่ยวกับการดาวน์โหลดหรือติดตั้งหรือไม่? เข้าร่วม ชุมชน Discord ของเราเพื่อรับการสนับสนุน!

logo
ภาษา

โซลูชันเกม

ทรัพยากร

พันธมิตร

ติดตามเราบน

discordfacebooktwitteryoutube
dc@xmodhub.com or cathy@business.xmodhub.com
Discord: catherine_79237
ข้อกำหนดและเงื่อนไข
นโยบายความเป็นส่วนตัว
การสนับสนุน

Larvas Limited

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