feat(偷窃系统): 添加新的偷窃系统功能
- 在FileConfig.json中添加偷窃系统配置 - 实现偷窃系统核心逻辑,包括物品消耗、奖励随机获取和每日重置 - 优化_PVF_Data_类的Seek和Get方法 - 修改Use_Item_Sp.nut中的回调函数为异步执行 - 更新测试命令功能,替换物品掉落为窗口通知
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -142,6 +142,11 @@
|
||||
"Script": [
|
||||
"换装系统/换装系统.nut"
|
||||
]
|
||||
},
|
||||
"偷窃系统": {
|
||||
"Script": [
|
||||
"偷窃系统/偷窃系统.nut"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
375
_DPS_/_BuiltProject/偷窃系统/偷窃系统.nut
Normal file
375
_DPS_/_BuiltProject/偷窃系统/偷窃系统.nut
Normal file
@@ -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);
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user