免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
如果看不懂、不知道现在做的什么,那就跟着做完看效果,代码看不懂是正常的,只要会抄就行,抄着抄着就能懂了
内容参考于:易道云信息技术研究院
上一个内容:90.导出游戏中的语言文件
代码下载地址,在 titan 目录下,文件名为:titan-加载游戏语言文件到内存.zip
链接:https://pan.baidu.com/s/1W-JpUcGOWbSJmMdmtMzYZg
提取码:q9n5
--来自百度网盘超级会员V4的分享
HOOK引擎,文件名为:黑兔sdk升级版.zip
链接:https://pan.baidu.com/s/1IB-Zs6hi3yU8LC2f-8hIEw
提取码:78h8
--来自百度网盘超级会员V4的分享
以 90.导出游戏中的语言文件 它的代码为基础进行修改
上一个内容里把游戏的语言包写到了我们本地磁盘文件中,然后现在要把这个文件读到我们C++程序的内存中,然后读取文件要把内容放到一个数组中,这个时候就有问题了,声明数组的时候不知道数组大小是多少,所以要把个数也给写到文件中
本次代码只是把架子搭起来了,还存在问题
CUIWnd_0.cpp文件的修改:修改了 OnBnClickedButton2函数,新加 txtMangerMain变量
// CUIWnd_0.cpp: 实现文件
//
#include "pch.h"
#include "htdMfcDll.h"
#include "CUIWnd_0.h"
#include "afxdialogex.h"
#include "extern_all.h"
#include "GameOBJECTDef.h"
// CUIWnd_0 对话框
float _xNext = 0.0f;
float _yNext = 0.0f;
void _stdcall loops(HWND, UINT, UINT_PTR, DWORD) {
PAIM aim = Client->GetAimByName(L"r");
if (aim == nullptr) {
return;
}
//AfxMessageBox(aim->Name);
float xDis = fabs(Client->Player.x - aim->x);
float hDis = fabs(Client->Player.h - aim->h);
float yDis = fabs(Client->Player.y - aim->y);
float xNext, yNext, thisx, thisy;
int v[2]{ -1, 1 };
if (xDis > 12) {
// 强制修改角色x坐标的值
thisx = Client->Player.x;
Client->Player.x = Client->Player.x + 6 * v[Client->Player.x < aim->x];
xNext = Client->Player.x;
}
else {
xNext = aim->x;
}
if (yDis > 12) {
// 强制修改角色y坐标的值
thisy = Client->Player.y;
Client->Player.y = Client->Player.y + 6 * v[Client->Player.y < aim->y];
yNext = Client->Player.y;
}else{
yNext = aim->y;
}
if ((xDis < 2)&&(hDis < 2)&&(yDis < 2)) {
Client->MoveStop(aim->x, aim->h, aim->y, 0.0f);
}
else {
Client->MoveWalk(Client->Player.x,aim->h, Client->Player.x, 0.0f, 0.0f, xNext, yNext);
}
}
IMPLEMENT_DYNAMIC(CUIWnd_0, CDialogEx)
CUIWnd_0::CUIWnd_0(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_PAGE_0, pParent)
{
}
CUIWnd_0::~CUIWnd_0()
{
}
void CUIWnd_0::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CUIWnd_0, CDialogEx)
ON_BN_CLICKED(IDC_BUTTON1, &CUIWnd_0::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON2, &CUIWnd_0::OnBnClickedButton2)
END_MESSAGE_MAP()
// CUIWnd_0 消息处理程序
void CUIWnd_0::OnBnClickedButton1()
{
// 发送坠落数据包
//Client->Fall();
设置移动速度
float Speed = 30.0;
Client->SetProperty(Client->Player.lId, INDEX_MoveSpeed, &Speed);
/*
// 修改血量
int HP = 10000000;
Client->SetProperty(Client->Player.lId, INDEX_HP, &HP);*/
/*CString txt;
txt.Format(L"通过AIM类获取角色信息 名字:%s,x坐标:%f", Client->Player.Name, Client->Player.x);
AfxMessageBox(txt);*/
// Client->HeartBeep();
// Client->TalkTo(L"r", L"打架吗?");
// Client->Talk(L"[欢迎来到麟科思]");
// Client->SelectRole(L"今晚打老虎");
/*Client->CreateRole(L"am4", 1.0, 2.0, 4.0, 8.0, "gui\BG_team\TeamRole\Teamrole_zq_humF_001.PNG",
"Face,0;Hat,0;Eyes,0;Beard,0;Ears,0;Tail,0;Finger,0;Cloth,0;Pants,0;Gloves,0;Shoes,0;Trait,0;HairColor,0;SkinColor,0;SkinMtl,0;Tattoo,0;TattooColor,16777215;",
"", 0.0);*/
//Client->SelectCamp("xuanrenZQ");
//Client->StartCreateRole();
//Client->DelRole(L"ranzhi11111");
/*
char buff[] = {
0xA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x4, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 00 ,0x00,
0x00, 0x07, 0x0E, 0x00, 0x00, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x31, 0x00, 0x32 ,0x00,
0x33, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
WinSock->OnSend(buff, sizeof(buff));
*/
/*char buff[] = {
0x27, 0x46, 0x92, 0x02, 0x00, 0x00, 0x89, 0x02, 0x00, 0x00, 0x06, 0x00, 0x06, 0x05,
0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x74, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x07,
0x0A, 0x00, 0x00, 0x00, 0x34, 0x00, 0x33, 0x00, 0x39, 0x00, 0x39, 0x00, 0x00, 0x00,
0x07, 0x5A, 0x02, 0x00, 0x00, 0x31, 0x00, 0x32, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32,
0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32,
0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32,
0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32,
0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32,
0x00, 0x32, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33,
0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33,
0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33,
0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33,
0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33,
0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33,
0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x35,
0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35,
0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35,
0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35,
0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35,
0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35,
0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x34,
0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34,
0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34,
0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34,
0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34,
0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34,
0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36,
0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36,
0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36,
0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x37,
0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00,
0x38, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00
};
WinSock->OnRecv(buff, sizeof(buff));*/
}
TextManger txtMangerMain;
void CUIWnd_0::OnBnClickedButton2()
{
// 根据语言表获取文字
//CString txt = txtManger->ReadTextById("npc_GRZJ_0001");// PGameProc->GetTextName("npc_GRZJ_0001");
//AfxMessageBox(txt);
//txtManger->CreateTextDat("F:\\语言包.txt");
// 读取导出到本地的语言包
txtMangerMain.LoadTextData("F:\\语言包.txt");
// 瞬移
//float decX = 3843.776123f;
//float decH = 11.731983f;
//float decY = -2005.533813f;
//float face = 0.0f;
//Client->Teleport(decX, decH, decY, face);
//PAIM aim = Client->GetAimByName(L"r");
//if (aim == nullptr) {
// return;
//}
//Client->Teleport(aim->x, aim->h, aim->y, aim->face);
// 修正坐标
/*PAIM aim = Client->GetAimByName(L"r");
if (aim == nullptr) {
return;
}
Client->SetCoord(Client->Player.lId, aim->x, aim->h, aim->y, aim->face);*/
// 面向
// Client->FaceTo(L"r");
// 飞天
// Client->HideMode = true;
// 遁地
//Client->MoveStop(Client->Player.x, Client->Player.h - 5, Client->Player.y, 0.0f);
// 跟随
// ::SetTimer(m_hWnd, 0x1000, 2000, loops);
//
// Client->Backtoroles();
}
TextManger.cpp文件的修改:修改了 CreateTextDat函数,新加 LoadTextData函数、GetNullText函数
#include "pch.h"
#include "TextManger.h"
unsigned TextManger::ReadTextProc = 0x10295FB0;
const wchar_t TextManger::NullText[2]{};
bool TextManger::CreateTextDat(const char* _filename)
{
if (!textTable) {
return false;
}
std::ofstream out(_filename, std::ios::out|std::ios::binary);
if (out.bad())return false;
out.write((char*)&hashCount, sizeof(hashCount));
for (int i = 0; i < hashCount; i++) {
// 游戏中的中文表结构是 中文名英文id 这样的
int lenId = strlen(textTable[i]->TxtId) + 1;
// 宽字节一个字是2字节,wcslen函数返回值是字的个数
int lenTxt = wcslen(textTable[i]->Txt) + 1;
lenTxt = lenTxt * 2;
out.write(textTable[i]->TxtId, lenId);
out.write((char*)textTable[i]->Txt, lenTxt);
}
out.close();
return true;
}
bool TextManger::LoadTextData(const char* _filename)
{
CString txt;
if (textTable) {// 这个textTable会在游戏链接的时候有值,有了值就不用再读取文件了
return false;
}
std::ifstream file(_filename, std::ios::in | std::ios::binary|std::ios::ate);
if(file.bad()) {
return false;
}
unsigned buffSize = file.tellg();
TextBuff = new char[buffSize];
file.seekg(std::ios::beg);
file.read(TextBuff, buffSize);
textTable = new PTextTable[Count[0]];
textDatas = new TextTable[Count[0]];
char* buffStart = TextBuff + 4;
char* buffEnd = buffStart + buffSize;
int icount = 0;
while(buffStart < buffEnd){// 读取语言文件的数据到 textDatas 变量里
int lenId = strlen(buffStart) + 1;
memcpy(textDatas[icount].TxtId, buffStart, lenId);
buffStart = buffStart + lenId;
int lenTxt = wcslen((wchar_t*)buffStart) + 1;
lenTxt = lenTxt * 2;
textDatas[icount].Txt = (wchar_t*)buffStart;
buffStart = buffStart + lenTxt;
icount++;
}
hashCount = Count[0];
HashIndexTable = new unsigned[hashCount];
memset(HashIndexTable, 0xFF, hashCount * sizeof(unsigned));
txt.Format(L"%X ---- %X", textTable, HashIndexTable);
AfxMessageBox(txt);
for (int i = 0; i < Count[0]; i++) {// 给 textDatas 变量添加哈希算法索引(哈希表存放 textDatas的下标)
unsigned hash = Hashcode(textDatas[i].TxtId);
hash = hash % (hashCount + 1);
if (HashIndexTable[hash] == -1) {
HashIndexTable[hash] = i;
}
else {
PTextTable nullTable = GetNullText(&textDatas[HashIndexTable[hash]]);
nullTable->next = i;
}
}
txt.Format(L"%X %X", textTable, HashIndexTable);
AfxMessageBox(txt);
return false;
}
const wchar_t* TextManger::ReadTextById(const char* _id)
{
// unsigned callProc = 0x10295FB0;
if (HashIndexTable) {
int index;
_asm {
push ebx
mov ebx, this
push _id
call ReadTextProc
mov index, eax
pop ebx
}
if (index < 0)return NullText;
PTextTable* _table = textTable;
return (wchar_t*)_table[index]->Txt;
}
return NullText;
}
unsigned TextManger::Hashcode(const char* id)
{
unsigned hash = 0;
for (int i = 0; id[i]; i++)
{
hash = hash * 131 + id[i];
}
return hash;
}
PTextTable TextManger::GetNullText(PTextTable _table)
{
while (_table->next != -1) {// 从链表中找出最后一个(next的值是-1的)
_table = &textDatas[_table->next];
}
return _table;
}
TextManger.h文件的修改:修改了 TextTable结构体、TextManger结构体,新加 GetNullText函数、LoadTextData函数、HashIndexTable变量、textDatas变量、textTable变量
#pragma once
#include <iostream>
#include <fstream>
/*
03E1B73B | 68 58120304 | push fxgamelogic.4031258 | 4031258:"gui"
03E1B740 | E8 7BEF0F00 | call fxgamelogic.3F1A6C0 |
03E1B745 | 83C4 04 | add esp,4 |
03E1B748 | 85C0 | test eax,eax |
03E1B74A | 0F84 10090000 | je fxgamelogic.3E1C060 |
03E1B750 | 68 4C120304 | push fxgamelogic.403124C | 403124C:"TextManager"
03E1B755 | 50 | push eax |
03E1B756 | 8D4C24 64 | lea ecx,dword ptr ss:[esp+64] |
03E1B75A | 51 | push ecx |
03E1B75B | E8 00091000 | call fxgamelogic.3F1C060 |
03E1B760 | 8D5424 68 | lea edx,dword ptr ss:[esp+68] |
03E1B764 | 52 | push edx |
03E1B765 | E8 16EF0F00 | call fxgamelogic.3F1A680 | 111111111111
03E1B76A | 83C4 10 | add esp,10 |
03E1B76D | 85C0 | test eax,eax |
03E1B76F | 894424 14 | mov dword ptr ss:[esp+14],eax | [esp+14]:CD3DDDIDX10_DrawIndexedPrimitive+113
*/
// 游戏中的中文表结构是 中文名英文id 这样的
typedef class TextTable {
public:
int next = 0xFFFFFFFF;
int un;
wchar_t* Txt;// 中文
char TxtId[0x24];// 中文对应的英文id
}*PTextTable;
typedef class TextManger
{
public:
static unsigned ReadTextProc;
static const wchar_t NullText[2];
private:
//int un[0x20];// 0x20 * 0x4 = 0x80
int un[0x1E];
union {
char* TextBuff;
unsigned* Count;
};
PTextTable textDatas = nullptr;
public:
PTextTable* textTable = nullptr;
private:
int un1;
public:
unsigned hashCount;
unsigned* HashIndexTable = nullptr;
public:
bool CreateTextDat(const char* filename); // 导出语言包
bool LoadTextData(const char* _filename); // 加载 CreateTextDat函数写出的文件
const wchar_t* ReadTextById(const char* _id); // 根据id获取中文名
unsigned Hashcode(const char* id);// 哈希函数
// 获取一个未使用的中文与对应id结构,用与存放从文件中读取的中文与对应id
PTextTable GetNullText(PTextTable _table);
}*PTextManger;