UnionChangeLeader_1.lua 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. UnionChangeLeader = {}
  2. local this = {}
  3. UnionConsts = {
  4. UNION_VOTE_TIME_CONST = "T$_UNION_VOTE_TIME_CONST"
  5. }
  6. -- 延迟任务类型
  7. this.DelayType = {
  8. RunForLeader = 1, -- 竞选/取代
  9. Impeach = 2 -- 弹劾
  10. }
  11. this.EMAIL_IDS = {
  12. START_RUN_FOR_LEADER = 207006, -- 发起竞选
  13. RUN_FOR_LEADER_FAIL = 207005, -- 竞选失败
  14. RUN_FOR_LEADER_SUCCESS = 207001, -- 竞选成功
  15. START_RUN_FOR_LEADER_REPLACE = 207008, -- 发起取代
  16. RUN_FOR_LEADER_REPLACE_FAIL = 207009, -- 取代失败
  17. RUN_FOR_LEADER_REPLACE_SUCCESS = 207010, -- 取代成功
  18. START_IMPEACH = 207007, -- 发起弹劾
  19. IMPEACH_FAIL = 207003, -- 弹劾失败
  20. IMPEACH_SUCCESS = 207002, -- 弹劾成功
  21. }
  22. function UnionChangeLeader.sendUnionInfo(actor)
  23. this.sendUnionInfo(actor)
  24. end
  25. function UnionChangeLeader.startInitUnionDelayTask()
  26. local success, result = xpcall(function()
  27. this.initUnionChangeLeaderData()
  28. this.initRunForLeaderTask()
  29. this.initGlobalImpeachData()
  30. this.initImpeachTask()
  31. end, debug.traceback)
  32. gameDebug.assertPrint(success, "竞选初始化失败", result)
  33. end
  34. function UnionChangeLeader.clearRunForLeaderMember(actor)
  35. -- 事件触发有问题,由客户端屏蔽退出的玩家
  36. -- this.runForLeaderMemberQuit(actor)
  37. end
  38. ----------------------------------------------------
  39. function this.sendUnionInfo(actor)
  40. local union_data = getunioninfo(actor)
  41. if table.isEmpty(union_data) then
  42. this.debug(actor, "获取战盟信息异常")
  43. return
  44. end
  45. union_data = table.valueConvertToString(union_data)
  46. union_data.ischangename = "1"
  47. sendluamsg(actor, LuaMessageIdToClient.RES_GET_UNION_INFO, union_data)
  48. end
  49. function this.initUnionChangeLeaderData()
  50. local global_data = {}
  51. local summary_list = getallunionsummary()
  52. if table.isEmpty(summary_list) then
  53. return
  54. end
  55. for _, summary in pairs(summary_list) do
  56. local union_id = summary.unionid
  57. local data = this.getRunForLeaderData(union_id)
  58. if not table.isEmpty(data) and not table.isEmpty(data.ridlist) then
  59. global_data[union_id] = data
  60. end
  61. end
  62. this.setAllRunForLeaderData(global_data)
  63. end
  64. ---------------------------------------------------------------------------------
  65. ---------------------------------- ↓战盟竞选逻辑开始↓ -------------------------------
  66. ---@class UnionChangeLeader.UnionRunForLeaderData
  67. ---@field ridlist table 竞选者列表
  68. ---@field endtime string 竞选结束时间
  69. ---@field unionid number 竞选战盟id
  70. ---@field isreplace boolean 是否有盟主[有盟主为取代, 无盟主为竞选]
  71. UnionChangeLeader.RunForLeader = {}
  72. UnionChangeLeader.runForLeaderGlobalKey = "G$_UNION_RUN_FOR_LEADER_GLOBAL_DATA"
  73. UnionChangeLeader.runForLeaderKey = "U$_UNION_RUN_FOR_LEADER_DATA"
  74. function UnionChangeLeader.RunForLeader.getRunForLeaderData(actor)
  75. this.sendRunForLeaderData(actor)
  76. end
  77. function UnionChangeLeader.RunForLeader.actorRunForLeader(actor)
  78. this.actorRunForLeader(actor)
  79. end
  80. function UnionChangeLeader.RunForLeader.actorVoteRunForLeader(actor, vote_data)
  81. this.actorVoteRunForLeader(actor, vote_data)
  82. end
  83. function UnionChangeLeader.RunForLeader.finishRunforLeaderActor()
  84. this.finishRunforLeaderActor()
  85. end
  86. -----------------------------------------------
  87. function this.sendRunForLeaderData(actor)
  88. local union_id = getbaseinfo(actor, "unionid")
  89. local data = this.getRunForLeaderData(union_id)
  90. if table.isEmpty(data) then
  91. data = {}
  92. end
  93. this.debug("---- panel data ----", data)
  94. sendluamsg(actor, LuaMessageIdToClient.RES_UNION_RUN_FOR_LEADER_DATA, data)
  95. end
  96. function this.getAllRunForLeaderData()
  97. return getsysvar(UnionChangeLeader.runForLeaderGlobalKey)
  98. end
  99. function this.setAllRunForLeaderData(data)
  100. setsysvar(UnionChangeLeader.runForLeaderGlobalKey, data)
  101. end
  102. function this.getRunForLeaderData(union_id)
  103. local union_actor = getguild(union_id)
  104. return getguilddef(union_actor, UnionChangeLeader.runForLeaderKey)
  105. end
  106. function this.setRunForLeaderData(union_id, data)
  107. local union_actor = getguild(union_id)
  108. setguilddef(union_actor, UnionChangeLeader.runForLeaderKey, data)
  109. -- 同步全服数据
  110. local all_data = this.getAllRunForLeaderData()
  111. if not all_data then
  112. all_data = {}
  113. end
  114. all_data[union_id] = data
  115. this.setAllRunForLeaderData(all_data)
  116. end
  117. function this.actorRunForLeader(actor)
  118. local union_data = getunioninfo(actor)
  119. if table.isEmpty(union_data) then
  120. this.debug(actor, "获取战盟信息异常")
  121. return
  122. end
  123. local rid_str = getbaseinfo(actor, "id")
  124. local rid = tostring(rid_str)
  125. local level = union_data.unionlevel
  126. local union_id = union_data.unionid
  127. local leader_id = tostring(union_data.leaderid)
  128. if tonumber(rid) == tonumber(leader_id) then
  129. this.info(actor, "盟主不能参与竞选/取代")
  130. return
  131. end
  132. local now = getbaseinfo(actor, "now")
  133. local is_replace = tonumber(leader_id) > 0
  134. if is_replace then
  135. local online_state = getbaseinfo(actor, "onlinestate")
  136. if tonumber(online_state) == 0 then
  137. local leader_info = union_data.memberinfos[union_data.leaderid]
  138. local quit_line_mil = (now - leader_info.quitlinetime) / 60 / 1000
  139. local offlinetime = ConfigDataManager.getTableValue("cfg_unionlevel", "continuousofflinetime", "unionLevel",
  140. level)
  141. if quit_line_mil < tonumber(offlinetime) then
  142. this.info(actor, "盟主离线时不长满足取代条件,不能被取代。 quit_line_mil " .. tostring(quit_line_mil))
  143. return
  144. end
  145. end
  146. local on_second = (now - union_data.leaderontime) / 60 / 1000
  147. local abdicationtime = ConfigDataManager.getTableValue("cfg_unionlevel", "abdicationtime", "unionLevel", level)
  148. if on_second < tonumber(abdicationtime) then
  149. this.info(actor, "盟主在位小于" .. abdicationtime .. "分钟。 on_second " .. tostring(on_second))
  150. return
  151. end
  152. end
  153. local condition = ""
  154. local cost_str = ""
  155. local campaign = 0
  156. if not is_replace then
  157. condition = ConfigDataManager.getTableValue("cfg_unionlevel", "electionConditions", "unionLevel", level)
  158. cost_str = ConfigDataManager.getTableValue("cfg_unionlevel", "cast", "unionLevel", level)
  159. campaign = ConfigDataManager.getTableValue("cfg_unionlevel", "campaign", "unionLevel", level)
  160. else
  161. condition = ConfigDataManager.getTableValue("cfg_unionlevel", "replaceConditions", "unionLevel", level)
  162. cost_str = ConfigDataManager.getTableValue("cfg_unionlevel", "replaceCast", "unionLevel", level)
  163. campaign = ConfigDataManager.getTableValue("cfg_unionlevel", "replaceTime", "unionLevel", level)
  164. end
  165. local delay_second = campaign * 60
  166. -- delay_second = 60 * 60 * 24
  167. -- 判断玩家是否可以发起竞选
  168. if condition then
  169. local isPass = ConditionManager.Check(actor, condition)
  170. if not isPass then
  171. this.info(actor, "不满足竞选/取代条件")
  172. return
  173. end
  174. end
  175. -- 扣除竞选费用
  176. local cost_ret = this.unionCostItem(actor, cost_str, 1)
  177. if not cost_ret then
  178. this.info(actor, "消耗道具失败!无法参与竞选/取代!")
  179. this.debug(actor, "cost_str" .. tostring(cost_str))
  180. return
  181. end
  182. -- 参与竞选
  183. local start_delay = false
  184. local all_data = this.getAllRunForLeaderData()
  185. this.debug("------ all_data is empty", all_data, table.isEmpty(all_data))
  186. if table.isEmpty(all_data) then
  187. this.debug(actor, "---- 发起新的定时任务 ----")
  188. start_delay = true
  189. end
  190. -- 初始化竞选玩家数据
  191. local member_data = { count = 0, cost_item = cost_str }
  192. local data = this.getRunForLeaderData(union_id)
  193. if table.isEmpty(data) or table.isEmpty(data.ridlist) then
  194. -- 第一个竞选者
  195. local end_mills = now + (delay_second * 1000)
  196. local leader_map = {
  197. [rid] = member_data
  198. }
  199. ---@type UnionChangeLeader.UnionRunForLeaderData
  200. data = {
  201. ridlist = leader_map,
  202. endtime = tostring(end_mills),
  203. unionid = union_id,
  204. isreplace = is_replace
  205. }
  206. else
  207. -- 添加竞选者
  208. data.ridlist[rid] = member_data
  209. end
  210. this.setRunForLeaderData(union_id, data)
  211. -- 调试数据
  212. -- start_delay = 1 == 1
  213. if start_delay then
  214. this.delaycallFunRunerforLeader(delay_second)
  215. -- 首次发起 -- 发送邮件给所有成员
  216. if is_replace then
  217. local leader_name = union_data.memberinfos[tonumber(leader_id)].name
  218. this.sendAllMemberMails(union_data, this.EMAIL_IDS.START_RUN_FOR_LEADER_REPLACE, leader_name)
  219. else
  220. this.sendAllMemberMails(union_data, this.EMAIL_IDS.START_RUN_FOR_LEADER, "")
  221. end
  222. end
  223. local result = is_replace and 2 or 1
  224. sendluamsg(actor, LuaMessageIdToClient.RES_PLAYER_RUN_FOR_LEADER, result)
  225. sendluamsg(actor, LuaMessageIdToClient.RES_UNION_RUN_FOR_LEADER_DATA, data)
  226. end
  227. function this.delaycallFunRunerforLeader(delay_second)
  228. this.debug("------ " .. delay_second .. "秒后结算竞选 -------")
  229. GlobalTimer.setontimerex(TimerIds.UNION_RUN_FOR_LEADER, delay_second)
  230. end
  231. function this.finishRunforLeaderActor()
  232. this.debug("---------- finishRunforLeaderActor ----------")
  233. local all_data = this.getAllRunForLeaderData()
  234. local uids = this.sortAllData(all_data)
  235. if table.isEmpty(uids) then
  236. return
  237. end
  238. local union_id = uids[1]
  239. local data = all_data[union_id]
  240. local union_data = getunioninfo(union_id)
  241. local member_infos = union_data.memberinfos
  242. local leaderid_list = {}
  243. local max_count = 0
  244. local rid_list = data.ridlist
  245. if table.notEmpty(rid_list) then
  246. for rid, rid_data in pairs(rid_list) do
  247. local count = rid_data["count"]
  248. if max_count < count then
  249. leaderid_list = { rid }
  250. max_count = count
  251. elseif max_count == count then
  252. if member_infos[tonumber(rid)] ~= nil then
  253. table.insert(leaderid_list, rid)
  254. end
  255. end
  256. end
  257. if table.notEmpty(leaderid_list) then
  258. local leader_id = this.getRandomElement(leaderid_list)
  259. local union_data = getunioninfo(union_id)
  260. -- 邮件信息
  261. local new_leader_name = ""
  262. if union_data.memberinfos[tonumber(leader_id)] ~= nil then
  263. new_leader_name = union_data.memberinfos[tonumber(leader_id)].name
  264. end
  265. local fail_mail_id = 0
  266. local success_mail_id = 0
  267. local fail_mail_param = ""
  268. local success_mail_param = ""
  269. if tonumber(union_data.leaderid) > 0 then
  270. fail_mail_id = this.EMAIL_IDS.RUN_FOR_LEADER_REPLACE_FAIL
  271. success_mail_id = this.EMAIL_IDS.RUN_FOR_LEADER_REPLACE_SUCCESS
  272. local old_leader_name = union_data.memberinfos[tonumber(union_data.leaderid)].name
  273. fail_mail_param = new_leader_name .. "#" .. old_leader_name
  274. success_mail_param = old_leader_name
  275. else
  276. fail_mail_id = this.EMAIL_IDS.RUN_FOR_LEADER_FAIL
  277. success_mail_id = this.EMAIL_IDS.RUN_FOR_LEADER_SUCCESS
  278. success_mail_param = union_data.unionname
  279. end
  280. -- 设置盟主
  281. setunionleader(union_id, leader_id)
  282. this.sendMemberMails(leader_id, success_mail_id, {}, success_mail_param)
  283. this.debug("【" .. union_data.unionname .. "】 " .. "竞选/取代 设置盟主成功")
  284. for member_id, data_member in pairs(rid_list) do
  285. if member_id == leader_id then
  286. goto continue
  287. end
  288. -- 返还其他竞选者的竞选费用
  289. local item_arr = string.split(data_member.cost_item, "#")
  290. local item = { [tonumber(item_arr[1])] = tonumber(item_arr[2]) }
  291. this.sendMemberMails(member_id, fail_mail_id, item, fail_mail_param)
  292. :: continue ::
  293. end
  294. end
  295. end
  296. table.remove(uids, 1)
  297. this.setRunForLeaderData(union_id, nil)
  298. local has_next, left_second = this.initNextUnionDelayTask(all_data, uids)
  299. if has_next then
  300. this.delaycallFunRunerforLeader(left_second)
  301. end
  302. end
  303. function this.initRunForLeaderTask()
  304. local all_data = this.getAllRunForLeaderData()
  305. this.startInitUnionDelayTask(all_data, this.DelayType.RunForLeader)
  306. end
  307. function this.getRandomElement(tbl)
  308. local count = #tbl
  309. if count == 0 then
  310. return nil
  311. end
  312. local index = math.random(1, count)
  313. return tbl[index]
  314. end
  315. function this.actorVoteRunForLeader(actor, vote_data)
  316. if #vote_data < 1 then
  317. this.debug("没有获取到投票数据!")
  318. return
  319. end
  320. local member_id = vote_data[1]
  321. local count = tonumber(vote_data[2])
  322. if tonumber(member_id) < 1 or count < 1 then
  323. this.debug("没有获取到玩家ID 或 票数!")
  324. return
  325. end
  326. local union_id = getbaseinfo(actor, "unionid")
  327. --- @type UnionChangeLeader.UnionRunForLeaderData
  328. local data = this.getRunForLeaderData(tostring(union_id))
  329. if table.isEmpty(data) then
  330. this.debug("没有获取到竞选/取代信息!")
  331. return
  332. end
  333. local union_data = getunioninfo(actor)
  334. if tonumber(union_data.leaderid) > 0 then
  335. this.info(actor, "取代盟主 不能投票.")
  336. return
  337. end
  338. local now = getbaseinfo("now")
  339. local last_vote_time = getplaydef(actor, UnionConsts.UNION_VOTE_TIME_CONST) or 0
  340. if last_vote_time > now - 86400 * 3000 then
  341. this.info(actor, "已经投票过了 不能投票.")
  342. return
  343. end
  344. local rid_list = data.ridlist
  345. local member_data = rid_list[tostring(member_id)]
  346. if table.isEmpty(member_data) then
  347. this.debug("没有获取到该玩家信息!")
  348. return
  349. end
  350. if table.isEmpty(union_data) then
  351. this.debug(actor, "获取战盟信息异常")
  352. return
  353. end
  354. local level = union_data.unionlevel
  355. local votecast = ConfigDataManager.getTableValue("cfg_unionlevel", "votecast", "unionLevel", level)
  356. local cost_ret = this.unionCostItem(actor, votecast, count)
  357. if not cost_ret then
  358. this.info(actor, "消耗道具失败!无法参与竞选投票.")
  359. this.debug("cost_str" .. tostring(votecast))
  360. return
  361. end
  362. setplaydef(actor, UnionConsts.UNION_VOTE_TIME_CONST, now)
  363. member_data.count = member_data.count + count
  364. this.setRunForLeaderData(union_id, data)
  365. sendluamsg(actor, LuaMessageIdToClient.RES_PLAYER_RUN_FOR_LEADER_VOTE, vote_data)
  366. end
  367. function this.runForLeaderMemberQuit(actor)
  368. local rid = actor:toString()
  369. local union_id = getbaseinfo(actor, "unionid")
  370. --- @type UnionChangeLeader.UnionRunForLeaderData
  371. local data = this.getRunForLeaderData(union_id)
  372. if table.isEmpty(data) then
  373. return
  374. end
  375. local member_data = data.ridlist[rid]
  376. if member_data == nil then
  377. return
  378. end
  379. data.ridlist[rid] = nil
  380. this.setRunForLeaderData(union_id, data)
  381. this.sendRunForLeaderData(actor)
  382. end
  383. --------------------------------- ↑战盟竞选逻辑结束↑ ----------------------------------
  384. ---------------------------------------------------------------------------------------
  385. ----------------------------------- ↓战盟弹劾逻辑↓ -------------------------------------
  386. UnionChangeLeader.Impeach = {}
  387. this.ImpeachDatKey = "U$_UNION_IMPEACH_DATA"
  388. this.ImpeachGlobalDataKey = "G$_UNION_IMPEACH_GLOBAL_DATA_KEY"
  389. ---@class UnionChangeLeader.ImpeachData
  390. ---@field endtime string
  391. ---@field initiator number
  392. ---@field agreelist number[]
  393. ---@field disagreelist number[]
  394. function UnionChangeLeader.Impeach.sendImpeachInfo(actor)
  395. this.sendImpeachInfo(actor)
  396. end
  397. function UnionChangeLeader.Impeach.actorImpeach(actor)
  398. this.actorImpeach(actor)
  399. end
  400. function UnionChangeLeader.Impeach.finishImpeachData()
  401. this.finishImpeachData()
  402. end
  403. function UnionChangeLeader.Impeach.actorVoteImpeach(actor, vote)
  404. this.actorVoteImpeach(actor, vote)
  405. end
  406. -----------------------------------------------
  407. function this.initGlobalImpeachData()
  408. local global_data = {}
  409. local summary_list = getallunionsummary()
  410. if table.isEmpty(summary_list) then
  411. return
  412. end
  413. for _, summary in pairs(summary_list) do
  414. local union_id = summary.unionid
  415. local data = this.getImpeachData(union_id)
  416. if not table.isEmpty(data) and not table.isEmpty(data.ridlist) then
  417. global_data[union_id] = data
  418. end
  419. end
  420. this.setAllImpeachData(global_data)
  421. end
  422. function this.getAllImpeachData()
  423. return getsysvar(this.ImpeachGlobalDataKey)
  424. end
  425. function this.setAllImpeachData(data)
  426. setsysvar(this.ImpeachGlobalDataKey, data)
  427. end
  428. function this.getImpeachData(union_id)
  429. local union_actor = getguild(union_id)
  430. return getguilddef(union_actor, this.ImpeachDatKey)
  431. end
  432. function this.setImpeachData(union_id, data)
  433. local union_actor = getguild(union_id)
  434. setguilddef(union_actor, this.ImpeachDatKey, data)
  435. -- 同步全服数据
  436. local all_data = this.getAllImpeachData()
  437. if not all_data then
  438. all_data = {}
  439. end
  440. all_data[union_id] = data
  441. this.setAllImpeachData(all_data)
  442. end
  443. function this.sendImpeachInfo(actor)
  444. local union_id = getbaseinfo(actor, "unionid")
  445. local data = this.getImpeachData(union_id)
  446. sendluamsg(actor, LuaMessageIdToClient.RES_SEND_UNION_IMPEACH_INFO, data)
  447. end
  448. function this.actorImpeach(actor)
  449. local union_data = getunioninfo(actor)
  450. if table.isEmpty(union_data) then
  451. this.debug( "获取战盟信息异常")
  452. return
  453. end
  454. local leader_id = tostring(union_data.leaderid)
  455. if tonumber(leader_id) < 1 then
  456. this.info(actor, "战盟中没有盟主, 无法弹劾")
  457. return
  458. end
  459. local rid = tostring(getbaseinfo(actor, "id"))
  460. if tonumber(rid) == tonumber(leader_id) then
  461. this.info(actor, "盟主不能弹劾自己")
  462. return
  463. end
  464. local now = getbaseinfo("now")
  465. local level = union_data.unionlevel
  466. local abdicationtime = ConfigDataManager.getTableValue("cfg_unionlevel", "abdicationtime", "unionLevel", level)
  467. local on_second = (now - union_data.leaderontime) / 60 / 1000
  468. if on_second < tonumber(abdicationtime) then
  469. this.info(actor, "盟主在位时间不足。 on_second " .. tostring(on_second))
  470. return
  471. end
  472. local impeach_data = this.getImpeachData(union_data.unionid)
  473. if not table.isEmpty(impeach_data) then
  474. this.info(actor, "该盟主正在被弹劾")
  475. return
  476. end
  477. local condition = ConfigDataManager.getTableValue("cfg_unionlevel", "campaignCondition", "unionLevel", level)
  478. if condition and condition ~= "" then
  479. local isPass = ConditionManager.Check(actor, condition)
  480. if not isPass then
  481. this.info(actor, "不满弹劾条件")
  482. return
  483. end
  484. end
  485. -- 消耗道具
  486. local cast_str = ConfigDataManager.getTableValue("cfg_unionlevel", "campaignCast", "unionLevel", level)
  487. if cast_str and cast_str ~= "" then
  488. local cost_item = string.split(cast_str, "#")
  489. local cost_ret = removeitemfrombag(actor, cost_item[1], cost_item[2], 0, 9999, '战盟-盟主竞选')
  490. if not cost_ret then
  491. this.info(actor, "消耗道具失败!无法参与竞选/取代!")
  492. this.debug("cost_str" .. tostring(cast_str))
  493. return
  494. end
  495. end
  496. -- 发起弹劾
  497. local impeachment = ConfigDataManager.getTableValue("cfg_unionlevel", "impeachment", "unionLevel", level)
  498. local delay_second = impeachment * 60
  499. -- delay_second = 60
  500. local end_time = now + (delay_second * 1000)
  501. ---@type UnionChangeLeader.ImpeachData
  502. impeach_data = {
  503. endtime = tostring(end_time),
  504. initiator = rid,
  505. agreelist = {},
  506. disagreelist = {},
  507. }
  508. this.setImpeachData(union_data.unionid, impeach_data)
  509. this.delaycallFunImpeach(delay_second)
  510. sendluamsg(actor, LuaMessageIdToClient.RES_UNION_IMPEACH_LEADER, union_data)
  511. -- 弹劾邮件
  512. local leader_name = union_data.memberinfos[tonumber(leader_id)].name
  513. this.sendAllMemberMails(union_data, this.EMAIL_IDS.START_IMPEACH, leader_name)
  514. end
  515. function this.delaycallFunImpeach(delay_second)
  516. this.debug(delay_second .. "秒后执行弹劾")
  517. GlobalTimer.setontimerex(TimerIds.UNION_IMPEACH, delay_second)
  518. end
  519. function this.finishImpeachData()
  520. local data = this.getAllImpeachData()
  521. local uids = this.sortAllData(data)
  522. if table.isEmpty(uids) then
  523. return
  524. end
  525. local union_id = uids[1]
  526. local impeach_data = data[union_id]
  527. local mail_id = 0
  528. local union_data = getunioninfo(union_id)
  529. local leader_name = union_data.memberinfos[tonumber(union_data.leaderid)].name
  530. -- 计算弹劾结果
  531. local success = #impeach_data.agreelist > #impeach_data.disagreelist
  532. if success then
  533. this.debug("-- 弹劾完成,盟主退位 --")
  534. setunionleader(union_id, 0)
  535. mail_id = this.EMAIL_IDS.IMPEACH_SUCCESS
  536. else
  537. mail_id = this.EMAIL_IDS.IMPEACH_FAIL
  538. end
  539. this.setImpeachData(union_id, nil)
  540. -- 发送弹劾完成邮件
  541. this.sendAllMemberMails(union_data, mail_id, leader_name)
  542. table.remove(uids, 1)
  543. local has_next, left_second = this.initNextUnionDelayTask(data, uids)
  544. if has_next then
  545. this.delaycallFunImpeach(left_second)
  546. end
  547. end
  548. function this.initImpeachTask()
  549. local all_data = this.getAllImpeachData()
  550. this.startInitUnionDelayTask(all_data, this.DelayType.Impeach)
  551. end
  552. function this.actorVoteImpeach(actor, is_aggree)
  553. local union_id = getbaseinfo(actor, "unionid")
  554. ---@type UnionChangeLeader.ImpeachData
  555. local data = this.getImpeachData(union_id)
  556. if table.isEmpty(data) then
  557. this.debug("没有获取到弹劾信息!")
  558. return
  559. end
  560. if is_aggree ~= 1 and is_aggree ~= 0 then
  561. this.info(actor, "无效票")
  562. return
  563. end
  564. local union_data = getunioninfo(actor)
  565. local leader_id = tostring(union_data.leaderid)
  566. local rid = tostring(getbaseinfo(actor, "id"))
  567. if tonumber(rid) == tonumber(leader_id) then
  568. this.info(actor, "盟主不能投票")
  569. return
  570. end
  571. if tonumber(rid) == tonumber(data.initiator) then
  572. this.info(actor, "发起人不能投票")
  573. return
  574. end
  575. if table.contains(data.agreelist, rid) then
  576. this.info(actor, "玩家已经投赞成票")
  577. return
  578. end
  579. if table.contains(data.disagreelist, rid) then
  580. this.info(actor, "玩家已经投反对票")
  581. return
  582. end
  583. local level = union_data.unionlevel
  584. local cost_str = ConfigDataManager.getTableValue("cfg_unionlevel", "campaignVoteCast", "unionLevel", level)
  585. if cost_str and cost_str ~= "" then
  586. local cost_item = string.split(cost_str, "#")
  587. local cost_ret = removeitemfrombag(actor, cost_item[1], cost_item[2], 0, 9999, '战盟-盟主竞选')
  588. if not cost_ret then
  589. this.info(actor, "消耗道具失败!无法参与竞选/取代!")
  590. this.debug("cost_str" .. tostring(cost_str))
  591. return
  592. end
  593. end
  594. if is_aggree == 1 then
  595. table.insert(data.agreelist, rid)
  596. elseif is_aggree == 0 then
  597. table.insert(data.disagreelist, rid)
  598. end
  599. this.setImpeachData(union_id, data)
  600. sendluamsg(actor, LuaMessageIdToClient.RES_UNION_IMPEACH_VOTE, is_aggree)
  601. end
  602. ----------------------------------- ↑战盟弹劾逻辑↑ -----------------------------------
  603. ------------------------------------------ 通用函数 ----------------------------------------
  604. function this.sortAllData(all_data)
  605. local uids = {}
  606. if table.isEmpty(all_data) then
  607. return uids
  608. end
  609. for uid in pairs(all_data) do
  610. table.insert(uids, uid)
  611. end
  612. function this.sortUidsByEndTimeDesc(a, b)
  613. return tonumber(all_data[a].endtime) < tonumber(all_data[b].endtime)
  614. end
  615. -- 排序函数
  616. table.sort(uids, this.sortUidsByEndTimeDesc)
  617. return uids
  618. end
  619. function this.startInitUnionDelayTask(data, type)
  620. local uids = this.sortAllData(data)
  621. if table.isEmpty(uids) then
  622. return
  623. end
  624. local has_next, left_second = this.initNextUnionDelayTask(data, uids)
  625. if not has_next then
  626. return
  627. end
  628. if type == this.DelayType.RunForLeader then
  629. this.delaycallFunRunerforLeader(left_second)
  630. elseif type == this.DelayType.Impeach then
  631. this.delaycallFunImpeach(left_second)
  632. end
  633. end
  634. function this.initNextUnionDelayTask(data, uids)
  635. if #uids < 1 then
  636. return false
  637. end
  638. local next_union_id = uids[1]
  639. local next_data = data[next_union_id]
  640. local now = tonumber(getbaseinfo("now"))
  641. local next_end_time = tonumber(next_data.endtime)
  642. if not next_end_time then
  643. this.debug("结束时间无效, 请检查next_data.endtime")
  644. return false
  645. end
  646. local left_second = (next_end_time - now) / 1000
  647. if left_second < 10 then
  648. left_second = 10
  649. end
  650. return true, left_second
  651. end
  652. function this.unionCostItem(actor, cost_str, rate)
  653. rate = rate or 1
  654. if not cost_str or cost_str == "" then
  655. return true
  656. end
  657. local cost_item = string.split(cost_str, "#")
  658. local item_id = cost_item[1]
  659. local item_count = cost_item[2]
  660. item_count = math.floor(item_count * rate)
  661. local cost_ret = removeitemfrombag(actor, item_id, item_count, 0, 9999, '战盟-盟主竞选')
  662. if not cost_ret then
  663. return false
  664. end
  665. return true
  666. end
  667. function this.sendAllMemberMails(union_data, mail_id, param)
  668. for id, _ in pairs(union_data.memberinfos) do
  669. this.sendMemberMails(id, mail_id, nil, param)
  670. end
  671. end
  672. function this.sendMemberMails(rid, mail_id, item, param)
  673. sendconfigmailbyrid(rid, mail_id, item, param)
  674. end
  675. ---------------------------- 日志打印 -----------------------------
  676. this.log_open = false
  677. this.log_name = "[union_change_leader]"
  678. function this.debug(...)
  679. if not this.log_open then
  680. return
  681. end
  682. gameDebug.print(this.log_name, ...)
  683. end
  684. function this.info(actor, ...)
  685. if this.log_open then
  686. jprint(this.log_name, ...)
  687. end
  688. tipinfo(actor, ...)
  689. end