diff --git a/MyProject/A.nut b/MyProject/A.nut index 39029b8..6bf7e54 100644 --- a/MyProject/A.nut +++ b/MyProject/A.nut @@ -116,13 +116,11 @@ Gm_InputFunc_Handle["点券"] <- function(SUser, CmdString) { Gm_InputFunc_Handle["test"] <- function(SUser, CmdString) { - SUser.DropItem(26058, 200, 200); - + SUser.SendItemWindowNotification([[33900, 1]]); } - Timer.SetTimeOut(function() { // _Dps_Equ2AvaJewel_Main_() // local Pack = Packet(); diff --git a/_DPS_/FileConfig.json b/_DPS_/FileConfig.json index c6a6a70..e6e9344 100644 --- a/_DPS_/FileConfig.json +++ b/_DPS_/FileConfig.json @@ -142,6 +142,11 @@ "Script": [ "换装系统/换装系统.nut" ] + }, + "偷窃系统": { + "Script": [ + "偷窃系统/偷窃系统.nut" + ] } } } \ No newline at end of file diff --git a/_DPS_/_BuiltProject/偷窃系统/偷窃系统.nut b/_DPS_/_BuiltProject/偷窃系统/偷窃系统.nut new file mode 100644 index 0000000..1346d2e --- /dev/null +++ b/_DPS_/_BuiltProject/偷窃系统/偷窃系统.nut @@ -0,0 +1,375 @@ +/* +File: 偷窃系统.nut +Path: _DPS_/_BuiltProject/偷窃系统/偷窃系统.nut +*/ + +class StealSystem { + + RandomCountMin = 0; + RandomCountMax = 0; + NpcConfig = null; + RequestCache = null; + Loaded = false; + UseItem = null; + + constructor() { + NpcConfig = {}; + RequestCache = {}; + Loaded = InitPvf(); + if (Loaded) { + RegisterClient(); + InitDailyResetTask(); + } + } + + function RegisterClient() { + ClientSocketPackFuncMap.rawset(21017001, function(SUser, Jso) { + local ret = false; + local npcId = null; + try { + npcId = Jso.npcid; + } catch (exception) { + npcId = null; + } + + local cid = SUser.GetCID(); + if (typeof npcId == "integer" && NpcConfig.rawin(npcId)) { + if (!RequestCache.rawin(cid)) { + RequestCache[cid] <- {}; + } + if (!RequestCache[cid].rawin(npcId)) { + ret = true; + } else { + SUser.SendNotiBox(" 偷窃失败 今日已对该他实施过偷窃", 1); + SUser.SendJso({ + op = 21017002, + ret = ret + }); + return; + } + } else { + print("StealSystem: 21017001 invalid npcid."); + SUser.SendJso({ + op = 21017002, + ret = ret + }); + return; + } + + local InvenObj = SUser.GetInven(); + local itemSlot = InvenObj.GetSlotById(UseItem); + if (itemSlot == -1) { + ret = false; + SUser.SendNotiBox(" 偷窃失败 您没有该偷窃消耗物品!", 1); + SUser.SendJso({ + op = 21017002, + ret = ret + }); + return; + } else if (!InvenObj.DeleteItemCount(UseItem, 1)) { + ret = false; + SUser.SendJso({ + op = 21017002, + ret = ret + }); + return; + } + + if (ret) { + RequestCache[cid].rawset(npcId, 1); + } + + SUser.SendJso({ + op = 21017002, + ret = ret + }); + + }.bindenv(this)); + + ClientSocketPackFuncMap.rawset(21017003, function(SUser, Jso) { + local npcId = null; + try { + npcId = Jso.npcid; + } catch (exception) { + npcId = null; + } + if (typeof npcId != "integer") { + print("StealSystem: 21017003 invalid npcid."); + return; + } + + local cid = SUser.GetCID(); + if (!RequestCache.rawin(cid) || !RequestCache[cid].rawin(npcId) || RequestCache[cid][npcId] != 1) { + print(format("StealSystem: 21017003 denied for cid=%d npc=%d because 21017001 is not passed.", cid, npcId)); + return; + } + if (!NpcConfig.rawin(npcId)) { + print(format("StealSystem: 21017003 npc config not found for npc=%d.", npcId)); + return; + } + + local groupName = GetRandomGroupName(); + local groupData = NpcConfig[npcId][groupName]; + if (groupData.len() == 0) { + print(format("StealSystem: 21017003 npc=%d picked empty group %s.", npcId, groupName)); + return; + } + + local drawCount = MathClass.Rand(RandomCountMin, RandomCountMax); + if (drawCount <= 0) { + print(format("StealSystem: 21017003 draw count <= 0 for npc=%d.", npcId)); + return; + } + + local rewardMap = BuildRewardMap(groupData, drawCount); + if (!rewardMap) { + print(format("StealSystem: 21017003 failed to build rewards for npc=%d group=%s.", npcId, groupName)); + return; + } + + if (!GiveRewardMap(SUser, rewardMap)) { + print(format("StealSystem: 21017003 failed to give rewards for cid=%d npc=%d.", cid, npcId)); + return; + } + + local notiadd = []; + foreach(Index, Count in rewardMap) { + notiadd.append([Index, Count]); + } + SUser.SendItemWindowNotification(notiadd); + + RequestCache[cid].rawset(npcId, 2); + }.bindenv(this)); + } + + function InitDailyResetTask() { + Timer.RemoveCronTask("StealSystemDailyReset"); + Timer.SetCronTask(function() { + RequestCache = {}; + print("StealSystem: daily request cache reset."); + }.bindenv(this), { + Cron = "0 0 6 * * *", + Name = "StealSystemDailyReset" + }); + } + + function ParseRewardGroup(Data, CloseTag, OutList, Path, NpcId, GroupName) { + while (true) { + local first = Data.Get(); + if (first == CloseTag) { + return true; + } + if (Data.Eof()) { + print(format("StealSystem: npc %d %s block missing close tag %s in %s.", NpcId, GroupName, CloseTag, Path)); + return false; + } + + local second = Data.Get(); + if (Data.Eof()) { + print(format("StealSystem: npc %d %s block has incomplete entry in %s.", NpcId, GroupName, Path)); + return false; + } + local third = Data.Get(); + + if (typeof first != "integer" || typeof second != "integer" || typeof third != "integer") { + print(format("StealSystem: npc %d %s block has non-integer entry in %s.", NpcId, GroupName, Path)); + return false; + } + + OutList.append({ + item = first, + rate = second, + count = third + }); + } + return false; + } + + function GetRandomGroupName() { + local groupNames = ["normal", "rarity", "epic"]; + return groupNames[MathClass.Rand(0, groupNames.len() - 1)]; + } + + function RollRewardFromGroup(GroupData) { + local totalRate = 0; + foreach(_idx, info in GroupData) { + if (info.rate > 0) { + totalRate += info.rate; + } + } + if (totalRate <= 0) { + return null; + } + + local randNum = MathClass.Rand(0, totalRate); + foreach(_idx, info in GroupData) { + if (info.rate <= 0) { + continue; + } + if (randNum< info.rate) { + return info; + } + randNum -= info.rate; + } + return GroupData[GroupData.len() - 1]; + } + + function BuildRewardMap(GroupData, DrawCount) { + local rewardMap = {}; + for (local i = 0; i< DrawCount; i++) { + local rewardInfo = RollRewardFromGroup(GroupData); + if (!rewardInfo) { + return null; + } + if (!rewardMap.rawin(rewardInfo.item)) { + rewardMap[rewardInfo.item] <- 0; + } + rewardMap[rewardInfo.item] += rewardInfo.count; + } + return rewardMap; + } + + function GiveRewardMap(SUser, RewardMap) { + foreach(itemId, itemCount in RewardMap) { + if (itemCount <= 0) { + continue; + } + local giveRet = SUser.GiveItem(itemId, itemCount); + if (!giveRet) { + return false; + } + } + return true; + } + + function LoadNpcConfig(NpcId) { + local path = format("etc/stealconfig/%d.etc", NpcId); + local parseFailed = false; + local foundNormal = false; + local foundRarity = false; + local foundEpic = false; + + local config = ScriptData.GetFileData(path, function(DataTable, Data) { + DataTable.normal <- []; + DataTable.rarity <- []; + DataTable.epic <- []; + + while (!Data.Eof()) { + local fragment = Data.Get(); + if (fragment == "[normal]") { + foundNormal = true; + if (!ParseRewardGroup(Data, "[/normal]", DataTable.normal, path, NpcId, "normal")) { + parseFailed = true; + return; + } + } else if (fragment == "[rarity]") { + foundRarity = true; + if (!ParseRewardGroup(Data, "[/rarity]", DataTable.rarity, path, NpcId, "rarity")) { + parseFailed = true; + return; + } + } else if (fragment == "[epic]") { + foundEpic = true; + if (!ParseRewardGroup(Data, "[/epic]", DataTable.epic, path, NpcId, "epic")) { + parseFailed = true; + return; + } + } + } + }.bindenv(this)); + + if (!config) { + print(format("StealSystem: npc %d config file not found: %s.", NpcId, path)); + return null; + } + if (parseFailed) { + return null; + } + if (!foundNormal || !foundRarity || !foundEpic) { + print(format("StealSystem: npc %d config missing required tags in %s.", NpcId, path)); + return null; + } + return config; + } + + function InitPvf() { + Script(); + local foundRandomCount = false; + local foundNpcTag = false; + local parseFailed = false; + local minCount = 0; + local maxCount = 0; + local npcList = []; + + local fileData = ScriptData.GetFileData("etc/steal.etc", function(_n, Data) { + while (!Data.Eof()) { + local fragment = Data.Get(); + if (fragment == "[random count]") { + local minValue = Data.Get(); + local maxValue = Data.Get(); + if (minValue > maxValue) { + print("StealSystem: [random count] min is greater than max in etc/steal.etc."); + parseFailed = true; + return; + } + minCount = minValue; + maxCount = maxValue; + foundRandomCount = true; + } else if (fragment == "[use item]") { + UseItem = Data.Get(); + } else { + foundNpcTag = true; + while (true) { + local npcId = Data.Get(); + if (npcId == "[/npc list]") { + break; + } + if (Data.Eof()) { + print("StealSystem: [npc list] block missing [/npc list] in etc/steal.etc."); + parseFailed = true; + return; + } + if (typeof npcId != "integer") { + print("StealSystem: [npc] contains non-integer npc id in etc/steal.etc."); + parseFailed = true; + return; + } + npcList.append(npcId); + } + } + } + }.bindenv(this)); + + if (!fileData) { + print("StealSystem: failed to load etc/steal.etc."); + return false; + } + if (parseFailed) { + return false; + } + RandomCountMin = minCount; + RandomCountMax = maxCount; + NpcConfig = {}; + + foreach(_idx, npcId in npcList) { + local npcConfig = LoadNpcConfig(npcId); + if (!npcConfig) { + print(format("StealSystem: skip npc %d due to invalid config.", npcId)); + continue; + } + NpcConfig.rawset(npcId, npcConfig); + } + + return true; + } +} + + +Timer.SetTimeOut(function() { + local stealSystem = StealSystem(); + if (!stealSystem.Loaded) { + print("StealSystem: initialization failed, object not registered."); + return; + } + getroottable()._StealSystem_ <- stealSystem; +}, 1); diff --git a/_DPS_/_Core/BaseClass/ScriptManager/ScriptManager.nut b/_DPS_/_Core/BaseClass/ScriptManager/ScriptManager.nut index f02fddc..071ad83 100644 --- a/_DPS_/_Core/BaseClass/ScriptManager/ScriptManager.nut +++ b/_DPS_/_Core/BaseClass/ScriptManager/ScriptManager.nut @@ -63,40 +63,38 @@ class _PVF_Data_ { function Last() { if (Pos > 0) { Pos--; - return Get(); + return Data[Pos]; } return null; } function Seek(i) { - if (Pos > 0 && Pos<(Max - 1)) { - Pos = i; - } + if (i < 0) + i = 0; + else if (i > Max) + i = Max; + Pos = i; } function Seekg(i) { - Pos += i; + Seek(Pos + i); } function Get() { - local Ret = Data[Pos]; - if (Pos<(Max - 1)) { - Pos++; + if (Pos >= Max) { + return null; } + local Ret = Data[Pos]; + Pos++; return Ret; } function Eof() { - if (Pos == Max - 1) - return true; + return Pos >= Max; } function Next() { - if (Pos<(Max - 1)) { - Pos++; - return Get(); - } - return null; + return Get(); } } @@ -217,4 +215,4 @@ class GlobaData { } } -getroottable().ScriptData <- GlobaData(); \ No newline at end of file +getroottable().ScriptData <- GlobaData(); diff --git a/_DPS_/_Core/CallBack/Use_Item_Sp.nut b/_DPS_/_Core/CallBack/Use_Item_Sp.nut index 585d8cd..b7520fb 100644 --- a/_DPS_/_Core/CallBack/Use_Item_Sp.nut +++ b/_DPS_/_Core/CallBack/Use_Item_Sp.nut @@ -22,7 +22,9 @@ Cb_History_ItemDown_Func["UseSharedEffectItem"] <- function(SUser, Data) { local ItemId = Data[15].tointeger(); if (ItemId in Cb_Use_Item_Sp_Func) { if (SUser) { - Cb_Use_Item_Sp_Func[ItemId](SUser, ItemId); + Timer.SetTimeOut(function() { + Cb_Use_Item_Sp_Func[ItemId](SUser, ItemId); + }, 1); } } }