UnionChangeLeader.lua 26 KB

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