WolfDB

Your Filebase for Games like Return to Castle Wolfenstein , Enemy Territory and more ...

LUA Anti-Spawnkill 0.8


Show Lua Code
--------------------------------------------------------------------------------
-- ETWsk - ETW-FZ Enemy Territory Anti-Spawnkill Mod for etpro
--------------------------------------------------------------------------------
-- This script can be freely used and modified as long as [ETW-FZ] and the 
-- original author are mentioned.
--------------------------------------------------------------------------------
module_name    = "ETWsk"
module_version = "0.8"
Author         = "[ETW-FZ] Mad@Mat , Editor [ETW-FZ] schnoog"
--------------------------------------------------------------------------------
-- DESCRIPTION
--------------------------------------------------------------------------------
-- ETWsk aims to reduce spawnkilling (SK) on public funservers. An SK here is if
-- someone kills an enemy near a fix spawn point. A fix spawn point means that
-- it can not be cleared by the enemy. E.g. on radar map, the allied Side Gate 
-- spawn is not fix as the axis can destroy the command post. However, the Main
-- Bunker spawn is fix after the Allies have destroyed the Main Gate. ETWsk does
-- not prevent but it detects and counts SKs for every player. If a player has
-- caused a certain number of SKs, he gets punished (putspec, kick, ban, ...).
-- As the detection of fix spawns is difficult especially on custom maps, little
-- configuration work has to be done.
--
-- Features:
--     - circular protection areas around spawn points
--     - two protection radius can be defined: heavy weapons and normal weapons
--     - the spawn protection expires when a player hurts an enemy
--       (can be disabled)
--     - fully configurable for individual maps: fixing radius, positions;
--       adding actions that change protected areas during the game; adding new
--       protection areas.
--     - client console commands for stats and help for configuration
--     - no RunFrame() -> low server load
--------------------------------------------------------------------------------
-- CONFIG
--------------------------------------------------------------------------------
ETWsk_putspec = 3                -- number of sk's needed for setting a client
                                 -- to spectators
ETWsk_kick = 4                   -- number of sk's needed for kicking a client
ETWsk_kicklen = 5                -- duration of kick
ETWsk_defaultradius1 = 400       -- protection radius for ordinary weapons
ETWsk_defaultradius2 = 800       -- protection radius for heavy weapons
ETWsk_savemode = 1               -- if enabled, protection is only active on
                                 -- maps that are configured
ETWsk_expires = 1                -- if enabled, spawn protection expires when
                                 -- the victim hurts an enemy
ETWsk_MapConfigFolder = "mapSpawns" --Subfolder for the map configurations e.g. mapSpawns for /etpro/mapSpawns
--------------------------------------------------------------------------------
heavyweapons = {17,27,57,30}     -- heavy weapon indexes 
                                 -- (pf, mortar, airstrike, arty)
maxcheckpointdist = 800          -- used to detect capturable flag poles
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
-- CONSTANTS
NO_PROTECT     = 0
PROTECT_AXIS   = 1
PROTECT_ALLIES = 2
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
function getConfig(map)
--------------------------------------------------------------------------------
-- configures protection of spawn areas in specific maps
--------------------------------------------------------------------------------
--	elseif map == "" then
--		
--		
--------------------------------------------------------------------------------
-- spawn definitions:
--      c.spawn[] = {}
-- spawn-num: spawn index (see /etwsk_spawns command)
-- spawn-fields: - comma-separated list of "key = value"
--               - for existing spawns all fields are optional (they overwrite
--                 default values).
--               - fields:
--                     name =   : name of spawn point
--                     state = NO_PROTECT|PROTECT_ALLIES|PROTECT_AXIS
--                     pos = {x,y,z}    : map coordinates of spawn point 
--                     radius1 =   : protection radius for normal weapons
--                     radius2 =   : protection radius for heavy weapons
-- action definitions: actions are definitions of transitions of one state of a
--                     spawn point into another one triggered by a message.
--      c.action[] = {}
-- action-num: just an increment number
-- action-fields: - comma-separated list of "key = value"
--                - all fields are mandatory
--                - fields:
--                     spawn = 
--                     newstate = NO_PROTECT|PROTECT_ALLIES|PROTECT_AXIS
--                     trigger = : part of a message that is displayed
--                                         by the server on a specific event.
-- adding new protection areas to maps:
--     new protection areas can easily been added:
--     1. enter the map and walk to the location where you want to add the area
--     2. type /etwsk_spawns and remember the highest spawn index number
--     3. type /etwsk_pos and write down the coordinates
--     4. add spawn to config with at least the name,state and pos field to a text
--To do this, create an empty text file and add the following lines:
-----------------Begin of map config
--local c = {spawns = {}, actions = {}, defaults = true}
-- --define your spawns here--
--return c
-----------------End of map config
--and save the file as "mapname.lua" in your ETWsk_MapConfigFolder
-- default values:
--     At mapstart, ETWsk scans for all spawnpoints and sets the state either to
--     PROTECT_ALLIES or PROTECT_AXIS. It also scans for capturable flag poles
--     and sets the state of a spawnpoint near a flag pole to NO_PROTECT. The
--     location of a spawnpoint is taken from the WOLF_objective entity, the
--     small spawn flag that can be selected in the command map. This entity is
--     usually placed in the center of the individual player-spawnpoints.
--     However, on some maps this is not the case. Check the positions of the
--     small spawn flags on the command map or type /etwsk_pos after you have
--     spawned to check the distance to protected areas. If needed, adjust the 
--     radius, or the pos or add a new protection area to the map.
--     If you wish to set all protection areas manually in a map, add:
--         c.defaults = false
--     to the definitions for a map.
--------------------------------------------------------------------------------
	--hier testen ob datei (etpro/mapsk/map.lua) existiert = hasconfig
	--wenn existiert auslesen und in c speichern
	--aus ETAsk:  dofile(et.trap_Cvar_Get("fs_homepath") .. '/etpro/mapSpawns/ETAsk.lua')
local c = {spawns = {}, actions = {}, defaults = true}
file = ETWsk_MapConfigFolder .. "/" .. map .. ".lua"
fd,len = et.trap_FS_FOpenFile(file, et.FS_READ)
    if len == -1 then
        strm = " ^2Sorry, no spawn configuration found for this map (^4" .. map .. "^2)..ETWsk disabled"
        et.trap_SendConsoleCommand(et.EXEC_APPEND, "say" .. strm)
        hasconfig = false 
    else
        --et.trap_SendConsoleCommand(et.EXEC_APPEND, "say konfig" .. file .. " gefunden")
        hasconfig = true 	
	et.trap_FS_FCloseFile(fd)
    	--dofile(et.trap_Cvar_Get(file))
    	loadfile(et.trap_Cvar_Get(file))
--    	dofile(et.trap_Cvar_Get("fs_homepath") .. '/etpro/' .. file)
--		loadfile(et.trap_Cvar_Get("fs_homepath") .. '/etpro/' .. file)
    end

return c
end


--------------------------------------------------------------------------------
-- called when client types a command like "/command" on console
function et_ClientCommand(cno, command) 
--------------------------------------------------------------------------------
-- commands: 
--     etwsk        : prints mod info and current spawnkill statistics
--     etwsk_spawns : prints list of spawnpoints with current state
--     etwsk_pos    : prints current position and distances to protected spawns
--------------------------------------------------------------------------------
    local cmd = string.lower(command) 
    if cmd == "etwsk_spawns" then 
        --et.trap_SendConsoleCommand(et.EXEC_APPEND, "say aaaaaaaaaaaaaaaaaaaaaaaaa")
		printSpawns(cno)
        return 1 
    elseif cmd == "etwsk_pos" then
        printPos(cno)
        return 1
    elseif cmd == "etwsk" then
        printStats(cno)
        return 1
    end 
    return 0 
end 

--------------------------------------------------------------------------------
-- calculates the distance
-- note: not true distance as hight is doubled. So the body defined by constant
--       distance is not a sphere, but an ellipsoid
function calcDist(pos1, pos2)
--------------------------------------------------------------------------------
	local dist2 = (pos1[1]-pos2[1])^2 + (pos1[2]-pos2[2])^2 
                  + ((pos1[3]-pos2[3])*2)^2
    return math.sqrt(dist2)
end
    
--------------------------------------------------------------------------------
-- called at map start
function et_InitGame( levelTime, randomSeed, restart)
--------------------------------------------------------------------------------
    local modname = string.format("%s v%s", module_name, module_version)
    et.G_Print(string.format("%s loaded\n", modname))
    et.RegisterModname(modname)

    mapname = et.trap_Cvar_Get("mapname")
    c = getConfig(mapname)
	
    damagegiven = {}
    spawnkills = {}
    
    local checkpoints = {}
    -- find capturable flag poles
    for i = 64, 1021 do
        if et.gentity_get(i, "classname") == "team_WOLF_checkpoint" then			
            table.insert(checkpoints,i)
        end
    end
	-- complete config with default extracted values
    local spawn = 1
    for i = 64, 1021 do
        if et.gentity_get(i, "classname") == "team_WOLF_objective" then
		local pos = et.gentity_get(i, "origin");
    		if c.spawns[spawn] == nil then 
			c.spawns[spawn] = {} end
		if c.spawns[spawn].name == nil then 
			c.spawns[spawn].name = et.gentity_get(i, "message") end
		if c.spawns[spawn].pos == nil then 
			c.spawns[spawn].pos = et.gentity_get(i, "origin") end
		if c.spawns[spawn].state == nil then 
			local iscapturable = false
			for k,v in pairs(checkpoints) do
            			local cp = et.gentity_get(v, "origin")
				if(calcDist(c.spawns[spawn].pos, cp) <= 
				  maxcheckpointdist) then
					iscapturable = true
				end
			end
			if iscapturable then
				c.spawns[spawn].state = NO_PROTECT
			else
				c.spawns[spawn].state = et.G_GetSpawnVar(i, "spawnflags")
			end
		end
		if c.spawns[spawn].radius1 == nil then
			c.spawns[spawn].radius1 = ETWsk_defaultradius1 end
		if c.spawns[spawn].radius2 == nil then 
			c.spawns[spawn].radius2 = ETWsk_defaultradius2 end
		spawn = spawn + 1
        end
    end
    -- auto complete spawns
    for i,spawn in pairs(c.spawns) do
	if spawn.radius1 == nil then
		spawn.radius1 = ETWsk_defaultradius1 end
	if spawn.radius2 == nil then
		spawn.radius2 = ETWsk_defaultradius2 end
    end
end

--------------------------------------------------------------------------------
-- called when something is printed on server console
function et_Print(text)
--------------------------------------------------------------------------------
	if(c == nil) then return end
	for i,action in pairs(c.actions) do
		if(string.find(text, action.trigger)) then
			local msg
			if action.newstate == NO_PROTECT then 
            	msg = "is no longer protected!"
            else msg = "is now protected!"
            end
	c.spawns[action.spawn].state = action.newstate
            et.trap_SendServerCommand(-1, "cpm \"^4ETW^2sk: The ^4"..
				c.spawns[action.spawn].name.." Spawn ^2"..msg.."\n\"")
		end	
	end
end

--------------------------------------------------------------------------------
-- called when client enters the game
function et_ClientBegin(cno)
--------------------------------------------------------------------------------
    -- reset spawnkills
    spawnkills[cno] = nil
end

--------------------------------------------------------------------------------
-- called when client spawns
function et_ClientSpawn(cno, revived )
--------------------------------------------------------------------------------
    if (hasconfig and revived == 0) then
        damagegiven[cno] = et.gentity_get(cno, "sess.damage_given")
	if(damagegiven[cno] == nil) then damagegiven[cno] = 0 end
    end
end

--------------------------------------------------------------------------------
function printSpawns(cno)
--------------------------------------------------------------------------------
    if not hasconfig then
        et.trap_SendServerCommand(cno, 
			"print \"^4ETW^2sk:^7 no config for this map!\n\"")
		if ETWsk_savemode == 1 then
	        et.trap_SendServerCommand(cno, 
				"print \"^4ETW^2sk:^7 protection deactivated (savemode)!\n\"")
		end
    end
    local protect = {}
    protect[0] = "NO_PROTECT"
    protect[1] = "^1PROTECT_AXIS"
    protect[2] = "^4PROTECT_ALLIES"
    if cno >= 0 then 
        et.trap_SendServerCommand(cno, 
			"print \"^4ETW^2sk:^7 Mapname: ^3"..mapname.."\n\"")
    end  
    for i,spawn in pairs(c.spawns) do
        if cno == -1 then et.G_Printf(
			"ETWsk> Spawn %d \"%s\" %s \n", i, spawn.name, protect[spawn.state])
        else et.trap_SendServerCommand(cno, "print \"^4ETW^2sk:^7 Spawn ^3"..
			i.."^7 "..spawn.name.." "..protect[spawn.state].."\n\"")
		end
    end
end

--------------------------------------------------------------------------------
function printPos(cno)
--------------------------------------------------------------------------------
    local pos = et.gentity_get(cno, "r.currentOrigin")
    local spos = string.format('%d, %d, %d',
		unpack(pos))
    et.trap_SendServerCommand(cno, 
		"print \"^4ETW^2sk:^7 current pos: "..spos.."\n\"")
    local team = et.gentity_get(cno, "sess.sessionTeam")
    local protect_normal = "^2protected_normal"
    local protect_heavy = "^2protected_heavy_only"
    for i,spawn in pairs(c.spawns) do
	local protect = "^1not protected"
        if spawn.state == team then
            local dist = calcDist(pos, spawn.pos)
            if dist < spawn.radius1 then 
				protect = protect_normal
            elseif dist < spawn.radius2 then
				protect = protect_heavy
			end
            et.trap_SendServerCommand(cno, string.format(
                "print \"^4ETW^2sk:^7 spawn ^3%d (%s): %s ^7distance: %d \n\"",
                i, spawn.name, protect, dist))
        end
    end     
end

--------------------------------------------------------------------------------
function printStats(cno)
--------------------------------------------------------------------------------
    et.trap_SendServerCommand(cno, "print \"^4ETW^2sk ^7v"..module_version ..
		" spawnkill protection by ^2[^4ETW^2-^4FZ^2] ^4Mad^2@^4Mat^7^, modified by ^2[^4ETW^2-^4FZ^2] ^2Schn^4oo^2g^7.\n\"")
    for killer,kills in pairs(spawnkills) do
        local killername = 
			et.Info_ValueForKey(et.trap_GetUserinfo(killer), "name")
        et.trap_SendServerCommand(cno, 
			"print \"       "..kills.." SKs: "..killername.."\n\"")
    end     
end

--------------------------------------------------------------------------------
-- called when someone has been killed
function et_Obituary(victim, killer, meansOfDeath)
--------------------------------------------------------------------------------
    -- same team
    -- et.trap_SendServerCommand(-1, "print \"SK: "..victim.." "..killer.."\n\"")
    local vteam = et.gentity_get(victim, "sess.sessionTeam")
    if( vteam == et.gentity_get(killer, "sess.sessionTeam")) then return end
    -- protection expired ?
    if ETWsk_expires == 1 then
	   local vdg = 0
	   vdg = et.gentity_get(victim, "sess.damage_given")
           -- et.G_Printf("vdg = %d, dg = %d\n", vdg, damagegiven[victim])
           if(vdg ~= nil and vdg > damagegiven[victim]) then return end
    end
    -- was heavyweapon?
    local isheavy = false
    for k,v in pairs(heavyweapons) do
        if (meansOfDeath == v) then isheavy = true end
    end
    -- protected spawn?
    local vpos = et.gentity_get(victim, "r.currentOrigin")
    local isprotected = false
    local dist2
    local radius2
    for i,spawn in pairs(c.spawns) do
        if spawn.state == vteam then
            if(isheavy) then
                radius2 = spawn.radius2
            else
                radius2 = spawn.radius1
            end
            dist = calcDist(vpos, spawn.pos)
			if(dist < radius2) then
                ClientSpawnkill(victim, killer, isheavy)
			end
        end
    end
end

--------------------------------------------------------------------------------
-- called when ETWsk has detected a spawnkill
function ClientSpawnkill(victim, killer, isheavy)
--------------------------------------------------------------------------------
    if killer < 0 or (ETWsk_savemode == 1 and not hasconfig) then return end
    if spawnkills[killer] == nil then spawnkills[killer] = 0 end
    spawnkills[killer] = spawnkills[killer] + 1
    local numsk = spawnkills[killer]
    local killername = et.Info_ValueForKey(et.trap_GetUserinfo(killer), "name")
    et.trap_SendServerCommand(-1, "cpm \"^4ETW^2sk: ^1WARNING: ^2Spawnkill (#"..
		numsk..") by "..killername.."\"\n" )
    et.trap_SendServerCommand(killer, "cp \""..killername.." : ^1DO NOT SPAWNKILL!!! \"\n")
    if(numsk >= ETWsk_putspec and numsk < ETWsk_kick) then
        et.trap_SendConsoleCommand(et.EXEC_APPEND, "ref remove "..killer.."\n")                
        et.trap_SendServerCommand(-1, "cpm \"^4ETW^2sk: ^0"..killername..
			" ^2was set to Spectators - too many Spawnkills!\"\n")
    elseif(numsk >= ETWsk_kick) then
	et.trap_SendConsoleCommand(et.EXEC_APPEND, "pb_sv_kick \""..killername.."\" "..ETWsk_kicklen.." \"too many spawnkills!\"\n") 
	et.trap_SendServerCommand(-1, "cpm \"^4ETW^2sk: ^0"..killername..
			" ^2has been kicked - too many Spawnkills!\"\n")
    else
	et.gentity_set(killer, "health", -511)
    end
   
end

--------------------------------------------------------------------------------
-- printf wrapper
function et.G_Printf(...)
--------------------------------------------------------------------------------
    et.G_Print(string.format(unpack(arg)))
end


DOWNLOAD

File size: 0.02 MB

Description: