/* 文件名:NpcTransaction.nut 路径:Dps_A/ProjectClass/NpcTransaction/NpcTransaction.nut 创建日期:2025-10-23 14:37 文件用途: */ return; class NpcTransaction { //装备价值 EquValue = null; //品级装备组 EquGroup = null; //金币易物浮动比例 GoldFloat = 0.5; //最低交换品级 MinRarity = 0; //交易消耗物品 TradeItem = null; //装备易物浮动等级 EquFloatMin = 5; EquFloatMax = 5; //事件概率 EventRate = null; //用户状态表 UserState = null; constructor() { //注册客户端收包 RegisterClient(); EquValue = {}; UserState = {}; EquGroup = [{}, {}, {}, {}, {}, {}, {}, {}]; //读取PVF InitPvf(); } function RegisterClient() { ClientSocketPackFuncMap.rawset(21005001, function(SUser, Jso) { local lastTime = GetTransactionInfo(SUser, Jso); if (lastTime && Sq_GetTimestampString().slice(-9).tointeger() - lastTime.time< 3600000) { local T = { op = 21005002, flag = 3 } SUser.SendJso(T); return; } local InvenObj = SUser.GetInven(); local Equ = InvenObj.GetSlot(Inven.INVENTORY_TYPE_ITEM, 9 + Jso.pos); if (Equ) { local EquId = Equ.GetIndex(); if (EquId) { local equ = PvfItem.GetPvfItemById(EquId); local Rarity = equ.GetRarity(); local Level = equ.GetUsableLevel(); //判断是否解封装 local CanTrade = GetTrade(InvenObj, Jso.pos); if ((Rarity == 2 || Rarity == 3) && CanTrade == 1) { local T = { op = 21005006, } SUser.SendJso(T); SUser.SendNotiPacketMessage("该装备属于封装装备,并已解封,无法进行交易!", 0); } else { //判断是进行什么交易逻辑 local Random = MathClass.Rand(600, 1000); //嘲讽 if (Random <= EventRate[0]) { local T = { op = 21005002, flag = 0 } SUser.SendJso(T); local Cid = SUser.GetCID(); if (!UserState.rawin(Cid)) UserState[Cid] <- {}; UserState[Cid].rawset(Jso.npc, { time = Sq_GetTimestampString().slice(-9).tointeger() }); } //金币易物 else if (Random <= EventRate[1]) { local thGoldFloat = MathClass.Rand(-EquValue[EquId].tofloat() * GoldFloat, EquValue[EquId].tofloat() * GoldFloat); local Glod = EquValue[EquId].tofloat() + thGoldFloat; local T = { op = 21005002, flag = 1, glod = Glod } SUser.SendJso(T); local Cid = SUser.GetCID(); if (!UserState.rawin(Cid)) UserState[Cid] <- {}; UserState[Cid].rawset(Jso.npc, { glod = Glod, pos = Jso.pos, oldid = EquId time = Sq_GetTimestampString().slice(-9).tointeger() }); } //装备易物 else if (Random <= EventRate[2]) { local setarr = []; local findtable = EquGroup[Rarity]; foreach(index, level in findtable) { if (level >= Level - EquFloatMin && level <= Level + EquFloatMax) { setarr.append(index); } } local SendId = setarr[MathClass.Rand(0, setarr.len() - 1)]; local T = { op = 21005002, flag = 2, equ = SendId } SUser.SendJso(T); local Cid = SUser.GetCID(); if (!UserState.rawin(Cid)) UserState[Cid] <- {}; UserState[Cid].rawset(Jso.npc, { equ = SendId, pos = Jso.pos, oldid = EquId time = Sq_GetTimestampString().slice(-9).tointeger() }); } } } } }.bindenv(this)); ClientSocketPackFuncMap.rawset(21005003, function(SUser, Jso) { //获取交易结构体 local Info = GetTransactionInfo(SUser, Jso); if (!Info) return; //获取旧装备ID local oldid = Info.oldid; //获取旧装备格子 local pos = Info.pos; //检测扣除 local InvenObj = SUser.GetInven(); local Equ = InvenObj.GetSlot(Inven.INVENTORY_TYPE_ITEM, 9 + Info.pos); if (Equ.GetIndex() != oldid) { SUser.SendNotiBox("交易时请不要移动背包中装备的位置!", 1); return; } Equ.Delete(); if (Info.rawin("equ")) { SUser.GiveItem(Info.equ, 1); SUser.SendNotiBox("与NPC交易获得装备 [" + PvfItem.GetNameById(Info.equ) + "]", 1); } else if (Info.rawin("glod")) { SUser.RechargeMoney(Info.glod); SUser.SendNotiBox("与NPC交易获得金币: " + Info.glod, 1); } SUser.SendItemSpace(0); }.bindenv(this)); } function GetTransactionInfo(SUser, Jso) { try { local Info = UserState[SUser.GetCID()][Jso.npc]; return Info; } catch (exception) {} return null; } function InitPvf() { Script(); ScriptData.GetFileData("etc/rindro/npctransaction/npctransaction.etc", function(DataTable, Data) { while (!Data.Eof()) { local Fragment = Data.Get(); if (Fragment == "[value]") { while (true) { local Fbuf = Data.Get(); if (Fbuf == "[/value]") { break; } local Value = Data.Get(); EquValue.rawset(Fbuf, Value); //读取装备品级 local equ = PvfItem.GetPvfItemById(Fbuf); local Rarity = equ.GetRarity(); local Level = equ.GetUsableLevel(); EquGroup[Rarity].rawset(Fbuf, Level); } } else if (Fragment == "[random]") { GoldFloat = Data.Get().tofloat() / 100.0; } else if (Fragment == "[allow rarity]") { MinRarity = Data.Get(); } else if (Fragment == "[exchange cost item]") { TradeItem = { item = Data.Get(), count = Data.Get() } } else if (Fragment == "[equipment random level lower]") { EquFloatMin = Data.Get(); } else if (Fragment == "[equipment random level upper]") { EquFloatMax = Data.Get(); } else if (Fragment == "[event rate]") { local o1 = Data.Get(); local o2 = Data.Get(); local o3 = Data.Get(); EventRate = [o1, o1 + o2, o1 + o2 + o3]; } } }.bindenv(this)); } function GetTrade(InvenObj, pos) { local ptr = Memory.alloc(10240); Sq_CallFunc(S_Ptr("0x084FB918"), "int", ["pointer", "pointer", "int", "int"], ptr.C_Object, InvenObj.C_Object, 1, pos); return ptr.readS8(); } } ProjectInitFuncMap.P_NpcTransaction <- NpcTransaction();