Started adding sabotaging.

master
Nathan Salapat 2022-05-25 21:43:57 -05:00
parent 96eae6f6da
commit 498236077d
9 changed files with 256 additions and 9 deletions

View File

@ -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 "..

View File

@ -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

View File

@ -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

View File

@ -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

119
mods/sabotage/init.lua Normal file
View File

@ -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,
})

1
mods/sabotage/mod.conf Normal file
View File

@ -0,0 +1 @@
name = sabotage

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -41,12 +41,12 @@ vents.Stations:deserialize(storage:get_string("Stations"))
vents.Elevators:deserialize(storage:get_string("Elevators"))
local function update_mod_storage()
minetest.log("action", "[Hyperloop] Store data...")
minetest.log("action", "[Vents] Store data...")
storage:set_string("Stations", vents.Stations:serialize())
storage:set_string("Elevators", vents.Elevators:serialize())
-- store data each hour
minetest.after(60*60, update_mod_storage)
minetest.log("action", "[Hyperloop] Data stored")
minetest.log("action", "[Vents] Data stored")
end
minetest.register_on_shutdown(function()

View File

@ -43,6 +43,7 @@ local function naming_formspec(pos)
local formspec =
'size[7,4.4]'..
'label[0,0;'..S('Please enter the vent name.')..']' ..
'label[0,.35;Punch the vent to see locations you can teleport too.]' ..
'field[0.2,1.5;7.1,1;name;'..S('Vent name')..';'..vent..']' ..
'field[0.2,2.7;7.1,1;info;'..S('Additional vent information')..';'..info..']' ..
'button_exit[2.5,3.7;2,1;exit;Save]'
@ -200,7 +201,7 @@ minetest.register_node('vents:station', {
local player_attributes = clicker:get_meta()
local mode = player_attributes:get_string('mode')
vents.player_pos[name] = pos
if mode == 'traitor' or mode == 'solo' or mode == 'ghost' then --allow everybody but crew mambers to use.
if mode == 'traitor' or mode == 'solo' or mode == 'ghost' then
minetest.show_formspec(name, 'vents:station_list', station_list_as_string(pos))
elseif mode == 'builder' then
minetest.show_formspec(name, 'vents:setup', naming_formspec(pos))
@ -209,6 +210,22 @@ minetest.register_node('vents:station', {
end
end,
on_punch = function(pos, node, puncher)
local wield = puncher:get_wielded_item()
local wield_name = wield:get_name()
if wield_name == 'creative:tool_breaking' then
return
else
local name = puncher:get_player_name()
local player_attributes = puncher:get_meta()
local mode = player_attributes:get_string('mode')
vents.player_pos[name] = pos
if mode == 'builder' then
minetest.show_formspec(name, 'vents:station_list', station_list_as_string(pos))
end
end
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Tube:after_dig_node(pos)
Stations:delete(pos)