SENT function problems.

I have a surf server and when you get to the end of the map, there is a ball (SENT) which calls a function to give the player some xp relative to the team they’re on. The problem I have is that when the person clicks the ball, even though the function should be called once, the player gets loads and loads of xp (At least 10x the amount they should). I think it’s something to do with the player pressing E on the ball and the amount of times it outputs to the function.

I’ve put these snips of code in order of how they work.

THE SENT’S USE FUNCTION >


function ENT:AcceptInput( Name, Activator, Caller )
	if Name == "Use" and Caller:IsPlayer( ) then
	Caller:KillSilent()
	_v = Caller
	finishhh( _v )
	Caller:Spawn()
	end
end

So, when the entity is used, it calls the function finishhh() >


function finishhh()
	if ( !IsValid( _v ) ) then print( "PlayerAliveTimeDeath:InValidPlayer"); return; end
	_v.__PlayerAliveTimeEnd = CurTime( );
	net.Start( "__PlayerAliveTime" );
		net.WriteTable( { player = _v:EntIndex( ), time = _v.__PlayerAliveTimeEnd, mode = MODE_PLAYER_ALIVE_TIME_DEATH } );
	net.Broadcast( );
end

This is then received by another function. >


net.Receive( "__PlayerAliveTime", function( _b, _p )
	local _tab = net.ReadTable( );
	local _time = _tab.time;
	_player = Entity( _tab.player );
	local _mode = _tab.mode;
	if ( !IsValid( _player ) ) then return end
	if ( _mode == MODE_PLAYER_ALIVE_TIME_SPAWN ) then
		_player.__PlayerAliveTimeStart = CurTime( );
		_player.__PlayerAliveTimeEnd = -1;
	else
		if _player:GetAliveTime() < 0.5 then else
			if _player:Team() == 0 then 
				chat.AddText( Color( 255, 50, 50, 255 ),"[HARD] ".._player:Nick( ) .. " finished in " .. string.FormattedTime( _player:GetAliveTime( ), "%02i:%02i.%02i" ) .. "! (+100xp)" );
				ex_time = (_player:GetAliveTime())
				net.Start( "mapfinish_leaderboards" ) 
					net.WriteFloat( ex_time )
				net.SendToServer()
			else 
				ex_time = (_player:GetAliveTime())
				net.Start( "mapfinish_leaderboards" ) 
					net.WriteFloat( ex_time )
				net.SendToServer()
				chat.AddText( Color( 255, 50, 50, 255 ),"[EASY] ".._player:Nick( ) .. " finished in " .. string.FormattedTime( _player:GetAliveTime( ), "%02i:%02i.%02i" ) .. "! (+25xp)" );
			end
		end
	end
end);

Which starts the net message >


util.AddNetworkString( "mapfinish_leaderboards" ) 
net.Receive( "mapfinish_leaderboards", function( length, client ) 
 
	if _v:Team() == 0 then
		GiveXP(100)
	else
		GiveXP(25)
	end
end)

Which then results in the player getting around 2000xp. Any ideas?

> WORKS PERFECTLY IN SINGLE PLAYER.



function ENT:AcceptInput( Name, Activator, Caller )
	if Activator.LastUseXP and (CurTime() - Activator.LastUseXP) < 1 then return end
	if Name == "Use" and Caller:IsPlayer( ) then
		Caller:KillSilent()
		_v = Caller
		finishhh( _v )
		Caller:Spawn()
	end
	Activator.LastUseXP = CurTime()
end


The reason I did Activator.LastUseXP instead of self.LastUseXP is because we don’t want to make it so 2 players can’t click it at the same time - if you don’t care it’s a fine idea to use self.LastUseXP instead of Activator.LastUseXP

Replace



		_v = Caller
		finishhh( _v )


With



		finishhh( Caller )


The way you current have it will cause tons of issues whatever you put as the argument for finish in your case ‘_v’ will be used in the function look at my below example. Not only is defining _v as a global reference to ‘Caller’ this brings up the issue if two players do this at the same time _v will reference to the second player.

Replace your finish function with



function finishhh(pl)
	if ( !IsValid( pl ) ) then print( "PlayerAliveTimeDeath:InValidPlayer"); return; end
	pl.__PlayerAliveTimeEnd = CurTime( );
	net.Start( "__PlayerAliveTime" );
		net.WriteTable( { player = pl:EntIndex( ), time = pl.__PlayerAliveTimeEnd, mode = MODE_PLAYER_ALIVE_TIME_DEATH } );
	net.Broadcast( );
end


On a side note - Why is GiveEXP a clientside command? that is very exploitable.

You should make a serverside function like



local meta = FindMetaTable("Player")
function meta:GiveEXP(amt)
       if !self.XP then self.XP = 0 end -- Remove this if you do self.XP = 0 on PlayerInitialSpawn or before this is called
       self.XP = self.XP + amt
end


Then stream from the Server to the Client instead of streaming from the Client to the Server.

If you need further assistance feel free to add me on steam.

I tried it, not working.

I am really confused because if I replace GiveXP(100) with Print(“Giving xp”) it doesn’t print anything…

GiveXP was being ran serverside without a player. So we switched to it meta:GiveXP
Another issue is you are including everything in every enviroment serverside in clientside and clientside in serverside etc, should be fixed now please marked this as solved.