This commit is contained in:
2025-03-23 10:51:55 +00:00
commit f11a45c8f9
94 changed files with 5026 additions and 0 deletions

26
Start/1.md Normal file
View File

@@ -0,0 +1,26 @@
> 第一步下载程序本体
![Alt text](../image/1.png)
> 第二步解压至服务器根目录
![Alt text](../image/2.png)
> 第三步创建Main.nut文件
![Alt text](../image/3.png)
> 第四步在Main.nut中写入以下代码
```
print("DP-S插件已加载");
```
![Alt text](../image/4.png)
> 第五步更改服务端run脚本
![Alt text](../image/5.png)
```LD_PRELOAD="/dp_s/lib/libAurora.so" ./df_game_r siroco15 start &```
自行将siroco15替换为你的频道

73
Start/Example/1.md Normal file
View File

@@ -0,0 +1,73 @@
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 ForgingEnhancement.nut 用于编写我们的代码
![Alt text](../../image/7.png)
> 然后我们在ForgeEnhancement.nut中写入以下代码
```
ForgingEnhancementStr1 <- "装备栏1号位没有装备.."
ForgingEnhancementStr2 <- "锻造成功,当前武器锻造[+%d]"
ForgingEnhancementStr3 <- "锻造失败,当前武器锻造[+%d]"
ForgingEnhancementStr4 <- "装备锻造等级已为最高等级,无法继续锻造.."
ForgingEnhancementMaxForgingLevel <- 31
Cb_Use_Item_Sp_Func[7577] <- function(SUser, ItemId) {
//定义锻造成功率
local DLevel = 60;
//获取玩家背包
local InvenObj = SUser.GetInven();
//如果背包存在
if (InvenObj) {
//获取玩家背包类型1的第9个格子
local ItemObj = InvenObj.GetSlot(1, 9);
//空装备
if (ItemObj.IsEmpty) {
//发送通知
SUser.SendNotiPacketMessage(ForgingEnhancementStr1, 8);
//返还消耗的道具
SUser.GiveItem(ItemId, 1);
return;
}
//获取原装备的锻造等级
local OldLevel = ItemObj.GetForging();
//判断锻造等级是否大于设定的最大等级
if (OldLevel >= ForgingEnhancementMaxForgingLevel) {
//发送通知
SUser.SendNotiPacketMessage(ForgingEnhancementStr4, 8);
//返还消耗的道具
SUser.GiveItem(ItemId, 1);
return;
}
//获得0-100的随机数
local RandNum = MathClass.Rand(0, 100);
//判断随机数是否小于设定的几率
if (RandNum <= DLevel) {
//将装备的锻造等级+1
ItemObj.SetForging(OldLevel + 1);
//刷写装备
ItemObj.Flush();
//刷新玩家背包
SUser.SendUpdateItemList(1, 0, 9);
//发送通知
SUser.SendNotiPacketMessage(format(ForgingEnhancementStr2, (OldLevel + 1)), 8);
} else {
//发送通知
SUser.SendNotiPacketMessage(format(ForgingEnhancementStr3, OldLevel), 8);
}
}
}
```
![Alt text](../../image/8.png)
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/ForgingEnhancement.nut");
```
![Alt text](../../image/9.png)
> 至此一个简单的锻造提升卷的逻辑就写完了,然后我们就可以在游戏中使用道具来提升武器锻造等级了

140
Start/Example/10.md Normal file
View File

@@ -0,0 +1,140 @@
## 任务清理券大全 (贡献者: X)
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 任务清理券大全.nut 用于编写我们的代码
![Alt text](../../image/31.png)
> 然后我们在任务清理券大全.nut中写入以下代码
```
//使用本功能需要群文件内233.dll插件用来弹窗提示用户如果不需要233插件请将SUser.SendNotiBox("这里写提示文字",1);修改为SUser.SendNotiPacketMessage("这里写提示文字", 8);
//数字11111代表你的主线任务清理券在pvf中的id下面同样修改为你的pvf内的文件id即可。
//如有疑问 群内询问
//主线任务清理券
Cb_Use_Item_Sp_Func[2021458802] <- function(SUser, ItemId) {
pdrw(SUser,ItemId,0,null);
};
//支线/普通任务清理券(会清掉副职业/转职任务这里添加了跳过副职业的任务ID
Cb_Use_Item_Sp_Func[11111] <- function(SUser, ItemId) {
local QuestArray =[2702,2708,2710,2712];
pdrw(SUser,ItemId,5,QuestArray);
};
//每日任务清理券
Cb_Use_Item_Sp_Func[22222] <- function(SUser, ItemId) {
pdrw(SUser,ItemId,3,null);
};
//成就任务清理券会清掉觉醒任务自行添加需要屏蔽的ID
Cb_Use_Item_Sp_Func[3333] <- function(SUser, ItemId) {
pdrw(SUser,ItemId,2,null);
};
//修炼任务清理券
Cb_Use_Item_Sp_Func[6666] <- function(SUser, ItemId) {
pdrw(SUser,ItemId,1,null);
};
//Tag:int型传递一个标记来表示本次完成哪种类型的任务0=主线5=普通/副职业/转职1=修炼3=每日/活动2=觉醒/成就)
//QuestArray一个包含int型的数组数组内是要过滤掉的任务ID。举例 local QuestArray = [1244],如果不需要过滤任务直接传null
function pdrw(SUser, ItemId,Tag,QuestArray){
local QuestArray = QuestArray;
//获取角色任务信息
local userQuest = SUser.GetQuest();
//当前角色已完成的任务
local questIsClear = NativePointer(userQuest).add(4);
//获取角色等级
local characLevel = SUser.GetCharacLevel();
//统计要完成的任务数量
local allClearQuest = 0;
//获取pvf数据
local DataManager = Sq_CallFunc(S_Ptr("0x80CC19B"), "pointer");
//清空已接任务
for(local i=0; i<20; i++) {
local a = NativePointer(userQuest).add(4 * (i + 7500 + 2)).readInt();
SUser.ClearQuest_Gm(a);
}
//循环开始清理
for(local questID = 1; questID < 30000; questID++){
//判断下不需要自动完成的任务数组,包含就跳过
if(QuestArray!=null){
if(QuestArray.find(questID)!=null){continue;};
}
//判断当前任务是否已经完成questID=任务ID;
local isClear = Sq_CallFunc(S_Ptr("0x808BAE0"),"bool",["pointer","int"],questIsClear.C_Object,questID);
//此任务已清理,跳过
if(isClear){continue;};
//从pvf中获取任务数据 questID=任务ID
local pvfQuest = Sq_CallFunc(S_Ptr("0x835FDC6"), "pointer", ["pointer", "int"],DataManager,questID );
if(pvfQuest){
//获取任务类型0=主线5=普通/副职业/转职1=修炼3=每日/活动2=觉醒/成就
local questGrade = NativePointer(pvfQuest).add(8).readInt();
if(questGrade == Tag){
//获取任务的级别
local questLv = NativePointer(pvfQuest).add(0x20).readInt();
if(questLv<=characLevel){
//将该任务设置为已完成状态
Sq_CallFunc(S_Ptr("0x808BA78"), "int", ["pointer", "int"], questIsClear.C_Object,questID);
allClearQuest++;
};
};
};
};
//已清理了0个以上的任务
if(allClearQuest>0){
//通知客户端刷新任务列表
local Pack = Packet();
Sq_CallFunc(S_Ptr("0x86ABBA8"), "int", ["pointer", "pointer"], userQuest, Pack.C_Object);
SUser.Send(Pack);
Pack.Delete();
SUser.SendNotiBox("已清理任务共 "+allClearQuest+" 个",1);
}else{
SUser.SendNotiBox("无任务需要清理",1);
SUser.GiveItem(ItemId, 1);
}
}
```
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/任务清理券大全.nut");
```
> 至此一个简单的任务清理券大全的逻辑就写完了

84
Start/Example/11.md Normal file
View File

@@ -0,0 +1,84 @@
## 通关时间播报 (贡献者: 邪神)
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 通关时间播报.nut 用于编写我们的代码
> 然后我们在通关时间播报.nut中写入以下代码
```
//贡献者: 邪神
ClearTimeMsg <- "玩家[%s]通关<%s>[%s]耗时:[%s]";
//难度对应难度名称
dungeon_diff_Map <- {
"0": "普通级",
"1": "冒险级",
"2": "王者级",
"3": "地狱级",
"4": "英雄级"
};
//通关时间回调
Cb_CParty_SetBestClearTime_Enter_Func.ClearTime <- function(args) {
local PartyObj = Party(args[0]);
local dungeon_diff = args[2];
local clearTime = args[3];
local Bfobj = PartyObj.GetBattleField();
local DgnObj = Bfobj.GetDgn();
local Dungeon_Name = DgnObj.GetName();
local diff_name = dungeon_diff_Map[(dungeon_diff).tostring()];
local MemberNames = [];
for (local i = 0; i < 4; ++i) {
local SUser = PartyObj.GetUser(i);
if (SUser) {
local name = SUser.GetCharacName();
MemberNames.push(name);
}
}
local joinedNames = join(MemberNames, ", ");
local time = formatMilliseconds(clearTime);
World.SendNotiPacketMessage(format(ClearTimeMsg, joinedNames, diff_name, Dungeon_Name, time), 0);
}
function join(array, delimiter) {
local result = "";
for (local i = 0; i < array.len(); ++i) {
if (i > 0) {
result += delimiter;
}
result += array[i];
}
return result;
}
//毫秒转换
function formatMilliseconds(ms) {
local str = "";
local minutes = ms / 60000;
local seconds = (ms % 60000) / 1000;
local milliseconds = (ms % 1000) / 10;
if (minutes > 0) {
str = minutes + "分" +
(seconds < 10 ? "0" : "") + seconds + "秒" +
(milliseconds < 10 ? "0" : "") + milliseconds;
} else {
str = seconds + "秒" +
(milliseconds < 10 ? "0" : "") + milliseconds;
}
return str;
}
```
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/通关时间播报.nut");
```
> 至此一个简单的通关时间播报的逻辑就写完了

66
Start/Example/12.md Normal file
View File

@@ -0,0 +1,66 @@
## 在线泡点 (贡献者: 邪神)
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 在线泡点.nut 用于编写我们的代码
> 然后我们在在线泡点.nut中写入以下代码
```
//贡献者: 邪神
//tips发放点券或代表可在配置中填写数值如两个选项都填写大于0的数值则点券代币都会发放如填写0则不会发放
RewardCera <- 0; // 每分钟XX点券
RewardCeraPoint <- 10; // 每分钟XX代币
total_cera_reward <- {}; // 存储每个玩家的累计点券奖励
total_ceraPoint_reward <- {}; // 存储每个玩家的累计代币奖励
function Online_rewards() {
local OnlinePlayerList = World.GetOnlinePlayer();
foreach(SUser in OnlinePlayerList) {
// 点券奖励处理
if (RewardCera > 0) {
if (!(SUser.GetUID() in total_cera_reward)) {
total_cera_reward[SUser.GetUID()] <- 0;
}
total_cera_reward[SUser.GetUID()] += RewardCera;
SUser.SendNotiPacketMessage("活跃奖励获得: " + RewardCera + "点券, 累计获得: " + total_cera_reward[SUser.GetUID()] + "点券", 14);
SUser.RechargeCera(RewardCera);
}
// 代币奖励处理
if (RewardCeraPoint > 0) {
if (!(SUser.GetUID() in total_ceraPoint_reward)) {
total_ceraPoint_reward[SUser.GetUID()] <- 0;
}
total_ceraPoint_reward[SUser.GetUID()] += RewardCeraPoint;
SUser.SendNotiPacketMessage("活跃奖励获得: " + RewardCeraPoint + "代币, 累计获得: " + total_ceraPoint_reward[SUser.GetUID()] + "代币", 14);
SUser.RechargeCeraPoint(RewardCeraPoint);
}
}
}
//默认为1分钟发放一次泡点
Timer.SetCronTask(function() {
Online_rewards();
}, "/1 * * * *");
```
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/在线泡点.nut");
```
> 至此一个简单的在线泡点的逻辑就写完了

33
Start/Example/13.md Normal file
View File

@@ -0,0 +1,33 @@
## 副本难度解锁 (贡献者: 邪神)
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 副本难度解锁.nut 用于编写我们的代码
> 然后我们在副本难度解锁.nut中写入以下代码
```
UnlockDGndiff_itemId <- 202203296 //副本难度解锁券道具ID
Cb_Use_Item_Sp_Func[UnlockDGndiff_itemId] <- function(SUser, ItemId) {
local a3 = Memory.allocUtf8String("3");
Sq_CallFunc(S_Ptr("0x0820BA90"), "int", ["pointer", "int", "pointer"], SUser.C_Object, 120, a3.C_Object);
Timer.SetTimeOut(function(SUser) {
Sq_CallFunc(S_Ptr("0x8686FEE"), "int", ["pointer", "int"], SUser.C_Object, 1);
}, 1, SUser);
}
```
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/副本难度解锁.nut");
```
> 至此一个简单的副本难度解锁的逻辑就写完了

22
Start/Example/14.md Normal file
View File

@@ -0,0 +1,22 @@
## 反外挂制裁 (贡献者: 邪神)
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 反外挂代码涉及逻辑不方便公开,以免被开挂者洞悉,请去群内下载加密文件直接加载
```
```
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/反外挂制裁.sut");
```
> 至此一个简单的反外挂制裁的逻辑就写完了

615
Start/Example/15.md Normal file
View File

@@ -0,0 +1,615 @@
## 装备镶嵌与时装镶嵌 (贡献者: 倾泪寒)
> 如果你不需要更改装备和时装镶嵌的逻辑则不需要添加 这个文件 直接去使用GameManager的接口即可
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 装备镶嵌与时装镶嵌.nut 用于编写我们的代码
> 然后我们在装备镶嵌与时装镶嵌.nut中写入以下代码
```
/*
文件名:EquimentUseJewel.nut
路径:Dps_A/ProjectClass/EquimentUseJewel/EquimentUseJewel.nut
创建日期:2024-10-28 21:18
文件用途:装备镶嵌
*/
class EquimentUseJewel {
ExecUser = null;
//建库建表
function CreateMysqlTable() {
local CreateSql1 = "create database if not exists l_equ_jewel default charset utf8;"
local CreateSql2 = "CREATE TABLE l_equ_jewel.equipment ( equ_id int(11) AUTO_INCREMENT, jewel_data blob NOT NULL,andonglishanbai_flag int(11),date VARCHAR(255), PRIMARY KEY (equ_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8,AUTO_INCREMENT = 150;"
local SqlObj = MysqlPool.GetInstance().GetConnect();
SqlObj.Exec_Sql(CreateSql1);
SqlObj.Exec_Sql(CreateSql2);
MysqlPool.GetInstance().PutConnect(SqlObj);
}
function api_get_jewel_socket_data(id) { //获取徽章数据,存在返回徽章数据,不存在返回空字节数据
local CheckSql = "SELECT jewel_data FROM l_equ_jewel.equipment where equ_id = " + id + ";";
//从池子拿连接
local SqlObj = MysqlPool.GetInstance().GetConnect();
local Ret = SqlObj.Select(CheckSql, ["binary"]);
//把连接还池子
MysqlPool.GetInstance().PutConnect(SqlObj);
//没结婚要返回false
if (Ret.len()< 1 || Ret[0][0] == null) {
return 0;
} else {
return Ret[0][0];
}
}
function api_exitjeweldata(id) { //0代表不存在,存在返回1
local CheckSql = "SELECT andonglishanbai_flag FROM l_equ_jewel.equipment where equ_id = " + id + ";";
//从池子拿连接
local SqlObj = MysqlPool.GetInstance().GetConnect();
local Ret = SqlObj.Select(CheckSql, ["int"]);
//把连接还池子
MysqlPool.GetInstance().PutConnect(SqlObj);
//没结婚要返回false
if (Ret.len()< 1 || Ret[0][0] == null) {
return 0;
} else {
return Ret[0][0];
}
}
function save_equiment_socket(socket_data, id) { //0代表不存在,存在返回1
local CheckSql = "UPDATE l_equ_jewel.equipment SET jewel_data = 0x" + socket_data + " WHERE equ_id = " + id + ";";
//从池子拿连接
local SqlObj = MysqlPool.GetInstance().GetConnect();
local Ret = SqlObj.Select(CheckSql, ["int"]);
//把连接还池子
MysqlPool.GetInstance().PutConnect(SqlObj);
//没结婚要返回false
if (Ret.len()< 1 || Ret[0][0] == null) {
return false;
} else {
return true;
}
}
function CUser_SendCmdErrorPacket(SUser, id, id2) {
local Pack = Packet();
Pack.Put_Header(1, id);
Pack.Put_Byte(0);
Pack.Put_Byte(id2);
Pack.Finalize(true);
SUser.Send(Pack);
Pack.Delete();
}
function api_PacketBuf_get_buf(packet_buf) {
return NativePointer(NativePointer(packet_buf).add(20).readPointer()).add(13);
}
function add_equiment_socket(equipment_type) { //0代表开孔失败 成功返回标识
/*
武器10
称号11
上衣12
头肩13
下衣14
鞋子15
腰带16
项链17
手镯18
戒指19
辅助装备20
魔法石21
*/
/*
红色:'010000000000010000000000000000000000000000000000000000000000' A
黄色:'020000000000020000000000000000000000000000000000000000000000' B
绿色:'040000000000040000000000000000000000000000000000000000000000' C
蓝色:'080000000000080000000000000000000000000000000000000000000000' D
白金:'100000000000100000000000000000000000000000000000000000000000'
*/
local DB_JewelsocketData = "";
switch (equipment_type) {
case 10: //武器10 SS
DB_JewelsocketData = "100000000000000000000000000000000000000000000000000000000000"
break;
case 11: //称号11 SS
DB_JewelsocketData = "100000000000000000000000000000000000000000000000000000000000"
break;
case 12: //上衣12 C
DB_JewelsocketData = "040000000000040000000000000000000000000000000000000000000000"
break;
case 13: //头肩13 B
DB_JewelsocketData = "020000000000020000000000000000000000000000000000000000000000"
break;
case 14: //下衣14 C
DB_JewelsocketData = "040000000000040000000000000000000000000000000000000000000000"
break;
case 15: //鞋子15 D
DB_JewelsocketData = "080000000000080000000000000000000000000000000000000000000000"
break;
case 16: //腰带16 A
DB_JewelsocketData = "010000000000010000000000000000000000000000000000000000000000"
break;
case 17: //项链17 B
DB_JewelsocketData = "020000000000020000000000000000000000000000000000000000000000"
break;
case 18: //手镯18 D
DB_JewelsocketData = "080000000000080000000000000000000000000000000000000000000000"
break;
case 19: //戒指19 A
DB_JewelsocketData = "010000000000010000000000000000000000000000000000000000000000"
break;
case 20: //辅助装备20 S
DB_JewelsocketData = "100000000000000000000000000000000000000000000000000000000000"
break;
case 21: //魔法石21 S
DB_JewelsocketData = "100000000000000000000000000000000000000000000000000000000000"
break;
default:
DB_JewelsocketData = "000000000000000000000000000000000000000000000000000000000000"
break;
}
local date = time();
local Ct = Sq_GetTimestampString();
date = date.tostring() + Ct;
local CheckSql = "INSERT INTO l_equ_jewel.equipment (andonglishanbai_flag,jewel_data,date) VALUES(1,0x" + DB_JewelsocketData + ",\'" + date + "\');";
local CheckSql1 = "SELECT equ_id FROM l_equ_jewel.equipment where date = \'" + date + "\';";
//从池子拿连接
local SqlObj = MysqlPool.GetInstance().GetConnect();
SqlObj.Select(CheckSql, ["int"]);
local Ret = SqlObj.Select(CheckSql1, ["int"]);
//把连接还池子
MysqlPool.GetInstance().PutConnect(SqlObj);
if (Ret.len()< 1 || Ret[0][0] == null) {
return 0;
} else {
return Ret[0][0];
}
return 0;
}
function CStackableItem_getJewelTargetSocket(C_Object) {
return Sq_CallFunc(S_Ptr("0x0822CA28"), "int", ["pointer"], C_Object);
}
function CUser_SendUpdateItemList_DB(SUser, Slot, DB_JewelSocketData) {
local Pack = Packet();
Pack.Put_Header(0, 14);
Pack.Put_Byte(0);
Pack.Put_Short(1);
local InvenObj = SUser.GetInven();
Sq_CallFunc(S_Ptr("0x084FC6BC"), "int", ["pointer", "int", "int", "pointer"], InvenObj.C_Object, 1, Slot, Pack.C_Object);
Pack.Put_BinaryEx(DB_JewelSocketData.C_Object, 30);
Pack.Finalize(true);
SUser.Send(Pack);
Pack.Delete();
}
function GetByte(value) {
local Blob = blob();
Blob.writen(value, 'w');
return Blob;
}
function intToHex(num) {
if (num == 0) {
return "0";
}
local hexDigits = "0123456789abcdef";
local hexString = "";
while (num > 0) {
local remainder = num % 16;
hexString = hexDigits[remainder] + hexString;
num = (num / 16).tointeger();
}
return hexString;
}
function lengthCutting(str, ystr, num, maxLength) {
// 如果字符串长度小于最大长度在前面补0
local lengthDiff = maxLength - str.len();
if (lengthDiff > 0) {
local zeroPadding = "";
for (local i = 0; i< lengthDiff; i++) {
zeroPadding += "0";
}
str = zeroPadding + str;
}
local strArr = "";
for (local i = 0; i< str.len(); i += num) {
local endIndex = i + num;
if (endIndex > str.len()) {
endIndex = str.len();
}
strArr += str.slice(i, endIndex);
}
return ystr + strArr;
}
HackReturnAddSocketToAvatarFalg = null;
function HackReturnAddSocketToAvatar(Code) {
//标记flag
HackReturnAddSocketToAvatarFalg = Code;
Cb_PacketBuf_get_short_Leave_Func.EquimentUseJewel <- function(args) {
Cb_PacketBuf_get_short_Leave_Func.rawdelete("EquimentUseJewel");
return 0;
}.bindenv(this);
}
function FixFunction() {
//称号回包
Cb_CTitleBook_putItemData_Leave_Func.EquimentUseJewel <- function(args) {
local JewelSocketData = api_get_jewel_socket_data(NativePointer(args[3]).add(25).readU32());
local ret = args.pop();
if (JewelSocketData && NativePointer(JewelSocketData).add(0).readU8() != 0) {
local Pack = Packet(args[1]);
Pack.Put_BinaryEx(JewelSocketData.C_Object, 30);
}
return null;
}.bindenv(this);
//设计图继承
Cb_CUsercopyItemOption_Enter_Func.EquimentUseJewel <- function(args) {
local jewelSocketID = NativePointer(args[2]).add(25).readU32();
NativePointer(args[1]).add(25).writeU32(jewelSocketID);
return null;
}.bindenv(this);
//装备开孔
Cb_AddSocketToAvatar_Enter_Func.EquimentUseJewel <- function(args) {
local SUser = User(args[1]);
local Pack = Packet(args[2]);
local equ_slot = Pack.GetShort();
local equitem_id = Pack.GetInt();
local sta_slot = Pack.GetShort();
local CurCharacInvenW = SUser.GetInven();
local inven_item = CurCharacInvenW.GetSlot(1, equ_slot);
if (equ_slot > 56) { //修改后大于56则是时装装备 原:如果不是装备文件就调用原逻辑
equ_slot = equ_slot - 57;
local C_PacketBuf = api_PacketBuf_get_buf(args[2]) //获取原始封包数据
C_PacketBuf.add(0).writeShort(equ_slot) //修改掉装备位置信息 时装类镶嵌从57开始。
//执行原逻辑
return null;
}
//如果已开启镶嵌槽则不执行
local equ_id = NativePointer(inven_item.C_Object).add(25).readU32();
if (api_exitjeweldata(equ_id)) {
HackReturnAddSocketToAvatar(0x13);
return null;
}
local item = PvfItem.GetPvfItemById(equitem_id);
local ItemType = Sq_CallFunc(S_Ptr("0x08514D26"), "int", ["pointer"], item.C_Object);
if (ItemType == 10) {
SUser.SendNotiBox("装备为武器类型,不支持打孔!", 1)
HackReturnAddSocketToAvatar(0x0);
return null;
} else if (ItemType == 11) {
SUser.SendNotiBox("装备为称号类型,不支持打孔!", 1)
HackReturnAddSocketToAvatar(0x0);
return null;
}
local id = add_equiment_socket(ItemType);
Sq_Inven_RemoveItemFormCount(CurCharacInvenW.C_Object, 1, sta_slot, 1, 8, 1); //删除打孔道具
NativePointer(inven_item.C_Object).add(25).writeU32(id) //写入槽位标识
SUser.SendUpdateItemList(1, 0, equ_slot);
local JewelSocketData = api_get_jewel_socket_data(id);
CUser_SendUpdateItemList_DB(SUser, equ_slot, JewelSocketData); //用于更新镶嵌后的装备显示,这里用的是带镶嵌数据的更新背包函数,并非CUser_SendUpdateItemList
local Pack = Packet();
Pack.Put_Header(1, 209);
Pack.Put_Byte(1);
Pack.Put_Short(equ_slot + 104);
Pack.Put_Short(sta_slot);
Pack.Finalize(true);
SUser.Send(Pack);
Pack.Delete();
HackReturnAddSocketToAvatar(0x0);
return null;
}.bindenv(this);
Cb_AddSocketToAvatar_Leave_Func.EquimentUseJewel <- function(args) {
//跳的错误返回0 正常调用的话不处理返回值
if (HackReturnAddSocketToAvatarFalg != null) {
local SUser = User(args[1]);
// SUser.SendItemSpace(0);
CUser_SendCmdErrorPacket(SUser, 209, HackReturnAddSocketToAvatarFalg);
HackReturnAddSocketToAvatarFalg = null;
return 0;
}
return null;
}.bindenv(this);
//装备镶嵌和时装镶嵌
Cb_Dispatcher_UseJewel_Enter_Func.EquimentUseJewel <- function(args) {
local SUser = User(args[1]);
local Pack = Packet(args[2]);
local PackIndex = NativePointer(args[2]).add(4).readInt();
local State = SUser.GetState();
if (State != 3) return null;
local avartar_inven_slot = Pack.GetShort();
local avartar_item_id = Pack.GetInt();
local emblem_cnt = Pack.GetByte();
//下面是参照原时装镶嵌的思路写的。个别点标记出来。
if (avartar_inven_slot > 104) {
local equipment_inven_slot = avartar_inven_slot - 104; //取出真实装备所在背包位置值
local Inven = SUser.GetInven();
local equipment = Inven.GetSlot(1, equipment_inven_slot);
//校验是否合法
if (!equipment || equipment.IsEmpty || (equipment.GetIndex() != avartar_item_id) || SUser.CheckItemLock(1, equipment_inven_slot)) return;
local id = NativePointer(equipment.C_Object).add(25).readU32();
local JewelSocketData = api_get_jewel_socket_data(id);
if (!JewelSocketData) return;
local emblems = {};
if (emblem_cnt <= 3) {
for (local i = 0; i< emblem_cnt; i++) {
local emblem_inven_slot = Pack.GetShort();
local emblem_item_id = Pack.GetInt();
local equipment_socket_slot = Pack.GetByte();
local emblem = Inven.GetSlot(1, emblem_inven_slot);
//校验徽章及插槽数据是否合法
if (!emblem || emblem.IsEmpty || (emblem.GetIndex() != emblem_item_id) || (equipment_socket_slot >= 3)) return;
//校验徽章是否满足时装插槽颜色要求
//获取徽章pvf数据
local citem = PvfItem.GetPvfItemById(emblem_item_id);
if (!citem) return;
//校验徽章类型
if (!citem.IsStackable() || citem.GetItemType() != 20) return;
//获取徽章支持的插槽
local emblem_socket_type = CStackableItem_getJewelTargetSocket(citem.C_Object);
//获取要镶嵌的时装插槽类型
local avartar_socket_type = JewelSocketData.add(equipment_socket_slot * 6).readShort();
if (!(emblem_socket_type & avartar_socket_type)) {
return;
}
emblems[equipment_socket_slot] <- [emblem_inven_slot, emblem_item_id];
}
}
foreach(equipment_socket_slot, emblemObject in emblems) {
//删除徽章
local emblem_inven_slot = emblemObject[0];
Sq_Inven_RemoveItemFormCount(Inven.C_Object, 1, emblem_inven_slot, 1, 8, 1); //删除打孔道具
//设置时装插槽数据
local emblem_item_id = emblemObject[1];
JewelSocketData.add(2 + 6 * equipment_socket_slot).writeU32(emblem_item_id);
}
local Buf = Sq_Point2Blob(JewelSocketData.C_Object, 30);
local Str = "";
foreach(Value in Buf) {
Str += format("%02X", Value);
}
save_equiment_socket(Str, id);
// if (!save_equiment_socket(DB_JewelSocketData, id)) {
// print("写入失败了");
// return null;
// }
CUser_SendUpdateItemList_DB(SUser, equipment_inven_slot, JewelSocketData); //用于更新镶嵌后的装备显示,这里用的是带镶嵌数据的更新背包函数,并非CUser_SendUpdateItemList
local Pack = Packet();
Pack.Put_Header(1, 209);
Pack.Put_Byte(1);
Pack.Put_Short(equipment_inven_slot + 104);
Pack.Finalize(true);
SUser.Send(Pack);
Pack.Delete();
return;
}
AvatarLogic(args, PackIndex);
return null;
}.bindenv(this);
Cb_Dispatcher_UseJewel_Leave_Func.EquimentUseJewel <- function(args) {
return -1;
}.bindenv(this);
//额外数据包,发送装备镶嵌数据给本地处理
Cb_InterfacePacketBuf_put_packet_Leave_Func.EquimentUseJewel <- function(args) {
local ret = args.pop();
local Inven_Item = NativePointer(args[1]);
if (Inven_Item.add(1).readU8() == 1) {
local ItemObj = Item(args[1]);
local JewelSocketData = api_get_jewel_socket_data(NativePointer(ItemObj.C_Object).add(25).readU32());
if (JewelSocketData && JewelSocketData.add(0).readU8() != 0) {
local Pack = Packet(args[0]);
Pack.Put_BinaryEx(JewelSocketData.C_Object, 30);
}
}
return null;
}.bindenv(this);
L_HookEquimentUseJewel();
}
function WongWork_CAvatarItemMgr_getJewelSocketData(a, b) {
return Sq_CallFunc(S_Ptr("0x82F98F8"), "pointer", ["pointer", "int"], a, b);
}
function CStackableItem_getJewelTargetSocket(C_Object) {
return Sq_CallFunc(S_Ptr("0x0822CA28"), "int", ["pointer"], C_Object);
}
function CInventory_delete_item(C_Object, Type, Slot, Count, Ps, Log) {
return Sq_CallFunc(S_Ptr("0x850400C"), "int", ["pointer", "int", "int", "int", "int", "int"], C_Object, Type, Slot, Count, Ps, Log);
}
function api_set_JewelSocketData(jewelSocketData, slot, emblem_item_id) {
if (jewelSocketData) {
NativePointer(jewelSocketData).add(slot * 6 + 2).writeInt(emblem_item_id);
}
}
function DB_UpdateAvatarJewelSlot_makeRequest(a, b, c) {
return Sq_CallFunc(S_Ptr("0x843081C"), "pointer", ["int", "int", "pointer"], a, b, c);
}
//获取时装在数据库中的uid
function api_get_avartar_ui_id(avartar) {
return NativePointer(avartar).add(7).readInt();
}
function AvatarLogic(args, PackIndex) {
//角色
local SUser = User(args[1]);
//包数据
local Pack = Packet(args[2]);
//还原包读取数据号位
NativePointer(args[2]).add(4).writeInt(PackIndex);
//校验角色状态是否允许镶嵌
if (!SUser || SUser.GetState() != 3) {
return;
}
//时装所在的背包槽
local Inven_Slot = Pack.GetShort();
//时装item_id
local Item_Id = Pack.GetInt();
//本次镶嵌徽章数量
local Emblem_Count = Pack.GetByte();
//获取时装道具
local InvemObj = SUser.GetInven();
local AvatarObj = InvemObj.GetSlot(2, Inven_Slot);
//校验时装 数据是否合法
if (!AvatarObj || AvatarObj.IsEmpty || (AvatarObj.GetIndex() != Item_Id) || SUser.CheckItemLock(2, Inven_Slot)) return;
local Avartar_AddInfo = AvatarObj.GetAdd_Info();
//获取时装管理器
local Inven_AvartarMgr = InvemObj.GetAvatarItemMgr();
//获取时装插槽数据
local Jewel_Socket_Data = WongWork_CAvatarItemMgr_getJewelSocketData(Inven_AvartarMgr, Avartar_AddInfo);
if (!Jewel_Socket_Data) return;
//最多只支持3个插槽
if (Emblem_Count <= 3) {
local emblems = {};
for (local i = 0; i< Emblem_Count; i++) {
//徽章所在的背包槽
local emblem_inven_slot = Pack.GetShort();
//徽章item_id
local emblem_item_id = Pack.GetInt();
//该徽章镶嵌的时装插槽id
local avartar_socket_slot = Pack.GetByte();
//获取徽章道具
local EmblemObje = InvemObj.GetSlot(1, emblem_inven_slot);
//校验徽章及插槽数据是否合法
if (!EmblemObje || EmblemObje.IsEmpty || (EmblemObje.GetIndex() != emblem_item_id) || (avartar_socket_slot >= 3)) return;
//校验徽章是否满足时装插槽颜色要求
//获取徽章pvf数据
local citem = PvfItem.GetPvfItemById(emblem_item_id);
if (!citem) return;
//校验徽章类型
if (!citem.IsStackable() || citem.GetItemType() != 20) return;
//获取徽章支持的插槽
local emblem_socket_type = CStackableItem_getJewelTargetSocket(citem.C_Object);
//获取要镶嵌的时装插槽类型
local avartar_socket_type = NativePointer(Jewel_Socket_Data).add(avartar_socket_slot * 6).readShort();
if (!(emblem_socket_type & avartar_socket_type)) return;
emblems[avartar_socket_slot] <- [emblem_inven_slot, emblem_item_id];
}
//开始镶嵌
foreach(avartar_socket_slot, emblemObject in emblems) {
//删除徽章
local emblem_inven_slot = emblemObject[0];
CInventory_delete_item(InvemObj.C_Object, 1, emblem_inven_slot, 1, 8, 1);
//设置时装插槽数据
local emblem_item_id = emblemObject[1];
api_set_JewelSocketData(Jewel_Socket_Data, avartar_socket_slot, emblem_item_id);
}
//时装插槽数据存档
DB_UpdateAvatarJewelSlot_makeRequest(SUser.GetCID(), api_get_avartar_ui_id(AvatarObj.C_Object), Jewel_Socket_Data);
//通知客户端时装数据已更新
SUser.SendUpdateItemList(1, 1, Inven_Slot);
//回包给客户端
local Pack = Packet();
Pack.Put_Header(1, 204);
Pack.Put_Int(1);
Pack.Finalize(true);
SUser.Send(Pack);
Pack.Delete();
}
return null;
}
constructor() {
CreateMysqlTable();
FixFunction();
}
}
```
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑 如果你已经开启过数据库连接池则不需要初始化数据库连接池的代码
```
sq_RunScript("MyProject/装备镶嵌与时装镶嵌.nut");
local PoolObj = MysqlPool.GetInstance();
PoolObj.SetBaseConfiguration("127.0.0.1", 3306, "game", "uu5!^%jg");
//连接池大小
PoolObj.PoolSize = 10;
//初始化
PoolObj.Init();
GameManager.FixEquipUseJewel();
```
> 至此一个简单的装备镶嵌与时装镶嵌的逻辑就写完了

71
Start/Example/2.md Normal file
View File

@@ -0,0 +1,71 @@
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 跨界石.nut 用于编写我们的代码
![Alt text](../../image/14.png)
> 然后我们在跨界石.nut中写入以下代码
```
CrossoverStr1 <- "装备栏1号位没有装备..";
CrossoverStr2 <- "跨界失败,请检查一下账号金库是否没有开启或者没有空位";
CrossoverStr3 <- "跨界失败";
CrossoverStr4 <- "跨界成功,已经装备栏第一格的 [%s] 转移至账号金库";
CrossoverId <- 7577;
Cb_Use_Item_Sp_Func[CrossoverId] <- function(SUser, ItemId) {
//获取账号金库对象
local CargoObj = SUser.GetAccountCargo();
//获取账号金库中的一个空格子
local EmptySlot = CargoObj.GetEmptySlot();
//如果没有空格子
if (EmptySlot == -1) {
SUser.SendNotiPacketMessage(CrossoverStr2, 8);
//不扣除道具
SUser.GiveItem(ItemId, 1);
return;
}
//获取角色背包
local InvenObj = SUser.GetInven();
//获取需要转移的装备 这里默认写的装备栏第一个格子
local ItemObj = InvenObj.GetSlot(Inven.INVENTORY_TYPE_ITEM, 9);
//获取装备名字
local ItemName = PvfItem.GetNameById(ItemObj.GetIndex());
//如果没找到这个格子的装备
if (!ItemName) {
SUser.SendNotiPacketMessage(CrossoverStr1, 8);
//不扣除道具
SUser.GiveItem(ItemId, 1);
return;
}
//跨界
local Flag = CargoObj.InsertItem(ItemObj, EmptySlot);
if (Flag == -1) {
SUser.SendNotiPacketMessage(CrossoverStr3, 8);
//不扣除道具
SUser.GiveItem(ItemId, 1);
} else {
//销毁背包中的道具
ItemObj.Delete();
//刷新玩家背包列表
SUser.SendUpdateItemList(1, 0, 9);
//刷新账号金库列表
CargoObj.SendItemList();
SUser.SendNotiPacketMessage(format(CrossoverStr4, ItemName), 7);
}
}
```
![Alt text](../../image/15.png)
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/跨界石.nut");
```
![Alt text](../../image/16.png)
> 至此一个简单的跨界石的逻辑就写完了,然后我们就可以在游戏中使用道具7577来跨界了

82
Start/Example/3.md Normal file
View File

@@ -0,0 +1,82 @@
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 融合石.nut 用于编写我们的代码
![Alt text](../../image/17.png)
> 然后我们在融合石.nut中写入以下代码
```
//本例子由凌众提供
//装备代码1 装备代码2 融合后产出代码
Ronghe_Config <- {
"27601,27601",27601
}
Cb_Use_Item_Sp_Func[7577] <- function(SUser, ItemId) {
//获取玩家背包
local InvenObj = SUser.GetInven();
//如果背包存在
if (InvenObj) {
//获取玩家背包类型1的第9个格子
local ItemObj = InvenObj.GetSlot(1, 9);
local ItemObj2 = InvenObj.GetSlot(1, 10);
//空装备
if (ItemObj.IsEmpty || ItemObj2.IsEmpty) {
//发送通知
SUser.SendNotiPacketMessage("装备融合失败,请检查装备位置是否正确", 8);
//返还消耗的道具
local test = SUser.GiveItem(ItemId, 1);
return;
}
local ItemId1 = ItemObj.GetIndex();
local ItemId2 = ItemObj2.GetIndex();
local Skey = ItemId1 + "," + ItemId2;
if (!(Skey in Ronghe_Config)) {
//发送通知
SUser.SendNotiPacketMessage("装备融合失败,装备不可融合", 8);
//返还消耗的道具
SUser.GiveItem(ItemId, 1);
return;
}
local itemid3 = Ronghe_Config[Skey];
local item = SUser.GiveItem(itemid3, 1);
//最后获得的道具
local reitem = InvenObj.GetSlot(1, item[1]);
local dz = ItemObj.GetForging();
local qh = ItemObj.GetUpgrade();
local zf = ItemObj.GetAmplification();
local fm = ItemObj.GetEnchanting();
local pj = ItemObj.GetAdd_Info();
ItemObj.Delete();
ItemObj2.Delete();
reitem.SetForging(dz);
reitem.SetUpgrade(qh);
reitem.SetAmplification(zf);
reitem.SetEnchanting(fm);
reitem.SetAdd_Info(pj);
reitem.Flush();
SUser.SendItemSpace(0);
SUser.SendNotiPacketMessage("装备融合成功", 8);
}
}
```
![Alt text](../../image/18.png)
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/融合石.nut");
```
![Alt text](../../image/19.png)
> 至此一个简单的融合石的逻辑就写完了,然后我们就可以在游戏中使用道具7577来融合了

180
Start/Example/4.md Normal file
View File

@@ -0,0 +1,180 @@
## 装备继承卷 (贡献者: X)
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 装备继承卷.nut 用于编写我们的代码
![Alt text](../../image/20.png)
> 然后我们在装备继承卷.nut中写入以下代码
```
//本例子由X提供
//提示弹窗需配合233.dll插件(插件在群文件内)。不用233插件请将此方法SUser.SendNotiBox("这里写提示文字",1);修改为SUser.SendNotiPacketMessage("这里写提示文字", 8);
Cb_Use_Item_Sp_Func[2023629246] <- function(SUser, ItemId) {
local InvenObj = SUser.GetInven();
if (InvenObj) {
//获取玩家背包类型1的第9个格子
local ItemObj1 = InvenObj.GetSlot(1, 9);
local ItemObj2 = InvenObj.GetSlot(1, 10);
//空装备
if (ItemObj1.IsEmpty || ItemObj2.IsEmpty) {
//发送通知
SUser.SendNotiBox("请将已强化/增幅/锻造的装备放到\n[装备栏] 的第一格,要继承的装备放到第二格。", 1);
//返还消耗的道具
SUser.GiveItem(ItemId, 1);
return;
}
//获取物品ID
local ItemId1 = ItemObj1.GetIndex();
local ItemId2 = ItemObj2.GetIndex();
//限制类型 10=武器;称号=1116=腰带15=鞋子14=下装13=护肩12=上衣;项链=17手镯=18戒指=19;魔法石=21辅助装备=20
local itemType1 = PvfItem.GetPvfData(ItemId1).add(141 * 4).readU32();
local itemType2 = PvfItem.GetPvfData(ItemId2).add(141 * 4).readU32();
if (itemType1 == 11 || itemType2 == 11) {
SUser.SendNotiBox("继承或要继承的装备不能是称号!", 1);
SUser.GiveItem(ItemId, 1);
return;
}
if (itemType1 == 10) {
if (itemType1 == itemType2) {
jc(SUser, ItemId, ItemObj1, ItemObj2);
} else {
SUser.SendNotiBox("继承失败!\n[武器]\n只能继承至\n[武器]", 1);
SUser.GiveItem(ItemId, 1);
return;
}
return;
}
if (itemType1 == 17 || itemType1 == 18 || itemType1 == 19) {
if (itemType2 == 17 || itemType2 == 18 || itemType2 == 19) {
jc(SUser, ItemId, ItemObj1, ItemObj2);
} else {
SUser.SendNotiBox("继承失败!\n[首饰]\n只能继承至\n[首饰]", 1);
SUser.GiveItem(ItemId, 1);
}
return;
}
if (itemType1 == 21 || itemType1 == 20) {
if (itemType2 == 21 || itemType2 == 20) {
jc(SUser, ItemId, ItemObj1, ItemObj2);
} else {
SUser.SendNotiBox("继承失败!\n[魔法石、辅助装备]只能继承至:\n[魔法石或辅助装备]", 1);
SUser.GiveItem(ItemId, 1);
return;
}
return;
}
if (itemType1 == 12 || itemType1 == 13 || itemType1 == 14 || itemType1 == 15 || itemType1 == 16) {
if (itemType2 == 12 || itemType2 == 13 || itemType2 == 14 || itemType2 == 15 || itemType2 == 16) {
jc(SUser, ItemId, ItemObj1, ItemObj2);
} else {
SUser.SendNotiBox("继承失败!\n[护肩、上衣、下装、腰带、鞋]\n只能继承至\n[护肩、上衣、下装、腰带、鞋]", 1);
SUser.GiveItem(ItemId, 1);
return;
}
return;
}
} else {
SUser.GiveItem(ItemId, 1);
SUser.SendNotiBox("遇到错误,暂无法继承。", 1);
}
}
function jc(SUser, ItemId, ItemObj1, ItemObj2) {
SUser.SendNotiPacketMessage("开始继承了", 8);
//获取物品ID
local ItemId1 = ItemObj1.GetIndex();
local ItemId2 = ItemObj2.GetIndex();
//获得pvf中物品
local PvfItem1 = PvfItem.GetPvfItemById(ItemId1);
local PvfItem2 = PvfItem.GetPvfItemById(ItemId2);
//获取装备名称
local itemName1 = PvfItem1.GetName();
local itemName2 = PvfItem2.GetName();
//获取物品1和2的等级与品级
local itemLevel1 = PvfItem1.GetUsableLevel();
local itemLevel2 = PvfItem2.GetUsableLevel();
//限制继承装备的级别
if (itemLevel1< 60 || itemLevel2< 60) {
SUser.SendNotiBox("只有大于或者等于 【60级】 的装备才可以继承。", 1);
SUser.GiveItem(ItemId, 1);
return;
}
//获取品级
local itemRarity1 = PvfItem1.GetRarity();
local itemRarity2 = PvfItem2.GetRarity();
//限制品级
if (itemRarity1< 3 || itemRarity2< 3) {
SUser.SendNotiBox("只有 【神器】 以上的品级才能继承。", 1);
SUser.GiveItem(ItemId, 1);
return;
}
//获取物品1的属性
local itemType1 = PvfItem.GetPvfData(ItemId1).add(141 * 4).readU32();
local itemType2 = PvfItem.GetPvfData(ItemId2).add(141 * 4).readU32();
local forging = ItemObj1.GetForging(); //锻造
local upgrade = ItemObj1.GetUpgrade(); //强化
local amplification = ItemObj1.GetAmplification(); //增幅
local enchanting = ItemObj1.GetEnchanting(); //附魔
if (itemType1 == 10 && itemType2 == 10 && forging > 0) {
ItemObj2.SetForging(forging);
}
if (upgrade > 0) {
ItemObj2.SetUpgrade(upgrade);
}
if (amplification != 0) {
ItemObj2.SetAmplification(amplification);
}
ItemObj2.SetEnchanting(enchanting);
//删除原武器,若不删除就把原武器的属性清掉。
ItemObj1.Delete();
//刷新背包
SUser.SendUpdateItemList(1, 0, 9);
ItemObj2.Flush();
SUser.SendUpdateItemList(1, 0, 10);
SUser.SendNotiBox("装备继承成功!\n获得\n[+" + upgrade + " " + itemName2 + "]", 1);
return;
}
```
![Alt text](../../image/21.png)
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/装备继承卷.nut");
```
![Alt text](../../image/22.png)
> 至此一个简单的装备继承卷的逻辑就写完了,然后我们就可以在游戏中使用道具7577来融合了

93
Start/Example/5.md Normal file
View File

@@ -0,0 +1,93 @@
## 主线任务完成卷 (贡献者: Trim)
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 主线任务完成卷.nut 用于编写我们的代码
![Alt text](../../image/23.png)
> 然后我们在主线任务完成卷.nut中写入以下代码
```
//本例子由 Trim 提供
//主线任务完成卷ID
CrossoverId <- 7577;
Cb_Use_Item_Sp_Func[CrossoverId] <- function(SUser, ItemId) {
// 不需要完成的任务ID数组
local skippedQuestIDs = [674]; //将不要清理的任务ID写入数组内即可
// 获取角色任务信息和等级
local userQuest = SUser.GetQuest();
local questIsClear = NativePointer(userQuest).add(4);
local characLevel = SUser.GetCharacLevel();
local allClearQuest = 0;
// 获取 pvf 数据
local DataManager = Sq_CallFunc(S_Ptr("0x80CC19B"), "pointer", []);
// 判断任务是否需要跳过
function shouldSkip(questID) {
return skippedQuestIDs.find(questID) != null;
}
// 判断任务是否为主线并且角色等级符合要求
function isMainQuestAndLevelValid(pvfQuest, characLevel) {
local questGrade = NativePointer(pvfQuest).add(8).readInt();
local questLv = NativePointer(pvfQuest).add(0x20).readInt();
return questGrade == 0 && questLv <= characLevel;
}
// 判断任务是否已完成
function isQuestCleared(questID) {
return Sq_CallFunc(S_Ptr("0x808BAE0"), "bool", ["pointer", "int"], questIsClear.C_Object, questID);
}
// 设置任务为已完成
function clearQuest(questID) {
Sq_CallFunc(S_Ptr("0x808BA78"), "int", ["pointer", "int"], questIsClear.C_Object, questID);
}
// 循环处理任务
for (local questID = 1; questID< 30000; questID++) {
// 从 pvf 中获取任务数据
local pvfQuest = Sq_CallFunc(S_Ptr("0x835FDC6"), "pointer", ["pointer", "int"], DataManager, questID);
if (!pvfQuest || shouldSkip(questID)) continue; // 跳过空任务或不需要完成的任务
// 判断是否为主线任务且等级符合要求
if (!isMainQuestAndLevelValid(pvfQuest, characLevel)) continue;
// 判断任务是否已完成,若未完成则清理任务
if (!isQuestCleared(questID)) {
clearQuest(questID);
allClearQuest++;
}
}
local Pack = Packet();
//通知客户端刷新任务列表
Sq_CallFunc(S_Ptr("0x86ABBA8"), "int", ["pointer", "pointer"], userQuest, Pack.C_Object);
SUser.Send(Pack);
Pack.Delete();
// 发送通知
SUser.SendNotiPacketMessage("已清理:" + allClearQuest + "个主线任务!", 8);
}
```
![Alt text](../../image/24.png)
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/主线任务完成卷.nut");
```
![Alt text](../../image/25.png)
> 至此一个简单的主线任务完成卷的逻辑就写完了,然后我们就可以在游戏中使用道具7577来完成主线任务了

96
Start/Example/6.md Normal file
View File

@@ -0,0 +1,96 @@
## 史诗掉落奖励 (贡献者: 凌众)
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 史诗掉落奖励.nut 用于编写我们的代码
![Alt text](../../image/26.png)
> 然后我们在史诗掉落奖励.nut中写入以下代码
```
//本例子由 凌众 提供
//单次副本累计掉落史诗奖励
rewardAmountMap <- {
"4": 3000,
"5": 5000,
"6": 20000
}
//掉落特定史诗奖励 比如涂鸦笔和无影剑 顺便发全服公告 参数为 物品id ,奖励的点券,公告,公告类型
rewardAmountOnId <- {
"34253": [3000, "恭喜玩家[%s]在地下城深渊挑战中获得了[%s] 让我们恭喜这个b", 14],
"27098": [5000, "恭喜玩家[%s]在地下城深渊挑战中获得了[%s] 让我们恭喜这个b", 14],
}
userCounters <- {}
dgnname <- {}
//离开副本
Cb_History_DungeonLeave_Func.RindroSSDL <- function(SUser, Data) {
local num = userCounters[SUser.GetCID()];
local rewardAmount = 0;
local numS = num.tostring();
if (numS in rewardAmountMap) {
rewardAmount = rewardAmountMap[numS]
}
if (rewardAmount == 0) return;
World.SendNotiPacketMessage("玩家" + SUser.GetCharacName() + "在" + Data[14] + "中获得了" + userCounters[SUser.GetCID()].tostring() + "件史诗装备 奖励" + rewardAmount + "点券", 14);
SUser.RechargeCera(rewardAmount)
userCounters[SUser.GetCID()] <- 0;
}
//进入副本
Cb_History_DungeonEnter_Func.RindroSSDL <- function(SUser, Data) {
userCounters[SUser.GetCID()] <- 0;
dgnname[SUser.GetCID()] <- Data[14];
}
//拾取道具
Cb_User_Get_Item_Leave_Func.RindroSSDL <- function(args) {
local itemId = args[2];
local SUser = User(args[1]);
local pvfitem = PvfItem.GetPvfItemById(itemId);
local itemids = itemId.tostring();
//这里发放特定道具的奖励
if (itemids in rewardAmountOnId) {
local rewardAmount = rewardAmountOnId[itemids][0];
local msg = format(rewardAmountOnId[itemids][1], SUser.GetCharacName(), pvfitem.GetName());
World.SendNotiPacketMessage(msg, 14);
SUser.RechargeCera(rewardAmount)
}
if (!pvfitem.IsStackable() == 0) return;
local rarity = pvfitem.GetRarity();
local level = pvfitem.GetUsableLevel();
if (pvfitem == 4 && level > 10) {
userCounters[SUser.GetCID()]++;
}
userCounters[SUser.GetCID()]++;
return null;
};
```
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/史诗掉落奖励.nut");
```
> 至此一个简单的史诗掉落奖励的逻辑就写完了

48
Start/Example/7.md Normal file
View File

@@ -0,0 +1,48 @@
## 公会讲话互通 (贡献者: 凌众)
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 公会讲话互通.nut 用于编写我们的代码
![Alt text](../../image/28.png)
> 然后我们在公会讲话互通.nut中写入以下代码
```
//本例子由凌众提供
//输入hook
Cb_Server_Chat_Log_Leave_Func.RindroGHHT <- function(args) {
local type = args[2];
local SUser = User(args[1]);
local msg = args[3];
if (type == 6) {
local guildName = SUser.GetGuildName();
local name = SUser.GetCharacName();
//遍历在线玩家
local users = World.GetOnlinePlayer()
users.apply(function(Value) {
local onguildName = Value.GetGuildName();
if (guildName != onguildName) {
Value.SendNotiPacketMessage(name + "[" + guildName + "] " + msg, 6)
}
});
}
return null;
}
```
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/公会讲话互通.nut");
```
> 至此一个简单的公会讲话互通的逻辑就写完了,这样其他公会的人也能互相看到了

58
Start/Example/8.md Normal file
View File

@@ -0,0 +1,58 @@
## 分解券 (贡献者: 凌众)
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 分解券.nut 用于编写我们的代码
![Alt text](../../image/29.png)
> 然后我们在分解券.nut中写入以下代码
```
//本例子由凌众提供
//分解券
Cb_Use_Item_Sp_Func[7577] <- function(SUser, ItemId) {
SUser.GiveItem(ItemId, 1);
local is = SUser.GetCurCharacExpertJob();
if (!is) {
SUser.SendNotiPacketMessage("未开启分解机", 8);
return;
}
local inven = SUser.GetInven();
for (local i = 9; i <= 48; i++) //<=16为一行 以此类推+8多一行
{
local itemObj = inven.GetSlot(1, i);
local itemid = itemObj.GetIndex();
//如果这个位置有道具
if (itemid != 0) {
local pvfitem = PvfItem.GetPvfItemById(itemid);
local rarity = pvfitem.GetRarity();
if (rarity <= 3) {
SUser.DisPatcher_DisJointItem_disjoint(i);
}
}
SUser.SendItemSpace(0);
}
};
```
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/分解券.nut");
```
> 至此一个简单的分解券的逻辑就写完了,这样其他公会的人也能互相看到了

184
Start/Example/9.md Normal file
View File

@@ -0,0 +1,184 @@
## 装备继承券 (贡献者: X)
> 首先我们先在dp_s文件夹中建立一个项目文件夹 MyProject 方便管理
![Alt text](../../image/6.png)
> 然后我们建立一个新文件 装备继承券.nut 用于编写我们的代码
![Alt text](../../image/30.png)
> 然后我们在装备继承券.nut中写入以下代码
```
Cb_Use_Item_Sp_Func[2023629246] <- function(SUser, ItemId) {
local InvenObj = SUser.GetInven();
if(InvenObj){
//获取玩家背包类型1的第9个格子
local ItemObj1 = InvenObj.GetSlot(1, 9);
local ItemObj2 = InvenObj.GetSlot(1, 10);
//空装备
if (ItemObj1.IsEmpty || ItemObj2.IsEmpty) {
//发送通知
SUser.SendNotiBox("请将已强化/增幅/锻造的装备放到\n[装备栏] 的第一格,要继承的装备放到第二格。",1);
//返还消耗的道具
SUser.GiveItem(ItemId, 1);
return;
}
//获取物品ID
local ItemId1 = ItemObj1.GetIndex();
local ItemId2 = ItemObj2.GetIndex();
//限制类型 10=武器;称号=1116=腰带15=鞋子14=下装13=护肩12=上衣;项链=17手镯=18戒指=19;魔法石=21辅助装备=20
local pP1 = PvfItem.GetPvfItemById(ItemId1);
local itemType1 = NativePointer(pP1.C_Object).add(141*4).readU32();
local pP2 = PvfItem.GetPvfItemById(ItemId2);
local itemType2 = NativePointer(pP2.C_Object).add(141*4).readU32();
if(itemType1==11 || itemType2 ==11){
SUser.SendNotiBox("继承或要继承的装备不能是称号!",1);
SUser.GiveItem(ItemId, 1);
return;
}
if(itemType1==10){
if(itemType1==itemType2){
jc(SUser,ItemObj1,ItemObj2);
}else{
SUser.SendNotiBox("继承失败!\n[武器]\n只能继承至\n[武器]",1);
SUser.GiveItem(ItemId, 1);
return;
}
return;
}
if(itemType1==17||itemType1==18||itemType1==19){
if(itemType2==17||itemType2==18||itemType2==19){
jc(SUser,ItemObj1,ItemObj2);
}else{
SUser.SendNotiBox("继承失败!\n[首饰]\n只能继承至\n[首饰]",1);
SUser.GiveItem(ItemId, 1);
}
return;
}
if(itemType1==21||itemType1==20){
if(itemType2==21||itemType2==20){
jc(SUser,ItemObj1,ItemObj2);
}else{
SUser.SendNotiBox("继承失败!\n[魔法石、辅助装备]只能继承至:\n[魔法石或辅助装备]",1);
SUser.GiveItem(ItemId, 1);
return;
}
return;
}
if(itemType1==12||itemType1==13||itemType1==14||itemType1==15||itemType1==16){
if(itemType2==12||itemType2==13||itemType2==14||itemType2==15||itemType2==16){
jc(SUser,ItemObj1,ItemObj2);
}else{
SUser.SendNotiBox("继承失败!\n[护肩、上衣、下装、腰带、鞋]\n只能继承至\n[护肩、上衣、下装、腰带、鞋]",1);
SUser.GiveItem(ItemId, 1);
return;
}
return;
}
}else{
SUser.GiveItem(ItemId, 1);
SUser.SendNotiBox("遇到错误,暂无法继承。",1);
}
}
function jc(SUser,ItemObj1,ItemObj2){
//获取物品ID
local ItemId1 = ItemObj1.GetIndex();
local ItemId2 = ItemObj2.GetIndex();
//获得pvf中物品
local PvfItem1 = PvfItem.GetPvfItemById(ItemId1);
local PvfItem2 = PvfItem.GetPvfItemById(ItemId2);
//获取装备名称
local itemName1 = PvfItem1.GetName();
local itemName2 = PvfItem2.GetName();
//获取物品1和2的等级与品级
local itemLevel1 = PvfItem1.GetUsableLevel();
local itemLevel2 = PvfItem2.GetUsableLevel();
//限制继承装备的级别
if(itemLevel1<60 ||itemLevel2<60){
SUser.SendNotiBox("只有大于或者等于 【60级】 的装备才可以继承。",1);
SUser.GiveItem(ItemId, 1);
return;
}
//获取品级
local itemRarity1 = PvfItem1.GetRarity();
local itemRarity2 = PvfItem2.GetRarity();
//限制品级
if(itemRarity1<3||itemRarity2<3){
SUser.SendNotiBox("只有 【神器】 以上的品级才能继承。",1);
SUser.GiveItem(ItemId, 1);
return;
}
local forging = ItemObj1.GetForging();//锻造
local upgrade = ItemObj1.GetUpgrade();//强化
local amplification = ItemObj1.GetAmplification();//增幅
local enchanting = ItemObj1.GetEnchanting();//附魔
if(forging>0){
ItemObj2.SetForging(forging);
}
if(upgrade>0){
ItemObj2.SetUpgrade(upgrade);
}
if(amplification!=0){
ItemObj2.SetAmplification(amplification);
}
ItemObj2.SetEnchanting(enchanting);
//删除原武器,若不删除就把原武器的属性清掉。
ItemObj1.Delete();
//刷新背包
SUser.SendUpdateItemList(1, 0, 9);
ItemObj2.Flush();
SUser.SendUpdateItemList(1, 0, 10);
SUser.SendNotiBox("装备继承成功!\n获得\n[+"+upgrade+" "+itemName2+"]",1);
return;
}
```
> 最后我们回到dp_s文件夹中打开Main.nut 加载我们刚才编写的逻辑
```
sq_RunScript("MyProject/装备继承券.nut");
```
> 至此一个简单的装备继承券的逻辑就写完了