站在了巨人的肩膀头上,感谢造轮子的大佬。根据自己的喜好进行了修改 自用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小时内删除























![严选手游[精品推荐]](https://vip.gmdnf.com/wp-content/uploads/2024/07/60.png)
![折扣手游[0.1折]](https://vip.gmdnf.com/wp-content/uploads/2024/07/196.png)











