- -- General infection settings
- zombie_team = 1 -- 0 is red, 1 is blue
- human_team = 1 - zombie_team
- zombie_speed = 2 -- zombie speed
- join_team = zombie_team -- the team that people will join as if a game is currently running
- lastman_speed = 1.5 -- last man speed
- lastman_dmgmodifier = 1.5 -- damage modifier for the last man (on top of human damage)
- lastman_invistime = 10 -- in seconds
- human_speed = 1.0 -- speed when not infected
- zombie_count = 1 -- if value is less than 1 is it used as a percentage, more than or equal to one is absolute count
- last_man_next_zombie = true -- if this value is true the last man standing becomes the next zombie, if not it's random
- max_zombie_count = 2 -- this caps what the zombie count would be w/ ratio (nil is disable)
- lastman_invulnerable = 5 -- time (in seconds) the last man is invulnerable for: replace with nil to disable
- alphazombie_frag_count = 0 -- number of frag nades they spawn with
- alphazombie_plasma_count = 0 -- number of plasma nades they spawn with
- zombie_frag_count = 0 -- number of frag nades they spawn with
- zombie_plasma_count = 0 -- number of plasma nades they spawn with
- alphazombie_clip_count = 0 -- number of shots in clip (loaded ammo)
- alphazombie_ammo_count = 0 -- backpack ammo they get (unloaded ammo)
- alphazombie_battery_count = 0 -- stored as a percent (0 to 1, do NOT go over or under)
- zombie_clip_count = 0 -- number of shots in clip for zombies once there are not only alpha zombies (loaded ammo)
- zombie_ammo_count = 0 -- backpack ammo zombies once there are not only alpha zombies (unloaded ammo)
- zombie_battery_count = 0 -- stored as a percent (0 to 1, do NOT go over or under)
- infect_on_fall = true -- if this is set to true then people who die from fall damage will become zombies.
- infect_on_guardians = false -- if this is set to true then people who get killed by the guardians will become zombies.
- infect_on_suicide = true -- if this is set to true then people who kill themselves will become a zombie.
- infect_on_betray = true -- if this is set to true then people who betray their teammates will become a zombie.
- humans_allowed_in_vehis = true -- if this is set to false then humans cannot enter vehicles
- zombies_allowed_in_vehis = false -- if this is set to false then zombies cannot enter vehicles.
- zombies_invisible_on_crouch = true -- if this is set to true then zombies will be invisible when they crouch.
- humans_invisible_on_crouch = false -- if this is set to true then humans will become invisible when they crouch.
- --Zombie weapons.
- -- Note: If you decide the player holds a flag or a ball, make sure the secondary, tertiary, and quarternary fields are "".
- -- DO NOT make zombies hold multiple weapons if you want them to hold an oddball or a flag. If you do it will not work right, and it's entirely your fault.
- zombie_weapon = {} -- don't touch this
- zombie_weapon[1] = "weapons\\flag\\flag" -- Primary weapon for zombies
- zombie_weapon[2] = "" -- Secondary weapon for zombies.
- zombie_weapon[3] = "" -- Tertiary weapon for zombies.
- zombie_weapon[4] = "" -- Quarternary weapon for zombies.
- -- Game messages
- zombie_message = "YOU'RE A ZOMBIE. KILL THE HUMANS!"
- human_message = "YOU'RE A HUMAN. SURVIVE."
- rejoin_message = "Please don't leave and rejoin. You've been put back onto your last team."
- infected_message = " has been infected!"
- teamkill_message = "Don't team kill..."
- blockteamchange_message = "You're not allowed to change team."
- zombieinvis_message = "The zombies are invisible for 20 seconds!"
- timer_team_change_msg = "Thank you. The game will now continue"
- in_hill_too_long_msg = " has been infected because they were in the hill too long!"
- welcome_message = "Welcome to Zombies, brought to you by Phasor\nhttp://phasor.proboards.com"
- koth_additional_welcome_msg = "The hill is a safezone! Use it for quick getaways!"
- slayer_additional_welcome_msg = "The nav points are not just for decoration!\nThey will point to the last man surviving!"
- lastman_message = "%s is the last human alive and is invisible for %.0f seconds!"
- nozombiesleftmessage = "There are no zombies left. Someone needs to change team, otherwise a random player will be forced to."
- -- Don't modify below variables unless you know what you're doing
- cur_zombie_count = 0
- cur_human_count = 0
- alpha_zombie_count = 0
- human_time = {}
- cur_players = 0
- cur_last_man = nil
- last_man_hash = 0
- processid = 0
- game_started = false
- allow_change = false
- new_game_timer = 0
- player_change_timer = 0
- flagball_weap = {}
- flags_balls_table = {}
- last_hill_time = {}
- hash_table = {}
- inhill_time = {}
- -- This function is required for scripts to run on Phasor (including and after 01.00.03.104)
- -- You should return the minimum required version of Phasor
- -- Official releases:
- -- 01.00.03.104 - 3104
- -- 01.00.10.057 - 10057
- function GetRequiredVersion()
- return 10057
- end
- -- called when the script is loaded
- function OnScriptLoad(process)
- for i = 1,4 do
- if zombie_weapon[i] == "weapons\\ball\\ball" or zombie_weapon[i] == "weapons\\flag\\flag" then
- oddball_or_flag = zombie_weapon[i]
- end
- end
- processid = process
- -- assume a game is running
- game_started = true
- game = GetGameAddresses()
- gametype = readbyte(gametype_base, 0x30)
- if gametype == 1 then
- gametype = "CTF"
- writedword(flag_respawn_addr, 0x0, 0xFFFFFFFF)
- registertimer(0, "DelayWriteCoords")
- elseif gametype == 2 then
- gametype = "Slayer"
- writebyte(gametype_base, 0x58, 3)
- speedtimer = registertimer(1000, "SpeedTimer")
- elseif gametype == 4 then
- gametype = "KOTH"
- end
- team_play = readbyte(gametype_base, 0x34) -- Confirmed. (Off = 0) (On = 1)
- if team_play == 1 then
- team_play = true
- else
- team_play = false
- zombie_team = 0
- function getteam(player)
- local m_player = getplayer(player)
- if m_player then
- local team = readbyte(m_player, 0x20)
- if team then
- return team
- end
- end
- end
- function changeteam(player, forcekill, team, updatecounters)
- local m_player = getplayer(player)
- local cur_team = readbyte(m_player, 0x20)
- if not team then
- if cur_team ~= zombie_team then
- team = zombie_team
- end
- end
- if m_player then
- if team == zombie_team then
- writebyte(m_player, 0x20, team)
- writebyte(m_player, 0x60, 3)
- if forcekill == true or forcekill == 1 then
- kill(player)
- end
- if team ~= cur_team then
- OnFFATeamChange(player, cur_team, team, updatecounters)
- end
- return
- elseif team then
- writebyte(m_player, 0x20, team)
- else
- for i = 1,15 do
- local bool
- for j = 0,15 do
- local m_player = getplayer(j)
- if m_player then
- local team = readbyte(m_player, 0x20)
- if team == i then
- bool = true
- break
- end
- end
- end
- if not bool then
- team = i
- writebyte(m_player, 0x20, i)
- break
- end
- end
- end
- for i = 0,17 do
- if i ~= 3 then
- local bool
- for j = 0,15 do
- local m_player = getplayer(j)
- if m_player then
- local color = readbyte(m_player, 0x60)
- if color == i then
- bool = true
- break
- end
- end
- end
- if not bool then
- writebyte(m_player, 0x60, i)
- break
- end
- end
- end
- if forcekill == true or forcekill == 1 then
- kill(player)
- end
- end
- if team ~= cur_team then
- OnFFATeamChange(player, cur_team, team, updatecounters)
- end
- end
- function OnFFATeamChange(player, cur_team, dest_team, updatecounters)
- -- update team counts
- if not updatecounters then
- if dest_team == zombie_team then
- cur_human_count = cur_human_count - 1
- cur_zombie_count = cur_zombie_count + 1
- elseif dest_team ~= zombie_team then
- cur_human_count = cur_human_count + 1
- cur_zombie_count = cur_zombie_count - 1
- end
- end
- -- check if the game has started yet
- if game_started == true then
- --[[-- set attributes
- if dest_team == zombie_team then
- makezombie(player, false)
- elseif dest_team ~= zombie_team then
- makehuman(player, false)
- end--]]
- checkgamestate(player)
- end
- -- update team with
- local thisHash = gethash(player)
- hash_table[thisHash] = dest_team
- end
- end
- starting_equipment = readbit(gametype_base, 0x38, 2) -- Generic = 0, Custom = 1
- if starting_equipment == 1 then
- starting_equipment = "Generic"
- else
- starting_equipment = "Custom"
- end
- humantimer = registertimer(1000, "HumanTimer")
- crouch_timer = registertimer(200, "invisCrouch")
- if oddball_or_flag then
- for i = 0,15 do
- if getplayer(i) then
- local m_object = getobject(getplayerobjectid(i))
- if m_object then
- local weapID = readdword(m_object, 0x118)
- local weap = getobject(weapID)
- local tagName = getobjecttag(weapID)
- if tagName == oddball_or_flag then
- flagball_weap[i] = weapID
- table.insert(flags_balls_table, weapID)
- end
- end
- end
- end
- end
- -- recalculate team counters
- cur_zombie_count = getzombiesize()
- cur_human_count = gethumansize()
- cur_players = cur_zombie_count + cur_human_count
- -- recalculate how many "alpha" zombies there are
- alpha_zombie_count = getalphacount()
- -- load the last man hash (if there is one)
- local file = io.open("lasthash_" .. processid .. ".tmp", "r")
- if (file ~= nil) then
- -- read the ip
- last_man_hash = file:read("*line")
- file:close()
- -- delete the file
- os.remove("lasthash_" .. processid .. ".tmp")
- end
- checkgamestate()
- end
- function SpeedTimer(id, count)
- for i = 0,15 do
- if getteam(i) == zombie_team then
- local m_player = getplayer(i)
- local speed = readfloat(m_player, 0x60)
- if speed < zombie_speed then
- setspeed(i, zombie_speed)
- end
- end
- end
- return 1
- end
- function gethumansize()
- local size = 0
- for i = 0,15 do
- local m_player = getplayer(i)
- if m_player then
- local team = readbyte(m_player, 0x20)
- if team ~= zombie_team then
- size = size + 1
- end
- end
- end
- return size
- end
- function getzombiesize()
- local size = 0
- for i = 0,15 do
- local m_player = getplayer(i)
- if m_player then
- local team = readbyte(m_player, 0x20)
- if team == zombie_team then
- size = size + 1
- end
- end
- end
- return size
- end
- GetGameAddresses = function()
- local map_header_version = readbyte(0x630E74, 0x4)
- if map_header_version == 7 then
- map_pointer = 0x63525c
- ctf_globals = 0x639B98
- slayer_globals = 0x63A0E8
- gametype_base = 0x671340
- ctf_flag_stolen = 0x639BB4
- ball_holder_addr = 0x639F1C
- team_oddball_score_array = 0x639E9C
- oddball_score_array = 0x639E5C
- koth_move_timer = 0x639D78
- team_koth_score_array = 0x639BD0
- team_race_score_array = 0x63A028
- machine_pointer = 0x745BA0
- flag_respawn_addr = 0x488A7E
- inhill_addr = 0x639C50
- return "PC"
- else
- map_pointer = 0x5B927C
- ctf_globals = 0x5BDBB8
- slayer_globals = 0x5BE108
- gametype_base = 0x5F5498
- ctf_flag_stolen = 0x5BD8B4
- ball_holder_addr = 0x5BDF3C
- team_oddball_score_array = 0x5BDE9C
- oddball_score_array = 0x5BDE5C
- koth_move_timer = 0x5BDD78
- team_koth_score_array = 0x5BDBF0
- team_race_score_array = 0x5BD028
- machine_pointer = 0x6C7980
- flag_respawn_addr = 0x4638EE
- inhill_addr = 0x5BDC70
- return "CE"
- end
- end
- -- called when the script is unloaded
- -- Do not return a value
- function OnScriptUnload()
- end
- function getobjecttag(object)
- local m_object = getobject(object)
- local object_map_id = readdword(m_object, 0x0)
- local map_base = readdword(map_pointer, 0x0)
- local map_tag_count = todec(endian(map_base, 0xC, 0x3))
- local tag_table_base = map_base + 0x28
- local tag_table_size = 0x20
- for i=0,(map_tag_count - 1) do
- local tag_id = todec(endian(tag_table_base, 0xC + (tag_table_size * i), 0x3))
- if tag_id == object_map_id then
- tag_name_address = endian(tag_table_base, 0x10 + (tag_table_size * i), 0x3)
- tag_name = readtagname("0x" .. tag_name_address)
- return tag_name
- end
- end
- end
- function endian(address, offset, length)
- local data_table = {}
- local data = ""
- for i=0,length do
- local hex = string.format("%X", readbyte(address, offset + i))
- if tonumber(hex, 16) < 16 then
- hex = 0 .. hex
- end
- table.insert(data_table, hex)
- end
- for k,v in pairs(data_table) do
- data = v .. data
- end
- return data
- end
- function todec(number)
- return tonumber(number, 16)
- end
- -- called when a game is starting (before any players join)
- -- Do not return a value.
- function OnNewGame(Map)
- -- reset our variables
- cur_zombie_count = 0
- cur_human_count = 0
- cur_players = 0
- map = Map
- -- the game hasn't started yet, will once timer runs down
- game_started = false
- new_game_timer = registertimer(2000, "NewGameTimer")
- if map == "putput" or map == "longest" or map == "beavercreek" then
- zombie_speed = 1.5
- lastman_speed = 1.25
- end
- end
- function DelayWriteCoords(id, count)
- writefloat(readdword(ctf_globals, 0x0), 0x8, readfloat(readdword(ctf_globals, 0x0), 0x8) - 100)
- writefloat(readdword(ctf_globals, 0x4), 0x8, readfloat(readdword(ctf_globals, 0x4), 0x8) - 100)
- return 0
- end
- -- called when a game is ending
- -- Do not return a value.
- function OnGameEnd(mode)
- -- mode 1 = score menu (F1) is being displayed to clients, they are still ingame
- -- mode 2 = post game menu appeared
- -- mode 3 = players can quit via the post game score card
- -- remove the new game timer (if still active)
- if mode == 1 then
- removetimer(new_game_timer)
- removetimer(crouch_timer)
- game_started = false
- end
- end
- -- Called when there is chat within the server
- -- It must return a value which indicates whether or not the chat is sent.
- function OnServerChat(player, chattype, message)
- return 1
- end
- -- Called when a server command is being executed
- -- It must return a value which indicates whether or not the command should be processed
- -- Note: It is only called when an authenticated (and allowed) player attempts to use the command.
- -- player is -1 when being executed via the server console.
- function OnServerCommand(player, command)
- local allow = 1
- local tokencount = getcmdtokencount(command)
- if tokencount > 0 then
- local cmd = getcmdtoken(command, 0)
- if cmd == "sv_changeteam" and tokencount == 2 then
- local player = getcmdtoken(command, 1)
- player = rresolveplayer(player)
- if getplayer(player) then
- local cur_team = getteam(player)
- if cur_team == zombie_team then
- makehuman(player, true)
- privatesay(player, human_message)
- elseif cur_team ~= zombie_team then
- makezombie(player, true)
- privatesay(player, zombie_message)
- end
- hprintf("The player's team has been changed.")
- else
- hprintf("The specified player is invalid")
- end
- allow = 0
- elseif cmd == "sv_map_reset" then
- for i = 0,15 do
- local m_player = getplayer(i)
- if m_player then
- local m_object = getobject(getplayerobjectid(i))
- if m_object then
- local team = getteam(i)
- if team == zombie_team then
- destroyweaps(i)
- end
- end
- end
- end
- end
- end
- return allow
- end
- function HumanTimer(id, count)
- if game_started == true then
- for i = 0,15 do
- local m_player = getplayer(i)
- if m_player then
- local hash = gethash(i)
- local team = readbyte(m_player, 0x20)
- local m_object = getobject(getplayerobjectid(i))
- if team ~= zombie_team and game_started then
- local m_playerObjId = getplayerobjectid(i)
- if getobject(m_playerObjId) then
- if tonumber(human_time[hash]) then
- human_time[hash] = tonumber(human_time[hash]) + 1
- else
- human_time[hash] = 1
- end
- end
- end
- if gametype == "KOTH" then
- if PlayerInHill(i) == true and m_object then
- --if cur_last_man ~= i then
- if inhill_time[hash] == nil then
- inhill_time[hash] = 0
- writebit(m_object, 0x10, 7, 1)
- --[[say(getname(i) .. " is in the hill and they are immortal until they leave!")
- if team ~= zombie_team then
- say(getname(i) .. " must leave the hill in 10 seconds or they will be infected!")
- else
- say(getname(i) .. " must leave the hill in 10 seconds or they will be killed!")
- end--]]
- elseif inhill_time[hash] >= 10 then
- if team ~= zombie_team then
- makezombie(i, true)
- say(getname(i) .. " is now a zombie because they were in the hill too long!")
- else
- kill(i)
- say(getname(i) .. " has been killed because they were in the hill too long!")
- end
- inhill_time[hash] = nil
- elseif team ~= zombie_team then
- privatesay(i, "You have " .. math.abs(inhill_time[hash] - 10) .. " seconds to leave the hill!")
- inhill_time[hash] = inhill_time[hash] + 1
- end
- --end
- elseif m_object then
- inhill_time[hash] = nil
- writebit(m_object, 0x10, 7, 0)
- end
- end
- end
- end
- end
- return 1
- end
- function PlayerInHill(player)
- player = tonumber(player)
- local bool = false
- local m_player = getplayer(player)
- if m_player then
- local InHill = readbyte(inhill_addr + player, 0x0)
- if InHill == 1 then
- bool = true
- end
- end
- return bool
- end
- function invisCrouch(id, count)
- if not zombies_invisible_on_crouch and not humans_invisible_on_crouch then return 0 end
- for i = 0,15 do
- if getplayer(i) then
- local m_object = getobject(getplayerobjectid(i))
- if m_object then
- local obj_crouch = readbyte(m_object, 0x2A0)
- if obj_crouch == 3 then
- local team = readbyte(getplayer(i), 0x20)
- if (team == zombie_team and zombies_invisible_on_crouch) or (team ~= zombie_team and humans_invisible_on_crouch) then
- applycamo(i, 1)
- end
- end
- end
- end
- end
- return 1
- end
- -- Called when a player's team is being chosen as the join the server.
- -- It must return a value which indicates the team the player is to be put on.
- -- Note: this function being called doesn't guarantee that the player will be able to successfully join.
- function OnTeamDecision(cur_team)
- local dest_team = join_team
- if game_started then
- if cur_players == 0 then -- if no zombies make them human
- dest_team = human_team
- elseif cur_zombie_count > 0 and cur_human_count == 0 then
- dest_team = human_team
- end
- end
- return dest_team
- end
- -- Called when a player joins the server.
- -- Do not return a value.
- function OnPlayerJoin(player, team)
- -- update the player counts
- cur_players = cur_players + 1
- -- onteamdecision isn't called for ffa gametypes
- if not team_play then
- -- initialize the destination team as the join team
- local dest_team = join_team
- -- make sure the game is started
- if game_started then
- -- if no zombies make them human
- if cur_players == 0 then
- -- change the destination team to human if cur_players 0 (doesn't matter if join_team is humanteam)
- dest_team = human_team
- -- check if there are zombies but no humans
- elseif cur_zombie_count > 0 and cur_human_count == 0 then
- -- change the destination team to human if condition met (doesn't matter if join_team is humanteam)
- dest_team = human_team
- end
- end
- -- we need to overwrite the 'team' variable being passed to onplayerjoin
- if dest_team == zombie_team then
- team = zombie_team
- elseif tonumber(dest_team) then
- team = 2
- end
- end
- local thisTeamSize = 0 -- used so we don't create empty teams for rejoining players
- if team == zombie_team then
- cur_zombie_count = cur_zombie_count + 1
- thisTeamSize = cur_zombie_count
- else
- cur_human_count = cur_human_count + 1
- thisTeamSize = cur_human_count
- end
- alpha_zombie_count = getalphacount()
- local thisHash = gethash(player)
- local alreadyExists = false
- -- check if the player has joined this game previously
- for k,v in pairs(hash_table) do
- if thisHash == k then
- if thisTeamSize > 1 then
- if v ~= team then
- --check what team they currently are (only added for ffa gametypes)
- if team == zombie_team then
- makehuman(player, false)
- else
- makezombie(player, false)
- end
- end
- --privatesay(player, rejoin_message)
- team = v
- end
- alreadyExists = true
- break
- end
- end
- -- add team entry for this hash
- if alreadyExists == false then
- hash_table[thisHash] = team
- end
- -- make sure the game is started
- if game_started == true then
- -- check if the player is a zombie
- if team == zombie_team then
- --we don't need to update the counters since they're already on the zombieteam
- makezombie(player, false, true)
- --send them the zombie message
- privatesay(player, zombie_message)
- else
- -- if we're at last man, make this player a zombie
- if cur_last_man then
- --make this person a zombie (they're currently a human)
- makezombie(player, true)
- --send them the zombie message
- privatesay(player, zombie_message)
- else
- --make this person a human (they're currently a zombie)
- makehuman(player, false, true)
- --send them the human message
- privatesay(player, human_message)
- end
- end
- --send the player the welcome message
- privatesay(player, welcome_message)
- if gametype == "KOTH" then
- privatesay(player, koth_additional_welcome_msg)
- elseif gametype == "Slayer" then
- privatesay(player, slayer_additional_welcome_msg)
- end
- checkgamestate(-1)
- else
- registertimer(10000, "MsgTimer", player)
- end
- end
- --called when a person joins before the game is started so that the welcome message
- --doesn't get lost in the spam
- function MsgTimer(id, count, player)
- privatesay(player, welcome_message)
- if gametype == "KOTH" then
- privatesay(player, koth_additional_welcome_msg)
- elseif gametype == "Slayer" then
- privatesay(player, slayer_additional_welcome_msg)
- end
- return 0
- end
- -- Called when a player the server.
- -- Do not return a value.
- function OnPlayerLeave(player, team)
- --check if they're a zombie
- if team == zombie_team then
- --get their object struct
- local m_object = getobject(getplayerobjectid(player))
- if m_object then -- make sure the player is alive
- for i = 0,3 do -- loop through all their weapons (primary through quartenary)
- --get their weapon's ID
- local weapID = readdword(m_object, 0x2F8 + i*4)
- --get their weapon's struct
- local weap = getobject(weapID)
- --make sure the weapon exists
- if weap then
- --weapon needs to be destroyed
- registertimer(0, "destroyweaps", weapID)
- end
- end
- end
- --take one away from the current zombie count
- cur_zombie_count = cur_zombie_count - 1
- elseif team ~= zombie_team then
- --take one away from the current human count
- cur_human_count = cur_human_count - 1
- end
- -- if last man is leaving, reset it
- if cur_last_man == player then
- cur_last_man = nil
- end
- --minus one from current players
- cur_players = cur_players - 1
- --check the current game state (the player that left might have been the last man or the only zombie)
- checkgamestate(-1)
- -- update team within table
- local thisHash = gethash(player)
- hash_table[thisHash] = team
- end
- -- called when a player kills another, 'killer' is the index of the killing player, 'victim' is the index of the dead player
- -- Do not return a value.
- function OnPlayerKill(killer, victim, mode)
- -- make sure this kill doesn't add to the score so that the game won't end prematurely
- if gametype == "Slayer" and killer and getplayer(killer) then writedword(slayer_globals, 0x40 + killer*4, 0) end
- -- make sure the game is started
- if game_started then
- -- get the victim's team
- local team = getteam(victim)
- -- i used this for debugging lol
- --hprintf("Victim Team: " .. tostring(team))
- if mode == 0 then -- server kill
- elseif mode == 1 then -- fall damage
- -- if this is true then a person who dies from falling will be infected
- if infect_on_fall then
- --chech if the team is the human team
- if tonumber(team) and team ~= zombie_team then
- --get the victim's name
- local name = getname(victim)
- --send the victim the infected message
- say(name .. infected_message)
- --make the victim a zombie
- makezombie(victim, false)
- end
- end
- elseif mode == 2 then -- killed by guardians
- -- if this is true then a person who dies from the guardians will be infected
- if infect_on_guardians then
- --check if the victim's team is the human team
- if tonumber(team) and team ~= zombie_team then
- --get the victim's name
- local name = getname(victim)
- --send the victim the infected message
- say(name .. infected_message)
- --make the victim a zombie
- makezombie(victim, false)
- end
- end
- elseif mode == 3 then -- killed by vehicle
- elseif mode == 4 then -- killed by another player
- --get the killer's team
- local killer_team = getteam(killer)
- -- check to see if a zombie killed them
- if tonumber(killer_team) and killer_team == zombie_team and tonumber(team) and team ~= zombie_team then
- --get the victim's name
- name = getname(victim)
- --send the victim the infected message
- say(name .. infected_message)
- --make the victim a zombie
- makezombie(victim, false)
- --privatesay(victim, zombie_message)
- end
- --i used this for debugging
- --hprintf("Killer Team: " .. killer_team)
- elseif mode == 5 then -- betrayed
- --if this is true then a person who betrays will be infected
- if infect_on_betray then
- --get the killer's team
- local killer_team = getteam(killer)
- --check if the killer is a human
- if tonumber(killer_team) and killer_team ~= zombie_team then
- --get the betrayer's name
- name = getname(killer)
- --send the betrayer the infected message
- say(tostring(name) .. infected_message)
- --make the betrayer a zombie
- makezombie(killer, true)
- end
- end
- elseif mode == 6 then -- suicide
- --if this is true then a person who suicides will be come a zombie
- if infect_on_suicide then
- -- if they're human, make them zombies
- if tonumber(team) and team ~= zombie_team then
- --get the suicider's name
- name = getname(victim)
- --they're not going to end their life that easily
- say(name .. infected_message)
- --make the suicider a zombie
- makezombie(victim, false)
- end
- end
- end
- -- this next block of code gets rid of any weapons a zombie is holding
- if tonumber(team) and team == zombie_team then
- local m_player = getplayer(victim) --get the player's struct
- local m_object = getobject(readdword(m_player, 0x34)) -- get the player's object struct
- --there's an off chance that the player might be dead (phasor bug) can't hurt to add this check
- if m_object then
- for i = 0,3 do -- loop through the player's weapons (primary to quartenary)
- local weapID = readdword(m_object, 0x2F8 + i*4)
- local weap = getobject(weapID)
- --make sure the weapon exists
- if weap then
- --destroy their weapons
- registertimer(0, "destroyweaps", weapID)
- end
- end
- end
- end
- end
- end
- --I made this function because there's a bug with destroyobject in phasor version 058X
- --basically all it does is move the objects under the map lol
- function destroyweaps(id, count, m_weaponId)
- local m_weapon = getobject(m_weaponId)
- if m_weapon then
- writefloat(m_weapon, 0x5C, readfloat(m_weapon, 0x5C) - 1000)
- end
- return 0
- end
- -- called when a player gets a double kill, killing spree etc
- -- see Phasor documentation for multiplier values
- function OnKillMultiplier(player, multiplier)
- end
- -- Called when a player s (after object is created, before players are notified)
- -- Do not return a value
- function OnPlayerSpawn(player, m_objectId)
- --get the player's team
- local team = getteam(player)
- --check if the player is a zombie
- if team == zombie_team then
- --get the player's object ID
- local m_objectId = getplayerobjectid(player)
- --get the player's object struct
- local m_object = getobject(m_objectId)
- --make sure the player is alive (off chance that there's a glitch in phasor)
- if m_object then
- -- set nade counts
- writebyte(m_object, 0x31E, zombie_frag_count)
- writebyte(m_object, 0x31F, zombie_plasma_count)
- -- set the ammo
- local clipcount = alphazombie_clip_count
- local ammocount = alphazombie_ammo_count
- local batterycount = alphazombie_battery_count
- -- set ammo counts for zombies when others have been infected
- if cur_zombie_count > alpha_zombie_count then
- clipcount = zombie_clip_count
- ammocount = zombie_ammo_count
- batterycount = zombie_battery_count
- else -- set alpha nades
- writebyte(m_object, 0x31E, alphazombie_frag_count)
- writebyte(m_object, 0x31F, alphazombie_plasma_count)
- end
- --check if the starting equipment is generic
- if starting_equipment == "Generic" then
- -- initialize this boolean as false
- local bool = false
- for i=0,3 do --loop through the player's weapons (primary through quartenary)
- --get the player's weapon's ID
- local m_weaponId = readdword(m_object, 0x2F8 + i*4)
- --check if the zombie weapon is an oddball or a flag
- if oddball_or_flag then
- --make sure the boolean is still false and the player's weapon exists.
- if bool == false and getobject(m_weaponId) then
- --get the weapon's tagname
- local tagName = getobjecttag(m_weaponId)
- --make sure the weapon's tagname is the zombie weapon (oddball/flag)
- if tagName == oddball_or_flag then
- --store the weapon's ID in the flagball_weap table
- flagball_weap[player] = m_weaponId
- --set bool to true
- bool = true
- end
- end
- --zombie weapon is not a flag or a ball
- elseif m_weaponId ~= 0xFFFFFFFF then
- --get the weapon's struct
- local m_weapon = getobject(m_weaponId)
- --make sure the weapon exists
- if m_weapon then
- -- set the ammo
- writeword(m_weapon, 0x2B6, ammocount)
- writeword(m_weapon, 0x2B8, clipcount)
- -- set the battery (math.abs is absolute value meaning it takes the opposite of battery count (meaning 0 needs to be 1 and 1 needs to be 0))
- writefloat(m_weapon, 0x240, math.abs(batterycount - 1))
- -- force it to sync
- updateammo(m_weaponId)
- end
- end
- end
- -- check if we still need to assign leftover weapons to zombies (tertiary and quartenary weapons)
- if (zombie_weapon[3] and zombie_weapon[3] ~= "") then -- make sure the script user isn't retarded
- --assign the leftover weapons to the player
- registertimer(0, "AssignLeftoverZombieWeapons", player, clipcount, ammocount, batterycount)
- end
- elseif starting_equipment == "Custom" then
- --assign the correct weapons to the player
- registertimer(0, "AssignZombieWeapons", player, clipcount, ammocount, batterycount)
- end
- end
- end
- --check if the gametype is slayer
- if gametype == "Slayer" then
- local m_player = getplayer(player)
- --check if we're at the last_man
- if cur_last_man then
- --write the navpoint to the current last man
- writeword(m_player, 0x88, cur_last_man)
- else
- --there is no last man so put a nav above this player's head
- writeword(m_player, 0x88, player)
- end
- end
- end
- --basically this timer assigns the tertiary and quarternary weapons to zombies if specified at the top
- --this is needed since onweaponassignment isn't called for tertiary and quartenary weapons
- function AssignLeftoverZombieWeapons(id, count, player, clipcount, ammocount, batterycount)
- local m_objectId = getplayerobjectid(player)
- if m_objectId ~= 0xFFFFFFFF then
- local m_object = getobject(m_objectId)
- if m_object then
- local m_weaponId = createobject("weap", zombie_weapon[3], 0, 0, false, 5, 2, 2)
- if m_weaponId ~= 0xFFFFFFFF then
- local m_weapon = getobject(m_weaponId)
- if m_weapon then
- -- set the ammo
- writeword(m_weapon, 0x2B6, ammocount)
- writeword(m_weapon, 0x2B8, clipcount)
- writefloat(m_weapon, 0x240, math.abs(batterycount - 1))
- -- force it to sync
- updateammo(m_weaponId)
- end
- end
- --make sure the script user isn't retarded so we don't get errors
- if zombie_weapon[4] and zombie_weapon[4] ~= "" then
- --create the quarternary weapon
- local m_weaponId = createobject("weap", zombie_weapon[4], 0, 0, false, 5, 5, 2)
- --make sure createobject didn't screw up
- if m_weaponId ~= 0xFFFFFFFF then
- --assign the weapon to the player
- assignweapon(player, m_weaponId)
- --make sure we can safely set the ammo
- local m_weapon = getobject(m_weaponId)
- if m_weapon then
- -- set the ammo
- writeword(m_weapon, 0x2B6, ammocount)
- writeword(m_weapon, 0x2B8, clipcount)
- writefloat(m_weapon, 0x240, math.abs(batterycount - 1))
- -- force it to sync
- updateammo(m_weaponId)
- end
- end
- end
- end
- end
- return 0
- end
- --this function is called when a gametype is 'custom'
- --this function will delete the player's weapons and reassign the weapon's specified at the top
- function AssignZombieWeapons(id, count, player, clipcount, ammocount, batterycount)
- local m_objectId = getplayerobjectid(player)
- if m_objectId ~= 0xFFFFFFFF then
- local m_object = getobject(m_objectId)
- if m_object then
- --count is increased everytime the timer is called
- if count == 1 then
- for i = 0,3 do -- this is used to remove any weapons they already have
- local m_weaponId = readdword(m_object, 0x2F8 + i*4)
- if getobject(m_weaponId) then
- destroyobject(m_weaponId)
- end
- end
- end
- local i = count
- if zombie_weapon and zombie_weapon[i] and zombie_weapon[i] ~= "" then
- local m_weaponId = createobject("weap", zombie_weapon[i], 0, 0, false, 1, 1, 1)
- if m_weaponId ~= 0xFFFFFFFF then
- assignweapon(player, m_weaponId)
- if oddball_or_flag then
- flagball_weap[player] = m_weaponId
- else
- local m_weapon = getobject(m_weaponId)
- if m_weapon then
- -- set the ammo
- writeword(m_weapon, 0x2B6, ammocount)
- writeword(m_weapon, 0x2B8, clipcount)
- writefloat(m_weapon, 0x240, 1)
- -- force it to sync
- updateammo(m_weaponId)
- end
- end
- end
- end
- if count < 4 then return 1 else return 0 end
- end
- end
- return 0
- end
- -- Called after clients have been notified of a player spawn
- -- Do not return a value
- function OnPlayerSpawnEnd(player, m_objectId)
- end
- -- Called when a player is attempting to change their team.
- -- A value must be returned. The return value indicates whether or not the player is allowed the change team.
- -- Notes: If relevant is 1 the return value is considered, if it's 0 then the return value is ignored.
- function OnTeamChange(relevant, player, team, dest_team)
- if relevant == 1 or relevant == true then
- if not allow_change then
- privatesay(player, blockteamchange_message)
- elseif allow_change and dest_team == zombie_team then
- -- this is so memory is updated for processing
- -- when relevant is 0 OnTeamChange is called once the changes
- -- have been committed
- changeteam(player, 1)
- end
- -- we don't let people change team
- return 0
- elseif (relevant == 0 or relevant == false) and dest_team ~= team then -- we can't stop the person changing teams, bein done by an admin
- -- update team counts
- if dest_team == zombie_team then
- cur_human_count = cur_human_count - 1
- cur_zombie_count = cur_zombie_count + 1
- elseif dest_team ~= zombie_team then
- cur_human_count = cur_human_count + 1
- cur_zombie_count = cur_zombie_count - 1
- end
- -- they're allowed to change if the timer is active, if it is disable it
- if allow_change == true and dest_team == zombie_team then
- allow_change = false
- -- remove change timer
- removetimer(player_change_timer)
- player_change_timer = 0
- say(timer_team_change_msg)
- end
- -- check if the game has started yet
- if game_started == true then
- -- set attributes
- if dest_team == zombie_team then
- makezombie(player, false)
- elseif dest_team ~= zombie_team then
- makehuman(player, false)
- end
- checkgamestate(player)
- end
- -- update team withf
- local thisHash = gethash(player)
- hash_table[thisHash] = dest_team
- end
- return 1
- end
- --i made code in here to make the oddball/flag impossible to be dropped except that was a long time ago and i have no idea how it works, sorry :(
- --there's a bunch of redundant code in here, i wouldn't touch it if i were you.
- -- this function is also used to continually set the scores
- function OnClientUpdate(player, m_objectId)
- local m_player = getplayer(player)
- local m_object = getobject(m_objectId)
- local hash = gethash(player)
- --if gametype == "CTF" then writebit(ctf_globals, 0x1C, human_team, 0) end
- if m_object and game_started == true then
- local team = readbyte(m_player, 0x20)
- if team == zombie_team and oddball_or_flag then
- local shooting = readbit(m_object, 0x209, 4)
- local nading2 = readbit(m_object, 0x209, 2)
- local nading = readbit(m_object, 0x209, 3)
- if shooting == 1 or nading == 1 then
- --[[local weapID = readdword(m_object, 0x2FC)
- local weap = getobject(weapID)
- say("IS SHOOTING")
- if weap then--]]
- weapID = flagball_weap[player]
- local m_player = getplayer(player)
- if m_player then
- if weapID == nil then
- flagball_weap[player] = createobject("weap", oddball_or_flag, 0, 0, false, 5, 5, 2)
- assignweapon(player, flagball_weap[player])
- else
- if getobject(weapID) then
- if IsFlagOrBall(weapID) then
- assignweapon(player, weapID)
- else
- flagball_weap[player] = createobject("weap", oddball_or_flag, 0, 0, false, 5, 5, 2)
- assignweapon(player, flagball_weap[player])
- end
- else
- flagball_weap[player] = createobject("weap", oddball_or_flag, 0, 0, false, 5, 5, 2)
- assignweapon(player, flagball_weap[player])
- end
- end
- end
- --end
- end
- end
- -- this block of code sets the player's score according to what it should be.
- if tonumber(human_time[hash]) then
- if gametype == "KOTH" then
- local hill_time = readword(m_player, 0xC4)
- if tonumber(hill_time) then
- writewordsigned(m_player, 0xC4, tonumber(human_time[hash])*30)
- end
- elseif gametype == "CTF" then
- local player_score = readdword(m_player, 0xC8)
- if tonumber(player_score) then
- writedwordsigned(m_player, 0xC8, human_time[hash])
- end
- elseif gametype == "Slayer" then
- writedwordsigned(slayer_globals, 0x40 + player * 4, human_time[hash])
- end
- else
- human_time[hash] = 0
- end
- end
- --continually write 0 to these addresses
- if gametype == "KOTH" then
- writedword(team_koth_score_array, 0x0, 0)
- writedword(team_koth_score_array, 0x4, 0)
- elseif gametype == "CTF" then
- writedword(ctf_globals, 0x10, 0)
- writedword(ctf_globals, 0x14, 0)
- elseif gametype == "Slayer" then
- writedword(slayer_globals, 0x0, 0)
- writedword(slayer_globals, 0x4, 0)
- end
- --this makes sure that people won't camp in unreachable places.
- local x,y,z = getobjectcoords(m_objectId)
- local team = getteam(player)
- if map == "damnation" and team ~= zombie_team then
- if object_in_sphere(m_objectId, 1.99, 9.03, 7.82, 5) then
- kill(player)
- privatesay(player, "Do not camp in unreachable spots!")
- elseif object_in_sphere(m_objectId, 11.4, 11.21, 10.51, 5) then
- kill(player)
- privatesay(player, "Do not camp in unreachable spots!")
- end
- elseif map == "icefields" and team ~= zombie_team then
- if object_in_sphere(m_objectId, -31.27, 42.44, 11.48, 5) then
- kill(player)
- privatesay(player, "Do not camp in unreachable spots!")
- elseif object_in_sphere(m_objectId, -71.29, 70.83, 6.67, 10) then
- kill(player)
- privatesay(player, "Do not camp in unreachable spots!")
- elseif object_in_sphere(m_objectId, -17.28, 19.63, 11.55, 5) then
- kill(player)
- privatesay(player, "Do not camp in unreachable spots!")
- end
- end
- end
- function writewordsigned(address, offset, value)
- if value and value > 0x7FFF then
- local max = 0xFFFF
- local difference = max - value
- value = -1 - difference
- end
- writeword(address, offset, value)
- end
- function writedwordsigned(address, offset, value)
- if value and value > 0x7FFFFFFF then
- local max = 0xFFFFFFFF
- local difference = max - value
- value = -1 - difference
- end
- writedword(address, offset, value)
- end
- --called to check if an object is in a virtual sphere
- --i use this to check if a person is in a unreachable spot.
- function object_in_sphere(m_objectId, X, Y, Z, R)
- local Pass = false
- if getobject(m_objectId) then
- local x,y,z = getobjectcoords(m_objectId)
- if (X - x)^2 + (Y - y)^2 + (Z - z)^2 <= R then
- Pass = true
- end
- end
- return Pass
- end
- --checks if the object is a flag or a ball
- function IsFlagOrBall(weapID)
- for i = 1,#flags_balls_table do
- if flags_balls_table[i] == weapID then
- return true
- end
- end
- end
- -- Called when a player interacts with an object
- -- It can be called while attempting to pick the object up
- -- It is also called when standing above an object so can be called various times quickly
- function OnObjectInteraction(player, m_ObjectId, tagType, tagName)
- local response = 1
- if game_started == true then
- -- we don't need to stop people from taking the flag
- -- since the flag is moved under the map
- if tagType == "weap" then
- if tagName == oddball_or_flag then
- local team = getteam(player)
- if team == zombie_team then
- return 1
- end
- return 0
- end
- end
- if response == 1 then
- local team = getteam(player)
- if team == zombie_team then
- -- we want to stop zombies picking up weapons
- if tagType == "weap" then
- response = 0
- elseif tagType == "eqip" then
- if tagName == "weapons\\frag grenade\\frag grenade" or tagName == "weapons\\plasma grenade\\plasma grenade" then
- response = 0 -- don't let them pick the nades
- elseif tagName == "powerups\\active camouflage" then
- -- check if the picking player is already invisible
- local m_player = getplayer(player)
- if m_player then
- local m_playerObjId = readdword(m_player, 0x34)
- local m_object = getobject(m_playerObjId)
- if m_object then
- local camoFlag = readdword(m_object, 0x204)
- if camoFlag ~= 0x51 then
- -- check if zombies are to be made invisible
- local doInvis = getrandomnumber(1, 10)
- if doInvis > 5 then
- -- make the whole zombie team invis for 20 seconds
- for x = 0,15 do
- local team = getteam(x)
- if team == zombie_team and x ~= player then
- --hprintf("applying camo to player " .. x)
- applycamo(x, 30.00)
- end
- end
- say(zombieinvis_message)
- end
- end
- end
- end
- end
- end
- end
- end
- end
- return response
- end
- -- Called when a player attempts to reload their weapon.
- -- A value must be returned. The return value indicates whether or not the player is allowed to reload.
- -- Notes: If player is -1 then the weapon being reload wasn't located (it could be a vehicle's weapon)
- function OnWeaponReload(player, weapon)
- return 1
- end
- -- Called when a player attempts to enter a vehicle.
- -- A value must be returned. The return value indicates whether or not the player is allowed to enter.
- function OnVehicleEntry(relevant, player, vehicleId, vehicle_tag, seat)
- local response = 0
- if game_started and relevant == 1 then
- local team = getteam(player)
- if (team == zombie_team and zombies_allowed_in_vehis) or (tonumber(team) and team ~= zombie_team and humans_allowed_in_vehis) then
- response = 1
- end
- end
- return response
- end
- function OnVehicleEject(player, forceEject)
- return 1
- end
- -- Called when damage is being done to an object.
- -- This doesn't always need to be a player.
- -- Do not return a value
- function OnDamageLookup(receiving_obj, causing_obj, tagdata, tagname)
- -- Resolve the object ids into player ids
- -- Remember, the damage doesn't always need to be done by a player.
- local receiver = objecttoplayer(receiving_obj)
- local causer = objecttoplayer(causing_obj)
- -- We want to amplify human damage, so make sure the causer is human
- if causer then
- local c_team = getteam(causer)
- -- Make sure the team was found
- if tonumber(c_team) then
- -- Check if it's a human causing the damage
- if c_team ~= zombie_team then
- -- It's human damage, read the current damage the weapon has
- local min_dmg = readfloat(tagdata, 0x1D0)
- local max_dmg_min = readfloat(tagdata, 0x1D4)
- local max_dmg_max = readfloat(tagdata, 0x1D8)
- -- This is used to increase human damage (for last man)
- local modifier = 1.0
- -- Check if we're up to last man
- if cur_last_man then
- -- Change the damage modifier to the last man's
- modifier = lastman_dmgmodifier
- end
- -- Change the damage that will be done
- writefloat(tagdata, 0x1D0, min_dmg * 1.75 * modifier)
- writefloat(tagdata, 0x1D4, max_dmg_min * 1.75 * modifier)
- writefloat(tagdata, 0x1D8, max_dmg_max * 1.75 * modifier)
- -- It's a zombie causing the damage
- elseif c_team == zombie_team then
- -- check if it is melee damage, if so increase it to instant kill
- local found = string.find(tagname, "melee", -5)
- local r_team = getteam(receiver)
- -- We only want to increase zombie's melee damage
- if found then
- -- make melee instant kill
- writefloat(tagdata, 0x1D0, 500)
- writefloat(tagdata, 0x1D4, 500)
- writefloat(tagdata, 0x1D8, 500)
- end
- --check if a person is trying to damage their own team (ffa only, basically friendly fire is on to reduce confusion)
- if not team_play and c_team == r_team and causer ~= receiver then
- writefloat(tagdata, 0x1D0, 0)
- writefloat(tagdata, 0x1D4, 0)
- writefloat(tagdata, 0x1D8, 0)
- privatesay(causer, "Do not hit your own team.")
- end
- end
- end
- end
- end
- -- Called when a player is being assigned a weapon (usually when they spawn)
- -- A value must be returned. The return value is the id of the weapon they're to spawn with. Return zero if the weapon shouldn't change.
- -- Notes: This is called for all weapon spawns the player has
- -- This is also called with player 255 when vehicles are being assigned weapons.
- -- This is only considered if in gametype, the weapon set is 'Custom' if not this has no effect.
- function OnWeaponAssignment(player, object, count, tag)
- if starting_equipment == "Custom" then return 0 end -- this function does nothing if starting equipment is Custom
- local actualWeapon = 0
- local team = getteam(player)
- if team == zombie_team then
- if count == 0 and zombie_weapon[1] ~= "" and zombie_weapon[1] then
- actualWeapon = lookuptag("weap", zombie_weapon[1])
- elseif count == 1 and zombie_weapon[2] ~= "" and zombie_weapon[2] then
- actualWeapon = lookuptag("weap", zombie_weapon[2])
- end
- end
- if not actualWeapon then actualWeapon = 0 end
- return actualWeapon
- end
- function readtagname(address)
- local char_table = {}
- local i = 0
- local string = ""
- while readbyte(address, i) ~= 0 do
- table.insert(char_table, string.char(readbyte(address, i)))
- i = i + 1
- end
- for k,v in pairs(char_table) do
- string = string .. v
- end
- return string
- end
- -- Called when an object is created
- -- Do not return a value.
- function OnObjectCreation(m_objectId, player_owner, tag)
- if gametype == "CTF" then
- -- move the ctf flags under the map
- if tag == "weapons\\flag\\flag" then
- local red_scoreflag_objId = readdword(ctf_globals, 0x8)
- local blue_scoreflag_objId = readdword(ctf_globals, 0x12)
- if m_objectId == red_scoreflag_objId or m_objectId == blue_scoreflag_objId then
- registertimer(0, "PutUnderMap", m_objectId)
- return -- return so it won't add this weapon to the flags_balls_table
- end
- end
- end
- if tag == oddball_or_flag then
- table.insert(flags_balls_table, m_objectId)
- end
- end
- --i basically use this to put the object under the map, i could use destroyweaps like i do above but w/e
- function PutUnderMap(id, count, m_objectId)
- local m_object = getobject(m_objectId)
- if m_object then
- local x,y,z = getobjectcoords(m_objectId)
- movobjcoords(m_objectId, x, y, z - 20)
- end
- return 0
- end
- -- The below functions are used internally within the Lua script
- function NewGameTimer(id, count)
- if count == 5 then
- say("The game is starting...")
- if cur_players ~= 0 then
- local newgame_zombie_count = 0
- -- by default make all players human
- for x=0,15 do
- local thisTeam = getteam(x)
- local hash = gethash(x)
- if thisTeam then
- if thisTeam == zombie_team then
- changeteam(x, 0)
- end
- human_time[hash] = 0
- end
- end
- local possible_count = cur_players
- -- make players zombie until the count has been met
- local finalZombies = 0
- if zombie_count >= 1 then
- finalZombies = zombie_count
- else
- finalZombies = round((possible_count * zombie_count) + 0.5)
- end
- -- make last man zombie
- local last_man_index = -1
- -- check if the last man is to be made a zombie
- -- if so find who was last man
- if last_man_next_zombie == true and cur_players > 1 then
- -- loop through all hashes and check if any match the last man
- for i=0,15 do
- if getplayer(i) then
- local hash = gethash(i)
- if last_man_hash == hash then
- -- make them a zombie and save their info
- makezombie(i, true)
- newgame_zombie_count = 1
- last_man_index = i
- break
- end
- end
- end
- end
- -- reset last man
- last_man_hash = 0
- --hprintf("Expecting " .. finalZombies .. " zombies. Cur players " .. cur_players .. " possibles " .. possible_count)
- if finalZombies == cur_players then -- if 0 players they will be human
- finalZombies = finalZombies - 1
- elseif finalZombies > possible_count then -- fix the count
- finalZombies = possible_count
- elseif max_zombie_count and finalZombies > max_zombie_count then -- cap the zombie count
- finalZombies = max_zombie_count
- elseif finalZombies < 0 then
- finalZombies = 0
- end
- -- set counters such that changeteam wont end the game
- cur_zombie_count = 16
- cur_human_count = 16
- --hprintf("Expecting " .. finalZombies .. " zombies. Cur players " .. cur_players .. " possibles " .. possible_count)
- -- loop through the players, randomly selecting ones to become
- -- zombies
- while (newgame_zombie_count < finalZombies) do
- -- randomly choose a player
- local newzomb = ChooseRandomPlayer(zombie_team)
- if newzomb == nil then
- break
- elseif newzomb ~= last_man_index then
- makezombie(newzomb, true)
- newgame_zombie_count = newgame_zombie_count + 1
- end
- end
- -- fix the team counters
- cur_zombie_count = newgame_zombie_count
- cur_human_count = cur_players - finalZombies
- -- reset the map
- svcmd("sv_map_reset")
- -- loop through and tell players which team they're on
- for i=0,15 do
- local pteam = getteam(i)
- if pteam then
- -- check if they're a zombie
- if pteam == zombie_team then
- privatesay(i, zombie_message)
- else
- if not team_play then makehuman(i) end
- privatesay(i, human_message)
- end
- end
- end
- end
- game_started = true
- return 0 -- remove timer
- else
- say("The game will start in " .. 10 - 2*count .. " seconds.")
- return 1 -- keep timer
- end
- end
- function PlayerChangeTimer(id, count)
- if count ~= 10 then
- local zombsize = cur_zombie_count
- if allow_change == false or zombsize > 0 then
- allow_change = false
- if team_play then say("Thank you, the game can continue.") end
- return 0
- end
- say("In " .. 10 - count .. " seconds a player will be forced to become a zombie.")
- return 1
- else -- timer up, force team change
- allow_change = false
- -- pick a human and make them zombie.
- local newZomb = ChooseRandomPlayer(zombie_team)
- if newZomb then
- makezombie(newZomb, true)
- privatesay(player, zombie_message)
- end
- return 0
- end
- end
- -- this function searches through current players and selects a random one
- function ChooseRandomPlayer(excludeTeam)
- local t = {}
- -- loop through all 16 possible spots and add to table
- for i=0,15 do
- -- check if the player exists
- local team = getteam(i)
- if team and team ~= excludeTeam then
- table.insert(t, i)
- end
- end
- if #t > 0 then
- -- generate a random number that we will use to select a player
- local tableCount = table.getn(t)
- local r = getrandomnumber(1, tableCount+1)
- return t[r]
- else
- return nil
- end
- end
- function RemoveLastmanProtection(id, count, m_object)
- writebit(m_object, 0x10, 7, 0)
- return 0
- end
- -- there are no zombies left
- function noZombiesLeft()
- allow_change = true
- say(nozombiesleftmessage)
- player_change_timer = registertimer(1000, "PlayerChangeTimer")
- end
- --this function writes navpoints to zombies which will point to the last man
- function WriteNavsToZombies()
- for i = 0,15 do
- local team = getteam(i)
- if team == zombie_team then
- local m_player = getplayer(i)
- if m_player then
- local slayer_target = readword(m_player, 0x88)
- if slayer_target < 16 and slayer_target > -1 then
- writeword(m_player, 0x88, cur_last_man)
- end
- end
- end
- end
- end
- -- called when a last man exists
- function onlastman()
- -- lookup the last man
- for x=0,15 do
- local team = getteam(x)
- if team ~= zombie_team and team then
- cur_last_man = x
- if gametype == "Slayer" then WriteNavsToZombies(x) end
- -- give the last man speed and extra ammo
- setspeed(x, lastman_speed)
- -- find the last man's weapons
- local m_player = getplayer(x)
- if m_player then
- local m_ObjId = readdword(m_player, 0x34)
- -- find the player's object
- local m_object = getobject(m_ObjId)
- if m_object then
- if lastman_invulnerable and lastman_invulnerable > 0 then
- -- setup the invulnerable timer
- writebit(m_object, 0x10, 7, 1)
- registertimer(lastman_invulnerable * 1000, "RemoveLastmanProtection", m_object)
- end
- -- give all weapons 600 ammo
- for i=0,3 do
- local m_weaponId = readdword(m_object, 0x2F8 + (i*4))
- if m_weaponId ~= 0xffffffff then
- -- get the weapons memory address
- local m_weapon = getobject(m_weaponId)
- if m_weapon then
- -- set the ammo
- writeword(m_weapon, 0x2B6, 600)
- end
- end
- end
- end
- end
- end
- end
- if cur_last_man then
- local lastman_name = getname(cur_last_man)
- local msg = string.format(lastman_message, tostring(lastman_name), lastman_invistime)
- say(msg)
- applycamo(cur_last_man, lastman_invistime)
- end
- end
- -- checks the game state, for last man, all zombies etc
- -- called onteamchange, onplayerjoin, onplayerleave, onffateamchange, and onscriptload
- function checkgamestate(player)
- -- check if the game has started yet
- if game_started == true then
- local zombie_count = cur_zombie_count
- local human_count = cur_human_count
- --hprintf("zombie count " .. tostring(zombie_count))
- --hprintf("human count " .. tostring(human_count))
- -- if no humans, but there are zombies, end the game
- if human_count == 0 and zombie_count > 0 then
- all_players_zombies(player)
- elseif human_count > 1 and zombie_count == 0 then
- noZombiesLeft()
- elseif human_count == 1 and zombie_count > 0 and not cur_last_man then
- onlastman()
- elseif cur_last_man and zombie_count == 0 then
- makehuman(cur_last_man, false)
- cur_last_man = nil
- elseif cur_last_man and human_count > 1 then
- if gametype == "Slayer" then takenavsaway(cur_last_man) end
- makehuman(cur_last_man, false)
- cur_last_man = nil
- end
- end
- end
- --called when the lastman no longer exists
- function takenavsaway(lastman)
- for i = 0,15 do
- local m_player = getplayer(i)
- if m_player then
- writeword(m_player, 0x88, i)
- end
- end
- end
- -- called when all players are zombies (no shit)
- function all_players_zombies(player)
- -- if there is a last man, store their hash
- if player ~= -1 then
- last_man_hash = gethash(player)
- -- write the hash to file
- local file = io.open("lasthash_" .. processid .. ".tmp", "w")
- if (file ~= nil) then
- file:write(tostring(last_man_hash))
- file:close()
- end
- end
- -- move onto the next map
- svcmd("sv_map_next")
- end
- --called when a player needs to be made a zombie
- function makezombie(player, forcekill, updatecounters)
- -- change the player's speed
- setspeed(player, zombie_speed)
- local team = getteam(player)
- if team ~= zombie_team then
- if team_play then
- changeteam(player, forcekill)
- else
- changeteam(player, forcekill, nil, updatecounters)
- end
- end
- end
- --called when a player needs to be a human
- function makehuman(player, forcekill, updatecounters)
- -- change the player's speed
- setspeed(player, human_speed)
- local team = getteam(player)
- if team == zombie_team then
- if team_play then
- changeteam(player, forcekill)
- else
- changeteam(player, forcekill, updatecounters)
- end
- end
- end
- --gets the number of alpha zombies
- function getalphacount()
- -- recalculate how many "alpha" zombies there are
- if zombie_count < 1 then
- alpha_zombie_count = round((cur_players * zombie_count) + 0.5)
- else
- alpha_zombie_count = zombie_count
- end
- if alpha_zombie_count > max_zombie_count then
- alpha_zombie_count = max_zombie_count
- end
- return alpha_zombie_count
- end
- --rounds the number
- function round(num)
- under = math.floor(num)
- upper = math.floor(num) + 1
- underV = -(under - num)
- upperV = upper - num
- if (upperV > underV) then
- return under
- else
- return upper
- end
- end
Recent Pastes