functions.lua 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. function lobby.load()
  2. local file = io.open(minetest.get_worldpath() .. '/levels', 'r')
  3. if file then
  4. lobby.savedata = minetest.deserialize(file:read('*a'))
  5. file:close()
  6. --lobby.savedata.stats = {}
  7. --lobby.savedata.name_2_id = {}
  8. --lobby.savedata.id_2_name = {}
  9. else
  10. lobby.savedata = {}
  11. lobby.savedata.IDs = {}
  12. lobby.savedata.data = {}
  13. lobby.savedata.stats = {}
  14. lobby.savedata.name_2_id = {}
  15. lobby.savedata.id_2_name = {}
  16. end
  17. end
  18. function lobby.save()
  19. local file = io.open(minetest.get_worldpath() .. '/levels', 'w')
  20. file:write(minetest.serialize(lobby.savedata))
  21. file:close()
  22. end
  23. function lobby.no_drop(itemstack, dropper, pos)
  24. return
  25. end
  26. function lobby.is_integer(input)
  27. local number = tonumber(input)
  28. if number then
  29. if math.floor(number) == number then
  30. return true
  31. end
  32. end
  33. end
  34. local storage = minetest.get_mod_storage()
  35. function lobby.queue_xp(name, xp) --Queues XP for offline players
  36. storage:set_int(name, xp)
  37. end
  38. function lobby.check_xp_queue(name) --Checks if a player was award xp whilst offline.
  39. local xp = storage:get_int(name)
  40. if xp > 0 then
  41. local player = minetest.get_player_by_name(name)
  42. lobby.give_xp(player, xp)
  43. storage:set_int(name, 0)
  44. minetest.chat_send_player(name, 'Hey, you just got '..xp..' xp!')
  45. end
  46. end
  47. function lobby.give_xp(player, amount)
  48. local player_attributes = player:get_meta()
  49. local xp = player_attributes:get_float('xp') or 0
  50. xp = xp + amount
  51. player_attributes:set_float('xp', xp)
  52. sfinv.set_player_inventory_formspec(player)
  53. end
  54. function lobby.take_xp(player, amount)
  55. local player_attributes = player:get_meta()
  56. local xp = player_attributes:get_float('xp')
  57. if xp >= amount then
  58. local xp = xp - amount
  59. player_attributes:set_float('xp', xp)
  60. sfinv.set_player_inventory_formspec(player)
  61. return true
  62. else
  63. return false
  64. end
  65. end
  66. function lobby.corpse_entry(pos, map_id)
  67. local corpse_pos = lobby.corpses[map_id]
  68. table.insert(corpse_pos, pos)
  69. lobby.corpses[map_id] = corpse_pos
  70. end
  71. function lobby.corpse_removal(map_id)
  72. local corpse_pos = lobby.corpses[map_id]
  73. if corpse_pos then
  74. for key, value in pairs(corpse_pos) do
  75. minetest.set_node(value, {name='air'})
  76. end
  77. end
  78. end
  79. function lobby.players_on_level(map_id)
  80. local survivors = ''
  81. for _, player in pairs(minetest.get_connected_players()) do
  82. local rname = player:get_player_name()
  83. if lobby.game[rname] == map_id then
  84. survivors = survivors..rname..', '
  85. end
  86. end
  87. return survivors
  88. end
  89. function lobby.update_maps(map_id)
  90. local count = lobby.map[map_id] - 1 or 10
  91. if count <= 1 then
  92. lobby.map[map_id] = 0
  93. lobby.corpse_removal(map_id)
  94. for _, player in pairs(minetest.get_connected_players()) do
  95. local rname = player:get_player_name()
  96. if lobby.game[rname] == map_id or lobby.game[rname] == map_id..'_ghost' then
  97. minetest.close_formspec(rname, '')
  98. player:respawn()
  99. local player_attributes = player:get_meta()
  100. player:set_nametag_attributes({
  101. color = {a = 255, r = 255, g = 255, b = 255}
  102. })
  103. player:set_properties({visual_size = {x = 10, y = 10}, collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}})
  104. player:set_pos(lobby.spawn_pos)
  105. player_attributes:set_string('mode', 'solo')
  106. minetest.chat_send_player(rname, 'Kicking you to the lobby')
  107. player:set_physics_override({speed=1})
  108. local player_inv = player:get_inventory()
  109. player_inv:set_list('main', {})
  110. lobby.game[rname] = 'lobby'
  111. local idx = sabotage.hud[rname]
  112. if idx then
  113. for key,value in pairs(idx) do
  114. player:hud_remove(value)
  115. end
  116. end
  117. end
  118. end
  119. else
  120. lobby.map[map_id] = count
  121. end
  122. end
  123. function lobby.vote(map_id, force)
  124. local needed_votes = lobby.map[map_id] - 1
  125. local actual_votes = lobby.votes[map_id]
  126. if actual_votes >= needed_votes or force then
  127. lobby.vote_timer[map_id] = -1
  128. --Reset vote status and kick player with the highest score.
  129. local high_score = 0
  130. local kick = ''
  131. local traitor = lobby.traitors[map_id]
  132. for _, player in pairs(minetest.get_connected_players()) do
  133. local rname = player:get_player_name()
  134. if lobby.game[rname] == map_id then
  135. local score = lobby.suspect[rname]
  136. local player_attributes = player:get_meta()
  137. if score > high_score then
  138. high_score = score
  139. kick = rname
  140. end
  141. lobby.suspect[rname] = 0
  142. player:set_physics_override({speed=1})
  143. player:set_armor_groups({})
  144. player_attributes:set_string('voting', 'false')
  145. end
  146. end
  147. if kick == traitor then
  148. lobby.team_win(map_id)
  149. elseif needed_votes == 1 and kick ~= traitor then
  150. lobby.traitor_win(traitor, map_id)
  151. elseif kick ~= '' then
  152. lobby.message_to_level(map_id, 'The votes are in, '..kick..' will be kicked.')
  153. local player = minetest.get_player_by_name(kick)
  154. local player_attributes = player:get_meta()
  155. player:set_nametag_attributes({
  156. color = {a = 0, r = 255, g = 255, b = 255}
  157. })
  158. player:set_properties({visual_size = {x = 0, y = 0}, collisionbox = {-0.3, 0.0, -0.3, 0.3, .2, 0.3}})
  159. player:set_physics_override({speed=1})
  160. player_attributes:set_string('mode', 'ghost')
  161. minetest.chat_send_player(kick, 'You were kicked, and are now a ghost. Return to the lobby with the /lobby chat command.')
  162. lobby.game[kick] = map_id..'_ghost'
  163. lobby.update_maps(map_id)
  164. else
  165. lobby.message_to_level(map_id, 'Nobody was kicked this round.')
  166. for _, player in pairs(minetest.get_connected_players()) do
  167. local rname = player:get_player_name()
  168. if lobby.game[rname] == map_id then
  169. minetest.close_formspec(rname, 'lobby:voting')
  170. end
  171. end
  172. end
  173. end
  174. end
  175. function lobby.team_win(map_id)
  176. lobby.corpse_removal(map_id)
  177. local traitor = lobby.traitors[map_id]
  178. for _, player in pairs(minetest.get_connected_players()) do
  179. local rname = player:get_player_name()
  180. if lobby.game[rname] == map_id then
  181. local player_attributes = player:get_meta()
  182. player_attributes:set_string('mode', 'solo')
  183. minetest.close_formspec(rname, '')
  184. player:respawn()
  185. lobby.give_xp(player, 25)
  186. minetest.chat_send_player(rname, 'The traitor ('..traitor..') was defeated.')
  187. player:set_pos(lobby.spawn_pos)
  188. player:set_physics_override({speed=1})
  189. local player_inv = player:get_inventory()
  190. player_inv:set_list('main', {})
  191. lobby.game[rname] = 'lobby'
  192. local idx = sabotage.hud[rname]
  193. if idx then
  194. for key,value in pairs(idx) do
  195. player:hud_remove(value)
  196. end
  197. end
  198. elseif lobby.game[rname] == map_id..'_ghost' then
  199. minetest.close_formspec(rname, '')
  200. player:respawn()
  201. local player_attributes = player:get_meta()
  202. player:set_nametag_attributes({
  203. color = {a = 255, r = 255, g = 255, b = 255}
  204. })
  205. player:set_properties({visual_size = {x = 10, y = 10}, collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}})
  206. player:set_pos(lobby.spawn_pos)
  207. player_attributes:set_string('mode', 'solo')
  208. minetest.chat_send_player(rname, 'The traitor ('..traitor..') was defeated.')
  209. player:set_physics_override({speed=1})
  210. local player_inv = player:get_inventory()
  211. player_inv:set_list('main', {})
  212. lobby.game[rname] = 'lobby'
  213. local idx = sabotage.hud[rname]
  214. if idx then
  215. for key,value in pairs(idx) do
  216. player:hud_remove(value)
  217. end
  218. end
  219. end
  220. end
  221. lobby.map[map_id] = 0
  222. local start_time = lobby.play_time[map_id]
  223. local finish_time = minetest.get_us_time()
  224. local play_time = (finish_time - start_time)/1000000
  225. lobby.update_stats(map_id, '', 'team', nil, play_time)
  226. local game_data = lobby.savedata.data[map_id]
  227. local map_name
  228. if game_data then
  229. map_name = game_data['map_name']
  230. else
  231. map_name = map_id
  232. end
  233. minetest.chat_send_all('The traitor was defeated on this round in '..map_name)
  234. end
  235. function lobby.traitor_win(traitor, map_id)
  236. local player = minetest.get_player_by_name(traitor)
  237. lobby.corpse_removal(map_id)
  238. lobby.give_xp(player, 25)
  239. minetest.chat_send_player(traitor, 'CONGRATULATIONS!!! You killed all the crew!')
  240. lobby.game[traitor] = 'lobby'
  241. player:set_pos(lobby.spawn_pos)
  242. player:set_physics_override({speed=1})
  243. local player_inv = player:get_inventory()
  244. player_inv:set_list('main', {})
  245. lobby.map[map_id] = 0
  246. local start_time = lobby.play_time[map_id]
  247. local finish_time = minetest.get_us_time()
  248. local play_time = (finish_time - start_time)/1000000
  249. lobby.update_stats(map_id, '', 'traitor', nil, play_time)
  250. local game_data = lobby.savedata.data[map_id]
  251. local map_name = game_data['map_name'] or map_id
  252. minetest.chat_send_all('The traitor ('..traitor..') was victorious on this round in the '..map_name)
  253. end
  254. --[[ is_builder(player: ObjectRef): bool
  255. Return true if `player` has builder privs.
  256. --]]
  257. function lobby.is_builder(player)
  258. if player == nil then return nil end
  259. local name = player:get_player_name()
  260. return minetest.check_player_privs(name, {builder = true})
  261. end
  262. --[[ builder_to_player(player: ObjectRef)
  263. Cast builder into regular player, including switching inventories, revoking privs, etc.
  264. --]]
  265. function lobby.builder_to_player(player)
  266. if player == nil then return end
  267. local pl_name = player:get_player_name()
  268. local pl_attr = player:get_meta()
  269. local pl_priv = minetest.get_player_privs(pl_name)
  270. local pl_mode = pl_attr:get_string('mode') or ''
  271. if pl_mode ~= 'builder' then return end
  272. pl_priv.creative = nil
  273. pl_priv.fly = nil
  274. pl_priv.fast = nil
  275. pl_priv.worldedit = nil
  276. pl_priv.areas = nil
  277. minetest.set_player_privs(pl_name, pl_priv)
  278. pl_attr:set_string('mode', 'solo')
  279. local inv = player:get_inventory()
  280. local old_inv = inv:get_list('main')
  281. inv:set_list('builder', old_inv)
  282. inv:set_size('main', 16)
  283. inv:set_list('main', {})
  284. end
  285. --[[ player_to_builder(player: ObjectRef)
  286. Cast regular player into builder, including switching inventories, granting privs, etc.
  287. Does NOT check if the player has acquired the builder priv. Call lobby.is_builder()
  288. beforehand to make sure player is allowed to be lifted.
  289. --]]
  290. function lobby.player_to_builder(player)
  291. if player == nil then return end
  292. local pl_name = player:get_player_name()
  293. local pl_attr = player:get_meta()
  294. local pl_priv = minetest.get_player_privs(pl_name)
  295. local pl_mode = pl_attr:get_string('mode') or ''
  296. if pl_mode == 'builder' then return end
  297. pl_priv.creative = true
  298. pl_priv.fly = true
  299. pl_priv.fast = true
  300. minetest.set_player_privs(pl_name, pl_priv)
  301. pl_attr:set_string('mode', 'builder')
  302. local inv = player:get_inventory()
  303. local old_inv = inv:get_list('builder')
  304. inv:set_list('builder', {})
  305. inv:set_size('main', 32)
  306. inv:set_list('main', old_inv)
  307. end
  308. function lobby.create_id(player_name)
  309. local i = 1
  310. local map_id = player_name..'_'..i
  311. while lobby.savedata.IDs[map_id] do
  312. i = i + 1
  313. map_id = player_name..'_'..i
  314. end
  315. return map_id
  316. end