UnionChangeLeader.lua 27 KB

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