395 lines
13 KiB
Plaintext
395 lines
13 KiB
Plaintext
/*
|
|
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));
|
|
|
|
|
|
ClientSocketPackFuncMap.rawset(21017005, function(SUser, Jso) {
|
|
local InvenObj = SUser.GetInven();
|
|
local itemSlot = InvenObj.GetSlotById(UseItem);
|
|
if (itemSlot == -1) {
|
|
SUser.SendJso({
|
|
op = 21017006,
|
|
ret = false
|
|
});
|
|
return;
|
|
}
|
|
else{
|
|
InvenObj.DeleteItemCount(UseItem, 1);
|
|
SUser.SendNotiPacketMessage("密码错误,已消耗一个材料!", 8);
|
|
}
|
|
|
|
}.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())];
|
|
}
|
|
|
|
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();
|
|
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);
|