496 lines
20 KiB
Plaintext
496 lines
20 KiB
Plaintext
/*
|
||
文件名:EquimentUseJewel.nut
|
||
路径:Dps_A/ProjectClass/EquimentUseJewel/EquimentUseJewel.nut
|
||
创建日期:2024-10-28 21:18
|
||
文件用途:装备镶嵌
|
||
*/
|
||
|
||
class EquimentUseJewel {
|
||
|
||
ExecUser = null;
|
||
|
||
//建库建表
|
||
function CreateMysqlTable() {
|
||
local CreateSql1 = "create database if not exists l_equ_jewel default charset utf8;"
|
||
local CreateSql2 = "CREATE TABLE l_equ_jewel.equipment ( equ_id int(11) AUTO_INCREMENT, jewel_data blob NOT NULL,andonglishanbai_flag int(11),date VARCHAR(255), PRIMARY KEY (equ_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8,AUTO_INCREMENT = 150;"
|
||
local SqlObj = MysqlPool.GetInstance().GetConnect();
|
||
SqlObj.Exec_Sql(CreateSql1);
|
||
SqlObj.Exec_Sql(CreateSql2);
|
||
MysqlPool.GetInstance().PutConnect(SqlObj);
|
||
}
|
||
|
||
function api_get_jewel_socket_data(id) { //获取徽章数据,存在返回徽章数据,不存在返回空字节数据
|
||
local CheckSql = "SELECT jewel_data FROM l_equ_jewel.equipment where equ_id = " + id + ";";
|
||
//从池子拿连接
|
||
local SqlObj = MysqlPool.GetInstance().GetConnect();
|
||
local Ret = SqlObj.Select(CheckSql, ["binary"]);
|
||
//把连接还池子
|
||
MysqlPool.GetInstance().PutConnect(SqlObj);
|
||
//没结婚要返回false
|
||
if (Ret.len()< 1 || Ret[0][0] == null) {
|
||
return 0;
|
||
} else {
|
||
return Ret[0][0];
|
||
}
|
||
}
|
||
|
||
function api_exitjeweldata(id) { //0代表不存在,存在返回1
|
||
local CheckSql = "SELECT andonglishanbai_flag FROM l_equ_jewel.equipment where equ_id = " + id + ";";
|
||
//从池子拿连接
|
||
local SqlObj = MysqlPool.GetInstance().GetConnect();
|
||
local Ret = SqlObj.Select(CheckSql, ["int"]);
|
||
//把连接还池子
|
||
MysqlPool.GetInstance().PutConnect(SqlObj);
|
||
//没结婚要返回false
|
||
if (Ret.len()< 1 || Ret[0][0] == null) {
|
||
return 0;
|
||
} else {
|
||
return Ret[0][0];
|
||
}
|
||
}
|
||
|
||
function save_equiment_socket(socket_data, id) { //0代表不存在,存在返回1
|
||
local CheckSql = "UPDATE l_equ_jewel.equipment SET jewel_data = 0x" + socket_data + " WHERE equ_id = " + id + ";";
|
||
//从池子拿连接
|
||
local SqlObj = MysqlPool.GetInstance().GetConnect();
|
||
local Ret = SqlObj.Select(CheckSql, ["int"]);
|
||
printT(Ret);
|
||
//把连接还池子
|
||
MysqlPool.GetInstance().PutConnect(SqlObj);
|
||
//没结婚要返回false
|
||
if (Ret.len()< 1 || Ret[0][0] == null) {
|
||
return false;
|
||
} else {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
function CUser_SendCmdErrorPacket(SUser, id, id2) {
|
||
local Pack = Packet();
|
||
Pack.Put_Header(1, id);
|
||
Pack.Put_Byte(0);
|
||
Pack.Put_Byte(id2);
|
||
Pack.Finalize(true);
|
||
SUser.Send(Pack);
|
||
Pack.Delete();
|
||
}
|
||
|
||
function api_PacketBuf_get_buf(packet_buf) {
|
||
return NativePointer(NativePointer(packet_buf).add(20).readPointer()).add(13);
|
||
}
|
||
|
||
function add_equiment_socket(equipment_type) { //0代表开孔失败 成功返回标识
|
||
/*
|
||
武器10
|
||
称号11
|
||
上衣12
|
||
头肩13
|
||
下衣14
|
||
鞋子15
|
||
腰带16
|
||
项链17
|
||
手镯18
|
||
戒指19
|
||
辅助装备20
|
||
魔法石21
|
||
*/
|
||
|
||
/*
|
||
红色:'010000000000010000000000000000000000000000000000000000000000' A
|
||
黄色:'020000000000020000000000000000000000000000000000000000000000' B
|
||
绿色:'040000000000040000000000000000000000000000000000000000000000' C
|
||
蓝色:'080000000000080000000000000000000000000000000000000000000000' D
|
||
白金:'100000000000100000000000000000000000000000000000000000000000'
|
||
*/
|
||
local DB_JewelsocketData = "";
|
||
switch (equipment_type) {
|
||
case 10: //武器10 SS
|
||
DB_JewelsocketData = "100000000000000000000000000000000000000000000000000000000000"
|
||
break;
|
||
case 11: //称号11 SS
|
||
DB_JewelsocketData = "100000000000000000000000000000000000000000000000000000000000"
|
||
break;
|
||
case 12: //上衣12 C
|
||
DB_JewelsocketData = "040000000000040000000000000000000000000000000000000000000000"
|
||
break;
|
||
case 13: //头肩13 B
|
||
DB_JewelsocketData = "020000000000020000000000000000000000000000000000000000000000"
|
||
break;
|
||
case 14: //下衣14 C
|
||
DB_JewelsocketData = "040000000000040000000000000000000000000000000000000000000000"
|
||
break;
|
||
case 15: //鞋子15 D
|
||
DB_JewelsocketData = "080000000000080000000000000000000000000000000000000000000000"
|
||
break;
|
||
case 16: //腰带16 A
|
||
DB_JewelsocketData = "010000000000010000000000000000000000000000000000000000000000"
|
||
break;
|
||
case 17: //项链17 B
|
||
DB_JewelsocketData = "020000000000020000000000000000000000000000000000000000000000"
|
||
break;
|
||
case 18: //手镯18 D
|
||
DB_JewelsocketData = "080000000000080000000000000000000000000000000000000000000000"
|
||
break;
|
||
case 19: //戒指19 A
|
||
DB_JewelsocketData = "010000000000010000000000000000000000000000000000000000000000"
|
||
break;
|
||
case 20: //辅助装备20 S
|
||
DB_JewelsocketData = "100000000000000000000000000000000000000000000000000000000000"
|
||
break;
|
||
case 21: //魔法石21 S
|
||
DB_JewelsocketData = "100000000000000000000000000000000000000000000000000000000000"
|
||
break;
|
||
default:
|
||
DB_JewelsocketData = "000000000000000000000000000000000000000000000000000000000000"
|
||
break;
|
||
}
|
||
local date = time();
|
||
local Ct = Sq_GetTimestampString();
|
||
date = date.tostring() + Ct;
|
||
|
||
local CheckSql = "INSERT INTO l_equ_jewel.equipment (andonglishanbai_flag,jewel_data,date) VALUES(1,0x" + DB_JewelsocketData + ",\'" + date + "\');";
|
||
local CheckSql1 = "SELECT equ_id FROM l_equ_jewel.equipment where date = \'" + date + "\';";
|
||
//从池子拿连接
|
||
local SqlObj = MysqlPool.GetInstance().GetConnect();
|
||
SqlObj.Select(CheckSql, ["int"]);
|
||
local Ret = SqlObj.Select(CheckSql1, ["int"]);
|
||
//把连接还池子
|
||
MysqlPool.GetInstance().PutConnect(SqlObj);
|
||
if (Ret.len()< 1 || Ret[0][0] == null) {
|
||
return 0;
|
||
} else {
|
||
return Ret[0][0];
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
function CStackableItem_getJewelTargetSocket(C_Object) {
|
||
return Sq_CallFunc(S_Ptr("0x0822CA28"), "int", ["pointer"], C_Object);
|
||
}
|
||
|
||
function CUser_SendUpdateItemList_DB(SUser, Slot, DB_JewelSocketData) {
|
||
local Pack = Packet();
|
||
Pack.Put_Header(0, 14);
|
||
Pack.Put_Byte(0);
|
||
Pack.Put_Short(1);
|
||
local InvenObj = SUser.GetInven();
|
||
Sq_CallFunc(S_Ptr("0x084FC6BC"), "int", ["pointer", "int", "int", "pointer"], InvenObj.C_Object, 1, Slot, Pack.C_Object);
|
||
Pack.Put_BinaryEx(DB_JewelSocketData.C_Object, 30);
|
||
Pack.Finalize(true);
|
||
SUser.Send(Pack);
|
||
Pack.Delete();
|
||
}
|
||
|
||
function GetByte(value) {
|
||
local Blob = blob();
|
||
Blob.writen(value, 'w');
|
||
print(Blob.len());
|
||
return Blob;
|
||
}
|
||
|
||
function intToHex(num) {
|
||
if (num == 0) {
|
||
return "0";
|
||
}
|
||
local hexDigits = "0123456789abcdef";
|
||
local hexString = "";
|
||
while (num > 0) {
|
||
local remainder = num % 16;
|
||
hexString = hexDigits[remainder] + hexString;
|
||
num = (num / 16).tointeger();
|
||
}
|
||
return hexString;
|
||
}
|
||
|
||
function lengthCutting(str, ystr, num, maxLength) {
|
||
// 如果字符串长度小于最大长度,在前面补0
|
||
local lengthDiff = maxLength - str.len();
|
||
if (lengthDiff > 0) {
|
||
local zeroPadding = "";
|
||
for (local i = 0; i< lengthDiff; i++) {
|
||
zeroPadding += "0";
|
||
}
|
||
str = zeroPadding + str;
|
||
}
|
||
local strArr = "";
|
||
for (local i = 0; i< str.len(); i += num) {
|
||
local endIndex = i + num;
|
||
if (endIndex > str.len()) {
|
||
endIndex = str.len();
|
||
}
|
||
strArr += str.slice(i, endIndex);
|
||
}
|
||
return ystr + strArr;
|
||
}
|
||
|
||
|
||
HackReturnAddSocketToAvatarFalg = null;
|
||
|
||
function HackReturnAddSocketToAvatar(Code) {
|
||
//通过hook get short直接返回0达到错误返回的效果
|
||
//标记flag
|
||
HackReturnAddSocketToAvatarFalg = Code;
|
||
Haker.LoadHook("0x0858D0B0", ["pointer", "pointer", "int"],
|
||
function(args) {
|
||
return null;
|
||
},
|
||
function(args) {
|
||
Haker.UnLoadHook("0x0858D0B0");
|
||
return 0;
|
||
});
|
||
}
|
||
|
||
|
||
function FixFunction() {
|
||
//称号回包
|
||
Haker.LoadHook("0x08641A6A", ["pointer", "pointer", "int", "pointer", "int"],
|
||
function(args) {
|
||
return null;
|
||
}.bindenv(this),
|
||
|
||
function(args) {
|
||
local JewelSocketData = api_get_jewel_socket_data(NativePointer(args[3]).add(25).readU32());
|
||
local ret = args.pop();
|
||
if (JewelSocketData && NativePointer(JewelSocketData).add(0).readU8() != 0) {
|
||
local Pack = Packet(args[1]);
|
||
Pack.Put_BinaryEx(JewelSocketData.C_Object, 30);
|
||
}
|
||
return null;
|
||
}.bindenv(this));
|
||
|
||
//设计图继承
|
||
Haker.LoadHook("0x08671EB2", ["pointer", "pointer", "pointer", "int"],
|
||
function(args) {
|
||
local jewelSocketID = NativePointer(args[2]).add(25).readU32();
|
||
NativePointer(args[1]).add(25).writeU32(jewelSocketID);
|
||
return null;
|
||
}.bindenv(this),
|
||
|
||
function(args) {
|
||
return null;
|
||
}.bindenv(this));
|
||
|
||
//装备开孔
|
||
Haker.LoadHook("0x0821A412", ["pointer", "pointer", "pointer", "int"],
|
||
function(args) {
|
||
local SUser = User(args[1]);
|
||
local Pack = Packet(args[2]);
|
||
local equ_slot = Pack.GetShort();
|
||
local equitem_id = Pack.GetInt();
|
||
local sta_slot = Pack.GetShort();
|
||
local CurCharacInvenW = SUser.GetInven();
|
||
local inven_item = CurCharacInvenW.GetSlot(1, equ_slot);
|
||
|
||
if (equ_slot > 56) { //修改后:大于56则是时装装备 原:如果不是装备文件就调用原逻辑
|
||
equ_slot = equ_slot - 57;
|
||
local C_PacketBuf = api_PacketBuf_get_buf(args[2]) //获取原始封包数据
|
||
C_PacketBuf.add(0).writeShort(equ_slot) //修改掉装备位置信息 时装类镶嵌从57开始。
|
||
//执行原逻辑
|
||
return null;
|
||
}
|
||
//如果已开启镶嵌槽则不执行
|
||
local equ_id = NativePointer(inven_item.C_Object).add(25).readU32();
|
||
if (api_exitjeweldata(equ_id)) {
|
||
HackReturnAddSocketToAvatar(0x13);
|
||
return null;
|
||
}
|
||
|
||
local item = PvfItem.GetPvfItemById(equitem_id);
|
||
local ItemType = Sq_CallFunc(S_Ptr("0x08514D26"), "int", ["pointer"], item.C_Object);
|
||
|
||
if (ItemType == 10) {
|
||
SUser.SendNotiBox("装备为武器类型,不支持打孔!", 1)
|
||
HackReturnAddSocketToAvatar(0x0);
|
||
return null;
|
||
} else if (ItemType == 11) {
|
||
SUser.SendNotiBox("装备为称号类型,不支持打孔!", 1)
|
||
HackReturnAddSocketToAvatar(0x0);
|
||
return null;
|
||
}
|
||
|
||
|
||
local id = add_equiment_socket(ItemType);
|
||
Sq_Inven_RemoveItemFormCount(CurCharacInvenW.C_Object, 1, sta_slot, 1, 8, 1); //删除打孔道具
|
||
NativePointer(inven_item.C_Object).add(25).writeU32(id) //写入槽位标识
|
||
SUser.SendUpdateItemList(1, 0, equ_slot);
|
||
|
||
local JewelSocketData = api_get_jewel_socket_data(id);
|
||
CUser_SendUpdateItemList_DB(SUser, equ_slot, JewelSocketData); //用于更新镶嵌后的装备显示,这里用的是带镶嵌数据的更新背包函数,并非CUser_SendUpdateItemList
|
||
|
||
local Pack = Packet();
|
||
Pack.Put_Header(1, 209);
|
||
Pack.Put_Byte(1);
|
||
Pack.Put_Short(equ_slot + 104);
|
||
Pack.Put_Short(sta_slot);
|
||
Pack.Finalize(true);
|
||
SUser.Send(Pack);
|
||
Pack.Delete();
|
||
HackReturnAddSocketToAvatar(0x0);
|
||
return null;
|
||
}.bindenv(this),
|
||
|
||
function(args) {
|
||
//跳的错误返回0 正常调用的话不处理返回值
|
||
if (HackReturnAddSocketToAvatarFalg != null) {
|
||
local SUser = User(args[1]);
|
||
// SUser.SendItemSpace(0);
|
||
CUser_SendCmdErrorPacket(SUser, 209, HackReturnAddSocketToAvatarFalg);
|
||
HackReturnAddSocketToAvatarFalg = null;
|
||
return 0;
|
||
}
|
||
|
||
return null;
|
||
}.bindenv(this));
|
||
|
||
//装备镶嵌和时装镶嵌
|
||
Haker.LoadHook("0x8217BD6", ["int", "pointer", "pointer", "int"],
|
||
function(args) {
|
||
local SUser = User(args[1]);
|
||
local Pack = Packet(args[2]);
|
||
local State = SUser.GetState();
|
||
if (State != 3) return null;
|
||
|
||
local avartar_inven_slot = Pack.GetShort();
|
||
local avartar_item_id = Pack.GetInt();
|
||
local emblem_cnt = Pack.GetByte();
|
||
|
||
//下面是参照原时装镶嵌的思路写的。个别点标记出来。
|
||
if (avartar_inven_slot > 104) {
|
||
local equipment_inven_slot = avartar_inven_slot - 104; //取出真实装备所在背包位置值
|
||
local Inven = SUser.GetInven();
|
||
local equipment = Inven.GetSlot(1, equipment_inven_slot);
|
||
//校验是否合法
|
||
if (!equipment || equipment.IsEmpty || (equipment.GetIndex() != avartar_item_id) || SUser.CheckItemLock(1, equipment_inven_slot)) return;
|
||
|
||
local id = NativePointer(equipment.C_Object).add(25).readU32();
|
||
local JewelSocketData = api_get_jewel_socket_data(id);
|
||
if (!JewelSocketData) return;
|
||
|
||
local emblems = {};
|
||
if (emblem_cnt <= 3) {
|
||
for (local i = 0; i< emblem_cnt; i++) {
|
||
local emblem_inven_slot = Pack.GetShort();
|
||
local emblem_item_id = Pack.GetInt();
|
||
local equipment_socket_slot = Pack.GetByte();
|
||
local emblem = Inven.GetSlot(1, emblem_inven_slot);
|
||
//校验徽章及插槽数据是否合法
|
||
if (!emblem || emblem.IsEmpty || (emblem.GetIndex() != emblem_item_id) || (equipment_socket_slot >= 3)) return;
|
||
|
||
//校验徽章是否满足时装插槽颜色要求
|
||
//获取徽章pvf数据
|
||
local citem = PvfItem.GetPvfItemById(emblem_item_id);
|
||
if (!citem) return;
|
||
|
||
//校验徽章类型
|
||
if (!citem.IsStackable() || citem.GetItemType() != 20) return;
|
||
|
||
//获取徽章支持的插槽
|
||
local emblem_socket_type = CStackableItem_getJewelTargetSocket(citem.C_Object);
|
||
//获取要镶嵌的时装插槽类型
|
||
local avartar_socket_type = JewelSocketData.add(equipment_socket_slot * 6).readShort();
|
||
|
||
if (!(emblem_socket_type & avartar_socket_type)) {
|
||
|
||
return;
|
||
}
|
||
|
||
emblems[equipment_socket_slot] <- [emblem_inven_slot, emblem_item_id];
|
||
}
|
||
}
|
||
|
||
|
||
foreach(equipment_socket_slot, emblemObject in emblems) {
|
||
//删除徽章
|
||
local emblem_inven_slot = emblemObject[0];
|
||
Sq_Inven_RemoveItemFormCount(Inven.C_Object, 1, emblem_inven_slot, 1, 8, 1); //删除打孔道具
|
||
//设置时装插槽数据
|
||
local emblem_item_id = emblemObject[1];
|
||
JewelSocketData.add(2 + 6 * equipment_socket_slot).writeU32(emblem_item_id);
|
||
}
|
||
|
||
local Buf = Sq_Point2Blob(JewelSocketData.C_Object, 30);
|
||
local Str = "";
|
||
foreach(Value in Buf) {
|
||
Str += format("%02X", Value);
|
||
}
|
||
|
||
save_equiment_socket(Str, id);
|
||
// if (!save_equiment_socket(DB_JewelSocketData, id)) {
|
||
// print("写入失败了");
|
||
// return null;
|
||
// }
|
||
|
||
CUser_SendUpdateItemList_DB(SUser, equipment_inven_slot, JewelSocketData); //用于更新镶嵌后的装备显示,这里用的是带镶嵌数据的更新背包函数,并非CUser_SendUpdateItemList
|
||
local Pack = Packet();
|
||
Pack.Put_Header(1, 209);
|
||
Pack.Put_Byte(1);
|
||
Pack.Put_Short(equipment_inven_slot + 104);
|
||
Pack.Finalize(true);
|
||
SUser.Send(Pack);
|
||
Pack.Delete();
|
||
|
||
}
|
||
|
||
return null;
|
||
}.bindenv(this),
|
||
|
||
function(args) {
|
||
return 0;
|
||
}.bindenv(this));
|
||
|
||
//额外数据包,发送装备镶嵌数据给本地处理
|
||
Haker.LoadHook("0x0815098e", ["pointer", "pointer", "int"],
|
||
function(args) {
|
||
return null;
|
||
}.bindenv(this),
|
||
|
||
function(args) {
|
||
local ret = args.pop();
|
||
local Inven_Item = NativePointer(args[1]);
|
||
if (Inven_Item.add(1).readU8() == 1) {
|
||
local ItemObj = Item(args[1]);
|
||
local JewelSocketData = api_get_jewel_socket_data(NativePointer(ItemObj.C_Object).add(25).readU32());
|
||
if (JewelSocketData && JewelSocketData.add(0).readU8() != 0) {
|
||
local Pack = Packet(args[0]);
|
||
Pack.Put_BinaryEx(JewelSocketData.C_Object, 30);
|
||
}
|
||
}
|
||
return null;
|
||
}.bindenv(this));
|
||
|
||
//装备全字节复制
|
||
Haker.LoadHook("0x0814A62E", ["pointer", "pointer", "pointer"],
|
||
function(args) {
|
||
return null;
|
||
}.bindenv(this),
|
||
|
||
function(args) {
|
||
local Old = NativePointer(args[1]);
|
||
local New = NativePointer(args[0]);
|
||
Memory.copy(New, Old, 61);
|
||
return args[0];
|
||
}.bindenv(this));
|
||
|
||
//装备全字节删除
|
||
Haker.LoadHook("0x080CB7D8", ["pointer", "int"],
|
||
function(args) {
|
||
return null;
|
||
}.bindenv(this),
|
||
|
||
function(args) {
|
||
local New = NativePointer(args[0]);
|
||
Memory.reset(New, 61);
|
||
return null;
|
||
}.bindenv(this));
|
||
}
|
||
|
||
constructor() {
|
||
CreateMysqlTable();
|
||
|
||
FixFunction();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
getroottable().RRR <- EquimentUseJewel(); |