398 lines
17 KiB
Plaintext
398 lines
17 KiB
Plaintext
//活动开始阶段
|
|
local VILLAGEATTACK_STATE_START = 0;
|
|
//活动结束阶段
|
|
local VILLAGEATTACK_STATE_END = 3;
|
|
|
|
//怪物攻城活动数据
|
|
local villageAttackEventInfo = {
|
|
"state": VILLAGEATTACK_STATE_END, //活动当前状态
|
|
"score": 0, //当前阶段频道内总PT
|
|
"start_time": 0, //活动开始时间
|
|
"defend_success": 0, //怪物攻城活动防守成功
|
|
"user_pt_info": {}, //角色个人pt数据
|
|
}
|
|
|
|
//重置活动数据
|
|
function Reset_Villageattack_info() {
|
|
villageAttackEventInfo.state = VILLAGEATTACK_STATE_START;
|
|
villageAttackEventInfo.score = 0;
|
|
villageAttackEventInfo.user_pt_info = {};
|
|
villageAttackEventInfo.start_time = time();
|
|
villageAttackEventInfo.defend_success = 0;
|
|
print(">>>>>>>>>>>>>>活动数据已初始化成功<<<<<<<<<<<<<<")
|
|
}
|
|
|
|
//怪物攻城活动计时器(每5秒触发一次)
|
|
function Event_Villageattack_Timer() {
|
|
if (villageAttackEventInfo.state == VILLAGEATTACK_STATE_END)
|
|
return;
|
|
//活动结束检测
|
|
local remain_time = event_villageattack_get_remain_time();
|
|
if (remain_time <= 0) {
|
|
//活动结束
|
|
on_end_event_villageattack();
|
|
return;
|
|
}
|
|
}
|
|
|
|
//计算活动剩余时间
|
|
function event_villageattack_get_remain_time() {
|
|
local Config = GlobalConfig.Get("怪物攻城_南瓜.json");
|
|
local cur_time = time();
|
|
local event_end_time = villageAttackEventInfo.start_time + Config["怪物攻城配置"]["怪物攻城总时长(秒)"];
|
|
local remain_time = event_end_time - cur_time;
|
|
return remain_time;
|
|
}
|
|
|
|
//更新怪物攻城当前进度(广播给频道内在线玩家)
|
|
function Gameworld_Update_Villageattack_Score() {
|
|
local Config = GlobalConfig.Get("怪物攻城_南瓜.json");
|
|
//计算活动剩余时间
|
|
local remain_time = event_villageattack_get_remain_time();
|
|
if ((remain_time <= 0) || (villageAttackEventInfo.state == VILLAGEATTACK_STATE_END))
|
|
return;
|
|
|
|
local Pack = Packet();
|
|
Pack.Put_Header(0, 247); //协议: ENUM_NOTIPACKET_UPDATE_VILLAGE_ATTACKED
|
|
Pack.Put_Int(remain_time); //活动剩余时间
|
|
Pack.Put_Int(villageAttackEventInfo.score); //当前频道PT点数
|
|
Pack.Put_Int(Config["怪物攻城配置"]["怪物攻城胜利所需pt点"]); //成功防守所需点数
|
|
|
|
Pack.Finalize(true);
|
|
World.SendAll(Pack);
|
|
Pack.Delete();
|
|
}
|
|
|
|
//开启怪物攻城活动
|
|
function Start_Villageattack() {
|
|
local Config = GlobalConfig.Get("怪物攻城_南瓜.json");
|
|
local a3 = Memory.alloc(100);
|
|
//活动剩余时间
|
|
NativePointer(a3).add(10).writeInt(Config["怪物攻城配置"]["怪物攻城总时长(秒)"]);
|
|
//当前频道PT点数
|
|
NativePointer(a3).add(14).writeInt(villageAttackEventInfo.score);
|
|
//成功防守所需点数
|
|
NativePointer(a3).add(18).writeInt(Config["怪物攻城配置"]["怪物攻城胜利所需pt点"]);
|
|
//开启怪物攻城
|
|
Sq_CallFunc(S_Ptr("0x84DF47A"), "pointer", ["pointer", "pointer", "pointer"], S_Ptr("0x0"), S_Ptr("0x0"), a3.C_Object);
|
|
//设置副本难度
|
|
NativePointer(S_Ptr("0x085B9605")).writeInt(Config["怪物攻城配置"]["活动默认难度(0-4: 普通-英雄)"]);
|
|
//patch相关函数, 修复活动流程
|
|
Hook_VillageAttack();
|
|
print(">>>>>>>>>>>>>>怪物攻城已启动<<<<<<<<<<<<<<<<<<<<");
|
|
}
|
|
|
|
//结束怪物攻城活动(立即销毁攻城怪物, 不开启逆袭之谷, 不发送活动奖励)
|
|
function end_villageattack() {
|
|
local GlobalData_s_villageMonsterMgr = NativePointer("0x941F77C").readPointer();
|
|
Sq_CallFunc(S_Ptr("0x086B43D4"), "pointer", ["pointer", "int"], GlobalData_s_villageMonsterMgr, 2);
|
|
print(">>>>>>>>>>>>>>怪物攻城已结束<<<<<<<<<<<<<<");
|
|
}
|
|
|
|
// 开始怪物攻城活动
|
|
function On_Start_Event_VillageattackBynangua() {
|
|
// 重置活动数据
|
|
Reset_Villageattack_info();
|
|
// 注册5秒检查定时器
|
|
Timer.SetCronTask(Event_Villageattack_Timer, {
|
|
Cron = "*/5 * * * * *", // 每5秒执行一次
|
|
Name = "VillageAttackCheckTask"
|
|
});
|
|
// 通知全服玩家活动开始 并刷新城镇怪物
|
|
Start_Villageattack();
|
|
Gameworld_Update_Villageattack_Score();
|
|
|
|
// 发送活动开始公告
|
|
local Config = GlobalConfig.Get("怪物攻城_南瓜.json");
|
|
World.SendNotiPacketMessage(Config["怪物攻城公告"]["开始"], Config["怪物攻城公告"]["发送位置"]);
|
|
}
|
|
|
|
Cb_reach_game_world_Func.villageattackByNangua <- function(SUser) {
|
|
//怪物攻城活动更新进度
|
|
if (villageAttackEventInfo.state != VILLAGEATTACK_STATE_END) {
|
|
//通知客户端打开活动UI
|
|
Notify_Villageattack_Score(SUser);
|
|
}
|
|
}
|
|
|
|
//通知玩家怪物攻城进度
|
|
function Notify_Villageattack_Score(SUser) {
|
|
local Config = GlobalConfig.Get("怪物攻城_南瓜.json");
|
|
// 玩家当前PT点
|
|
local charac_no = SUser.GetCID().tostring();
|
|
local villageattack_pt = 0;
|
|
|
|
if (charac_no in villageAttackEventInfo.user_pt_info)
|
|
villageattack_pt = villageAttackEventInfo.user_pt_info[charac_no][1];
|
|
|
|
// 计算活动剩余时间
|
|
local remain_time = event_villageattack_get_remain_time();
|
|
|
|
if ((remain_time <= 0) || (villageAttackEventInfo.state == VILLAGEATTACK_STATE_END))
|
|
return;
|
|
// 发包通知角色打开怪物攻城UI并更新当前进度
|
|
local Pack = Packet();
|
|
Pack.Put_Header(0, 248);
|
|
Pack.Put_Int(remain_time); // 活动剩余时间
|
|
Pack.Put_Int(villageAttackEventInfo.score); // 当前频道PT点数
|
|
Pack.Put_Int(Config["怪物攻城配置"]["怪物攻城胜利所需pt点"]); // 成功防守所需点数
|
|
Pack.Put_Int(villageattack_pt); // 个人PT点数
|
|
Pack.Finalize(true);
|
|
SUser.Send(Pack);
|
|
Pack.Delete();
|
|
}
|
|
|
|
//怪物攻城活动相关patch
|
|
function Hook_VillageAttack() {
|
|
Cb_CVillageMonster_SendVillageMonsterFightResult_Leave_Func.Bynangua <- function(args) {
|
|
local Config = GlobalConfig.Get("怪物攻城_南瓜.json");
|
|
local village_monster = args[0];
|
|
local SUser = User(args[1]);
|
|
local result = args[2];
|
|
if (result) {
|
|
local bonus_pt = 1;
|
|
local PartyObj = SUser.GetParty();
|
|
if (!PartyObj) return;
|
|
for (local i = 0; i < 4; ++i) {
|
|
local TUser = PartyObj.GetUser(i);
|
|
if (TUser) {
|
|
local charac_no = TUser.GetCID().tostring();
|
|
if (!(charac_no in villageAttackEventInfo.user_pt_info)){
|
|
villageAttackEventInfo.user_pt_info[charac_no] <- [TUser.GetUID(), 0];
|
|
}
|
|
villageAttackEventInfo.user_pt_info[charac_no][1] += bonus_pt;
|
|
VillageAttackedRewardSendReward(TUser);
|
|
}
|
|
}
|
|
villageAttackEventInfo.score += bonus_pt;
|
|
Gameworld_Update_Villageattack_Score();
|
|
if (villageAttackEventInfo.score >= Config["怪物攻城配置"]["怪物攻城胜利所需pt点"]) {
|
|
//怪物攻城活动防守成功, 立即结束活动
|
|
villageAttackEventInfo.defend_success = 1;
|
|
Timer.SetTimeOut(on_end_event_villageattack, 15);
|
|
return;
|
|
}
|
|
//通知队伍中的所有玩家更新PT点数
|
|
for (local i = 0; i < 4; ++i) {
|
|
local TUser = PartyObj.GetUser(i);
|
|
if (TUser) {
|
|
Notify_Villageattack_Score(TUser);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//结束怪物攻城活动
|
|
function on_end_event_villageattack() {
|
|
local Config = GlobalConfig.Get("怪物攻城_南瓜.json");
|
|
if (villageAttackEventInfo.state == VILLAGEATTACK_STATE_END)
|
|
return;
|
|
// 设置活动状态
|
|
villageAttackEventInfo.state = VILLAGEATTACK_STATE_END;
|
|
// 移除5秒检查定时器
|
|
Timer.RemoveCronTask("VillageAttackCheckTask");
|
|
// 立即结束怪物攻城活动
|
|
end_villageattack();
|
|
local OnlinePlayerList = World.GetOnlinePlayer();
|
|
// 防守成功
|
|
if (villageAttackEventInfo.defend_success == 1) {
|
|
// 频道内在线玩家发奖
|
|
foreach(SUser in OnlinePlayerList) {
|
|
local RewardItems = [];
|
|
|
|
// 从配置文件中获取固定奖励
|
|
foreach(reward in Config["怪物攻城配置"]["怪物攻城防守成功固定奖励配置"]) {
|
|
RewardItems.append([reward[0], reward[1]]);
|
|
}
|
|
|
|
// 发送邮件
|
|
local title = "<怪物攻城活动>"
|
|
local Text = "恭喜勇士成功守护我们的家园!"
|
|
SUser.ReqDBSendMultiMail(title, Text, 0, RewardItems)
|
|
}
|
|
|
|
// 榜一大哥
|
|
local rank_first_charac_no = 0;
|
|
local rank_first_account_id = 0;
|
|
local max_pt = 0;
|
|
|
|
// 论功行赏
|
|
foreach(charac_no, data in villageAttackEventInfo.user_pt_info) {
|
|
// 发点券
|
|
local account_id = villageAttackEventInfo.user_pt_info[charac_no][0];
|
|
local pt = villageAttackEventInfo.user_pt_info[charac_no][1];
|
|
local reward_cera = pt * Config["怪物攻城配置"]["怪物攻城其余玩家点券奖励"];
|
|
// 点券奖励 = 个人PT * 10
|
|
|
|
local user_pr = World.GetUserByUid(account_id);
|
|
if(Config["怪物攻城配置"]["怪物攻城其余玩家点券奖励"] > 0){
|
|
user_pr.RechargeCera(reward_cera);
|
|
user_pr.SendNotiPacketMessage("<怪物攻城活动> 防守成功, 获得pt点 * " + Config["怪物攻城配置"]["怪物攻城其余玩家点券奖励"] + " 的点券奖励", 14);
|
|
}
|
|
// 找出榜一大哥
|
|
if (pt > max_pt) {
|
|
rank_first_charac_no = charac_no;
|
|
rank_first_account_id = account_id;
|
|
max_pt = pt;
|
|
}
|
|
}
|
|
|
|
// 频道内公告活动已结束
|
|
World.SendNotiPacketMessage(Config["怪物攻城公告"]["防守成功"], Config["怪物攻城公告"]["发送位置"]);
|
|
if (rank_first_charac_no) {
|
|
// 个人积分排行榜第一名 额外获得10倍点券奖励
|
|
local user_pr = World.GetUserByUid(rank_first_account_id);
|
|
if(Config["怪物攻城配置"]["怪物攻城榜一大哥额外点券奖励"] > 0){
|
|
user_pr.RechargeCera(max_pt * Config["怪物攻城配置"]["怪物攻城榜一大哥额外点券奖励"]);
|
|
user_pr.SendNotiPacketMessage("<怪物攻城活动> 排行榜第一名, 获得pt点 * " + Config["怪物攻城配置"]["怪物攻城榜一大哥额外点券奖励"] + " 的点券奖励", 14);
|
|
}
|
|
if(Config["怪物攻城配置"]["怪物攻城榜一大哥额外奖励道具(true开启/false关闭)"]){
|
|
local reward_items = {};
|
|
foreach(reward in Config["怪物攻城配置"]["怪物攻城榜一大哥额外奖励道具"]){
|
|
reward_items[reward[0]] <- reward[1];
|
|
}
|
|
Timer.SetTimeOut(function(){
|
|
user_pr.SendMail(reward_items, {
|
|
Title = "<怪物攻城活动>",
|
|
Text = "恭喜获得排行榜第一名!"
|
|
});
|
|
user_pr.SendNotiPacketMessage("<怪物攻城活动> 恭喜获得排行榜第一名,请前往邮箱查看奖励", 14);
|
|
}, 3);
|
|
}
|
|
// 频道内广播本轮活动排行榜第一名玩家名字
|
|
local rank_first_charac_name = _VillageAttackBynangua.Get_charac_name_ByCID(rank_first_charac_no.tointeger());
|
|
World.SendNotiPacketMessage("<怪物攻城活动> 恭喜勇士 【" + rank_first_charac_name + "】 成为个人积分排行榜第一名(" + max_pt + "pt)!", 14);
|
|
}
|
|
} else {
|
|
// 防守失败
|
|
World.SendNotiPacketMessage(Config["怪物攻城公告"]["防守失败"], Config["怪物攻城公告"]["发送位置"]);
|
|
}
|
|
|
|
// 释放空间
|
|
villageAttackEventInfo.user_pt_info = {};
|
|
}
|
|
|
|
function VillageAttackedRewardSendReward(SUser) {
|
|
local villageAttack_ConfigBynangua = GlobalConfig.Get("怪物攻城_南瓜.json");
|
|
local charac_no = SUser.GetCID().tostring();
|
|
if ((charac_no in villageAttackEventInfo.user_pt_info)) {
|
|
local Count = villageAttackEventInfo.user_pt_info[charac_no][1];
|
|
local Config = villageAttack_ConfigBynangua["怪物攻城配置"]["怪物攻城奖励配置"]["击杀次数"];
|
|
|
|
if (Config.rawin(Count.tostring())) {
|
|
local rewardConfig = Config[Count.tostring()];
|
|
if (rewardConfig) {
|
|
local title = "<怪物攻城活动>"
|
|
local Text = "恭喜勇士成功守护我们的家园!"
|
|
local RewardItems = [];
|
|
RewardItems.append([rewardConfig[0], rewardConfig[1]]);
|
|
SUser.ReqDBSendMultiMail(title, Text, 0, RewardItems);
|
|
}
|
|
} else {
|
|
local title = "<怪物攻城活动>"
|
|
local Text = "恭喜勇士成功守护我们的家园!"
|
|
// 使用默认奖励配置
|
|
local defaultRewards = villageAttack_ConfigBynangua["怪物攻城配置"]["不在配置表里的击杀次数默认奖励道具"];
|
|
local RewardItems = [];
|
|
RewardItems.append([defaultRewards[0], defaultRewards[1]]);
|
|
SUser.ReqDBSendMultiMail(title, Text, 0, RewardItems);
|
|
}
|
|
}
|
|
}
|
|
class _VillageAttackBynangua{
|
|
function Get_charac_name_ByCID(charac_no) {
|
|
local Config = GlobalConfig.Get("怪物攻城_南瓜.json");
|
|
local PoolObj = MysqlPool.GetInstance();
|
|
local Ip = Config["数据库IP 不是外置数据库不要更改"];
|
|
local Port = Config["数据库端口 不懂不要更改"];
|
|
local DbName = Config["数据库用户名 本地用户名不懂不要更改"];
|
|
local Password = Config["数据库密码 本地密码不懂不要更改"];
|
|
//设置数据库连接信息
|
|
PoolObj.SetBaseConfiguration(Ip, Port, DbName, Password);
|
|
//连接池大小
|
|
PoolObj.PoolSize = 10;
|
|
//初始化
|
|
PoolObj.Init();
|
|
local sql = "select charac_name from charac_info where charac_no=" + charac_no + ";";
|
|
local column_type_list = ["string"];
|
|
local SqlObj = MysqlPool.GetInstance().GetConnect();
|
|
local result = SqlObj.Select(sql, column_type_list);
|
|
MysqlPool.GetInstance().PutConnect(SqlObj);
|
|
if (result.len() > 0) {
|
|
return result[0][0];
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// 怪物攻城活动入口点
|
|
function _Dps_VillageAttack_nangua_Main_() {
|
|
_Dps_VillageAttack_nangua_Logic_();
|
|
}
|
|
|
|
// 怪物攻城活动重载入口点
|
|
function _Dps_VillageAttack_nangua_Main_Reload_(OldConfig) {
|
|
// 先移除旧的定时任务
|
|
Timer.RemoveCronTask("VillageAttackTask");
|
|
|
|
// 重新注册
|
|
_Dps_VillageAttack_nangua_Logic_();
|
|
}
|
|
|
|
// 怪物攻城活动逻辑入口点
|
|
function _Dps_VillageAttack_nangua_Logic_() {
|
|
// 从配置中读取开启时间
|
|
local Config = GlobalConfig.Get("怪物攻城_南瓜.json");
|
|
local hour = Config["怪物攻城配置"]["开启时间[XX点(24小时制), XX分(0-59)]"][0];
|
|
local minute = Config["怪物攻城配置"]["开启时间[XX点(24小时制), XX分(0-59)]"][1];
|
|
|
|
// cron 表达式 (秒 分 时 日 月 周)
|
|
local cronExpression = format("0 %d %d * * *", minute, hour);
|
|
|
|
// 注册定时任务
|
|
Timer.SetCronTask(On_Start_Event_VillageattackBynangua, {
|
|
Cron = cronExpression,
|
|
Name = "VillageAttackTask"
|
|
});
|
|
}
|
|
//发送Item邮件 Pubilc
|
|
function User::SendItemMailtest(UID, ItemList, title, content) {
|
|
local SUser = World.GetUserByUid(UID);
|
|
local CID = SUser.GetCID();
|
|
local sql = "select letter_id from taiwan_cain_2nd.postal order by letter_id DESC";
|
|
local column_type_list = ["int"];
|
|
|
|
local SqlObj = MysqlPool.GetInstance().GetConnect();
|
|
local result = SqlObj.Select(sql, column_type_list);
|
|
local sl = 1;
|
|
if (result.len() > 0) {
|
|
sl = result[0][0] + 1;
|
|
}
|
|
|
|
local time = date();
|
|
local timeStr = time["year"] + "-" + (time["month"] + 1) + "-" + time["day"] + " " + time["hour"] + ":" + time["min"] + ":" + time["sec"];
|
|
|
|
foreach(value in ItemList) {
|
|
local sql1 = "insert into taiwan_cain_2nd.postal (occ_time,send_charac_name,receive_charac_no,amplify_option,amplify_value,seperate_upgrade,seal_flag,item_id,add_info,upgrade,gold,letter_id,avata_flag,creature_flag) values ('" + timeStr + "','" + title + "'," + CID + ",0,0,0,0," + value.item + "," + value.num + ",0,0," + sl + ",'0','0')";
|
|
SqlObj.Select(sql1, []);
|
|
}
|
|
|
|
local sql2 = "insert into taiwan_cain_2nd.letter (letter_id,charac_no,send_charac_name,letter_text,reg_date,stat) values ('" + sl + "'," + CID + ",'" + title + "','" + content + "','" + timeStr + "','1')";
|
|
SqlObj.Select(sql2, []);
|
|
|
|
MysqlPool.GetInstance().PutConnect(SqlObj);
|
|
|
|
if (SUser) {
|
|
local Pack = Packet();
|
|
Pack.Put_Header(0, 9);
|
|
local MailBox = Sq_CallFunc(S_Ptr("0x0823020C"), "int", ["pointer"], SUser.C_Object);
|
|
Sq_CallFunc(S_Ptr("0x0823455A"), "int", ["int"], MailBox);
|
|
local Not_Count = Sq_CallFunc(S_Ptr("0x084ED330"), "int", ["int"], MailBox);
|
|
Pack.Put_Short(Not_Count);
|
|
Pack.Finalize(true);
|
|
SUser.Send(Pack);
|
|
Pack.Delete();
|
|
}
|
|
}
|