/*
文件名:灵魂救赎武器.nut
路径:_DPS_/_BuiltProject/灵魂救赎武器/灵魂救赎武器.nut
创建日期:2026-01-20	19:24
文件用途:
*/

class SoulSalvationC {


    MysqlObject = null;

    //灵魂救赎武器标识 (阶段1)
    Equipment1List = null;
    //1阶段所需灵魂数量
    Stage1SoulCount = 1000;
    //1阶段进阶所需材料
    Equipment1Upgrade = null;
    //灵魂救赎武器标识 (阶段2)
    Equipment2List = null;
    //2阶段所需灵魂数量
    Stage2SoulCount = 100;
    //灵魂救赎武器标识 (阶段3)
    Equipment3List = null;

    //数据
    data = null;

    constructor() {
        Equipment1List = {};
        Equipment1Upgrade = {};
        Equipment2List = {};
        Equipment3List = {};
        data = {};

        //创建数据库
        MysqlObject = Mysql(Str_Ptr("127.0.0.1"), 3306, Str_Ptr("taiwan_cain"), Str_Ptr("game"), Str_Ptr("uu5!^%jg"));
        MysqlObject.Exec_Sql(format("SET NAMES %s", "latin1"));

        local check_table_sql = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'soulsalvation';"
        local Ret = MysqlObject.Select(check_table_sql, ["int"]);
        if (Ret.len() == 0 || Ret[0][0] == 0) {
            local sql = "CREATE TABLE soulsalvation (`uid` INT(11) NOT NULL COMMENT '主键ID',`soul_id` INT(11) NOT NULL DEFAULT 0 COMMENT '灵魂ID', `soul_count` INT(11) NOT NULL DEFAULT 0 COMMENT '数值字段（默认值0）',PRIMARY KEY (`uid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='soulsalvation表';";
            MysqlObject.Exec_Sql(sql);
        }

        //读取PVF
        InitPvf();

        //注册客户端收包
        RegisterClient();

        //读取数据库数据到缓存
        InitMysqlData();

    }

    function RegisterClient() {
        //测试用客户端主动查询灵魂数
        ClientSocketPackFuncMap.rawset(21011001, function(SUser, Jso) {
            local SendInfo = GetUserData(SUser);
            SUser.SendJso({
                op = 21011002,
                Info = SendInfo
            })
        }.bindenv(this));

        Cb_CParty_OnKillMonster_Leave_Func.rawset("SoulSalvationC", function(args) {
            local SUser = User(args[1]);
            //获取佩戴的武器
            local Weapon = GetUserWeapon(SUser);
            local WeaponIndex = Weapon.GetIndex();
            //可积累灵魂数量
            if (Equipment1List.rawin(WeaponIndex) || Equipment2List.rawin(WeaponIndex)) {
                local uuid = Weapon.GetUuid();
                //有数据则+1 无数据则新增
                if (data.rawin(uuid)) {
                    if (data[uuid].soul_count< Stage1SoulCount)
                        data[uuid].soul_count += 1;
                } else {
                    data[uuid] <- {
                        soul_count = 1,
                        soul_id = 0
                    };
                }
                SUser.SendJso({
                    op = 21011004,
                    uuid = uuid,
                    info = data[uuid]
                })
            }
        }.bindenv(this));

        //上线时 获取自己的灵魂武器信息
        Cb_reach_game_world_Func.rawset("SoulSalvationC", function(SUser) {
            local SendInfo = GetUserData(SUser);
            SUser.SendJso({
                op = 21011002,
                Info = SendInfo
            })
        }.bindenv(this));

        //查看他人信息的时候 获取灵魂武器信息
        Cb_GetUserInfo_Leave_Func.rawset("SoulSalvationC", function(args) {
            local SUser = User(args[1])
            local CheckWorldId = NativePointer(args[2]).add(13).readShort();
            local CheckUser = World.GetUserBySession(CheckWorldId);
            if (CheckUser) {
                local SendInfo = GetUserData(CheckUser);
                SUser.SendJso({
                    op = 21011006,
                    Info = SendInfo
                })
            }
        }.bindenv(this));

        //每5分钟固化一次数据到数据库
        Timer.RemoveCronTask("SoulSalvationC");
        Timer.SetCronTask(function() {
            local DataList = [];
            foreach(uuid, value in data) {
                local str = format("(%d,%d,%d),", uuid, value.soul_id, value.soul_count);
                DataList.push(str);
            }
            local sql = "REPLACE INTO soulsalvation (uid, soul_id, soul_count) VALUES";
            foreach(value in DataList) {
                sql += value;
            }
            //去除最后一个,
            sql = sql.slice(0, -1);
            sql += ";";
            MysqlObject.Exec_Sql(sql);
            // }.bindenv(this), {
            //     Cron = "0 */5 * * * *",
            //     Name = "SoulSalvationC"
            // });
        }.bindenv(this), {
            Cron = "*/5 * * * * *",
            Name = "SoulSalvationC"
        });


        ClientSocketPackFuncMap.rawset(21011007, function(SUser, Jso) {
            //获取背包
            local InvenObj = SUser.GetInven();
            //装备ID
            local Id = Jso.item.ItemId;
            //判断是否为灵魂武器一阶段
            if (!Equipment1List.rawin(Id)) {
                SUser.SendJso({
                    op = 21011008,
                    error = 1
                });
                return;
            }

            // //判断灵魂数量是否已经达到要求
            // local SlotItem = InvenObj.GetSlot(Inven.INVENTORY_TYPE_ITEM, 9 + Jso.item.Pos);
            // local uuid = SlotItem.GetUuid();
            // local SoulCount = 0;
            // if(data.rawin(uuid)){
            //     SoulCount = data[uuid].soul_count;
            // }
            // if(SoulCount < Stage1SoulCount){
            //     SUser.SendJso({
            //         op = 21011008,
            //         error = 2
            //     });
            //     return;
            // }


            local MgArr = [];
            foreach(Index, Count in Equipment1Upgrade) {
                //查询自己有多少个道具
                MgArr.push({
                    Item = Index,
                    RealCount = InvenObj.GetCountById(Index),
                    NeedCount = Count.tointeger()
                });
            }
            SUser.SendJso({
                op = 21011008,
                MgInfo = MgArr
            });

        }.bindenv(this));


        ClientSocketPackFuncMap.rawset(21011009, function(SUser, Jso) {
            //获取背包
            local InvenObj = SUser.GetInven();
            //装备ID
            local Id = Jso.item.ItemId;
            //判断是否为灵魂武器一阶段
            if (!Equipment1List.rawin(Id)) {
                SUser.SendJso({
                    op = 21011008,
                    error = 1
                });
                return;
            }
            //要给予的装备ID
            local giveid = Id + 1;

            //获取对应槽位的装备
            local SlotItem = InvenObj.GetSlot(Inven.INVENTORY_TYPE_ITEM, 9 + Jso.item.Pos);
            local uuid = SlotItem.GetUuid();
            if (SlotItem.GetIndex() != Id) {
                SUser.SendNotiBox("          升级失败             升级时请不要操作背包", 1);
                return;
            } else {
                local MgArr = [];
                foreach(Index, Count in Equipment1Upgrade) {
                    //查询自己有多少个道具
                    MgArr.push({
                        Id = Index,
                        Count = Count.tointeger()
                    });
                }

                local Flag = InvenObj.CheckArrItemCount(MgArr);
                if (!Flag) {
                    print("扣除失败");
                    SUser.SendNotiBox("          升级失败             升级时请不要操作背包", 1);
                    return;
                } else {
                    local SlogInfo = SUser.GiveItem(giveid, 1);
                    if (!SlogInfo) {
                        SUser.SendNotiBox("          升级失败             请确定背包有空余空间", 1);
                        return;
                    }
                    local giveItemObj = InvenObj.GetSlot(1, SlogInfo[1])
                    //扣除道具
                    InvenObj.DeleteArrItemCount(MgArr);

                    local forging = SlotItem.GetForging(); //锻造
                    local upgrade = SlotItem.GetUpgrade(); //强化
                    local amplification = SlotItem.GetAmplification(); //增幅
                    local enchanting = SlotItem.GetEnchanting(); //附魔
                    if (forging > 0) {
                        giveItemObj.SetForging(forging);
                    }
                    if (upgrade > 0) {
                        giveItemObj.SetUpgrade(upgrade);
                    }
                    if (amplification != 0) {
                        giveItemObj.SetAmplification(amplification);
                    }
                    giveItemObj.SetEnchanting(enchanting);
                    giveItemObj.SetAdd_Info(SlotItem.GetAdd_Info()); //品级
                    giveItemObj.Flush();

                    //销毁背包中的道具
                    SlotItem.Delete();
                    //刷新玩家背包列表
                    SUser.SendUpdateItemList(1, 0, 9 + Jso.item.Pos);
                    SUser.SendUpdateItemList(1, 0, SlogInfo[1]);

                    //刷新
                    SUser.SendNotiBox("          升级成功", 1);
                    SUser.SendJso({
                        op = 21011010
                    });

                    //从缓存中移除这个uuid
                    data.rawdelete(uuid);
                    local Sql = "DELETE FROM soulsalvation WHERE uid = " + uuid + ";";
                    MysqlObject.Exec_Sql(Sql);
                }
            }
        }.bindenv(this));
    };

    //获取角色的武器
    function GetUserWeapon(SUser) {
        local InvenObj = SUser.GetInven();
        if (!InvenObj) return null;
        return InvenObj.GetSlot(Inven.INVENTORY_TYPE_BODY, 10);
    }

    //获取角色的灵魂武器信息
    function GetUserData(SUser) {
        //获取背包对象
        local InvenObj = SUser.GetInven();
        if (!InvenObj) return {};
        local UUIDList = [];
        //遍历身上
        for (local i = 0; i< 26; i++) {
            local Inven_Item = InvenObj.GetSlot(Inven.INVENTORY_TYPE_BODY, i);
            if (Inven_Item) {
                local Index = Inven_Item.GetIndex();
                if (Equipment1List.rawin(Index) || Equipment2List.rawin(Index)) {
                    local uuid = Inven_Item.GetUuid();
                    UUIDList.push(uuid);
                }
            }
        }
        //遍历物品栏
        for (local i = 0; i< 70; i++) {
            local Inven_Item = InvenObj.GetSlot(Inven.INVENTORY_TYPE_ITEM, i);
            if (Inven_Item) {
                local Index = Inven_Item.GetIndex();
                if (Equipment1List.rawin(Index) || Equipment2List.rawin(Index)) {
                    local uuid = Inven_Item.GetUuid();
                    UUIDList.push(uuid);
                }
            }
        }
        local SendInfo = {};
        foreach(uuid in UUIDList) {
            if (data.rawin(uuid)) {
                SendInfo.rawset(uuid, data[uuid]);
            } else {
                data[uuid] <- {
                    soul_count = 0,
                    soul_id = 0
                };
            }
        }
        return SendInfo;
    }

    function InitPvf() {
        Script();
        ScriptData.GetFileData("etc/rindro/expandequipment/soulsalvation.etc", function(DataTable, Data) {
            while (!Data.Eof()) {
                local Fragment = Data.Get();
                if (Fragment == "[EQUIPMENT1]") {
                    Equipment1List = {};
                    while (true) {
                        local Fbuf = Data.Get();
                        if (Fbuf == "[/EQUIPMENT1]") {
                            break;
                        }
                        Equipment1List.rawset(Fbuf, true);
                    }
                } else if (Fragment == "[EQUIPMENT2]") {
                    Equipment2List = {};
                    while (true) {
                        local Fbuf = Data.Get();
                        if (Fbuf == "[/EQUIPMENT2]") {
                            break;
                        }
                        Equipment2List.rawset(Fbuf, true);
                    }
                } else if (Fragment == "[EQUIPMENT3]") {
                    Equipment3List = {};
                    while (true) {
                        local Fbuf = Data.Get();
                        if (Fbuf == "[/EQUIPMENT3]") {
                            break;
                        }
                        Equipment3List.rawset(Fbuf, true);
                    }
                } else if (Fragment == "[STAGE1 VALUE]") {
                    Stage1SoulCount = Data.Get();
                } else if (Fragment == "[STAGE2 VALUE]") {
                    Stage2SoulCount = Data.Get();
                } else if (Fragment == "[STAGE1 NEED ITEM]") {
                    Equipment1Upgrade = {};
                    while (true) {
                        local Fbuf = Data.Get();
                        if (Fbuf == "[/STAGE1 NEED ITEM]") {
                            break;
                        }
                        Equipment1Upgrade.rawset(Fbuf, Data.Get());
                    }
                }
            }
        }.bindenv(this));
    }

    function InitMysqlData() {
        local Sql = "SELECT * FROM soulsalvation"
        local Ret = MysqlObject.Select(Sql, ["int", "int", "int"]);
        foreach(Row in Ret) {
            local uuid = Row[0];
            local soul_id = Row[1];
            local soul_count = Row[2];
            data.rawset(uuid, {
                soul_id = soul_id,
                soul_count = soul_count
            })
        }
    }
}




Timer.SetTimeOut(function() {

    getroottable()._SoulSalvation_ <- SoulSalvationC();
    print("双端插件·灵魂救赎武器 - 已加载");
}, 1);