--[[ =CE= Chris's Essentials Script
Script by: =CE= Chris
Version History:
0.1: Initial Creation
]]
--- Settings ---
haloVersion = "CE" -- Halo PC or Halo CE. (PC, CE)
useDatabase = false -- Use a mysql database for admins and clan roster. (true, false)
welcomeMessage = "Welcome to the server!" -- Welcome message for players. nil for none, \n to seperate multiple messages. (nil, "string")
restoreScores = true -- Resume player scores when they quit and rejoin in the same round. (true, false)
showDetails = true -- Show more detailed info in console when loading up the script. (true, false)
privateChat = true -- Enable private chat with @. (true, false)
antiImposter = true -- Enable anti-imposter for clans. (true, false)
useLog = true -- Enable custom log file. (true, false)
-- Anti-Imposter Settings --
tagLength = 4 -- Length of your clan's tag. (real)
clanTags = {"-EX-", "=EX=", "«EX»"} -- For multiple types of tags. (table)
impAction = "sv_kick" -- Command to run when an imposter is found. (string)
-- Database Settings --
sourcename = "" -- Database source name. (string)
username = "" -- Database username. (string)
password = "" -- Datbase password. (string)
hostname = "" -- Database hostname. (string)
port = 0 -- Database port. (real)
adminTable = "admins" -- Admin table name. (string)
clanTable = "members" -- Clan roster table name. (string)
-- File Settings --
membersFile = "members.txt" -- Clan roster text file name. (string)
logFile = "log.log" -- Log file name. (string)
----------------
--- Internal Stuff (Don't touch!) ---
global_admins = {}
global_members = {}
global_gametype = nil
global_players = {}
-------------------------------------
if useDatabase then
require('luasql.mysql')
end
function GetRequiredVersion()
return 10057
end
function OnScriptLoad(process)
hprintf("Script by: =CE= Chris\nXfire: chrisk123999")
if useDatabase then
hprintf("Loading admins...")
local env = assert (luasql.mysql())
local con = assert (env:connect(sourcename,username,password,hostname,port))
local i = 0
for name, hash, access in rows (con, "SELECT * FROM `" .. adminTable .. "`") do
local temp_table = {id, name, hash, access}
global_admins[i] = temp_table
i = i + 1
if showDetails then
hprintf("Name: " .. name .. " Hash: " .. hash .. " Access: " .. access)
end
hprintf(#global_admins .. " admins loaded.")
end
if antiImposter then
hprintf("Loading clan members...")
i = 0
for name, hash in rows (con, "SELECT * FROM `" .. clanTable .. "`") do
global_members[i] = hash
i = i + 1
if showDetails then
hprintf("Name: " .. name .. " Hash: " .. hash)
end
hprintf(#global_members .. " clan members loaded.")
end
end
con:close()
env:close()
else
if antiImposter then
hprintf("Loading clan members...")
local file = io.open(membersFile)
if file ~= nil then
local memberString = file:read("*a")
local count = gettokencount(memberString, "\n") -1
for i=0, count do
local mHash = gettoken(memberString, "\n", i)
global_members[i] = mHash
if showDetails then
hprintf("Hash: " .. mHash)
end
end
hprintf(#global_members .. " clan members loaded.")
else
hprintf(membersFile .. " doesn't exist!")
end
end
end
local gametype_base = 0x671340
if haloVersion == "CE" then
gametype_base = 0x5F5498
end
global_gametype = readbyte(gametype_base, 0x30)
end
function OnScriptUnload()
end
function OnNewGame(map)
if useLog then
aLog("[Info] New game on " .. map)
end
end
function OnGameEnd(mode)
end
function OnServerChat(player, chattype, message)
local C_Allow = true
if string.sub(message, 1, 1) == "\\" then
C_Allow = false
if C_Command == "about" then
privatesay(player, "=CE= Chris's Phasor Essentials Script\nXfire: chrisk123999")
end
elseif string.sub(message, 1, 1) == "/" then
if isadmin(player) or isDatabaseAdmin(player) then
privatesay(player, svcmd(string.sub(message, 2), player) )
else
privatesay(player, "You're not allowed to do that!")
end
elseif string.sub(message, 1, 1) == "@" and privateChat then
C_Allow = false
local toPlayer = string.sub(gettoken(message, " ", 0), 2)
if toPlayer >= 0 and toPlayer <= 15 then
local C_Name = getname(player)
if toPlayer >= 0 and toPlayer <= 9 then
privatesay(toPlayer, C_Name .. " says: " .. string.sub(message, 3) )
else
privatesay(toPlayer, C_Name .. " says: " .. string.sub(message, 4) )
end
else
privatesay(player, "Invalid player.")
end
end
if useLog then
aLog("[Chat] " .. getname(player) .. ":" .. message)
end
return C_Allow
end
function OnServerCommand(player, command)
if useLog then
if player == -1 then
aLog("[Command] Console: " .. command)
else
aLog("[Command] " .. getname(player) .. ": " .. command)
end
end
end
function OnTeamDecision(cur_team)
return cur_team
end
function OnPlayerJoin(player, team)
local name = getname(player)
if useLog then
aLog("[Info] " .. name .. " joined the game.")
end
local tag = string.sub(name, 1, tagLength)
if matchedTag(tag) then
local hash = gethash(player)
local inClan = false
for i=0, #member_list do
if member_list[i] == hash then
inclan = true
break
end
end
if inclan == false then
svcmd(impAction .. " " .. resolveplayer(player) )
if useLog then
aLog("[Action] Imposter detected. Using name: " .. name)
end
end
end
local player_hash = gethash(player)
if player_hash ~= nil then
if global_players[player_hash] == nil then
global_players[player_hash] = { hash=player_hash}
else
local player_struct = getplayer(player)
local score = nil
if global_gametype == 1 then -- CTF
score = stat_read(player_hash, "ctf_score")
if score ~= nil then
writeword(player_struct, 0xC8, score)
end
elseif global_gametype == 2 then -- Slayer
score = stat_read(player_hash, "slayer_score")
if score ~= nil then
writedword(0x63A128, 0x4 * player, score)
end
elseif global_gametype == 3 then -- Oddball
score = stat_read(player_hash, "oddball_score")
if score ~= nil then
writedword(0x639E9C, 0x4 * player, score)
end
elseif global_gametype == 4 then -- KOTH
score = stat_read(player_hash, "koth_score")
if score ~= nil then
writeword(player_struct, 0x0C4, score)
end
elseif global_gametype == 5 then -- Race
score = stat_read(player_hash, "race_score")
if score ~= nil then
writeword(player_struct, 0xC6, score)
end
end
local kills = stat_read(player_hash, "kills")
if kills ~= nil then
writeword(player_struct, 0x9C, kills)
end
local assists = stat_read(player_hash, "assists")
if assits ~= nil then
writeword(player_struct, 0xA4, assists)
end
local deaths = stat_read(player_hash, "deaths")
if deaths ~= nil then
writeword(player_struct, 0xAE, deaths)
end
privatesay(player, "Your scores have been resumed.")
end
if welcomeMessage ~= nil then
privatesay(player, welcomeMessage)
end
end
end
function OnPlayerLeave(player, team)
local player_hash = gethash(player)
if global_players[player_hash] ~= nil then
local player_struct = getplayer(player)
if global_gametype == 1 then -- CTF
stat_write(player_hash, "ctf_score", readword(player_struct, 0xC8) )
elseif global_gametype == 2 then -- Slayer
stat_write(player_hash, "slayer_score", readdwordsigned(0x63A128, 0x4 * player) )
elseif global_gametype == 3 then -- Oddball
stat_write(player_hash, "oddball_score", readdword(0x639E9C, 0x4 * player) )
elseif global_gametype == 4 then -- KOTH
stat_write(player_hash, "koth_score", readword(player_struct, 0xC4) )
elseif global_gametype == 5 then -- Race
stat_write(player_hash, "race_score", readword(player_struct, 0xC6) )
end
local player_kills = readword(player_struct, 0x9C)
stat_write(player_hash, "kills", player_kills)
local player_assists = readword(player_struct, 0xA4)
stat_write(player_hash, "assists", player_assists)
local player_deaths = readword(player_struct, 0xAE)
stat_write(player_hash, "deaths", player_deaths)
end
if useLog then
aLog("[Info] " .. getname(player) .. " left the game.")
end
end
function OnPlayerKill(killer, victim, mode)
end
function OnKillMultiplier(player, multiplier)
end
function OnPlayerSpawn(player, m_objectId)
end
function OnPlayerSpawnEnd(player, m_objectId)
end
function OnTeamChange(relevant, player, team, dest_team)
return 1
end
function OnClientUpdate(player, m_objectId)
end
function OnObjectInteraction(player, m_ObjectId, tagType, tagName)
return 1
end
function OnWeaponReload(player, weapon)
return 1
end
function OnVehicleEntry(relevant, player, vehicleId, vehicle_tag, seat)
return 1
end
function OnVehicleEject(player, forceEject)
return 1
end
function OnDamageLookup(receiving_obj, causing_obj, tagdata, tagname)
end
function OnWeaponAssignment(player, object, count, tag)
end
function OnObjectCreation(m_objectId, player_owner, tag)
end
-- Misc Functions
function rows (connection, sql_statement)
local cursor = assert (connection:execute (sql_statement))
return function ()
return cursor:fetch()
end
end
function stat_read(hash, stat)
local value = nil
if global_players[hash] ~= nil then
if global_players[hash][stat] ~= nil then
value = global_players[hash][stat]
else
global_players[hash][stat] = 0
value = 0
end
end
return value
end
function stat_write(hash, stat, value)
if global_players[hash] ~= nil then
if global_players[hash][stat] ~= nil then
global_players[hash][stat] = value
else
global_players[hash][stat] = value
end
end
end
function stat_add(hash, stat, value)
if global_players[hash] ~= nil then
if global_players[hash][stat] ~= nil then
global_players[hash][stat] = global_players[hash][stat] + value
else
global_players[hash][stat] = value
end
end
end
function isDatabaseAdmin(player)
local pass = false
local hash = gethash(player)
for i=0, #adminTable do
if hash == adminTable[i] then
pass = true
break
end
end
return pass
end
function aLog(message)
local file = io.open(logFile, "a")
if file ~= nil then
file:write(message .. "\n")
end
file:close()
end
function matchedTag(tag)
local matched = false
for i=0, #clanTags do
if tag == clanTags[i] then
matched = true
break
end
end
return matched
end