Installing this Script (Confused)

Disclaimer: I originally posted this in that 18 page help thread, but a while afterwards I decided, as I ask a lot of questions, this deserves it’s own thread. I would delete that post if possible.

Hello. I’m trying to install a vote-kick module into a game mode. The vote-kick script can be found here. The !vk or !votekick commands should be initiating a vote-kick, but nothing happens when I enter them. Thus, I believe I have made a mistake installing this.

I at first assumed it was a server-side file, as that made more sense than clientside. So I threw it into the folder titled gamemode along with the cl_init, init, shared, and all that jazz. Then back in init.lua I added it using include(“votekick.lua”). I entered the server, tried the commands, and got nothing. Then I tried the same except by assuming it was client-side. I erased the include() in init.lua and put it in cl_init.lua, and I also did an AddCSLuaFile(“votekick.lua”) in init.lua, as that would cause the client to download votekick.lua right?

I’m not sure what I’m doing wrong here. Is this my fault? Or the fault of the script? Was I right that the script is server-side, as the first line in the main code block is “if CLIENT then return nil end”.

It’s a serverside file, so an include in init.lua should work. Maybe try autorun/server? If it still doesn’t work then it’s likely the script is at fault.

Okay, I’ll try that, thanks.

Or would it perhaps have to do with the fact that I’m running the gamemode on a mutliplayer listening server I put up when I test? Would it make a difference if dedicated?

Probably not.

After further invesitigation, I have concluded that I have installed the script correctly and that the error is the fault of the script.

Now, when I enter the !vk command, the console prints:

It obviously means that the GAMEMODE:AddNotify function cannot be found, and I looked into it, at the wiki page, but as far as I can tell the script is written correctly. It has crossed my mind that the AddNotify function is client-side, and the script looks to be server-side, but if it contained both wouldn’t it just be shared? Can scripts be shared? If anyone can explain this to me, I would be grateful.

Here is the script:


/*

Name: Vote Kick (+ Ban)
Version: 1.1
Author: Luk0r - luk0r@luk0r.net
For: Garry's Mod v10

*/

vk = {}; vk.Settings = {}; vk.VotedFor = {}

// Configure these variables to suit your needs, the defaults will probably be fine though

vk.Settings.advertise  =  true        // Advertise the script?
vk.Settings.advdelay   =  600          // Delay in seconds between advertising.
vk.Settings.trigger    =  {"!votekick", "/votekick", "!vk", "/vk"}  // The chat triggers to begin a vote.
vk.Settings.votetrig   =  "!votefor"   // Trigger to vote for the vote kick (used when a vote is taking place)
vk.Settings.votetimer  =  60           // How long players have to vote.
vk.Settings.majority   =  60           // The majority of votes required for a kick in percent (%).
vk.Settings.spamdelay  =  120          // Delay between kick vote requests to prevent spam.
vk.Settings.bantime    =  30           // The script will ban the votekicked player for this many minutes. Set to 0 for perma-ban.


// Main code block

if CLIENT then return nil end

Msg("The vote-kick module is running.
");

function vk.sendNotify( ply, text, sound, notifytype )
	ply:SendLua("GAMEMODE:AddNotify(\"" .. text .. "\", " .. notifytype .. ", 5); surface.PlaySound( \"" .. sound .. "\" )")
end

function vk.checkForVoteTrigger( ply, txt )
        local triggerfound = 0
        for i, trig in ipairs(vk.Settings.trigger) do
                if string.find( txt, trig ) then
                        local trigstart, trigend = string.find( txt, trig )
                        if trigstart == 1 then triggerfound = 1
                        vk.triggerused = trig end
                end
        end
        if vk.votetakingplace == 0 then
                if triggerfound == 1 then
  	                if vk.spamPrevent == 1 then
                                vk.sendNotify( ply, "You cannot start another vote for " .. vk.spamPreventCount .. " seconds!", "buttons/button2.wav", "NOTIFY_ERROR" )
                                return ""
                        end
                        vk.playerkick = {}
                        local triggerstart, triggerend = string.find( txt, vk.triggerused )
			vk.playerkick.name = string.sub( txt, triggerend + 2 )
			if vk.playerkick.name == "" then vk.sendNotify( ply, "Give me a name!", "buttons/button2.wav", "NOTIFY_ERROR" ); return "" end
			vk.playernamefound = 0
			local players = player.GetAll()
			for i, plyr in ipairs( players ) do
                        	if string.find(string.lower(plyr:Nick()), string.lower(vk.playerkick.name)) then
                                        if plyr:Nick() == ply:Nick() then vk.sendNotify( ply, "You cannot vote to kick yourself, stupid!", "buttons/button2.wav", "NOTIFY_ERROR" ); return "" end
                                        vk.playerkick = { name = plyr:Nick(), userid = plyr:UserID{}, steamid = plyr:SteamID() }
                        		vk.playernamefound = 1
                                        break
                        	end
			end
			if vk.playernamefound == 0 then
				vk.sendNotify( ply, "Not a valid player!", "buttons/button2.wav", "NOTIFY_ERROR" )
				return ""
			end
                        vk.votetakingplace = 1
			vk.votesfor = 1
			vk.spamPrevent = 1
			vk.spamPreventCount = vk.Settings.spamdelay
			timer.Create( "vk.SpamPreventer", vk.Settings.spamdelay, 1, vk.spamRelease )
			timer.Create( "vk.CountSpamPreventer", 1, vk.Settings.spamdelay, vk.countSpamPreventer )
			table.insert( vk.VotedFor, ply:SteamID() )
			local players = player.GetAll()
			for i, plyr in ipairs( players ) do
				vk.sendNotify( plyr, ply:Nick() .. " has requested to kick player " .. vk.playerkick.name .. ".", "ambient/water/drip" .. math.random(1, 4) .. ".wav", "NOTIFY_GENERIC" )
				plyr:PrintMessage( HUD_PRINTTALK, "Type " .. vk.Settings.votetrig .. " to vote for this kick.
" )
				plyr:PrintMessage( HUD_PRINTTALK, "Type nothing if you disagree.
" )
			end
			vk.votereminder = vk.Settings.votetimer
			vk.votereminderchunk = math.Round( vk.votereminder / 3 )
			timer.Create( "vk.RemindPlayersOfVote", vk.votereminderchunk, 3, vk.voteTimerCheck )
			timer.Create( "vk.EndOfVote", vk.Settings.votetimer, 1, vk.voteEnded )
			return ""
		end
	else
		if triggerfound == 1 then
			vk.sendNotify( ply, "A kick vote is already running!", "buttons/button2.wav", "NOTIFY_ERROR" )
			return ""
		else
			if string.find( txt, vk.Settings.votetrig ) then
				for i, vfornick in ipairs( vk.VotedFor ) do
					if vfornick == ply:SteamID() then
						vk.sendNotify( ply, "You have already voted!", "buttons/button2.wav", "NOTIFY_ERROR" )
						return ""
					end
				end
				vk.votesfor = vk.votesfor + 1
				vk.sendNotify( ply, "You have voted to kick this player.", "ambient/water/drip" .. math.random(1, 4) .. ".wav", "NOTIFY_GENERIC" )
				table.insert( vk.VotedFor, ply:SteamID() )
				local players = player.GetAll()
				for i, plyr in ipairs( players ) do
					plyr:PrintMessage( HUD_PRINTTALK, ply:Nick() .. " has voted for the kick.
" )
				end
				return ""
			end
		end
	end
end

function vk.voteTimerCheck()
	vk.votereminder = vk.votereminder - vk.votereminderchunk
	if vk.votereminder > 0 then
		local players = player.GetAll()
		for i, plyr in ipairs( players ) do
			vk.sendNotify( plyr, "Around " .. vk.votereminder .. " seconds remaining on the vote to kick " .. vk.playerkick.name .. "!", "ambient/water/drip" .. math.random(1, 4) .. ".wav", "NOTIFY_GENERIC" )
		end
	end
end

function vk.voteEnded()
	playersonserver = 0
	local players = player.GetAll()
	for i, v in ipairs( players ) do
		playersonserver = playersonserver + 1
	end
	local majorityplayers = math.ceil( ( playersonserver * vk.Settings.majority ) / 100 )
	if vk.votesfor >= majorityplayers then
		local players = player.GetAll()
		for i, plyr in ipairs( players ) do
			vk.sendNotify( plyr, "The kick vote has succeeded!", "ambient/water/drip" .. math.random(1, 4) .. ".wav", "NOTIFY_GENERIC" )
		end
                vk.kickPlayer()
	else
		local players = player.GetAll()
		for i, plyr in ipairs( players ) do
			vk.sendNotify( plyr, "The kick vote has failed " .. "(" .. vk.votesfor .. " voted, " .. majorityplayers .. " needed).", "buttons/button2.wav", "NOTIFY_ERROR" )
		end
	end
        vk.VotedFor = {}
	vk.votetakingplace = 0
	vk.votesfor = 0
end

function vk.kickPlayer()
	game.ConsoleCommand( "banid " .. vk.Settings.bantime .. " " .. vk.playerkick.steamid .. "
" )
        game.ConsoleCommand( "writeid
" )
	game.ConsoleCommand( "kickid " .. vk.playerkick.userid .. " Player kick vote succeeded. Banned for " .. tostring(vk.Settings.bantime) .. " minutes.
" )
end

function vk.advertise()
	local players = player.GetAll()
	for i, plyr in ipairs( players ) do
		vk.sendNotify( plyr, "To begin a player kick vote, type " .. vk.Settings.trigger[1] .. " <part of name> in chat.", "ambient/water/drip" .. math.random(1, 4) .. ".wav", "NOTIFY_GENERIC" )
	end
end

function vk.spamRelease()
        vk.spamPrevent = 0
end

function vk.countSpamPreventer()
        vk.spamPreventCount = vk.spamPreventCount - 1
end

if vk.Settings.advertise == true then
	timer.Create( "vk.Advertise", vk.Settings.advdelay, 0, vk.advertise )
end

vk.votetakingplace = 0  // Don't change these
vk.votesfor = 0
vk.spamPrevent = 0
vk.spamPreventCount = 0

hook.Add( "PlayerSay", "vk.CheckForVoteTrigger", vk.checkForVoteTrigger )

You don’t need to run it clientside, the GAMEMODE:AddNotify call is done using SendLua.

Could you paste the full Lua error? Your post just has “[LuaCmd:1] attempt”, which isn’t really useful.

Oh, sorry, that was a mistake. The full error is:

I’m guessing the problem is that your gamemode is not derived from Sandbox.

You could substitute:

GAMEMODE:AddNotify("" … text … “”, " … notifytype … ", 5);

…with a simple chat print:

LocalPlayer():ChatPrint("" … text … “”, " … notifytype … ");

…to remove the Sandbox dependency.

Thanks, I did notice the other day that the game mode I’m working off of is derived from base, so it makes sense that this problem would arise.

Now I just need to decide whether it’s worth deriving from Sandbox and overwriting a few things rather than leaving it and facing more workarounds in the future.

Any opinion on the best way to go?

EDIT:

Yep, I derived it from Sandbox and the vote-kick script works like a charm.

I think I’d prefer to derive from Sandbox in the long run, but I was curious if anyone knows any fancy (or not so fancy) documentation about overriding key sandbox stuff, like the Q menu, etc.

I would go with the ChatPrint replacement because it’s a minimal change and doesn’t require Sandbox.

[editline]24th March 2011[/editline]

You might actually be able to use the notification.AddLegacy( str, type, length ) function instead. I’ve never seen it before so I’m guessing it’s new, but the parameters are the same and it doesn’t look like it’s Sandbox dependent.

[editline]24th March 2011[/editline]

If you want to try it then just replace GAMEMODE:AddNotify with notification.AddLegacy.

Nah, I just discovered a whole list of server-side and client-side functions that are sandbox specific; they’re just what I needed. Overriding Sandbox will be a quick process.

In addition, I’d like to thank you for your help. Pointing that out made a big difference.

It’s up to you, but I really would advise using notification.AddLegacy instead. I just checked and it’s definitely gamemode independent, so unless you need Sandbox for any other reason then deriving is completely unnecessary.

Oh, I missed your edits, but yeah that Legacy thing looks to be the exact same thing.

I was planning on using sandbox functionality to allow administrators to spawn crap, but that’s really not that important, and this gives me a reason to put that off.

Thank you.