站在了巨人的肩膀头上,感谢造轮子的大佬。根据自己的喜好进行了修改 自用Frida
仅供测试使用
换装
装备栏检索全部格子,时装和宠物栏只检索最上面两行
注意:1️⃣时装和宠物换装后外观不会改变,但是属性变化了(不知道有没有刷新外观的接口)2️⃣镶嵌换不了
函数
部分函数
读取套装
从数据库读取指定套装
/** * 根据套装编号获取指定换装 * * 20250102 by Tim * @param cid * @param num 套装编号 */ function get_user_equ_replace(cid, num) { var suit_record = {}; var selectQuery = `SELECT cid, suit_num, equip_0, equip_1, equip_2, equip_3, equip_4, equip_5, equip_6, equip_7, equip_8, equip_9, equip_10, equip_11, equip_12, equip_13, equip_14, equip_15, equip_16, equip_17, equip_18, equip_19, equip_20, equip_21, equip_22 FROM user_equ_replace WHERE cid = ${cid} AND suit_num = ${num}; `; if (api_MySQL_exec(mysql_frida, selectQuery)) { // 获取查询的行数 var rows = MySQL_get_n_rows(mysql_frida); if (rows > 0) { // 查询成功,读取数据 MySQL_fetch(mysql_frida); // 获取单行数据 //读取套装 for (let index = 0; index <= 22; index++) { suit_record[index] = {}; suit_record[index] = JSON.parse(api_MySQL_get_str(mysql_frida, 0 + 2 + index)); // log(index + ‘ ‘ + api_MySQL_get_str(mysql_frida, 0 + 2 + index)); } return suit_record; } } }
保存套装
保存到数据库
20250103 数据库改为保存
equBackPack.add(7).readU32()
/** | |
* 保存用户指定套装 | |
* | |
* 20250102 by Tim | |
* @param user | |
* @param suit_num | |
*/ | |
function saveEquSuit(user, suit_num) { | |
let userSuit = {}; | |
let inven = CUserCharacInfo_getCurCharacInvenW(user); | |
let itemSize = 61; // 每个物品的大小 | |
for (let index = 0; index <= 22; index++) { | |
let equ = CInventory_GetInvenRef(inven, INVENTORY_TYPE.INVENTORY_TYPE_BODY, index);//身上的装备 | |
let data = Memory.readByteArray(equ, itemSize); | |
let str = arrayBufferToHexStr(data); | |
let item_id = Inven_Item_getKey(equ); | |
userSuit[index] = {}; | |
userSuit[index].id = item_id; | |
userSuit[index].data = str; | |
// log(index + ‘ ‘ + JSON.stringify(userSuit[index])); | |
} | |
let charac_no = CUserCharacInfo_getCurCharacNo(user); | |
//写入数据库 | |
api_MySQL_exec(mysql_frida, ` | |
INSERT INTO user_equ_replace ( | |
cid, suit_num, equip_0, equip_1, equip_2, equip_3, equip_4, equip_5, equip_6, | |
equip_7, equip_8, equip_9, equip_10, equip_11, equip_12, equip_13, equip_14, | |
equip_15, equip_16, equip_17, equip_18, equip_19, equip_20, equip_21, equip_22 | |
) VALUES ( | |
${charac_no}, ${suit_num}, | |
‘${JSON.stringify(userSuit[0])}‘, ‘${JSON.stringify(userSuit[1])}‘, ‘${JSON.stringify(userSuit[2])}‘, ‘${JSON.stringify(userSuit[3])}‘, ‘${JSON.stringify(userSuit[4])}‘, | |
‘${JSON.stringify(userSuit[5])}‘, ‘${JSON.stringify(userSuit[6])}‘, ‘${JSON.stringify(userSuit[7])}‘, ‘${JSON.stringify(userSuit[8])}‘, ‘${JSON.stringify(userSuit[9])}‘, | |
‘${JSON.stringify(userSuit[10])}‘, ‘${JSON.stringify(userSuit[11])}‘, ‘${JSON.stringify(userSuit[12])}‘, ‘${JSON.stringify(userSuit[13])}‘, ‘${JSON.stringify(userSuit[14])}‘, | |
‘${JSON.stringify(userSuit[15])}‘, ‘${JSON.stringify(userSuit[16])}‘, ‘${JSON.stringify(userSuit[17])}‘, ‘${JSON.stringify(userSuit[18])}‘, ‘${JSON.stringify(userSuit[19])}‘, | |
‘${JSON.stringify(userSuit[20])}‘, ‘${JSON.stringify(userSuit[21])}‘, ‘${JSON.stringify(userSuit[22])}‘ | |
) | |
ON DUPLICATE KEY UPDATE | |
equip_0 = ‘${JSON.stringify(userSuit[0])}‘, equip_1 = ‘${JSON.stringify(userSuit[1])}‘, equip_2 = ‘${JSON.stringify(userSuit[2])}‘, | |
equip_3 = ‘${JSON.stringify(userSuit[3])}‘, equip_4 = ‘${JSON.stringify(userSuit[4])}‘, equip_5 = ‘${JSON.stringify(userSuit[5])}‘, | |
equip_6 = ‘${JSON.stringify(userSuit[6])}‘, equip_7 = ‘${JSON.stringify(userSuit[7])}‘, equip_8 = ‘${JSON.stringify(userSuit[8])}‘, | |
equip_9 = ‘${JSON.stringify(userSuit[9])}‘, equip_10 = ‘${JSON.stringify(userSuit[10])}‘, equip_11 = ‘${JSON.stringify(userSuit[11])}‘, | |
equip_12 = ‘${JSON.stringify(userSuit[12])}‘, equip_13 = ‘${JSON.stringify(userSuit[13])}‘, equip_14 = ‘${JSON.stringify(userSuit[14])}‘, | |
equip_15 = ‘${JSON.stringify(userSuit[15])}‘, equip_16 = ‘${JSON.stringify(userSuit[16])}‘, equip_17 = ‘${JSON.stringify(userSuit[17])}‘, | |
equip_18 = ‘${JSON.stringify(userSuit[18])}‘, equip_19 = ‘${JSON.stringify(userSuit[19])}‘, equip_20 = ‘${JSON.stringify(userSuit[20])}‘, | |
equip_21 = ‘${JSON.stringify(userSuit[21])}‘, equip_22 = ‘${JSON.stringify(userSuit[22])}‘; | |
`); | |
api_CUser_SendNotiPacketMessage(user, ‘保存成功!’, 1); | |
} |
换装(新)
通过接口实现换装(未找到换宠物的方法)
/** | |
* 换装HOOK | |
* @param a1 User指针 | |
* @param a2 换装类型 0:装备 1:时装 | |
* @param a3 背包slot | |
* @param a4 穿戴栏slot (10-21) | |
* @retval 返回值 0代表成功 | |
*/ | |
var CUser_change_equip = new NativeFunction(ptr(0x0865EED2), ‘int’, [‘pointer’, ‘int’, ‘int’, ‘int’], { “abi”: “sysv” }); |
换装(旧)
/** | |
* 交换装备 | |
* | |
* 20250102 by Tim | |
* @param user | |
* @param minIndex 栏位格子的开始索引 | |
* @param maxIndex 栏位格子的结束索引 | |
* @param bodyIndex 身上装备的位置索引 | |
* @param suit 保存的换装套装 | |
* @param inventoryType 栏位类型 INVENTORY_TYPE | |
* @param itemspaceType 更新栏位的类型 ENUM_ITEMSPACE | |
*/ | |
function exchangeEqu(user, minIndex, maxIndex, bodyIndex, suit, inventoryType, itemspaceType) { | |
let inven = CUserCharacInfo_getCurCharacInvenW(user); | |
let itemSize = 61; // 每个物品的大小 | |
//范围内循环匹配 | |
for (let i = minIndex; i <= maxIndex; i++) { | |
let equBackPack = CInventory_GetInvenRef(inven, inventoryType, i);//背包装备 | |
let dataBackPack = Memory.readByteArray(equBackPack, itemSize); | |
let item_id = Inven_Item_getKey(equBackPack);//背包装备id | |
let str = arrayBufferToHexStr(dataBackPack); | |
//匹配 | |
if (suit.data != str || suit.id != item_id || !suit.id) | |
continue; | |
let equ = CInventory_GetInvenRef(inven, INVENTORY_TYPE.INVENTORY_TYPE_BODY, bodyIndex);//身上的装备 | |
let data = Memory.readByteArray(equ, itemSize); | |
// 交换物品的数据 | |
Memory.writeByteArray(equBackPack, data); | |
Memory.writeByteArray(equ, dataBackPack); | |
CUser_SendUpdateItemList(user, 1, inventoryType – 1, i);//更新槽位(0:物品 1:时装 2:宠物 3:身上) | |
CUser_SendUpdateItemList(user, 1, 3, bodyIndex);//更新身上的 | |
CUser_SendNotiPacket(user, 1, 2, 1); | |
CUser_send_itemspace(user, itemspaceType); | |
break; | |
} | |
} | |
/** | |
* 角色更换指定套装 | |
* | |
* 20250102 by Tim | |
* @param user | |
* @param suit_num 套装编号 | |
*/ | |
function changeEquSuit(user, suit_num) { | |
let charac_no = CUserCharacInfo_getCurCharacNo(user); | |
let userSuit = get_user_equ_replace(charac_no, suit_num);//从数据库读取保存的套装 | |
if (!userSuit) | |
return; | |
for (const key in userSuit) { | |
let bodyIndex = parseInt(key); | |
if (bodyIndex >= 0 && bodyIndex <= 9) { | |
//检查时装 0~13 | |
exchangeEqu(user, 0, 13, bodyIndex, userSuit[bodyIndex], INVENTORY_TYPE.INVENTORY_TYPE_AVARTAR, ENUM_ITEMSPACE.ENUM_ITEMSPACE_AVATAR); | |
} | |
else if (bodyIndex >= 10 && bodyIndex <= 21) { | |
//检查装备 9-56 | |
exchangeEqu(user, 9, 56, bodyIndex, userSuit[bodyIndex], INVENTORY_TYPE.INVENTORY_TYPE_ITEM, ENUM_ITEMSPACE.ENUM_ITEMSPACE_INVENTORY); | |
} else if (bodyIndex == 22) { | |
//检查宠物 0~13 | |
exchangeEqu(user, 0, 13, bodyIndex, userSuit[bodyIndex], INVENTORY_TYPE.INVENTORY_TYPE_CREATURE, ENUM_ITEMSPACE.ENUM_ITEMSPACE_CREATURE); | |
} | |
} | |
} |
深渊奖励(旧)
退出副本后统计奖励
函数
//20240801 by Tim 添加道具 | |
var CUser_AddItem = new NativeFunction(ptr(0x867B6D4), ‘int’, [‘pointer’, ‘int’, ‘int’, ‘int’, ‘pointer’, ‘int’], {“abi”:“sysv”}); | |
//20240801 by Tim 给角色发道具 | |
function api_CUser_AddItem(user, item_id, item_cnt) | |
{ | |
var item_space = Memory.alloc(4); | |
var slot = CUser_AddItem(user, item_id, item_cnt, 6, item_space, 0); | |
if(slot >= 0) | |
{ | |
//通知客户端有游戏道具更新 | |
CUser_SendUpdateItemList(user, 1, item_space.readInt(), slot); | |
} | |
return; | |
} | |
//20240801 by Tim 深渊奖励 | |
var userAddItemCountDic={}; | |
var userDungeonStateDic={}; | |
var awardMessages=[ | |
“『金光三闪闪, 爽!』”, | |
“『史诗四连爆, 赞!』”, | |
“『五彩史诗雨, 强!』”, | |
“『六星连珠现, 牛!』”, | |
“『史诗满屏飞, 逆天啦!』”]; | |
function hook_history_log2() { | |
// cHistoryTrace::operator() | |
Interceptor.attach(ptr(0x854f990), { | |
onEnter: function(args) { | |
// 解析日志内容: “18000008”,18000008,D,145636,”nickname”,1,72,8,0,192.168.200.1,192.168.200.1,50963,11, DungeonLeave,”龍人之塔”,0,0,”aabb”,”aabb”,”N/A”,”N/A”,”N/A” | |
var history_log = args[1].readUtf8String(-1); | |
var group = history_log.split(“,”); | |
// 角色信息 | |
var account_id = parseInt(group[1]); | |
var time_hh_mm_ss = group[3]; | |
var charac_name = group[4]; | |
var charac_no = group[5]; | |
var charac_level = group[6]; | |
var charac_job = group[7]; | |
var charac_growtype = group[8]; | |
var user_web_address = group[9]; | |
var user_peer_ip2 = group[10]; | |
var user_port = group[11]; | |
var channel_index = group[12]; // 当前频道id | |
// 玩家游戏事件 | |
var game_event = group[13].slice(1); // 删除多余空格 | |
var Dungeon_nameget = group[14]; | |
var item_id = parseInt(group[15]); // 本次操作道具id | |
var item_cnt = parseInt(group[17]); // 本次操作道具数量 | |
var reason = parseInt(group[18]); // 本次操作原因 | |
if (game_event) { | |
console.log(‘history_log’, history_log) | |
} | |
// 触发游戏事件的角色 | |
var user = GameWorld_find_user_from_world_byaccid(G_GameWorld(), account_id); | |
if (user.isNull()) { | |
return; | |
} | |
// DungeonLeave离开副本 DungeonEnter进入副本 KillMob杀死怪物 Money+ | |
if(game_event == “DungeonEnter”) | |
{ | |
//进入副本改变状态 | |
userAddItemCountDic[user] = 0; | |
userDungeonStateDic[user] = true; | |
} | |
else if (game_event == “Item+”) { | |
var itemData = CDataManager_find_item(G_CDataManager(), item_id); | |
var needLevel = CItem_getUsableLevel(itemData); // 等级 | |
var inEquRarity = CItem_getRarity(itemData); // 稀有度 | |
// 道具增加: Item+ | |
// reason 4副本内拾取 | inEquRarity 4史诗品级 | |
if (reason == 4 && userDungeonStateDic[user]) { | |
if (inEquRarity == 4) { | |
userAddItemCountDic[user]++; | |
//api_gameWorld_SendNotiPacketMessage(‘玩家[‘ + api_CUserCharacInfo_getCurCharacName(user) + ‘]’ + ‘]在地下城中获得了[‘ + api_CItem_getItemName(item_id) + ‘] x1’, 14); | |
} | |
} | |
} else if (game_event == “DungeonLeave”) { | |
//计算奖励 | |
userDungeonStateDic[user] = false; | |
var addItemCount = userAddItemCountDic[user]; | |
userAddItemCountDic[user] = 0;//清空 | |
if(addItemCount <3){ | |
return ; | |
} | |
//奖励划分 | |
var message=“”; | |
if(addItemCount==3) | |
message=awardMessages[0]; | |
else if (addItemCount==4) | |
message=awardMessages[1]; | |
else if (addItemCount==5) | |
message=awardMessages[2]; | |
else if (addItemCount==6) | |
message=awardMessages[3]; | |
else | |
message=awardMessages[4]; | |
var goldnum=addItemCount-2;//金币 | |
var cashnum=(addItemCount-3)*200+300; | |
api_GameWorld_SendNotiPacketMessage(message + ‘ 玩家[‘ + api_CUserCharacInfo_getCurCharacName(user) + ‘]在地下城中获得了【’ + addItemCount + ‘】个史诗, 奖励:\r\n璀璨水晶x’+addItemCount + ” \r\n100万金币x”+goldnum + ” \r\n”+cashnum+“点券”, 14); | |
api_CUser_AddItem(user,400001000,addItemCount); | |
api_CUser_AddItem(user,3340,goldnum); | |
api_recharge_cash_cera(user,cashnum); | |
} | |
}, | |
onLeave: function(retval) {} | |
}); | |
} |
调用
// 加载主功能 | |
function start() { | |
console.log(‘==========================================================frida start df_game_r.js – dp2.9 start ===========================================================’); | |
hook_history_log2();// 深渊奖励 | |
console.log(‘==========================================================frida start df_game_r.js – dp2.9 end =============================================================’); | |
} |
效果
旧版
新版
超链接消息 – 多表情
根据初六的dp2插件拓展,支持多个表情显示(没怎么测试)
函数
/** | |
* 多表情超链接高亮消息 | |
* @param {*} user 用户 | |
* @param {*} strarr 消息数组【消息类型str/其他,消息,rgba,Symbol】 | |
* @param {*} msgtype 广播类型 | |
//0为上方系统公告栏 | |
//1为下方对话框/绿色 | |
//2为下方对话框/蓝色 | |
//3为下方对话框/白色 | |
//5为下方对话框/白色 | |
//6为下方对话框/紫色 | |
//7为下方对话框/绿色 | |
//8为下方对话框/橙色 | |
//9为下方对话框/蓝色 | |
//10为喇叭,但是会乱码 | |
//11为喇叭 | |
//12为喇叭 | |
//13为喇叭 | |
//14为喇叭 | |
* @param {*} type 发给 1(个人)/0(全部) | |
*/ | |
function api_SendHyperLinkChatMsg_multi_emoji(user, strarr, msgtype, type) { | |
const bufferSize = 255; | |
const strptr = Memory.alloc(bufferSize); | |
let startlen = 0; | |
let cnt = 0; | |
// 准备表情符号数据 | |
const emojiBytes1 = [0xc2, 0x80, 0x20]; | |
strptr.add(startlen).writeByteArray(emojiBytes1); | |
startlen += emojiBytes1.length; | |
// 处理消息字符串数组 | |
for (const item of strarr) { | |
const [strtype, msgContent, flags, symbol] = item; | |
// strptr.add(startlen).writeByteArray([0xc2, 0x80]); | |
// startlen += 2; // 更新起始长度 | |
// 准备表情符号数据 | |
const emojiBytes = symbol >= 1 ? [0xc2, 0x80, 0x20, 0x1e, 0x20, symbol, 0x1f] : [0xc2, 0x80, 0x20]; | |
strptr.add(startlen).writeByteArray(emojiBytes); | |
startlen += emojiBytes.length; | |
const msgstr = (strtype === ‘str’) ? msgContent + ” : ‘[‘ + api_CItem_GetItemName(parseInt(msgContent)) + ‘]’; | |
const str_ptr = Memory.allocUtf8String(msgstr); | |
const str_len = strlen(str_ptr); | |
strptr.add(startlen).writeByteArray(str_ptr.readByteArray(str_len)); | |
startlen += str_len; | |
// 检查是否需要添加额外的字节 | |
if (flags[3] === 255) { | |
strptr.add(startlen).writeByteArray([0xc2, 0x80]); | |
startlen += 2; | |
cnt++; | |
} | |
} | |
// 结束字符串并准备数据包 | |
strptr.add(startlen).writeByteArray([0xc2, 0x80]); | |
startlen += 2; | |
const packet_guard = api_PacketGuard_PacketGuard(); | |
InterfacePacketBuf_put_header(packet_guard, 0, 370); | |
InterfacePacketBuf_put_byte(packet_guard, msgtype); | |
InterfacePacketBuf_put_short(packet_guard, 0); | |
InterfacePacketBuf_put_byte(packet_guard, 0); | |
InterfacePacketBuf_put_int(packet_guard, startlen); | |
InterfacePacketBuf_put_str(packet_guard, strptr, startlen); | |
InterfacePacketBuf_put_byte(packet_guard, cnt); | |
// 处理附加信息 | |
for (const item of strarr) { | |
const [_, msgtype, flags, symbo] = item; | |
if (flags[3] === 255) { | |
const RbgInfoptr = Memory.alloc(104); | |
RbgInfoptr.writeByteArray(flags); | |
// 处理消息类型 | |
if (typeof msgtype === ‘number’) { | |
RbgInfoptr.add(0x4).writeU32(msgtype); | |
const Citem = CDataManager_find_item(G_CDataManager(), msgtype); | |
if (!CItem_is_stackable(Citem)) { | |
RbgInfoptr.add(0x8).writeU32(get_rand_int(0)); | |
RbgInfoptr.add(0xe).writeU16(CEquipItem_get_endurance(Citem)); | |
} | |
} | |
InterfacePacketBuf_put_binary(packet_guard, RbgInfoptr, 104); | |
} | |
} | |
// 完成数据包 | |
InterfacePacketBuf_finalize(packet_guard, 1); | |
// 根据类型发送数据包 | |
if (type === 1) { | |
CUser_SendPacket(user, 1, packet_guard); | |
} | |
else { | |
GameWorld_send_all_with_state(G_GameWorld(), packet_guard, 3); // 只给状态 >= 3 的玩家发送公告 | |
} | |
// 清理数据包 | |
Destroy_PacketGuard_PacketGuard(packet_guard); | |
} |
调用
api_SendHyperLinkChatMsg_multi_emoji(user, [ | |
[‘str’, ‘玩家’, [150, 255, 30, 255], 1], | |
[‘str’, ‘『test』’, [0, 136, 255, 255], 3], | |
[‘str’, ‘爆出’, [150, 255, 30, 255], 32], | |
[‘item’, 3340, [150, 255, 30, 255], 32], | |
], 8, 1); |
效果
字符串转高亮超链接数组
将字符串转化成高亮超链接数组。做了一些限制,其中字符串不能太长,会导致异常(高亮超链接函数那块不会修改)
函数
/** | |
* 将字符串转化成高亮超链接数组 | |
* @param {*} str 字符串 | |
* @param {*} rgba 指定rgba | |
*/ | |
function hyperLinkChatStrConvertArray(str, rgba) { | |
// 如果包含 \r \n \t或空字符串,直接返回一个数组。字符串太长也不行 | |
if (str.includes(‘\r’) || str.includes(‘\n’) || str.includes(‘\t’) || str.includes(‘ ‘) || str.length >= 15) { | |
return [[‘str’, str, rgba]]; | |
} | |
let result = []; | |
for (let i = 0; i < str.length; i++) { | |
// 将字符和rgba值作为一个数组添加到结果数组中 | |
result.push([‘str’, str[i], rgba]); | |
} | |
return result; | |
} |
调用
var array = hyperLinkChatStrConvertArray('完成悬赏任务!', [150, 255, 30, 255])
效果
悬赏功能
悬赏功能为全服共享,以下部分函数,需要搭配
frida_config.json
文件
处理悬赏
/** | |
* 处理悬赏 | |
* | |
* //20241222 by Tim | |
* @param {*} user | |
* @param {*} target_id 目标id (装备id/副本id) | |
* @param {*} type 类型(装备/副本) | |
* @returns | |
*/ | |
function handle_offer_reward_record(user, target_id, type) { | |
//20241222 by Tim 添加悬赏检查 | |
if (!global_config[‘offer_reward’][‘isEnable’]) | |
return; | |
//判断target_id是否存在配置中 | |
var targetlist = global_config[‘offer_reward’][‘target’]; | |
if (!targetlist[” + target_id]) | |
return; | |
var targetInfo = targetlist[” + target_id]; | |
//检查今天是否已存在记录 | |
var today = get_date(); | |
var record = get_offer_reward_record_byItem(target_id, today, type); | |
if (record) | |
return; | |
var des = ”; | |
var targetArray = []; | |
//根据类型显示相关 | |
if (type == ‘equ’) { | |
des = ‘爆出’; | |
targetArray = [‘item’, target_id, getItemRGBAByItemId(target_id)]; | |
} else { | |
des = ‘通关’; | |
targetArray = [‘str’, ‘[‘ + api_CDungeon_getDungeonName(target_id) + ‘]’, [244, 0, 123, 255]]; | |
} | |
var noticeArray = [ | |
[‘str’, ‘玩家’, [150, 255, 30, 255]], | |
[‘str’, ‘『’ + api_CUserCharacInfo_getCurCharacName(user) + ‘』’, [0, 136, 255, 255]], | |
[‘str’, des, [150, 255, 30, 255]], | |
targetArray, | |
…hyperLinkChatStrConvertArray(‘完成悬赏任务!’, [150, 255, 30, 255]) | |
]; | |
var charac_no = CUserCharacInfo_getCurCharacNo(user); | |
//20241225 by Tim 添加特殊称号 | |
if (cidSpecialTitle[charac_no]) | |
noticeArray.splice(1, 0, [‘str’, cidSpecialTitle[charac_no][0], cidSpecialTitle[charac_no][1]]); | |
api_SendHyperLinkChatMsg_emoji(user, noticeArray, 0, 0, 35); | |
//奖励并记录数据库 | |
var rewards = targetInfo.reward; | |
for (let i = 0; i < rewards.length; i++) { | |
const element = rewards[i]; | |
//发送道具到玩家背包 | |
api_CUser_AddItem(user, element[0], element[1]); | |
} | |
api_MySQL_exec(mysql_frida, `insert into offer_reward_record (date, cid, targetid, type) values (‘${today}‘,${charac_no},${target_id},’${type}‘);`); | |
} |
处理悬赏称号
/** | |
* 处理悬赏称号 | |
* | |
* //20241225 by Tim | |
*/ | |
function handle_offer_reward_specialTitle(user) { | |
//20241225 by Tim 添加悬赏结算 | |
var charac_no = CUserCharacInfo_getCurCharacNo(user); | |
var date = addDaysToDate(-1); | |
var offer_reward = global_config[‘offer_reward’]; | |
var completeCount = get_offer_reward_record_byUser(charac_no, date); | |
if (completeCount > 0 && offer_reward[‘titles’][completeCount + ”]) | |
cidSpecialTitle[charac_no] = offer_reward[‘titles’][completeCount + ”]; | |
else | |
cidSpecialTitle[charac_no] = ”; | |
} |
查询悬赏进度
添加到
hook_characterMessageLog
函数中
if (msg == ‘查询悬赏’) { | |
//20241222 by Tim | |
if (!global_config[‘offer_reward’][‘isEnable’]) { | |
api_CUser_SendNotiPacketMessage(user, ” 暂未开通悬赏!”, 8); | |
return; | |
} | |
var isNull = false; | |
var today = get_date(); | |
var record_list = get_offer_reward_record(today); | |
if (!record_list) | |
isNull = true; | |
api_CUser_SendNotiPacketMessage(user, “——————今日悬赏—————–“, 8); | |
var targetlist = global_config[‘offer_reward’][‘target’]; | |
for (const key in targetlist) { | |
if (!targetlist.hasOwnProperty(key)) continue; | |
var targetid = parseInt(key); | |
var status1 = ‘○’;//悬赏状态1 | |
var status2 = ‘『未完成』’;//悬赏状态2 | |
var status2Rgba = [255, 0, 0, 255]; | |
var symbolIndex = 10; | |
if (!isNull) { | |
var record = record_list.find(x => x.targetid == targetid); | |
if (record) { | |
status1 = ‘●’; | |
status2 = ‘『’ + api_get_charac_name_by_charac_no(record.cid) + ‘』’; | |
status2Rgba = [0, 136, 255, 255]; | |
symbolIndex = 31; | |
} | |
} | |
var des = ”;//悬赏前缀说明 | |
var targetArray = [];//存放悬赏目标 | |
//区分equ(装备)和dgn(副本)类型 | |
if (targetlist[key].type != ‘equ’) { | |
des = targetlist[key].des || ‘通关副本’; | |
targetArray = [‘str’, ‘[‘ + api_CDungeon_getDungeonName(targetid) + ‘]’, [244, 0, 123, 255]] | |
} else { | |
des = targetlist[key].des || ‘深渊爆出史诗’; | |
targetArray = [‘item’, targetid, getItemRGBAByItemId(targetid)] | |
} | |
api_SendHyperLinkChatMsg_emoji(user, [ | |
[‘str’, ‘ ‘ + status1 + ‘ ‘, [255, 255, 0, 255]], | |
…hyperLinkChatStrConvertArray(des, [150, 255, 30, 255]), | |
targetArray, | |
[‘str’, ‘ – ‘, [255, 255, 0, 255]], | |
[‘str’, status2, status2Rgba] | |
], 8, 1, symbolIndex); | |
} | |
api_CUser_SendNotiPacketMessage(user, “——————————————“, 8); | |
} |
效果
悬赏任务
称号效果
悬赏通知
配置说明
声明:本站文章素材多源于网络,版权归原作者。 声明中文字加粗部分,仅为突出重点信息展示,无其他特殊含义。任何个人或组织,在未经原版权方及本站许可时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
重要限制:本站素材仅供单机学习交流,请在24小时内删除