/* 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 if (fragment == "[npc list]") { foundNpcTag = true; while (true) { local npcId = Data.Get(); print(npcId) 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; print("偷窃系统 - 已加载"); }, 1);