From 498236077d2d2edac307a7d71903ed111edda1a0 Mon Sep 17 00:00:00 2001 From: Nathan Salapat Date: Wed, 25 May 2022 21:43:57 -0500 Subject: [PATCH] Started adding sabotaging. --- mods/lobby/formspec.lua | 4 +- mods/lobby/functions.lua | 13 ++- mods/sabotage/formspecs.lua | 51 ++++++++++ mods/sabotage/functions.lua | 54 ++++++++++ mods/sabotage/init.lua | 119 +++++++++++++++++++++++ mods/sabotage/mod.conf | 1 + mods/sabotage/textures/sabotage_test.png | Bin 0 -> 4068 bytes mods/vents/data_base.lua | 4 +- mods/vents/station.lua | 19 +++- 9 files changed, 256 insertions(+), 9 deletions(-) create mode 100644 mods/sabotage/formspecs.lua create mode 100644 mods/sabotage/functions.lua create mode 100644 mods/sabotage/init.lua create mode 100644 mods/sabotage/mod.conf create mode 100644 mods/sabotage/textures/sabotage_test.png diff --git a/mods/lobby/formspec.lua b/mods/lobby/formspec.lua index e82a5cf..203b687 100644 --- a/mods/lobby/formspec.lua +++ b/mods/lobby/formspec.lua @@ -13,9 +13,7 @@ local page_2 = "Tasks\n".. "There are a wide variety of tasks, different tasks can give different amounts of XP. ".. "Map makers are able to set their own XP requirements, but don't worry, every time you earn XP ".. "you'll get a helpful chat message telling you how much more XP you need to defeat the traitor.\n".. - "Some tasks require you to get a replacement part, click a button, enter a code, or even just punch the node. ".. - "We won't get into detail about every task here, because there are more being added all the time, and you'll ".. - "have an oppertunity to try some different tasks out upon completing this short corse." + "Some tasks require you to get a replacement part, click a button, enter a code, or even just punch the node. " local page_3 = "Voting\n".. "Voting is one way to try and defeat the traitor. When a corpse is reported all players on a level will teleport ".. diff --git a/mods/lobby/functions.lua b/mods/lobby/functions.lua index fefb4eb..abf0e47 100644 --- a/mods/lobby/functions.lua +++ b/mods/lobby/functions.lua @@ -78,8 +78,10 @@ end function lobby.corpse_removal(map_id) local corpse_pos = lobby.corpses[map_id] - for key, value in pairs(corpse_pos) do - minetest.set_node(value, {name='air'}) + if corpse_pos then + for key, value in pairs(corpse_pos) do + minetest.set_node(value, {name='air'}) + end end end @@ -197,7 +199,12 @@ function lobby.team_win(map_id) lobby.map[map_id] = 0 lobby.update_stats(map_id, '', 'team') local game_data = lobby.savedata.data[map_id] - local map_name = game_data['map_name'] or map_id + local map_name + if game_data then + map_name = game_data['map_name'] + else + map_name = map_id + end minetest.chat_send_all('The traitor was defeated on this round in the '..map_name) end diff --git a/mods/sabotage/formspecs.lua b/mods/sabotage/formspecs.lua new file mode 100644 index 0000000..f1a1e09 --- /dev/null +++ b/mods/sabotage/formspecs.lua @@ -0,0 +1,51 @@ +function sabotage.traitor_formspec(pos) + local meta = minetest.get_meta(pos) + local timer = meta:get_int('timer') or 120 + local chance = meta:get_int('chance') or 1 + local damage = meta:get_int('damage') or 1 + local formspec = + 'formspec_version[3]'.. + 'size[10,8]'.. + 'textarea[.5,.5;9,6;;;Sabotage the crew, and risk life and limb. '.. + 'If the crew doesn\'t fix it in time you win, but you could die sabotaging.\n'.. + 'If you fail in sabotaging you could take up '..damage..' damage. '.. + 'The other players will be alerted and have time to attempt to \'repair\' the node, '.. + 'if they are successful they win the round, otherwise you win!'.. + '\n\nRisk Factor: '..chance..'/10 \nPotential Health Impact: '..damage..' \nFailure Timer: '..timer..' seconds]'.. + 'button_exit[3.5,7;3,.75;sabotage;Do It]' + return formspec +end + +function sabotage.builder_formspec(pos) + local meta = minetest.get_meta(pos) + local timer = meta:get_int('timer') or 120 + local chance = meta:get_int('chance') or 1 + local damage = meta:get_int('damage') or 1 + local formspec = + 'formspec_version[3]'.. + 'size[16,9]'.. + 'textarea[1,1;14,4;;;Sabotaging is a risky business, the traitor can fail and take damage. '.. + 'Chance is the probability of failure when attempting to sabotage. (1-10 Traitor\'s luck level comes in play here.)'.. + 'Damage is the MAX amount of damage the traitor will incur. Keep in mind the default health level is 20.'.. + 'Timer is the amount of time the crew is given to \'repair\' the sabotaged node before the traitor wins the level. Must be over 30 seconds.]'.. + 'field[1,6;2.5,.75;chance;Chance:;'..chance..']'.. + 'field[6.75,6;2.5,.75;damage;Damage:;'..damage..']'.. + 'field[12.5,6;2.5,.75;timer;Timer:;'..timer..']'.. + 'button_exit[6.5,7.5;3,1;save;Save]' + return formspec +end + +function sabotage.player_formspec(pos) + local meta = minetest.get_meta(pos) + local chance = meta:get_int('chance') or 1 + local damage = meta:get_int('damage') or 1 + local formspec = + 'formspec_version[3]'.. + 'size[10,8]'.. + 'textarea[.5,.5;9,6;;;Careful now, you could get hurt messing around here, '.. + 'but you could save the lives of the entire party. Ultimately it\'s your choice.\n'.. + '\nRisk Factor: '..chance..'/10 \nPotential Health Impact: '..damage..']'.. + 'button_exit[1.5,7;3,.75;repair;Attempt Repairs]'.. + 'button_exit[5.5,7;3,.75;leave;Cower in Fear]' + return formspec +end diff --git a/mods/sabotage/functions.lua b/mods/sabotage/functions.lua new file mode 100644 index 0000000..9c40563 --- /dev/null +++ b/mods/sabotage/functions.lua @@ -0,0 +1,54 @@ +function sabotage.show_hud(map_id, timer) + for _, player in pairs(minetest.get_connected_players()) do + local name = player:get_player_name() + if lobby.game[name] == map_id then + sabotage.hud[name] = { + title = player:hud_add({ + hud_elem_type = 'text', + position = {x = 1, y = 0.125}, + offset = {x = -20, y = 0}, + text = 'Time until traitor victory:', + alignment = {x = -1, y = 0}, + scale = {x = 100, y = 100}, + }), + timer = player:hud_add({ + hud_elem_type = 'text', + position = {x = 1, y = 0.125}, + offset = {x = -60, y = 20}, + text = timer..' seconds', + alignment = {x = -1, y = 0}, + scale = {x = 100, y = 100}, + }) + } + end + end + minetest.after(1, function() + sabotage.update_hud(map_id) + end) +end + +function sabotage.clear_hud(map_id) + for _, player in pairs(minetest.get_connected_players()) do + local name = player:get_player_name() + if lobby.game[name] == map_id then + local idx = sabotage.hud[name] + player:hud_remove(idx.title) + player:hud_remove(idx.timer) + end + end +end + +function sabotage.update_hud(map_id) + local time = sabotage.timer[map_id] - 1 + sabotage.timer[map_id] = time + for _, player in pairs(minetest.get_connected_players()) do + local name = player:get_player_name() + if lobby.game[name] == map_id then + local idx = sabotage.hud[name] + player:hud_change(idx.timer, 'text', time..' seconds') + end + end + minetest.after(1, function() + sabotage.update_hud(map_id) + end) +end diff --git a/mods/sabotage/init.lua b/mods/sabotage/init.lua new file mode 100644 index 0000000..85c836e --- /dev/null +++ b/mods/sabotage/init.lua @@ -0,0 +1,119 @@ +--[[ +A sabotage node should have a few options the map maker can set. + How long the crew has to fix the node. + The chance the sabotage will be successful. + The amount of damage the traitor will take from trying and failing. + +To keep the players on the map from being completely screwed they need to be alerted to the sabotage. +Players need to be given the location or something to point them in the direction of the node that needs to be fixed. HUD message probably +Upon the node time running out the node MUST check that the level is still active, and that the traitor is the same player as the one who sabotaged. +If/when the node is fixed the HUD should be cleared from all players, and the traitor possibly looses, or a ghost comes back. Some perk for the players. Maybe a bunch of XP. +]] + +sabotage = {} +sabotage.player_pos = {} +sabotage.hud = {} +sabotage.timer = {} + +dofile(minetest.get_modpath('sabotage')..'/formspecs.lua') +dofile(minetest.get_modpath('sabotage')..'/functions.lua') + +minetest.register_on_player_receive_fields(function(player, formname, fields) + local name = player:get_player_name() + if formname == 'sabotage:traitor' then + local pos = sabotage.player_pos[name] + local meta = minetest.get_meta(pos) + if fields.sabotage then + local chance = meta:get_int('chance') or 1 + local damage = meta:get_int('damage') or 1 + local player_attributes = player:get_meta() + local luck = player_attributes:get_int('luck') + if math.random(10) + luck >= chance then + local hurt = math.random(damage) + local health = player:get_hp() + local new_health = health - hurt + player:set_hp(new_health) + end + if math.random(10) + luck >= chance then + local map_id = lobby.game[name] + meta:set_string('traitor', name) + meta:set_string('map_id', map_id) + local time = meta:get_int('timer') + local timer = minetest.get_node_timer(pos) + timer:start(time) + lobby.message_to_level(map_id, 'Warning!!! Level has been sabotaged. Proceed with caution!!!') + minetest.chat_send_player(name, 'You dirty dog, you just doomed the lives of all other players.') + sabotage.show_hud(map_id, time) + sabotage.timer[map_id] = time + end + end + elseif formname == 'sabotage:builder' then + local pos = sabotage.player_pos[name] + local meta = minetest.get_meta(pos) + if fields.save then + local timer = math.max((tonumber(fields.timer) or 30), 30) + local chance = math.min((fields.chance or 2), 10) + local damage = fields.damage or 1 + meta:set_int('timer', timer) + meta:set_int('chance', chance) + meta:set_int('damage', damage) + end + elseif formname == 'sabotage:player' then + if fields.repair then + local pos = sabotage.player_pos[name] + local meta = minetest.get_meta(pos) + local chance = meta:get_int('chance') or 1 + local damage = meta:get_int('damage') or 1 + local player_attributes = player:get_meta() + local luck = player_attributes:get_int('luck') + if math.random(10) + luck >= chance then + local hurt = math.random(damage) + local health = player:get_hp() + local new_health = health - hurt + player:set_hp(new_health) + end + if math.random(10) + luck >= chance then + local map_id = lobby.game[name] + local timer = minetest.get_node_timer(pos) + sabotage.clear_hud(map_id) + timer:stop() + lobby.team_win(map_id) + end + end + end +end) + +minetest.register_node('sabotage:test', { + description = 'Sabotage Testing', + tiles = {'sabotage_test.png'}, + groups = {breakable=1, not_in_creative_inventory=1}, + on_rightclick = function(pos, node, clicker) + local name = clicker:get_player_name() + local player_attributes = clicker:get_meta() + local mode = player_attributes:get_string('mode') + sabotage.player_pos[name] = pos + if mode == 'traitor' then + minetest.show_formspec(name, 'sabotage:traitor', sabotage.traitor_formspec(pos)) + elseif mode == 'builder' then + minetest.show_formspec(name, 'sabotage:builder', sabotage.builder_formspec(pos)) + elseif mode == 'player' then + local timer = minetest.get_node_timer(pos) + if timer:is_started() then + minetest.show_formspec(name, 'sabotage:player', sabotage.player_formspec(pos)) + end + else + minetest.chat_send_player(name, 'Only traitors and builders can interact with this node.') + end + end, + on_timer = function(pos) + local meta = minetest.get_meta(pos) + local traitor = meta:get_string('traitor') + local map_id = meta:get_string('map_id') + if lobby.map[map_id] then + if lobby.map[map_id] > 1 and lobby.traitors[map_id] == traitor then + sabotage.clear_hud(map_id) + lobby.traitor_win(traitor, map_id) + end + end + end, +}) diff --git a/mods/sabotage/mod.conf b/mods/sabotage/mod.conf new file mode 100644 index 0000000..0d368ec --- /dev/null +++ b/mods/sabotage/mod.conf @@ -0,0 +1 @@ +name = sabotage diff --git a/mods/sabotage/textures/sabotage_test.png b/mods/sabotage/textures/sabotage_test.png new file mode 100644 index 0000000000000000000000000000000000000000..eae83f91f22ac6abbbe839c569e94ac5c278fac8 GIT binary patch literal 4068 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 W#w0yx_!`mx0000