/*
文件名: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();