X-Git-Url: https://jfr.im/git/irc/quakenet/lua-labspace.git/blobdiff_plain/da8af74a3db62e04f490fb9e235b7dc274abb073..730acd4f06ae822aa5fdaaaa530945cc94adeff2:/labspace.lua diff --git a/labspace.lua b/labspace.lua index a7eac80..ff0b89c 100644 --- a/labspace.lua +++ b/labspace.lua @@ -17,7 +17,7 @@ -- TODO -- logging --- make idle notifications independent from game delay +-- vote info in !status -- Ideas: -- scientists vote on kills @@ -135,6 +135,8 @@ function handler(target, revent, ...) ls_cmd_investigate(numeric, argument) elseif command == "vote" then ls_cmd_vote(numeric, argument) + elseif command == "guard" then + ls_cmd_guard(numeric, argument) elseif command == "smite" and onstaff(numeric) then ls_cmd_smite(numeric, argument) elseif command == "addchan" and ontlz(numeric) then @@ -459,6 +461,11 @@ function ls_cmd_hl(channel, numeric) return end + if string.lower(channel) ~= "#labspace" then + ls_notice(numeric, "Sorry, you can't use this command here.") + return + end + ls_set_lasthl(channel, os.time()) local numerics = {} @@ -489,7 +496,7 @@ function ls_cmd_enable(channel, numeric) return end - ls_set_enabled(channel, false) + ls_set_enabled(channel, true) ls_notice(numeric, "Game has been enabled.") end @@ -558,6 +565,22 @@ function ls_cmd_kill(numeric, victim) if math.random(100) > 85 then ls_chanmsg(channel, "The scientists' attack was not successful tonight. Nobody died.") + elseif ls_get_guarded(channel, victimnumeric) then + for _, player in pairs(ls_get_players(channel)) do + ls_set_trait(channel, player, "force", false) + end + + ls_set_guarded(channel, victimnumeric, false) + + ls_chanmsg(channel, "The attack on " .. ls_format_player(channel, victimnumeric) .. " was deflected by a force field. The force field generator has now run out of power.") + elseif ls_get_trait(channel, victimnumeric, "infested") then + ls_devoice_player(channel, numeric) + ls_devoice_player(channel, victimnumeric) + + ls_chanmsg(channel, "An alien bursts out of " .. ls_format_player(channel, victimnumeric, true) .. "'s chest just as " .. ls_format_player(channel, numeric, true) .. " was about to murder them, killing them both.") + + ls_remove_player(channel, numeric, true) + ls_remove_player(channel, victimnumeric, true) else ls_devoice_player(channel, victimnumeric) @@ -692,6 +715,55 @@ function ls_cmd_vote(numeric, victim) ls_flush_modes(channel) end +function ls_cmd_guard(numeric, victim) + if not victim then + ls_notice(numeric, "Syntax: vote ") + return + end + + local channel = ls_chan_for_numeric(numeric) + + if not channel then + ls_notice(numeric, "You haven't joined any game lobby.") + return + end + + if not ls_get_trait(channel, numeric, "force") then + ls_notice(numeric, "Sorry, you need the force field generator to use this command.") + return + end + + ls_keepalive(channel, numeric) + + local victimnick = irc_getnickbynick(victim) + + if not victimnick then + ls_notice(numeric, "Sorry, I don't know who that is.") + return + end + + local victimnumeric = victimnick.numeric + + if not ls_get_role(channel, victimnumeric) then + ls_notice(numeric, "Sorry, " .. ls_format_player(channel, victimnumeric) .. " isn't playing the game.") + return + end + + local target + + if victimnumeric == numeric then + target = "yourself" + else + target = ls_format_player(channel, victimnumeric) + end + + for _, player in pairs(ls_get_players(channel)) do + ls_set_guarded(channel, player, (player == victimnumeric)) + end + + ls_notice(numeric, "You are now protecting " .. target .. ".") +end + function ls_cmd_smite(numeric, victim) if not victim then ls_notice(numeric, "Syntax: smite ") @@ -871,7 +943,7 @@ function ls_add_player(channel, numeric, forced) end if chanuser.opped then - ls_notice(channel, "You must not be opped to use this command.") + ls_notice(numeric, "You must not be opped to use this command.") return end @@ -943,6 +1015,8 @@ function ls_remove_player(channel, numeric, forced) local announced = ls_get_announced(channel, numeric) + local force_field = ls_get_trait(channel, numeric, "force") + ls_set_role(channel, numeric, nil) ls_devoice_player(channel, numeric) @@ -951,6 +1025,10 @@ function ls_remove_player(channel, numeric, forced) if ls_get_vote(channel, player) == numeric then ls_set_vote(channel, player, nil) end + + if force_field then + ls_set_guarded(channel, player, false) + end end if not forced then @@ -994,8 +1072,13 @@ function ls_get_role(channel, numeric) end function ls_set_role(channel, numeric, role) - if not ls_gamestate[channel]["players"][numeric] then - ls_gamestate[channel]["players"][numeric] = { active = false, announced = false } + if not ls_gamestate[channel]["players"][numeric] or role == "lobby" then + ls_gamestate[channel]["players"][numeric] = { + active = false, + announced = false, + traits = {}, + guarded = false + } end if role then @@ -1009,6 +1092,22 @@ function ls_set_role(channel, numeric, role) end end +function ls_get_trait(channel, numeric, trait) + return ls_gamestate[channel]["players"][numeric]["traits"][trait] +end + +function ls_set_trait(channel, numeric, trait, enabled) + ls_gamestate[channel]["players"][numeric]["traits"][trait] = enabled +end + +function ls_get_guarded(channel, numeric, guarded) + return ls_gamestate[channel]["players"][numeric]["guarded"] +end + +function ls_set_guarded(channel, numeric, guarded) + ls_gamestate[channel]["players"][numeric]["guarded"] = guarded +end + function ls_get_seen(channel, numeric) return ls_gamestate[channel]["players"][numeric]["seen"] end @@ -1121,8 +1220,8 @@ function ls_start_game(channel) -- notify scientists about each other for _, scientist in pairs(ls_get_players(channel, "scientist")) do for _, scientist_notify in pairs(ls_get_players(channel, "scientist")) do - if scientists ~= scientist_notify then - ls_notice(scientists_notify, ls_format_player(channel, scientist) .. " is also a scientist.") + if scientist ~= scientist_notify then + ls_notice(scientist_notify, ls_format_player(channel, scientist) .. " is also a scientist.") end end end @@ -1141,7 +1240,21 @@ function ls_start_game(channel) for _, player in pairs(players) do ls_set_role(channel, player, "citizen") end - + + -- give someone the force field generator + local force_owner = players[math.random(table.getn(players))] + ls_set_trait(channel, force_owner, "force", true) + ls_set_guarded(channel, force_owner, true) + ls_notice(force_owner, "You've found the \002force field generator\002. Use /notice " .. BOTNICK .. " guard to protect someone.") + ls_notice(force_owner, "You are currently protecting yourself.") + + -- make someone infested if there are at least 6 citizens + if table.getn(players) > 6 then + local infested_player = players[math.random(table.getn(players))] + ls_set_trait(channel, infested_player, "infested", true) + ls_notice(infested_player, "You're infested with an \002alien parasite\002.") + end + ls_chanmsg(channel, "Roles have been assigned: " .. table.getn(ls_get_players(channel, "scientist")) .. "x " .. ls_format_role("scientist") .. ", " .. table.getn(ls_get_players(channel, "investigator")) .. "x " .. ls_format_role("investigator") .. ", " .. @@ -1174,10 +1287,12 @@ function ls_check_alive(channel) for _, player in pairs(ls_get_players(channel)) do local seen = ls_get_seen(channel, player) - if seen < os.time() - 120 then - table.insert(dead_players, player) - elseif seen < os.time() - 60 then - table.insert(idle_players, player) + if seen then + if seen < os.time() - 120 then + table.insert(dead_players, player) + elseif seen < os.time() - 60 then + table.insert(idle_players, player) + end end end @@ -1260,9 +1375,7 @@ function ls_advance_state(channel, delayed) if state == "kill" then if timeout == -1 then - local candidates = ls_get_players(channel, "scientist") - local active_index = math.random(table.getn(candidates)) - local active_scientist = table.remove(candidates, active_index) + local active_scientist = scientists[math.random(table.getn(scientists))] for _, scientist in pairs(scientists) do if scientist == active_scientist then @@ -1299,9 +1412,7 @@ function ls_advance_state(channel, delayed) end if timeout == -1 then - local candidates = ls_get_players(channel, "investigator") - local active_index = math.random(table.getn(candidates)) - local active_investigator = table.remove(candidates, active_index) + local active_investigator = investigators[math.random(table.getn(investigators))] for _, investigator in pairs(investigators) do if investigator == active_investigator then