role.lua 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. local skynet = require "skynet"
  2. local schema = require "model.schema"
  3. local logger = require "logger"
  4. local asset = require "model.asset"
  5. local reward = require "model.reward"
  6. local common_fun = require "model.common_fun"
  7. local stringify = require "stringify"
  8. local embattle
  9. local mailbox
  10. local namecenter
  11. local shengtian
  12. local math_max = math.max
  13. local math_min = math.min
  14. local table_insert = table.insert
  15. local MAX_STM = 100
  16. local currency
  17. local module_name = "role"
  18. local _M = schema.new(module_name, {
  19. login_tims = 0; -- 登录次数
  20. re_stm = 0;
  21. first = false;
  22. })
  23. local REQUEST = {}
  24. local CMD = {}
  25. local MODULE = {}
  26. local THIS = {}
  27. local function func_ret(fname, character, args)
  28. local f = THIS[fname]
  29. if not f then
  30. logger.error("func_ret not fname:%s !!!", fname)
  31. return {errno = STD_ERR.COMMON_SYS_ERR}
  32. end
  33. local errno, ret = f(character, args)
  34. if errno ~= 0 then
  35. return {errno = errno}
  36. end
  37. ret = ret or {}
  38. ret.errno = 0
  39. return ret
  40. end
  41. function MODULE.list_request_interests() return REQUEST end
  42. function MODULE.list_command_interests() return CMD end
  43. -- TODO: 解析/升级模块数据
  44. function MODULE.parse(character)
  45. local d = _M.load(character)
  46. end
  47. -- TODO: 侦听事件
  48. function MODULE.monitor(character)
  49. local d = _M.assert_get(character)
  50. local reset_stm = THIS.reset_stm(d, character)
  51. character.monitor('timer.sec', function(_, ti)
  52. reset_stm(ti)
  53. end)
  54. character.monitor("currency_add", function(_, id, num)
  55. if id == CURRENCY_ID_ROLE_EXP then
  56. THIS.role_add_exp(character, num)
  57. end
  58. end)
  59. character.monitor("role_level", function(_, pre, cur)
  60. shengtian = shengtian or require "service.loginserver.shengtian"
  61. local content = {
  62. account = character.account,
  63. uid = character.uid,
  64. name = character.nickname,
  65. server = character.sid,
  66. level = character.level,
  67. power = character.power,
  68. }
  69. shengtian.upload(2, content)
  70. end)
  71. end
  72. -- TODO: 类似泰利的 prepare 接口
  73. function MODULE.launch(character)
  74. local d = _M.assert_get(character)
  75. currency = currency or require "model.currency"
  76. embattle = embattle or require "model.embattle"
  77. namecenter = skynet.localname(".namecenter")
  78. end
  79. -- TODO: 与客户端同步数据
  80. function MODULE.ready(character)
  81. local d = _M.assert_get(character)
  82. if not d.first then
  83. THIS.first_login(d, character)
  84. d.first = true
  85. end
  86. d.login_tims = math_max(0, d.login_tims) + 1
  87. _M.persist(character)
  88. end
  89. -- TODO: 玩家下线时的处理
  90. function MODULE.saybye(character)
  91. end
  92. -- -- TODO: 在这定义网络请求的处理代码
  93. -- function REQUEST.echo(character, args)
  94. -- end
  95. function MODULE.stm_change(character)
  96. local u = _M.assert_runtime(character)
  97. u.stm_change = true
  98. end
  99. function THIS.check_stm_change(d, character, bsend)
  100. local d = d or _M.assert_get(character)
  101. local bfull = THIS.check_stm_full(d, character)
  102. local change = false
  103. -- 满了且有重置时间
  104. if bfull and d.re_stm > 0 then
  105. d.re_stm = 0
  106. change = true
  107. end
  108. -- 没满也没有重置时间
  109. if not bfull and d.re_stm <= 0 then
  110. d.re_stm = os.time()
  111. change = true
  112. end
  113. if change or bsend then
  114. local time = d.re_stm
  115. if time > 0 then
  116. local conf = assert(asset.DataConfig_proto[1], "DataConfig_proto[1]")
  117. local one_time = conf.data1
  118. time = time + one_time
  119. end
  120. character.send("city_change", {currency = {id = CURRENCY_ID_STM, num = currency.get_money(character, CURRENCY_ID_STM)}, time = time})
  121. if change then
  122. _M.persist(character)
  123. end
  124. end
  125. return false
  126. end
  127. function THIS.check_stm_full(d, character)
  128. local d = d or _M.assert_get(character)
  129. local num = THIS.max_stm(d, character) - currency.get_money(character, CURRENCY_ID_STM)
  130. return num <= 0, num
  131. end
  132. function THIS.max_stm(d, character)
  133. return asset.DataConfig_proto[2].data3
  134. end
  135. function THIS.first_login(d, character)
  136. local DataConf = asset.DataConfig_proto[2]
  137. local errno, award_list = common_fun.get_award(DataConf.data2)
  138. if errno ~= 0 then
  139. return errno
  140. end
  141. if not award_list or not next(award_list) then
  142. return STD_ERR.COMMON_CONF_ERR -- 配置异常
  143. end
  144. -- 发奖励
  145. local desc = {
  146. module="first_login",
  147. brief="首次登录",
  148. context= "首次登录",
  149. mailgen={subject=2, body=""},
  150. notify={
  151. flags="first_login"
  152. },
  153. detail=award_list
  154. }
  155. reward(character, desc)
  156. embattle.first_battle(character)
  157. -- mailbox = mailbox or require "model.mailbox"
  158. -- local desc = {
  159. -- module = "首次登录",
  160. -- brief = "首次登录",
  161. -- context = "首次登录",
  162. -- }
  163. -- mailbox.send(character, 3, "", {}, desc)
  164. -- currency.add_money(character, CURRENCY_ID_STM, MAX_STM)
  165. end
  166. function THIS.reset_stm(d, character)
  167. local conf = assert(asset.DataConfig_proto[1], "DataConfig_proto[1]")
  168. local one_time = conf.data1
  169. local one_add = conf.data2
  170. local u = _M.assert_runtime(character)
  171. u.stm_change = true
  172. u.stm_send = true
  173. return function (ti)
  174. if d.re_stm > 0 then
  175. if d.re_stm + one_time <= ti then
  176. local bfull, max_add = THIS.check_stm_full(d, character)
  177. if not bfull then
  178. local times = math.floor((ti - d.re_stm) / one_time)
  179. local add_num = times * one_add
  180. if add_num >= max_add then
  181. currency.add_money(character, CURRENCY_ID_STM, max_add)
  182. d.re_stm = 0
  183. else
  184. currency.add_money(character, CURRENCY_ID_STM, add_num)
  185. d.re_stm = d.re_stm + times * one_time
  186. end
  187. else
  188. d.re_stm = 0
  189. end
  190. u.stm_change = true
  191. u.stm_send = true
  192. _M.persist(character)
  193. end
  194. end
  195. if u.stm_change then
  196. THIS.check_stm_change(d, character, u.stm_send)
  197. u.stm_change = false
  198. u.stm_send = false
  199. end
  200. end
  201. end
  202. function THIS.role_get_client_data(character)
  203. local level = character.level
  204. local exp = character.exp
  205. local conf = asset.RanksLevelConfig_proto[level+1]
  206. if not conf then
  207. exp = 0
  208. else
  209. exp = math_min(conf.exp, exp)
  210. end
  211. return {level = level, exp = exp}
  212. end
  213. function THIS.role_add_exp(character, num)
  214. local conf = asset.RanksLevelConfig_proto[character.level+1]
  215. if not conf then
  216. character.set_exp(0)
  217. else
  218. if num > 0 then
  219. character.set_exp(character.exp + num)
  220. end
  221. end
  222. end
  223. function THIS.role_get_data(character, args)
  224. return 0, THIS.role_get_client_data(character)
  225. end
  226. function THIS.role_upgrade(character, args)
  227. local exp = character.exp
  228. local level = character.level
  229. local award_list = {}
  230. while true do
  231. local conf = asset.RanksLevelConfig_proto[level+1]
  232. if not conf then
  233. exp = 0
  234. break
  235. end
  236. if exp > conf.exp then
  237. exp = exp - conf.exp
  238. level = level + 1
  239. for i = 1, #conf.award, 2 do
  240. local id = conf.award[i]
  241. local num = conf.award[i+1]
  242. if id and num and id > 0 and num > 0 then
  243. table_insert(award_list, {id = id, num = num})
  244. else
  245. break
  246. end
  247. end
  248. else
  249. break
  250. end
  251. end
  252. if level ~= character.level then
  253. if next(award_list) then
  254. local desc = {
  255. module="role",
  256. brief="队伍等级提升",
  257. context= string.format("队伍等级提升%d=>%d", character.level, level),
  258. mailgen={subject=2, body=""},
  259. notify={
  260. flags="role_upgrade"
  261. },
  262. detail=award_list
  263. }
  264. reward(character, desc)
  265. end
  266. local pre = character.level
  267. character.set_level(level)
  268. character.set_exp(exp)
  269. character.dispatch("role_level", pre, level)
  270. end
  271. return 0, THIS.role_get_client_data(character)
  272. end
  273. function THIS.role_rename(character, args)
  274. local name = args.name
  275. if not name then
  276. return STD_ERR.COMMON_PARM_ERR -- 参数异常
  277. end
  278. if name == character.nickname then
  279. return STD_ERR.COMMON_PARM_ERR -- 参数异常
  280. end
  281. local length = string.len(name)
  282. if length <=1 or length >21 then
  283. return STD_ERR.COMMON_PARM_ERR -- 参数异常
  284. end
  285. if string.match(name, "[%p]") then
  286. return -- 参数异常
  287. end
  288. if os.time() - character.rename_time < 48*HOUR_SEC then
  289. return STD_ERR.COMMON_PARM_ERR -- 参数异常
  290. end
  291. local errno = skynet.call(namecenter, "lua", "rename", character.nickname, name, character.uid)
  292. if errno ~= 0 then
  293. return errno
  294. end
  295. local oldname = character.nickname
  296. character.set_nickname(name)
  297. character.set_rename_time(os.time())
  298. skynet.call(namecenter, "lua", "unlock_name", oldname)
  299. return 0, {name = args.name, time = character.rename_time}
  300. end
  301. function REQUEST.role_get_data(character, args)
  302. return func_ret("role_get_data", character, args)
  303. end
  304. function REQUEST.role_upgrade(character, args)
  305. return func_ret("role_upgrade", character, args)
  306. end
  307. function REQUEST.role_rename(character, args)
  308. return func_ret("role_rename", character, args)
  309. end
  310. function CMD.ban_rank(character, ban)
  311. if character.ban_rank ~= ban then
  312. character.set_ban_rank(ban)
  313. end
  314. end
  315. return MODULE