All pastes #619902 Raw Edit

Unnamed

public text v1 · immutable
·published 2007-07-15 03:14 UTC
rendered paste body
--- [[[ Zombie Zone Script ]]] ---
--- [[ Constants ]] ------

gc_startingammo = 250	-- The amount of ammo the marine starts with
gc_mapcenterx = 5032	-- The center of the map along the x axis
gc_mapcentery = 2280	-- The center of the map along the y axis


--- [[ Globals ]] --------

g_state = nil		-- The global GameState class
g_arena = nil		-- The global arena class, to avoid having to pass it around functions
g_bGameRunning = false	-- Is the game running?

g_winner = nil		-- The player who won
g_winnerevent = 0	-- The eventid for the repeating winner event
g_supplyevent = 0	-- The eventid for dropping supplies

g_roundnum = 0		-- The round we are currently on (Defined by supply drops)

g_portal = nil		-- The currently active portal
g_portalqueued = nil	-- Player queued for a portal (used for spawning vehicles out of portals)

g_bMarineFact = false	-- Has anyone built a marine factory yet?


--- [[ Includes ]] ---
dofile("events.lua")
dofile("stats.lua")
dofile("setup.lua")


-----------------------------------------------------------------------
-----------------------------------------------------------------------
------------------------ [[ Event Functions ]] ------------------------
-----------------------------------------------------------------------
function Laboratory_Produce(lab, chemist, menuitem)
	-- Action taken differs on what the player is trying to do

	-- Scavenge Ammo = Attempts to create some ammo
	if (menuitem == 0) then
		-- Check if he's waited long enough to create more ammo
		if (chemist:getstat(7) >= g_roundnum) then
			chemist:message("You look around, but don't see any spare parts available.")
			return false
		end

		-- Increase his 'attempt' count
		chemist:setstat(7, chemist:getstat(7) + 1)

		-- He may randomly fail
		if (math.random(1, 100) > 50) then
			chemist:message("Due to your inept handling you fail to create ammo and mess up the spare parts.")
			return false
		else
			-- Give the guy some ammo
			chemist:message("You have successfully created some ammo!")
			chemist:inventory_modify("Ammo", 25)
			return false
		end		
	end

	return true
end

function Vehicle_OnProduce(producer, user, menuitem)
	-- Divert to the appropriate function depending on what's producing

	-- Laboratory?
	if (producer:vehicletypeid() == 400) then
		local retval = Laboratory_Produce(producer, user, menuitem)
		return retval
	end

	return true
end

function Vehicle_OnDeath(victim, killer, itemid)
	local vid = victim:vehicletypeid()

	-- Check if the dead vehicle is a corpse
	if (vid == 300) then
		-- Reward the killer with a corsplosion!
		if (killer:valid() == true) then
			killer:setstat(5, killer:getstat(5) + 1)
		end

		-- Check if the itemid is the resurrection item
		if (itemid == 2016) then
			-- We get to resurrect the player! :)
			-- Attempt to find the player that the corpse references
			local repplayer = victim:getvar("Represents")
			local deadplayer = g_arena:getPlayer(repplayer)
			local oldvehicle = victim:getvarint("OldVehicle")
			local oldteam = victim:getvar("OldTeam")
			local oldpassword = victim:getvar("OldPassword")

			-- Check to see if he exists
			if (deadplayer:valid() == false) then
				-- If he doesn't, give the chemist his kit back
				killer:inventory_modify("Resurrection Kit", 1)
	
				-- Tell him
				killer:message("The corpse has degraded too far to be revived.")
				killer:message("You gather your kit back and move on.")
			else
				-- Change him back into a marine!
				deadplayer:setVehicle(oldvehicle)

				-- Put him back on his original team
				deadplayer:team_change(oldteam, oldpassword)

				-- warp him to the corpse's location
				local corpseloc = victim:coords()
				deadplayer:resurrect_warp(corpseloc.x, corpseloc.y, 0)

				-- Notify him
				deadplayer:message("&You have been revived by " .. killer.m_name .. "!")
				
				-- Give the player a resurrection stat
				killer:setstat(8, killer:getstat(8) + 1)
			end			
		end

	-- Or is it a laboratory?
	elseif (vid == 400) then
		-- Was it killed with a convert action?
		if (itemid == 1040) then
			-- Make sexy graphics
			local labcoords = victim:coords()
			g_arena:explosion_create("Necro Cloud", labcoords.x, labcoords.y, 0)

			-- Turn it into a marine factory
			local newlab = g_arena:vehicle_create(401, labcoords.x, labcoords.y, 0)
			newlab:setfrequency(killer:frequency())

			-- Set the global flag
			g_bMarineFact = true
		end
	end	
end

function Item_OnPickUp(looter, loot, loot_type, amounttopickup)
	-- If he picked up an engineer kit
	if (loot_type.m_name == "Engineer Kit") then
		-- Player needs to be a marine, and only picking up one kit
		if (amounttopickup > 1) then
			looter:message("You are only allowed one engineer kit.")
			return false
		elseif (looter:getVehicle():vehicletypeid() >= 15) then
			looter:message("You need to be a marine to become an engineer.")
			return false
		end

		-- Find out how experienced he is
		local vehicletype = 15

		if (looter:skill_find(13) == true) then
			vehicletype = 18
		elseif (looter:skill_find(12) == true) then
			vehicletype = 17
		elseif (looter:skill_find(11) == true) then
			vehicletype = 16
		end
		
		-- Otherwise, we want to make him an engineer. :)
		looter:setVehicle(vehicletype)

		-- Gear him up
		SetupEngineer(looter)

		-- Now we want to destroy the item
		local itmstruct = loot:get_struct()
		if (itmstruct.amount == 1) then
			loot:destroy()
		else
			itmstruct.amount = itmstruct.amount - 1
			loot:update()
		end

		return false

	-----------------------------------------------------------------------------------
	elseif (loot_type.m_name == "Heavy Marine Kit") then
		-- Player needs to be a marine, and only picking up one kit
		if (amounttopickup > 1) then
			looter:message("You are only allowed one heavy marine kit.")
			return false
		elseif (looter:getVehicle():vehicletypeid() >= 15) then
			looter:message("You need to be a marine to become a heavy marine.")
			return false
		end
		
		-- Find out how experienced he is
		local vehicletype = 20

		if (looter:skill_find(13) == true) then
			vehicletype = 23
		elseif (looter:skill_find(12) == true) then
			vehicletype = 22
		elseif (looter:skill_find(11) == true) then
			vehicletype = 21
		end

		-- Otherwise, we want to make him a heavy. :)
		looter:setVehicle(vehicletype)

		-- Now we want to destroy the item
		local itmstruct = loot:get_struct()
		if (itmstruct.amount == 1) then
			loot:destroy()
		else
			itmstruct.amount = itmstruct.amount - 1
			loot:update()
		end

		return false

	-----------------------------------------------------------------------------------
	elseif (loot_type.m_name == "Chemist Kit") then
		-- Player needs to be a marine, and only picking up one kit
		if (amounttopickup > 1) then
			looter:message("You are only allowed one chemist kit.")
			return false
		elseif (looter:getVehicle():vehicletypeid() >= 15) then
			looter:message("You need to be a marine to become a chemist.")
			return false
		end
		
		-- Give him a laboratory kit
		looter:inventory_modify("Laboratory Kit", 1)

		-- How prepared is he?
		if (looter:skill_find(48) == true) then
			-- Give him a marine part
			looter:inventory_modify("Marine Parts", 2)
		end
		
		if (looter:skill_find(47) == true) then
			-- Give him some zombie parts
			looter:inventory_modify("Zombie Parts", 4)
		end

		-- Find out how experienced he is
		local vehicletype = 25

		if (looter:skill_find(13) == true) then
			vehicletype = 28
		elseif (looter:skill_find(12) == true) then
			vehicletype = 27
		elseif (looter:skill_find(11) == true) then
			vehicletype = 26
		end

		-- Otherwise, we want to make him a chemist. :)
		looter:setVehicle(vehicletype)

		-- Now we want to destroy the item
		local itmstruct = loot:get_struct()
		if (itmstruct.amount == 1) then
			loot:destroy()
		else
			itmstruct.amount = itmstruct.amount - 1
			loot:update()
		end

		return false
	
	-----------------------------------------------------------------------------------
	elseif (loot_type.m_name == "Squad Leader Kit") then
		-- Player needs to be a marine, and only picking up one kit
		if (amounttopickup > 1) then
			looter:message("You are only allowed one squad leader kit.")
			return false
		elseif (looter:getVehicle():vehicletypeid() >= 15) then
			looter:message("You need to be a marine to become a squad leader.")
			return false
		end
		
		-- Give him a summon item
		looter:inventory_modify("Summon Team", 1)

		-- Find out how experienced he is
		local vehicletype = 30

		if (looter:skill_find(13) == true) then
			vehicletype = 33
		elseif (looter:skill_find(12) == true) then
			vehicletype = 32
		elseif (looter:skill_find(11) == true) then
			vehicletype = 31
		end

		-- Otherwise, we want to make him a chemist. :)
		looter:setVehicle(vehicletype)

		-- Now we want to destroy the item
		local itmstruct = loot:get_struct()
		if (itmstruct.amount == 1) then
			loot:destroy()
		else
			itmstruct.amount = itmstruct.amount - 1
			loot:update()
		end

		return false

	-----------------------------------------------------------------------------------
	elseif (loot_type.m_name == "Ammo") then
		-- Don't let zombies pick up ammo
		if (looter:getVehicle():vehicletypeid() >= 100) then
			looter:message("Zombies have no use for ammo.")
			return false
		end

		-- Constrict the amount of ammo you can pick up
		local amountpermitted = gc_startingammo - looter:inventory_find("Ammo")
		
		if (amounttopickup > amountpermitted) then
			looter:message("You can't eat the ammo.")
			return false
		end
			
		-- Add to the player's ammo count
		looter:setstat(3, looter:getstat(3) + amounttopickup)

	-----------------------------------------------------------------------------------
	elseif (loot_type.m_name == "Medikit") then
		-- Don't let zombies pick up medikits
		if (looter:getVehicle():vehicletypeid() >= 100) then
			looter:message("Thief. That's for the marines.")
			return false
		end

		-- Has the player had enough medication for now?
		if (looter:getstat(6) < g_roundnum + 1) then
			-- Give this man his kit!
			-- .. if he's not being greedy
			if (amounttopickup > 1) then
				-- Tell him and refuse the request
				looter:message("You can only grab one medikit at a time.")
				return false
			end
	
			-- Increase his medication
			looter:setstat(6, looter:getstat(6) + 1)
			return true
		else
			-- He's not allowed anymore until the next supply drop
			looter:message("You've had your medication for this drop!")
			return false
		end

	-----------------------------------------------------------------------------------
	elseif (loot_type.m_name == "Plasma Turret Kit") or (loot_type.m_name == "Wall Kit") then
		-- Check to see if he's an engineer
		local vehicletypeid = looter:getVehicle():vehicletypeid()
		if (vehicletypeid < 15) or (vehicletypeid > 18) then
			looter:message("You can't use that.")
			return false
		end

	-----------------------------------------------------------------------------------
	elseif (loot_type.m_name == "Improved Plasma Turret Kit") or (loot_type.m_name == "Enhanced Wall Kit") then
		-- Check to see if he's an engineer
		local vehicletypeid = looter:getVehicle():vehicletypeid()
		if (vehicletypeid < 15) or (vehicletypeid > 18) then
			looter:message("You can't use that.")
			return false
		end

	-----------------------------------------------------------------------------------
	elseif (loot_type.m_name == "Tractor Turret Kit") or (loot_type.m_name == "Gas Turret Kit") then
		-- Check to see if he's an engineer
		local vehicletypeid = looter:getVehicle():vehicletypeid()
		if (vehicletypeid < 15) or (vehicletypeid > 18) then
			looter:message("You can't use that.")
			return false
		end

	-----------------------------------------------------------------------------------
	elseif (loot_type.m_name == "Zombie Parts") or (loot_type.m_name == "Marine Parts") then
		local vehicletypeid = looter:getVehicle():vehicletypeid()

		-- Zombies?
		if (vehicletypeid == 103) or (vehicletypeid == 110) or (vehicletypeid == 104) or (vehicletypeid == 115) then
			if (g_bMarineFact == false) then
				looter:message("You have no use for this yet.")
			end
		
			return true
		end

		if (vehicletypeid < 25) or (vehicletypeid > 28) then
			looter:message("You should leave these for chemists.")
			return false
		end

	end

	return true
end


function Arena_OnCreate(arena)
	-- Set our global value
	g_arena = arena

	-- Initialize random
	math.randomseed(os.time())

	-- Use our own game dynamic
	local cfg = GameSettings()

	cfg.minplayers = 3
	cfg.gamedelay = 5
	
	cfg.str_pregame = "Game starting in "
	cfg.str_noplayers = "Not Enough Zombiefood"

	cfg.bDesertedGameEnd = false

	cfg.bIngameTicker = true
	cfg.tckrUpdateSpacing = 10000

	g_state = g_arena:Takeover_State(cfg)
end

function Arena_OnGameStart()
	-- Destroy the celebration event and all phase events, etc
	event_flush(g_arena)
	g_winner = nil

	-- By this point players should either be on Zombie Horde, private teams or public teams
	-- We want to put all the unassigned zombie players back onto publics
	local zombieteam = team_fromname(g_arena, "Zombie Horde")	
	if (zombieteam:exists() == true) then
		-- Stuff each player back onto the marine team
		while (zombieteam:num() > 0) do
			zombieteam:get(1):team_fill()
		end
	end

	-- Disable and archive teams
	g_arena:toggle_privateteams(false)
	g_arena:toggle_manualswitch(false)
	ArchiveTeams()

	-- Set the supply event in motion
	g_supplyevent = event_create(SupplySpawn, -60000, g_arena)	-- Every minute	

	-- Set variables
	g_bGameRunning = true
	g_bMarineFact = false
	g_roundnum = 0

	-- Perform some calculations for the type of game we want
	local arenaplaying = g_arena:numplaying()
	local amountzombies = math.floor(math.max((arenaplaying / 4), 1))

	-- First, search for professional zombies
	for x = 1, g_arena:num() do
		local marine = g_arena:get(x)

		-- Reset their stats while we're walking through the playerlist
		marine:clearstats()
		marine:setstat(3, gc_startingammo)

		-- Are they a Professional Zombie? (And not in spec)
		if (marine:skill_find(200) == true) and if (player:spectator() == false) then
			-- Turn him!
			marine:team_change("Zombie Horde", "")
			ChooseZombie(marine)

			-- Warp zombies anywhere
			marine:warp(gc_mapcenterx, gc_mapcentery, gc_mapcentery*2)

			-- Decrease the number of zombies we need
			amountzombies = amountzombies - 1

			-- He has been picked
			marine:setstat(9, 1)

			-- Check to see if we have enough
			if (amountzombies <= 0) then
				break
			end
		end
	end

	-- Locate the player ids which we will turn to zombies
	local numplayers = g_arena:num()

	for x = 1, amountzombies do
		local zombie = g_arena:get(math.random(1, numplayers))
		
		-- If he's not in spec and not already picked
		if (zombie:spectator() == false) and (zombie:getstat(9) == 0) then
			-- Turn him
			zombie:team_change("Zombie Horde", "")
			ChooseZombie(zombie)

			-- He has been picked
			zombie:setstat(9, 1)

			-- Warp zombies anywhere
			zombie:resurrect_warp(gc_mapcenterx, gc_mapcentery, gc_mapcentery*2)
		else
			-- We'll have to try again
			x = x - 1
		end
	end

	-- Check if we have enough people in the arena
	local people = g_arena:numplaying()
	if (people < 6) then
		g_arena:message("&Not enough players (6) to commence a full game.");
		return
	end

	-- By this point we should have a selection of zombies,
	-- and people on private and public teams

	-- Configure the teams
	g_spawns = nil
	local numteams = g_arena:numteam()
			
	for i = 1,  numteams do
		-- Get team structure
		local cteam = g_arena:getteam(i)

		-- If it's a private team..
		if (cteam.m_name ~= "spec") and (cteam.m_name ~= "Zombie Horde") then
			-- Sort it out!
			SetupTeam(cteam)
		end
	end
end	

function Arena_OnGameEnd()
	-- Kill the supply event (and all others)
	event_flush(g_arena)

	-- Tell people to join the arena
	g_arena:message("Game is about to start. Enter the game now to play.")
	g_bGameRunning = false

	-- Restore the teams!
	RestoreTeams()

	-- Show endgame stats
	ReportStats()

	-- Should we enable private teams?
	if (g_arena:numplaying() > 50) then
		g_arena:toggle_privateteams(true)
		g_arena:toggle_manualswitch(true)
		g_arena:message("$NOTICE: Private teams are enabled! Pick your teams quickly!")
	else
		g_arena:toggle_privateteams(false)
		g_arena:toggle_manualswitch(false)
	end
end

function Player_OnDeath(killer, victim)
	-- If the game isn't running, we don't want to do any of the other dynamics
	if g_bGameRunning == false then
		return
	end

	-- Check if the victim is a marine	(isn't a zombie)
	if (victim:getVehicle():vehicletypeid() < 35) then
		-- Has there been a teamkill!?
		if (killer:getVehicle():vehicletypeid() < 35) then
			-- The killer is a marine too! Was it a traitorous kill or a marine kill?
			if (victim:frequency() == killer:frequency()) then
				-- Teamkill!
				killer:setstat(4, killer:getstat(4) + 1)
			else
				-- Traitor!!!
				killer:setstat(13, killer:getstat(13) + 1)
			end
		elseif (killer:getVehicle():vehicletypeid() >= 100) then
			-- Otherwise, the killer is a zombie and we need to up his marine kills
			killer:setstat(1, killer:getstat(1) + 1)
		end

		-- Check if he has a preservation kit
		local pos = victim:coords()

		if (victim:inventory_find("Preservation Kit") >= 1) then
			-- Take his kit and res him
			victim:inventory_modify("Preservation Kit", -1)
			victim:resurrect()

			-- Make a nice res cloud on him
			g_arena:explosion_create("Resurrection Cloud", pos.x, pos.y, 0)
			return
		end

		-- First, we'll stick a corpse on top of him
		local corpse = g_arena:vehicle_create(300, pos.x, pos.y, pos.rotation)

		-- Issue details to the corpse
		local victimteam = victim:getTeam()
		corpse:setvar("Represents", victim.m_name)
		corpse:setvarint("OldVehicle", victim:getVehicle():vehicletypeid())		
		corpse:setvar("OldTeam", victimteam.m_name)
		corpse:setvar("OldPassword", victimteam.m_password)

		-- .. and marine parts
		g_arena:item_create("Marine Parts", 1, pos.x, pos.y)	

		-- If he has the Bloody Mess skill make him explode
		if (victim:skill_find(41) == true) then
			g_arena:explosion_create("Super Body Explosion (M)", pos.x, pos.y, 0)
		end

		-- Remove any engineer items
		victim:inventory_modify("Plasma Turret Kit", -1000)
		victim:inventory_modify("Wall Kit", -1000)
		victim:inventory_modify("Tractor Turret Kit", -1000)
		victim:inventory_modify("Gas Turret Kit", -1000)

		-- We want to turn the player into a zombie
		victim:team_change("Zombie Horde", "")
		ChooseZombie(victim)

		-- Has the game been won?
		CheckVictory()

	-- If the victim is a zombie
	elseif (victim:getVehicle():vehicletypeid() >= 100) then
		-- Check to see if he has the Detachable Head skill (and not already a head)
		if (victim:skill_find(82) == true) and (victim:getVehicle():vehicletypeid() ~= 109) then
			-- Roll the dice
			local chance = math.random(0, 100)
		
			if (chance > 60) then
				-- Turn him into a head
				victim:setVehicle(109)
				victim:resurrect()
				
				-- Make him spew zombie fx
				local pos = victim:coords()
				g_arena:explosion_create("Child - Zombie Roar", pos.x, pos.y, 0)

				return
			end
		end

		-- Add one to his zombie deaths
		victim:setstat(2, victim:getstat(2) + 1)

		-- Spawn some zombie parts on his death-bed
		local pos = victim:coords()
		g_arena:item_create("Zombie Parts", 1, pos.x, pos.y)	

		-- Is there a portal active?
		if (g_portal ~= nil) then
			-- Get the current portal's credentials
			local pc = g_portal:coords()
			local portsleft = g_portal:getvarint("PortsLeft")

			local randx = pc.x + math.random(-20, 20)
			local randy = pc.y + math.random(-20, 20)

			-- Is there a queued player awaiting a partner?
			if (g_portalqueued ~= nil) then
				-- Create a bike
				local mybike = g_arena:vehicle_create(113, randx, randy, 0)

				-- Res players
				g_portalqueued:resurrect_warp(randx, randy, 0)
				victim:resurrect_warp(randx, randy, 0)

				-- Stuff them in the bike
				g_portalqueued:setVehicle(112)
				victim:setVehicle(112)
				g_portalqueued:enterVehicle(mybike:vehicleid())
				victim:enterVehicle(mybike:childvehicleid(0))

				-- Effects
				g_arena:explosion_create("Child - Portal In", randx, randy, 0)

				-- Cleanup
				g_portal:setvarint("PortsLeft", portsleft - 2)
				g_portalqueued = nil

			else
				-- Spawn a vehicle?
				local vehchance = math.random(0, 100)

				-- A bike?
				if (vehchance > 80) and (portsleft > 1) and (g_arena:numplaying() > 20) then
					g_portalqueued = victim
					victim:setdeathtimer(0)

				-- Otherwise port them in normally
				else
					-- Resurrect the player at the coords and make an effect
					-- Turn him into portal spawn
					victim:setVehicle(112)
					victim:resurrect_warp(randx, randy, 0)
					g_arena:explosion_create("Child - Portal In", randx, randy, 0)

					g_portal:setvarint("PortsLeft", portsleft - 1)
				end
			end

			-- Assert the portal's life
			if (g_portal:getvarint("PortsLeft") == 0) then
				-- This portal is no longer viable - close it
				g_arena:explosion_create("Child - Portal Create", pc.x, pc.y, 0)
				g_portal:destroy()
				g_portal = nil
			end
		else
			-- Make him a random class
			ChooseZombie(victim)
		end
		
		-- If the killer is a marine..
		if (killer:getVehicle():vehicletypeid() < 15) then
			-- Get his zombie kills
			local zombiekills = killer:getstat(0)
			local zombievehicle = killer:getVehicle():vehicletypeid()
			zombiekills = zombiekills + 1

			-- Is he ready for an upgrade?
			if (zombiekills == 2) and (zombievehicle == 10) then
				killer:setVehicle(11)
			elseif (zombiekills == 4) and (zombievehicle == 11) then
				killer:setVehicle(12)
			elseif (zombiekills == 6) and (zombievehicle == 12) then
				killer:setVehicle(13)
			end

			killer:setstat(0, zombiekills)

		-- .. an engineer?
		elseif (killer:getVehicle():vehicletypeid() < 20) then
			-- Get his zombie kills
			local zombiekills = killer:getstat(0)
			local zombievehicle = killer:getVehicle():vehicletypeid()
			zombiekills = zombiekills + 1

			-- Is he ready for an upgrade?
			if (zombiekills == 2) and (zombievehicle == 15) then
				killer:setVehicle(16)
			elseif (zombiekills == 4) and (zombievehicle == 16) then
				killer:setVehicle(17)
			elseif (zombiekills == 6) and (zombievehicle == 17) then
				killer:setVehicle(18)
			end

			killer:setstat(0, zombiekills)

		-- .. a heavy?
		elseif (killer:getVehicle():vehicletypeid() < 25) then
			-- Get his zombie kills
			local zombiekills = killer:getstat(0)
			local zombievehicle = killer:getVehicle():vehicletypeid()
			zombiekills = zombiekills + 1

			-- Is he ready for an upgrade?
			if (zombiekills == 2) and (zombievehicle == 20) then
				killer:setVehicle(21)
			elseif (zombiekills == 4) and (zombievehicle == 21) then
				killer:setVehicle(22)
			elseif (zombiekills == 6) and (zombievehicle == 22) then
				killer:setVehicle(23)
			end

			killer:setstat(0, zombiekills)

		-- .. a chemist?
		elseif (killer:getVehicle():vehicletypeid() < 30) then
			-- Get his zombie kills
			local zombiekills = killer:getstat(0)
			local zombievehicle = killer:getVehicle():vehicletypeid()
			zombiekills = zombiekills + 1

			-- Is he ready for an upgrade?
			if (zombiekills == 2) and (zombievehicle == 25) then
				killer:setVehicle(26)
			elseif (zombiekills == 4) and (zombievehicle == 26) then
				killer:setVehicle(27)
			elseif (zombiekills == 6) and (zombievehicle == 27) then
				killer:setVehicle(28)
			end

			killer:setstat(0, zombiekills)

		-- .. a squad leader?
		elseif (killer:getVehicle():vehicletypeid() < 35) then
			-- Get his zombie kills
			local zombiekills = killer:getstat(0)
			local zombievehicle = killer:getVehicle():vehicletypeid()
			zombiekills = zombiekills + 1

			-- Is he ready for an upgrade?
			if (zombiekills == 2) and (zombievehicle == 30) then
				-- Give him a gift
				killer:inventory_modify("Cloak Team", 1)
				killer:setVehicle(31)
			elseif (zombiekills == 4) and (zombievehicle == 31) then
				killer:setVehicle(32)
			elseif (zombiekills == 6) and (zombievehicle == 32) then
				killer:setVehicle(33)
			end

			killer:setstat(0, zombiekills)
		end
	end
end

function Player_OnJoin(visitor)
	-- Give him information! :)
	visitor:message("&Note: This zone is essentially just a test of the server's new scripting capabilities.")
	visitor:message("&-     Please post suggestions on the www.freeinfantry.com forum. Also, read the news file.")
end

function Player_OnUnspec(visitor)
	-- Check if the game is in progress
	if (g_bGameRunning == true) then
		-- Remove illegal items
		Conviscate(visitor)
		
		-- Reset all his stats
		visitor:clearstats()
		visitor:setstat(3, gc_startingammo)

		-- We want to unspec the player into the zombie team
		visitor:unspec("Zombie Horde", "")	
		ChooseZombie(visitor)

		-- Warp him anywhere
		visitor:warp(gc_mapcenterx, gc_mapcentery, gc_mapcenterx*2)

		-- Tell him why he spawned as a zombie
		visitor:message("&The game is already in progress so you have been spawned as a zombie.")
		
		-- Don't allow the typical game logic to take effect
		return false
	end
	
	-- Process as per normal
	return true
end

function Player_OnWarpItem(user, itemid, target)
	------------------------------------------------- Invite
	if (itemid == 24) then
		if (target:valid() == false) then
			user:message("Please select a valid player to invite.")
			user:inventory_modify("Invite", 1)
			return false
		end

		-- Make him a 'winner', and warp him to the original
		local winnercoord = user:coords()
		local winnerteam = user:getTeam()

		target:setVehicle(50)
		target:team_change(winnerteam.m_name, winnerteam.m_password)
		target:warp(winnercoord.x, winnercoord.y, 0)
		return true

	------------------------------------------------- Phase
	elseif (itemid == 27) then
		-- Make a phase explosion
		local c = user:coords()
		g_arena:explosion_create("Child - Phase Out", c.x, c.y, 0)

		-- Store which type of wraith he is
		user:setstat(50, user:getVehicle():vehicletypeid())

		-- Change him to the phased vehicle
		user:setVehicle(111)

		-- Create an event to phase him back
		event_createarg(PhaseBack, 9000, g_arena, user.m_base)
		return false

	------------------------------------------------- Portal
	elseif (itemid == 34) then
		-- Create the portal vehicle at the player's position
		local c = user:coords()
		local portal = g_arena:vehicle_create(402, c.x, c.y, 0)

		-- Make a portal create effect
		g_arena:explosion_create("Child - Portal Create", c.x, c.y, 0)

		-- Give the portal an amount of players to port in
		portal:setvarint("PortsLeft", math.random(3, 6))

		-- Make this the active portal (replace the current one)
		if (g_portal ~= nil) then
			local gc = g_portal:coords()
			
			g_portal:destroy()
			g_portal = nil

			g_arena:explosion_create("Child - Portal Create", gc.x, gc.y, 0)
		end

		g_portal = portal
		return false

	------------------------------------------------- Freeze
	elseif (itemid == 30) then
		local players = {}
		local instigatorc = user:coords()

		-- Boom!
		g_arena:explosion_create("Child - Freezekill", instigatorc.x, instigatorc.y, 0)

		-- Get all the players around the user
		local numplayers = g_arena:GetPlayersInArea(players, instigatorc.x, instigatorc.y, 50)
		if (numplayers == 0) then
			return false
		end

		for i = 1, numplayers do
			local plyr = players[i]
			local vid = plyr:getVehicle():vehicletypeid()
			local health = plyr:health()

			-- Is the player an alive zombie?
			if (vid >= 100) and (vid ~= 107) and (vid ~= 111) and (health ~= 0) then
				-- Store his stats
				plyr:setstat(50, vid)

				-- Turn him into a frozen zombie
				plyr:setVehicle(107)

				-- Booom!
				local c = plyr:coords()
				g_arena:explosion_create("Child - Frozen", c.x, c.y, 0)

				-- Set an event for him
				event_createarg(Unfreeze, 8000, g_arena, plyr.m_base)
			end
		end
		return false

	------------------------------------------------- Meteor Storm
	elseif (itemid == 36) then
		-- Create the portal vehicle at the player's position
		local c = user:coords()

		-- Create clouds above the user
		for i = -225, 225, 30 do
			local cloudtype = nil
			local chance = math.random(1, 100)
			if (chance > 50) then
				cloudtype = "Child - Meteor Cloud 1"
			else
				cloudtype = "Child - Meteor Cloud 2"
			end

			g_arena:explosion_create(cloudtype, c.x + i, c.y + math.random(-90, 90), 0)
		end

		-- Start the meteors
		g_arena:explosion_create("Child - Meteor Create", c.x, c.y, 0)
		event_createarg(MeteorStorm, -1500, g_arena, c)
		return false

	------------------------------------------------- Cloak Team
	elseif (itemid == 38) then
		local playerteam = user:getTeam()
		local playercoords = user:coords()
		local teamnum = playerteam:num()

		for x = 1, teamnum do
			local teammate = playerteam:get(x)

			-- If not in spec..
			if (teammate:spectator() == false) then
				-- Give him some temporary cloaking
				teammate:inventory_modify("Temporary Cloak", 1)

				-- Make it look cool.
				local c = teammate:coords()
				g_arena:explosion_create("Child - Phase Out", c.x, c.y, 0)
			end
		end

		return false

	------------------------------------------------- Summon Team
	elseif (itemid == 39) then
		local playerteam = user:getTeam()
		local playercoords = user:coords()
		local teamnum = playerteam:num()

		for x = 1, teamnum do
			local teammate = playerteam:get(x)

			-- If not in spec..
			if (teammate:spectator() == false) then
				-- Warp him
				teammate:warp(playercoords.x, playercoords.y, 0)
			end
		end
		

		return false

	------------------------------------------------- Turret kits
	elseif (itemid == 11) or (itemid == 8) or (itemid == 35) or (itemid == 23) then
		-- Increase his turrets built stat
		user:setstat(10, user:getstat(10) + 1)
		return true

	------------------------------------------------- Wall kits
	elseif (itemid == 13) or (itemid == 17) then
		-- Increase his turrets built stat
		user:setstat(11, user:getstat(11) + 1)
		return true
	end

	return true
end

function Arena_TickerUpdate()
	-- Keep track of the most rewarded player
	local bestreward = 0
	local rewardowner = nil

	-- For every player..
	for x = 1, g_arena:num() do
		local plyr = g_arena:get(x)

		-- If he's not in spec..
		if (plyr:spectator() == false) then
			-- Calculate and show his reward
			local reward = CalculateReward(plyr)
			plyr:setticker(1, "Your reward=" .. reward)

			-- Keep tabs on the best reward
			if (reward > bestreward) or (bestreward == 0) then
				bestreward = reward
				rewardowner = plyr
			end
		end
	end

	-- Show the best player
	g_state:SetNotice(0, "Best Player=" .. rewardowner.m_name .. " (" .. bestreward .. ")")
end