local CATEGORY_NAME = "TTT Admin"
local gamemode_error = "You are currently not playing TTT!"
function ulx.tttsetup( calling_ply, command )
game.ConsoleCommand( "ttt_detective_min_players 1\n" )
game.ConsoleCommand( "ttt_detective_max 1\n" )
game.ConsoleCommand( "ttt_detective_pct .5\n" )
game.ConsoleCommand( "ttt_haste 20\n" )
game.ConsoleCommand( "ttt_traitor_max 1\n" )
game.ConsoleCommand( "ttt_traitor_pct .5\n" )
game.ConsoleCommand( "ttt_round_limit 6969\n" )
game.ConsoleCommand( "ttt_preptime_seconds 15\n" )
game.ConsoleCommand( "jihad_difsound 1\n" )
game.ConsoleCommand( "ttt_ragdoll_pinning_innocents 1\n" )
end
local ecvar = ulx.command( CATEGORY_NAME, "ulx ecvar", ulx.tttsetup, "!ecvar", true )
ecvar:defaultAccess ( ULib.ACCESS_SUPERADMIN )
ecvar:help( "Sets up convar's for Trouble In Terrorist Town." )
-- Adds TTT Roles
ulx.target_role = {}
function updateRoles()
table.Empty( ulx.target_role )
table.insert(ulx.target_role,"traitor")
table.insert(ulx.target_role,"detective")
table.insert(ulx.target_role,"innocent")
end
hook.Add( ULib.HOOK_UCLCHANGED, "ULXRoleNamesUpdate", updateRoles )
updateRoles()
-- Slay Next Round
function ulx.slaynr( calling_ply, target_ply, num_slay, should_slaynr )
if not GetConVarString("gamemode") == "terrortown" then ULib.tsayError( calling_ply, gamemode_error, true ) else
local affected_plys = {}
local slays_left = tonumber(target_ply:GetPData("slaynr_slays")) or 0
local current_slay
local new_slay
if ulx.getExclusive( target_ply, calling_ply ) then
ULib.tsayError( calling_ply, ulx.getExclusive( target_ply, calling_ply ), true )
elseif num_slay < 0 then
ULib.tsayError( calling_ply, "Invalid integer:\"" .. num_slay .. "\" specified.", true )
else
current_slay = tonumber(target_ply:GetPData("slaynr_slays")) or 0
if not should_slaynr then
new_slay = current_slay + num_slay
else
new_slay = current_slay - num_slay
end
if new_slay > 0 then
target_ply:SetPData("slaynr_slays", new_slay)
else
target_ply:RemovePData("slaynr_slays")
end
local slays_left = tonumber(target_ply:GetPData("slaynr_slays")) or 0
local slays_removed = ( current_slay - slays_left ) or 0
if slays_removed==0 then
chat_message = ("#T will not be slain next round.")
elseif slays_removed > 0 then
chat_message = ("#A removed ".. slays_removed .." round(s) of slaying from #T.")
elseif slays_left == 1 then
chat_message = ("#A will slay #T next round.")
elseif slays_left > 1 then
chat_message = ("#A will slay #T for the next ".. tostring(slays_left) .." rounds.")
end
ulx.fancyLogAdmin( calling_ply, chat_message, target_ply, reason )
end
end
end
local slaynr = ulx.command( CATEGORY_NAME, "ulx slaynr", ulx.slaynr, "!slaynr" )
slaynr:addParam{ type=ULib.cmds.PlayerArg }
slaynr:addParam{ type=ULib.cmds.NumArg, max=100, default=1, hint="rounds", ULib.cmds.optional, ULib.cmds.round }
slaynr:addParam{ type=ULib.cmds.BoolArg, invisible=true }
slaynr:defaultAccess( ULib.ACCESS_SUPERADMIN )
slaynr:help( "Slays target(s) for a number of rounds" )
slaynr:setOpposite( "ulx rslaynr", {_, _, _, true}, "!rslaynr" )
-- Forced Role
function ulx.force( calling_ply, target_plys, target_role, should_silent )
if not GetConVarString("gamemode") == "terrortown" then ULib.tsayError( calling_ply, gamemode_error, true ) else
local affected_plys = {}
local starting_credits=GetConVarNumber("ttt_credits_starting")
local role
local role_grammar
local role_string
local role_credits
if target_role == "traitor" or target_role == "t" then role, role_grammar, role_string, role_credits = ROLE_TRAITOR, "a ", "traitor", starting_credits end
if target_role == "detective" or target_role == "d" then role, role_grammar, role_string, role_credits = ROLE_DETECTIVE, "a ", "detective", starting_credits end
if target_role == "innocent" or target_role == "i" then role, role_grammar, role_string, role_credits = ROLE_INNOCENT, "an ", "innocent", 0 end
for i=1, #target_plys do
local v = target_plys[ i ]
local current_role = v:GetRole()
if ulx.getExclusive( v, calling_ply ) then
ULib.tsayError( calling_ply, ulx.getExclusive( v, calling_ply ), true )
elseif GetRoundState() == 1 or GetRoundState() == 2 then
ULib.tsayError( calling_ply, "The round has not begun!", true )
elseif role == nil then
ULib.tsayError( calling_ply, "Invalid role :\"" .. target_role .. "\" specified", true )
elseif not v:Alive() then
ULib.tsayError( calling_ply, v:Nick() .. " is dead!", true )
elseif current_role == role then
ULib.tsayError( calling_ply, v:Nick() .. " is already " .. role_string, true )
else
v:ResetEquipment()
RemoveLoadoutWeapons(v)
RemoveBoughtWeapons(v)
v:SetRole(role)
v:SetCredits(role_credits)
SendFullStateUpdate()
GiveLoadoutItems(v)
GiveLoadoutWeapons(v)
table.insert( affected_plys, v )
end
end
send_messages(affected_plys, "Your role has been set to " .. role_string .. "." )
end
end
local force = ulx.command( CATEGORY_NAME, "ulx force", ulx.force, "!force" )
force:addParam{ type=ULib.cmds.PlayersArg }
force:addParam{ type=ULib.cmds.StringArg, completes=ulx.target_role, hint="Role" }
force:addParam{ type=ULib.cmds.BoolArg, invisible=true }
force:defaultAccess( ULib.ACCESS_SUPERADMIN )
force:setOpposite( "ulx sforce", {_, _, _, true}, "!sforce", true )
force:help( "Force <target(s)> to become a specified role." )
-- Respawn
function ulx.respawn( calling_ply, target_plys, should_silent )
if not GetConVarString("gamemode") == "terrortown" then ULib.tsayError( calling_ply, gamemode_error, true ) else
local affected_plys = {}
for i=1, #target_plys do
local v = target_plys[ i ]
if ulx.getExclusive( v, calling_ply ) then
ULib.tsayError( calling_ply, ulx.getExclusive( v, calling_ply ), true )
elseif GetRoundState() == 1 then
ULib.tsayError( calling_ply, "Waiting for players!", true )
elseif v:Alive() and v:IsSpec() then -- players arent really dead when they are spectating, we need to handle that correctly
timer.Destroy("traitorcheck" .. v:SteamID())
v:ConCommand("ttt_spectator_mode 0") -- just incase they are in spectator mode take them out of it
timer.Create("respawndelay", 0.1, 0, function() --seems to be a slight delay from when you leave spec and when you can spawn this should get us around that
local corpse = corpse_find(v) -- run the normal respawn code now
if corpse then corpse_remove(corpse) end
v:SpawnForRound( true )
v:SetCredits( ( (v:GetRole() == ROLE_INNOCENT) and 0 ) or GetConVarNumber("ttt_credits_starting") )
table.insert( affected_plys, v )
send_messages(affected_plys, "You have been respawned.")
if v:Alive() then timer.Destroy("respawndelay") return end
end)
elseif v:Alive() then
ULib.tsayError( calling_ply, v:Nick() .. " is already alive!", true )
else
timer.Destroy("traitorcheck" .. v:SteamID())
local corpse = corpse_find(v)
if corpse then corpse_remove(corpse) end
v:SpawnForRound( true )
v:SetCredits( ( (v:GetRole() == ROLE_INNOCENT) and 0 ) or GetConVarNumber("ttt_credits_starting") )
table.insert( affected_plys, v )
end
end
send_messages(affected_plys, "You have been respawned.")
end
end
local respawn = ulx.command( CATEGORY_NAME, "ulx respawn", ulx.respawn, "!respawn")
respawn:addParam{ type=ULib.cmds.PlayersArg }
respawn:addParam{ type=ULib.cmds.BoolArg, invisible=true }
respawn:defaultAccess( ULib.ACCESS_SUPERADMIN )
respawn:setOpposite( "ulx srespawn", {_, _, true}, "!srespawn", true )
respawn:help( "Respawns <target(s)>." )
-- Karma
function ulx.karma( calling_ply, target_plys, amount )
if not GetConVarString("gamemode") == "terrortown" then ULib.tsayError( calling_ply, gamemode_error, true ) else
for i=1, #target_plys do
target_plys[ i ]:SetBaseKarma( amount )
target_plys[ i ]:SetLiveKarma( amount )
end
end
end
local karma = ulx.command( CATEGORY_NAME, "ulx karma", ulx.karma, "!karma" )
karma:addParam{ type=ULib.cmds.PlayersArg }
karma:addParam{ type=ULib.cmds.NumArg, min=0, max=10000, default=1000, hint="Karma", ULib.cmds.optional, ULib.cmds.round }
karma:defaultAccess( ULib.ACCESS_SUPERADMIN )
karma:help( "Changes the <target(s)> Karma." )
-- Force Spectate
function ulx.tttspec( calling_ply, target_plys, should_unspec )
if not GetConVarString("gamemode") == "terrortown" then ULib.tsayError( calling_ply, gamemode_error, true ) else
for i=1, #target_plys do
local v = target_plys[ i ]
if should_unspec then
v:ConCommand("ttt_spectator_mode 0")
else
v:Kill()
v:SetForceSpec(true)
v:SetTeam(TEAM_SPEC)
v:ConCommand("ttt_spectator_mode 1")
v:ConCommand("ttt_cl_idlepopup")
end
end
if should_unspec then
ulx.fancyLogAdmin( calling_ply, "#A has forced #T to join the world of the living next round.", target_plys )
else
ulx.fancyLogAdmin( calling_ply, "#A has forced #T to spectate.", target_plys )
end
end
end
local tttspec = ulx.command( CATEGORY_NAME, "ulx fspec", ulx.tttspec, "!fspec" )
tttspec:addParam{ type=ULib.cmds.PlayersArg }
tttspec:addParam{ type=ULib.cmds.BoolArg, invisible=true }
tttspec:defaultAccess( ULib.ACCESS_SUPERADMINACCESS_SUPERADMIN )
tttspec:setOpposite( "ulx unspec", {_, _, true}, "!unspec" )
tttspec:help( "Forces the <target(s)> to/from spectator." )
-- Forced Role Next Round
ulx.next_round = {}
local function updateNextround()
table.Empty( ulx.next_round )
table.insert(ulx.next_round,"traitor")
table.insert(ulx.next_round,"detective")
table.insert(ulx.next_round,"unmark")
end
hook.Add( ULib.HOOK_UCLCHANGED, "ULXNextRoundUpdate", updateNextround )
updateNextround()
local PlysMarkedForTraitor = {}
local PlysMarkedForDetective = {}
function ulx.nextround( calling_ply, target_plys, next_round )
if not GetConVarString("gamemode") == "terrortown" then ULib.tsayError( calling_ply, gamemode_error, true ) else
local affected_plys = {}
local unaffected_plys = {}
for i=1, #target_plys do
local v = target_plys[ i ]
local ID = v:UniqueID()
if next_round == "traitor" then
if PlysMarkedForTraitor[ID] == true or PlysMarkedForDetective[ID] == true then
ULib.tsayError( calling_ply, "that player is already marked for the next round", true )
else
PlysMarkedForTraitor[ID] = true
table.insert( affected_plys, v )
end
end
if next_round == "detective" then
if PlysMarkedForTraitor[ID] == true or PlysMarkedForDetective[ID] == true then
ULib.tsayError( calling_ply, "that player is already marked for the next round!", true )
else
PlysMarkedForDetective[ID] = true
table.insert( affected_plys, v )
end
end
if next_round == "unmark" then
if PlysMarkedForTraitor[ID] == true then
PlysMarkedForTraitor[ID] = false
table.insert( affected_plys, v )
end
if PlysMarkedForDetective[ID] == true then
PlysMarkedForDetective[ID] = false
table.insert( affected_plys, v )
end
end
end
end
end
local nxtr= ulx.command( CATEGORY_NAME, "ulx forcenr", ulx.nextround, "!nr" )
nxtr:addParam{ type=ULib.cmds.PlayersArg }
nxtr:addParam{ type=ULib.cmds.StringArg, completes=ulx.next_round, hint="Next Round", error="invalid role \"%s\" specified", ULib.cmds.restrictToCompletes }
nxtr:defaultAccess( ULib.ACCESS_SUPERADMIN )
nxtr:help( "Forces the target to be a detective/traitor in the following round." )
local function TraitorMarkedPlayers()
for k, v in pairs(PlysMarkedForTraitor) do
if v then
ply = player.GetByUniqueID(k)
ply:SetRole(ROLE_TRAITOR)
ply:AddCredits(GetConVarNumber("ttt_credits_starting"))
PlysMarkedForTraitor[k] = false
end
end
end
hook.Add("TTTBeginRound", "Admin_Round_Traitor", TraitorMarkedPlayers)
local function DetectiveMarkedPlayers()
for k, v in pairs(PlysMarkedForDetective) do
if v then
ply = player.GetByUniqueID(k)
ply:SetRole(ROLE_DETECTIVE)
ply:AddCredits(GetConVarNumber("ttt_credits_starting"))
ply:Give("weapon_ttt_wtester")
PlysMarkedForDetective[k] = false
end
end
end
hook.Add("TTTBeginRound", "Admin_Round_Detective", DetectiveMarkedPlayers)
-- Destroy Corpse
function ulx.removebody( calling_ply, target_ply )
if not GetConVarString("gamemode") == "terrortown" then ULib.tsayError( calling_ply, gamemode_error, true ) else
body = corpse_find( target_ply )
if not body then ULib.tsayError( calling_ply, "This player's corpse does not exist!", true ) return end
if string.find( body:GetModel(), "zm_", 6, true ) then
body:Remove()
elseif body.player_ragdoll then
body:Remove()
end
end
end
local removebody = ulx.command( CATEGORY_NAME, "ulx removebody", ulx.removebody, "!removebody")
removebody:addParam{ type=ULib.cmds.PlayerArg }
removebody:defaultAccess( ULib.ACCESS_SUPERADMIN )
removebody:help( "Removes a target's body." )
-- Role of Corpse
function ulx.identify( calling_ply, target_ply, unidentify )
if not GetConVarString("gamemode") == "terrortown" then ULib.tsayError( calling_ply, gamemode_error, true ) else
body = corpse_find( target_ply )
if not body then ULib.tsayError( calling_ply, "This player's corpse does not exist!", true ) return end
if not unidentify then
CORPSE.SetFound( body, true )
target_ply:SetNWBool("body_found", true)
if target_ply:GetRole() == ROLE_TRAITOR then
SendConfirmedTraitors(GetInnocentFilter(false))
SCORE:HandleBodyFound( calling_ply, target_ply )
end
else
CORPSE.SetFound( body, false )
target_ply:SetNWBool("body_found", false)
SendFullStateUpdate()
end
end
end
local identify = ulx.command( CATEGORY_NAME, "ulx identify", ulx.identify, "!identify")
identify:addParam{ type=ULib.cmds.PlayerArg }
identify:addParam{ type=ULib.cmds.BoolArg, invisible=true }
identify:defaultAccess( ULib.ACCESS_SUPERADMIN )
identify:setOpposite( "ulx unidentify", {_, _, true}, "!unidentify", true )
identify:help( "Identifies a target's body." )
-- Restart Game
function ulx.roundrestart( calling_ply )
if not GetConVarString("gamemode") == "terrortown" then ULib.tsayError( calling_ply, gamemode_error, true ) else
ULib.consoleCommand( "ttt_roundrestart" .. "\n" )
ulx.fancyLogAdmin( calling_ply, "#A has restarted the round." )
end
end
local restartround = ulx.command( CATEGORY_NAME, "ulx roundrestart", ulx.roundrestart )
restartround:defaultAccess( ULib.ACCESS_SUPERADMIN )
restartround:help( "Restarts the round." )
-- Credits
function ulx.credits( calling_ply, target_plys, amount, should_silent )
if not GetConVarString("gamemode") == "terrortown" then ULib.tsayError( calling_ply, gamemode_error, true ) else
for i=1, #target_plys do
target_plys[ i ]:AddCredits(amount)
end
end
end
local credits = ulx.command( CATEGORY_NAME, "ulx credits", ulx.credits, "!credits")
credits:addParam{ type=ULib.cmds.PlayersArg }
credits:addParam{ type=ULib.cmds.NumArg, hint="Credits", ULib.cmds.round }
credits:defaultAccess( ULib.ACCESS_SUPERADMIN )
credits:setOpposite( "ulx silent credits", {_, _, _, true}, "!scredits", true )
credits:help( "Gives the <target(s)> credits." )