-- CounterStrike gametype like --
-- Inspired from Nuggets's Conquest and geo scripts --
-- The goal for the blue team is to explode the red base --
-- Red team have to kill the player holding the bomb to avoid it --
-- Contains Nuggets, AelitePrime and Wizard codes --
-- The script works only on BloodGulch --
-- It requieres a ctf gametype with the nav points disabled --
-- Also made in a Rockets only purpose --
RocketId = nil
BombId = nil
bombarea = nil
bomb = {}
bomb.respawn = 45.0
bomb.spawns = {40.15, -81.55, 0.01} --blue base
flagcoords = {95.69, -159.44, 0.01} --red flag coords
players = {}
players.bomb = nil
players.monitored = false
terroristneedweap = nil
respawn_time = 7
weapons = {}
finalscore = 0
function GetRequiredVersion()
return 200
end
function OnScriptLoad(processid, game, persistent)
--writedword(0x671340, 0x3C, 2)
writedword(0x488A7E, 0, 0xFFFFFFFF)
writedword(0x488A7E, 1, 0xFFFFFFFF)
writedword(0x671340, 0x48, respawn_time * 30)
writebyte(0x671340, 0x58, 2)
end
function OnScriptUnload()
end
function OnGameEnd(stage)
if stage == 1 then
if finalscore ~= 2 then
say("red team won")
writedword(0x639B98, 0x10, 2)
terroristneedweap = nil
else
say("blue team won")
writedword(0x639B98 + 0x4, 0x10, 2)
terroristneedweap = nil
end
elseif stage == 3 then
writedword(0x488A7E, 0, 17 * 30)
end
end
function OnNewGame(map)
RocketId = gettagid("weap", "weapons\\rocket launcher\\rocket launcher")
BombId = gettagid("weap", "weapons\\ball\\ball")
bomb.x = bomb.spawns[1]
bomb.y = bomb.spawns[2]
bomb.z = bomb.spawns[3]
bomb.objId = createobject(BombId, 0, 0, false, bomb.x, bomb.y, bomb.z)
local m_object = getobject(bomb.objId)
writefloat(m_object + 0x74, 0)
writefloat(m_object + 0x78, -0.3)
bomb.respawn_remain = bomb.respawn
registertimer(1000, "Respawn", "bomb")
registertimer(5000, "CreateBomb")
writedword(0x488A7E + 0x0, 0xFFFFFFFF)
registertimer(0, "CreationDelay")
end
function CreateBomb(id, count)
if count == 1 then
bombarea = GEO.newRectPrism("bombarea", 5, 5, 5, flagcoords[1], flagcoords[2], flagcoords[3])
return false
end
end
function newplayer(player)
local hash = gethash(player)
local team = getteam(player)
players[hash] = players[hash] or {}
players[hash].bomb = false
players[hash].monitored = false
if team == 1 then
privatesay(player, "You are a terrorist, explode the red base")
else
privatesay(player, "Protect your base from the blue terrorists")
end
end
function CreationDelay(id, count)
for i = 0,1 do
ctf_flag_coords_pointer = readdword(0x639B98 + i * 4, 0x0)
writefloat(ctf_flag_coords_pointer, 0)
writefloat(ctf_flag_coords_pointer + 4, 0)
writefloat(ctf_flag_coords_pointer + 8, -1000)
end
return false
end
function OnPlayerJoin(player)
newplayer(player)
end
function OnObjectCreationAttempt(mapId, parentId, player)
local tagname, tagtype = gettaginfo(mapId)
if tagname == "weapons\\flag\\flag" then
local m_objectId = readdword(0x639B98 + 0x8)
registertimer(0, "PutUnderMap", m_objectId)
return
end
return nil
end
function OnPlayerSpawnEnd(player, m_objectId)
for i = 0,3 do
local m_object = getobject(m_objectId)
if m_object then
local weapID = readdword(m_object + 0x2F8 + i*4)
local weap = getobject(weapID)
if weap then
destroyobject(weapID)
end
end
end
local rocketla = createobject(RocketId, 0, 1, false, 0, 0, 0)
assignweapon(player, rocketla)
registertimer(1000, "InfiniteAmmo", player)
end
function OnObjectInteraction(player, objId, mapId)
local team = getteam(player)
local tagname, tagtype = gettaginfo(mapId)
if tagtype == "weap" then
if tagname == "weapons\\ball\\ball" then
if team == 0 then
return false
end
elseif tagname == "weapons\\flag\\flag" then
return false
end
end
end
function OnWeaponPickup(player, weapId, slot, mapId)
local hash = gethash(player)
local tagname = gettaginfo(mapId)
if tagname == "weapons\\ball\\ball" then
players[hash].bomb = true
bomb.player = player
sendconsoletext(player, "You have the bomb")
sendconsoletext(player, "Go blow the red base")
end
end
function OnWeaponDrop(player, weapId, slot, mapId)
local hash = gethash(player)
local tagname = gettaginfo(mapId)
if tagname == "weapons\\ball\\ball" then
players[hash].bomb = false
bomb.player = nil
end
end
function Respawn(id, count, item)
if _G[item].player then
_G[item].respawn_remain = _G[item].respawn
else
local objId = _G[item].objId
local m_object = getobject(objId)
if m_object then
local x, y, z = getobjectcoords(objId)
if math.round(x, 1) == math.round(_G[item].x, 1) and math.round(y, 1) == math.round(_G[item].y, 1) and math.round(z, 1) == math.round(_G[item].z, 1) then
_G[item].respawn_remain = _G[item].respawn
else
_G[item].respawn_remain = _G[item].respawn_remain - 1
if _G[item].respawn_remain <= 0 then
movobjectcoords(objId, _G[item].x, _G[item].y, _G[item].z)
local m_object = getobject(_G[item].objId)
writebit(m_object, 0x10, 5, 0)
_G[item].respawn_remain = _G[item].respawn
end
end
else
_G[item].respawn_remain = _G[item].respawn_remain - 1
if _G[item].respawn_remain <= 0 then
--[[local mapId --pb?
if item == "bomb" then
mapId = gettaginfo("weap", "weapons\\ball\\ball")
end ]]--
_G[item].objId = createobject(BombId, 0, 0, false, _G[item].x, _G[item].y, _G[item].z)
--writefloat(_G[item].objId + 0x74, 0)
--writefloat(_G[item].objId + 0x78, -0.3)
_G[item].respawn_remain = _G[item].respawn
end
end
end
return true
end
registertimer(10, "WeaponMonitor")
function WeaponMonitor(id, count)
for player = 0,15 do
weapons[player] = weapons[player] or {}
local m_player = getplayer(player)
if m_player then
local temp = {}
local objId = readdword(m_player, 0x34)
local m_object = getobject(objId)
if m_object then
for i = 0,3 do
local weapId = readdword(m_object, 0x2F8 + (i * 4))
local m_weapon = getobject(weapId)
if m_weapon then
local mapId = readdword(m_weapon)
if weapons[player][i] then
if weapons[player][i].weapId ~= weapId then
OnWeaponDrop(player, weapons[player][i].weapId, i, weapons[player][i].mapId)
weapons[player][i] = {}
weapons[player][i].weapId = weapId
weapons[player][i].mapId = mapId
OnWeaponPickup(player, weapId, i, mapId)
end
else
weapons[player][i] = {}
weapons[player][i].weapId = weapId
weapons[player][i].mapId = mapId
OnWeaponPickup(player, weapId, i, mapId)
end
else
if weapons[player][i] then
OnWeaponDrop(player, weapons[player][i].weapId, i, weapons[player][i].mapId)
weapons[player][i] = nil
end
end
end
else
for i = 0,3 do
if weapons[player][i] then
OnWeaponDrop(player, weapons[player][i].weapId, i, weapons[player][i].mapId)
weapons[player][i] = nil
end
end
end
end
end
return true
end
function setscore(player, score)
finalscore = finalscore + 1
local m_player = getplayer(player)
if m_player then
local actualscore = readdword(m_player + 0xC8)
local playerscore = actualscore + score
writeword(m_player, 0xC8, playerscore)
end
end
function PutUnderMap(id, count, m_objectId)
local m_object = getobject(m_objectId)
if m_object then
local x,y,z = getobjectcoords(m_objectId)
movobjectcoords(m_objectId, x, y, z - 20)
end
return false
end
function OnTeamChange(player, old_team, dest_team, relevant)
if relevant == 1 or relevant == true then
local hash = gethash(player)
if dest_team == 0 then
privatesay(player, "You are a terrorist, explode the red base")
else
privatesay(player, "Protect your base from the blue terrorists")
end
players[hash].bomb = false
players[hash].monitored = false
end
end
function OnPlayerLeave(player)
local hash = gethash(player)
local m_objectId = getplayerobjectid(player)
if m_objectId then
local m_object = getobject(m_objectId)
if m_object then
for i = 0,3 do
local weapID = readdword(m_object + 0x2F8 + i*4)
if weapID then
local weap = getobject(weapID)
if weap then
--registertimer(0, "destroyweaps", weapID)
destroyobject(weapID)
end
end
end
end
end
players[hash].bomb = false
players[hash].monitored = false
end
function OnPlayerKill(killer, victim, mode)
local hash = gethash(victim)
local m_player = getplayer(victim)
if m_player == nil then
return
end
local m_object = getobject(readdword(m_player + 0x34))
if m_object then
for i = 0,3 do
local weapID = readdword(m_object + 0x2F8 + i*4)
if weapID then
local weap = getobject(weapID)
if weap then
--registertimer(0, "destroyweaps", weapID)
destroyobject(weapID)
end
end
end
end
players[hash].bomb = false
players[hash].monitored = false
end
function OnClientUpdate(player)
writedword(0x639B98 + 0x10, 0)
writedword(0x639B98 + 0x14, 0)
local objectid = getplayerobjectid(player)
local hash = gethash(player)
local team = getteam(player)
if team == 1 and bombarea ~= nil then
if not players[hash].monitored then
bombarea:monitor(objectid)
players[hash].monitored = true
end
if players[hash].bomb then
local m_player = getplayer(player)
if m_player == nil then
return
end
local m_objectId = getplayerobjectid(player)
if m_objectId == nil then
return
end
local m_object = getobject(m_objectId)
if m_object then
local shooting = readbit(m_object + 0x209, 4)
local nading2 = readbit(m_object + 0x209, 2)
local nading = readbit(m_object + 0x209, 3)
if shooting == true or nading == true then
weapID = bomb.objId
if m_player then
if weapID then
if getobject(weapID) then
assignweapon(player, weapID)
end
end
end
end
end
end
end
if terroristneedweap then
local rocketl = createobject(RocketId, 0, 1, false, 0, 0, 0)
assignweapon(player, rocketl)
registertimer(1000, "InfiniteAmmo", player)
terroristneedweap = nil
end
if finalscore == 2 then
svcmd("sv_map_next")
end
end
function ExplosionTimer(id, count)
if count == 4 then
for i=0,15 do
if getplayer(i) then
local hash = gethash(i)
if players[hash].bomb then
setscore(i, 1)
local m_player = getplayer(i)
local m_object = getobject(readdword(m_player + 0x34))
if m_object then
for x = 0,3 do
local weapId = readdword(m_object + 0x2F8 + x*4)
local weap = getobject(weapId)
if weap then
registertimer(0, "replacebomb", weapId)
destroyobject(weapId)
terroristneedweap = true
end
end
end
end
end
end
return true
elseif count == 5 then
say("The bomb exploded!")
bombarea:killzone(true)
return true
elseif count == 6 then
say("Area cleared")
bombarea:killzone(false)
return false
else
say("The bomb will explode in " .. 5 - 1*count .. " seconds.")
return true
end
end
function replacebomb(id, count, m_weaponId)
if m_weaponId then
local m_weapon = getobject(m_weaponId)
if m_weapon then
--[[bomb.x = bomb.spawns[1]
bomb.y = bomb.spawns[2]
bomb.z = bomb.spawns[3]
movobjectcoords(m_weaponId, bomb.x, bomb.y, bomb.z)--]]
writefloat(m_weapon + 0x5C, readfloat(m_weapon + 0x5C) +95.69)
writefloat(m_weapon + 0x60, readfloat(m_weapon + 0x60) +-159.44)
writefloat(m_weapon + 0x64, readfloat(m_weapon + 0x64) +0.01)
end
end
return false
end
function InfiniteAmmo(id, count, player)
local m_player = getplayer(player)
if m_player then
local objId = readdword(m_player, 0x34)
local m_object = getobject(objId)
if m_object then
for i = 0,3 do
local weapId = readdword(m_object, 0x2F8 + (i * 4))
local m_weapon = getobject(weapId)
if m_weapon then
writeword(m_weapon, 0x2B6, 9999)
writeword(m_weapon, 0x2B8, 9999)
updateammo(weapId)
end
end
return true
end
end
return false
end
function math.round(input, precision)
return math.floor(input * (10 ^ precision) + 0.5) / (10 ^ precision)
end
-------------------------Nuggets GEO Script----------------------------------------------------------------
-- Create Metatable
GEO = {}
GEO.__index = GEO
-- Set random seed and define infinity
math.randomseed(os.time())
math.inf = 1 / 0
function inSphere(objId, x, y, z, r)
local ox, oy, oz = getobjectcoords(objId)
if ox then
-- Pythagorean
local dist = math.sqrt((x - ox) ^ 2 + (y - oy) ^ 2 + (z - oz) ^ 2)
if dist <= r then
return true
end
end
return false
end
function inCircle(objId, x, y, z, r, orientation)
local ox, oy, oz = getobjectcoords(objId)
if ox then
-- Default orientation to "z"
orientation = orientation or "z"
-- Pythagorean based on circle's orientation
if orientation == "z" then
local dist = math.sqrt((x - ox) ^ 2 + (y - oy) ^ 2)
if dist <= r and oz == z then
return true
end
elseif orientation == "y" then
local dist = math.sqrt((x - ox) ^ 2 + (z - oz) ^ 2)
if dist <= r and oy == y then
return true
end
elseif orientation == "x" then
local dist = math.sqrt((y - oy) ^ 2 + (z - oz) ^ 2)
if dist <= r and ox == x then
return true
end
end
end
return false
end
function inCylinder(objId, x, y, zlow, zhigh, r)
local ox, oy, oz = getobjectcoords(objId)
if ox then
-- Pythagorean to see if object is within radius of circle
local dist = math.sqrt((x - ox) ^ 2 + (y - oy) ^ 2)
-- Make sure the object is also within the height of the cylinder
if dist <= r and z >= zlow and z <= zhigh then
return true
end
end
return false
end
function inRectangle(objId, xlow, xhigh, ylow, yhigh, zlow, zhigh)
-- These functions are essentially the same
return inRectPrism(objId, xlow, xhigh, ylow, yhigh, zlow, zhigh)
end
function inRectPrism(objId, xlow, xhigh, ylow, yhigh, zlow, zhigh)
if getobject(objId) then
local x, y, z = getobjectcoords(objId)
if x then
-- Make sure the coordinates are inside of each extreme of the rectangular prism
if x <= xhigh and x >= xlow and y <= yhigh and y >= ylow and z <= zhigh and z >= zlow then
return true
end
end
end
return false
end
function randomInSphere(x, y, z, r)
-- Increase precision
x = math.floor(x * 100)
y = math.floor(y * 100)
z = math.floor(z * 100)
r = math.floor(r * 100)
-- Find random values inside of the sphere.
return math.random(x - r, x + r + 1) / 100, math.random(y - r, y + r + 1) / 100, math.random(z - r, z + r + 1) / 100
end
function randomInCircle(x, y, z, r, orientation)
-- Increase precision
r = math.floor(r * 100)
-- Possible values depend on circle's orientation.
if orientation == "z" then
x = math.floor(x * 100)
y = math.floor(y * 100)
return math.random(x - r, x + r + 1) / 100, math.random(y - r, y + r + 1) / 100, z
elseif orientation == "x" then
y = math.floor(y * 100)
z = math.floor(z * 100)
return x, math.random(y - r, y + r + 1) / 100, math.random(z - r, z + r + 1) / 100
elseif orientation == "y" then
x = math.floor(x * 100)
z = math.floor(z * 100)
return math.random(x - r, x + r + 1) / 100, y, math.random(z - r, z + r + 1) / 100
end
end
function randomInCylinder(x, y, zlow, zhigh, r)
-- Increase precision
x = math.floor(x * 100)
y = math.floor(y * 100)
zlow = math.floor(zlow * 100)
zhigh = math.floor(zhigh * 100)
r = math.floor(r * 100)
-- Find random values inside of the cylinder.
return math.random(x - r, x + r + 1) / 100, math.random(y - r, y + r + 1) / 100, math.random(zlow, zhigh + 1) / 100
end
function randomInRectPrism(xlow, xhigh, ylow, yhigh, zlow, zhigh)
-- Increase precision
xlow = math.floor(xlow * 100)
xhigh = math.floor(xhigh * 100)
ylow = math.floor(ylow * 100)
yhigh = math.floor(yhigh * 100)
zlow = math.floor(zlow * 100)
zhigh = math.floor(zhigh * 100)
-- Find random values inside of the rectangular prism.
return math.random(xlow, xhigh + 1) / 100, math.random(ylow, yhigh + 1) / 100, math.random(zlow, zhigh)
end
-- Object Creation Comments (refer to this function for questions on how the other ones work)
function GEO.newSphere(name, r, x, y, z)
-- Check to see if there is already a GEO with this name.
if not GEO[name] then
-- Create new table
GEO[name] = {}
GEO[name].t = "sphere" -- type
GEO[name].n = name -- name
GEO[name].r = r or 1 -- radius (default value of 1)
GEO[name].x = x or 0 -- x coordinate of center (default value of 0)
GEO[name].y = y or 0 -- y coordinate of center (default value of 0)
GEO[name].z = z or 0 -- z coordinate of center (default value of 0)
-- Notify the console that a sphere has been created.
hprintf("Sphere \"" .. name .. "\" created.")
setmetatable(GEO[name], GEO) -- Add this object to the GEO metatable to allow GEO-editing functions to work on it.
return GEO[name] -- Return the object
end
-- If no object was returned, the name was invalid; notify the console.
hprintf("Invalid name: \"" .. name .. "\"")
end
function GEO.newCircle(name, r, x, y, z, orientation)
if not GEO[name] then
GEO[name] = {}
GEO[name].t = "circle"
GEO[name].n = name
GEO[name].o = orientation or "z" -- orientation
GEO[name].r = r or 0
GEO[name].x = x or 0
GEO[name].y = y or 0
GEO[name].z = z or 0
hprintf("Circle \"" .. name .. "\" created.")
setmetatable(GEO[name], GEO)
return GEO[name]
end
hprintf("Invalid name: \"" .. name .. "\"")
end
function GEO.newCylinder(name, r, h, x, y, z)
if not GEO[name] then
GEO[name] = {}
GEO[name].t = "cylinder"
GEO[name].n = name
x = x or 0
y = y or 0
z = z or 0
r = r or 1
h = h or 1
GEO[name].x = x
GEO[name].y = y
GEO[name].z = z
GEO[name].r = r
GEO[name].h = h -- height
GEO[name].zlow = z - h / 2 -- lowest z-coordinate still within the cylinder
GEO[name].zhigh = z + h / 2 -- highest z-coordinate still within the cylinder
hprintf("Cylinder \"" .. name .. "\" created.")
setmetatable(GEO[name], GEO)
return GEO[name]
end
end
function GEO.newRectPrism(name, lx, ly, lz, x, y, z)
if not GEO[name] then
GEO[name] = {}
GEO[name].t = "rectprism"
GEO[name].n = name
lx = lx or 1
ly = ly or 1
lz = lz or 1
x = x or 0
y = y or 0
z = z or 0
GEO[name].lx = lx -- x length
GEO[name].ly = ly -- y length
GEO[name].lz = lz -- z length
GEO[name].x = x
GEO[name].y = y
GEO[name].z = z
GEO[name].xlow = x - lx / 2 -- lowest x-coordinate still within the rectangular prism
GEO[name].xhigh = lx / 2 + x -- highest x-coordinate still within in the rectangular prism
GEO[name].ylow = y - ly / 2 -- lowest y-coordinate still within the rectangular prism
GEO[name].yhigh = ly / 2 + y -- highest y-coordinate still within the rectangular prism
GEO[name].zlow = z - lz / 2 -- lowest z-coordinate still within the rectangular prism
GEO[name].zhigh = lz / 2 + z -- highest z-coordinate still within the rectangular prism
hprintf("Rectangular Prism \"" .. name .. "\" created.")
setmetatable(GEO[name], GEO)
return GEO[name]
end
hprintf("Invalid name: \"" .. name .. "\"")
end
function GEO.newRect(name, width, height, x, y, z, orientation)
if not GEO[name] then
GEO[name] = {}
GEO[name].t = "rectangle"
GEO[name].n = name
width = width or 1
height = height or 1
x = x or 0
y = y or 0
z = z or 0
orientation = orientation or "z"
GEO[name].width = width
GEO[name].height = height
GEO[name].x = x
GEO[name].y = y
GEO[name].z = z
GEO[name].o = orientation
-- Coordinates' highs and lows depend on orientation
if orientation == "z" then
GEO[name].xlow = x - width / 2
GEO[name].xhigh = x + width / 2
GEO[name].ylow = y - height / 2
GEO[name].yhigh = y + height / 2
GEO[name].zlow = z
GEO[name].zhigh = z
elseif orientation == "x" then
GEO[name].xlow = x
GEO[name].xhigh = x
GEO[name].ylow = y - width / 2
GEO[name].yhigh = y + width / 2
GEO[name].zlow = z - height / 2
GEO[name].zhigh = z + height / 2
elseif orientation == "y" then
GEO[name].xlow = x - width / 2
GEO[name].xhigh = x + width / 2
GEO[name].ylow = y
GEO[name].yhigh = y
GEO[name].zlow = z - height / 2
GEO[name].zhigh = z + height / 2
end
hprintf("Rectangle \"" .. name .. "\" created.")
setmetatable(GEO[name], GEO)
return GEO[name]
end
hprintf("Invalid name: \"" .. name .. "\"")
end
function GEO.get(name)
return GEO[name]
end
function GEO:delete()
self:hide()
GEO[self.n] = nil
hprintf("Geo \"" .. self.n .. "\" deleted.")
end
function GEO:move(x, y, z)
-- Move the center of the object
-- Default to GEO's current coordinates
GEO[self.n].x = x or GEO[self.n].x
GEO[self.n].y = y or GEO[self.n].y
GEO[self.n].z = z or GEO[self.n].z
-- If this is a rectangular prism...
if self.t == "rectprism" then
-- Change the x, y, and z lows and highs accordingly to adjust to the new center
GEO[self.n].xlow = x - GEO[self.n].lx / 2
GEO[self.n].xhigh = GEO[self.n].lx / 2 + x
GEO[self.n].ylow = y - GEO[self.n].ly / 2
GEO[self.n].yhigh = GEO[self.n].ly / 2 + y
GEO[self.n].zlow = z - GEO[self.n].lz / 2
GEO[self.n].zhigh = GEO[self.n].lz / 2 + z
-- If this is a rectangle...
elseif self.t == "rectangle" then
-- Change the x, y, and z lows and highs accordingly to adjust to the new center (depends on orientation)
if self.o == "z" then
GEO[self.n].xlow = self.x - self.width / 2
GEO[self.n].xhigh = self.x + self.width / 2
GEO[self.n].ylow = self.y - self.height / 2
GEO[self.n].yhigh = self.y + self.height / 2
GEO[self.n].zlow = self.z
GEO[self.n].zhigh = self.z
elseif self.o == "x" then
GEO[self.n].xlow = self.x
GEO[self.n].xhigh = self.x
GEO[self.n].ylow = self.y - self.width / 2
GEO[self.n].yhigh = self.y + self.width / 2
GEO[self.n].zlow = self.z - self.height / 2
GEO[self.n].zhigh = self.z + self.height / 2
elseif self.o == "y" then
GEO[self.n].xlow = self.x - self.width / 2
GEO[self.n].xhigh = self.x + self.width / 2
GEO[self.n].ylow = self.y
GEO[self.n].yhigh = self.y
GEO[self.n].zlow = self.z - self.height / 2
GEO[self.n].zhigh = self.z + self.height / 2
end
-- If this is a cylinder...
elseif self.t == "cylinder" then
GEO[self.n].zlow = self.z - self.h / 2
GEO[self.n].zhigh = self.z + self.h / 2
end
end
function GEO:radius(new)
if self.t == "sphere" or self.t == "circle" or self.t == "cylinder" then
if new then -- If "new" is defined...
GEO[self.n].r = new -- Change the radius to its value.
else -- If not...
return GEO[self.n].r -- Return its current radius.
end
end
end
function GEO:size(x, y, z)
-- If this is a rectangular prism...
if self.t == "rectprism" then
if x or y or z then -- If any of these variables have been defined...
-- Adjust lengths and x, y, and z highs and lows accordingly.
GEO[self.n].lx = x or GEO[self.n].lx
GEO[self.n].ly = y or GEO[self.n].ly
GEO[self.n].lz = z or GEO[self.n].lz
GEO[self.n].xlow = GEO[self.n].x - x / 2
GEO[self.n].xhigh = x / 2 + GEO[self.n].x
GEO[self.n].ylow = GEO[self.n].y - y / 2
GEO[self.n].yhigh = y / 2 + GEO[self.n].y
GEO[self.n].zlow = GEO[self.n].z - z / 2
GEO[self.n].zhigh = z / 2 + GEO[self.n].z
else -- Otherwise...
return GEO[self.n].lx, GEO[self.n].ly, GEO[self.n].lz -- Return the x, y, and z lengths.
end
-- If this is a rectangle...
elseif self.t == "rectangle" then
if x or y or z then -- If any of these variables are defined...
-- Adjust width, height, and x, y, and z highs and lows accordingly (depends on orientation).
if self.o == "z" then
GEO[self.n].width = x
GEO[self.n].height = y
GEO[self.n].xlow = self.x - self.width / 2
GEO[self.n].xhigh = self.x + self.width / 2
GEO[self.n].ylow = self.y - self.height / 2
GEO[self.n].yhigh = self.y + self.height / 2
GEO[self.n].zlow = self.z
GEO[self.n].zhigh = self.z
elseif self.o == "x" then
GEO[self.n].width = y
GEO[self.n].height = z
GEO[self.n].xlow = self.x
GEO[self.n].xhigh = self.x
GEO[self.n].ylow = self.y - self.width / 2
GEO[self.n].yhigh = self.y + self.width / 2
GEO[self.n].zlow = self.z - self.height / 2
GEO[self.n].zhigh = self.z + self.height / 2
elseif self.o == "y" then
GEO[self.n].width = x
GEO[self.n].height = z
GEO[self.n].xlow = self.x - self.width / 2
GEO[self.n].xhigh = self.x + self.width / 2
GEO[self.n].ylow = self.y
GEO[self.n].yhigh = self.y
GEO[self.n].zlow = self.z - self.height / 2
GEO[self.n].zhigh = self.z + self.height / 2
end
else -- Otherwise...
return GEO[self.n].width, GEO[self.n].height -- Return the width and height of the rectangle.
end
-- If this is a cylinder...
elseif self.t == "cylinder" then
local h = x or y or z -- Whichever variable is defined, it is taken as the height.
if h then -- If a height is specified...
-- Adjust height and z high and low accordingly.
GEO[self.n].h = h
GEO[self.n].zlow = self.z - h / 2
GEO[self.n].zhigh = self.z + h / 2
else -- Otherwise...
return GEO[self.n].h -- Return the height.
end
end
end
function GEO:extend(orienation, direction, amount)
-- Change the direction from "+" or "-" to "high" or "low".
local dir
dir = string.gsub(direction, "-", "low")
dir = string.gsub(direction, "+", "high")
-- Get the face we're trying to extend (i.e. "xhigh")
local face = string.lower(orientation) .. direction
-- If this is a rectangular prism or a rectangle...
if self.t == "rectprism" or self.t == "rectangle" then
-- Make sure "face" is actually a valid face (and not something like "cheesederp")
if self[face] then
-- Use "GEO[self.n]" when you want to actually permanently change the value of something within the object; use "self" for reading information from the object.
-- Change the length of the GEO in the orientation specified.
GEO[self.n]["l" .. string.lower(orientation)] = self["l" .. string.lower(orientation)] + amount
-- Figure out if the positive or negative face is being extended.
if direction == "+" then
GEO[self.n][face] = self[face] + amount
GEO[self.n][string.lower(orientation)] = self[string.lower(orientation)] + amount / 2
else
GEO[self.n][face] = self[face] - amount
GEO[self.n][string.lower(orientation)] = self[string.lower(orientation)] - amount / 2
end
end
-- If this is a cylinder...
elseif self.t == "cylinder" then
-- The orientation must be "z"
if orientation == "z" then
if self[face] then
GEO[self.n].h = self.h + amount
-- Figure out if the top or bottom face is being extended.
if direction == "+" then
GEO[self.n][face] = self[face] + amount
GEO[self.n].z = self.z + amount / 2
else
GEO[self.n][face] = self[face] - amount
GEO[self.n].z = self.z - amount / 2
end
end
end
end
end
function GEO:coords()
return self.x, self.y, self.z
end
function GEO:high(orientation)
if self.t == "sphere" or self.t == "circle" then
return self[orientation] + self.r
elseif self.t == "rectprism" or self.t == "rectangle" then
return self[orientation .. "high"]
elseif self.t == "cylinder" then
if orientation == "z" then
return self.zhigh
else
return self[orientation] + self.r
end
end
end
function GEO:low(orientation)
if self.t == "sphere" or self.t == "circle" then
return self[orientation] - self.r
elseif self.t == "rectprism" or self.t == "rectangle" then
return self[orientation .. "low"]
elseif self.t == "cylinder" then
if orientation == "z" then
return self.zlow
else
return self[orientation] - self.r
end
end
end
function GEO:randcoords()
if self.t == "sphere" then
return randomInSphere(self.x, self.y, self.z, self.r)
elseif self.t == "circle" then
return randomInCircle(self.x, self.y, self.z, self.r, self.o)
elseif self.t == "cylinder" then
return randomInCylinder(self.x, self.y, self.zlow, self.zhigh, self.r)
elseif self.t == "rectprism" or self.t == "rectangle" then
return randomInRectPrism(self.xlow, self.xhigh, self.ylow, self.yhigh, self.zlow, self.zhigh)
end
end
function GEO:type()
return self.t
end
function GEO:orientation()
return self.o
end
function GEO:name()
return self.n
end
function GEO:perimeter(density, mapId)
-- Default density to 10
density = density or 10
-- Default tagtype and tagname to Full-Spectrum Visions
mapId = mapId or gettagid("eqip", "powerups\\full-spectrum vision")
tagname, tagtype = gettaginfo(mapId)
-- Store all of the perimeter objects in a table
GEO[self.n].p = GEO[self.n].p or {}
-- Find the change in angle per point from 0 - 2pi (0° - 360°)
local angle_increment = 2 * math.pi / density
if self.t == "sphere" or self.t == "cylinder" then
for i = 1,density do
-- Use trigonometry to find the outer edge of the circle (for a sphere, this will be at the z-center -- the widest part of the sphere).
local x = self.r * math.cos(angle_increment * i)
local y = self.r * math.sin(angle_increment * i)
local z = self.z
local objId = createobject(mapId, 0, 0, false, self.x + x, self.y + y, self.z + z)
GEO[self.n].p[objId] = {self.x + x, self.y + y, self.z + z}
end
elseif self.t == "circle" then
if self.o == "z" then
for i = 1,density do
-- Use trigonometry to find the outer edge of the circle (for a sphere, this will be at the z-center -- the widest part of the sphere).
local x = self.r * math.cos(angle_increment * i)
local y = self.r * math.sin(angle_increment * i)
local z = self.z
local objId = createobject(mapId, 0, 0, false, self.x + x, self.y + y, self.z + z)
GEO[self.n].p[objId] = {self.x + x, self.y + y, self.z + z}
end
end
elseif self.t == "rectprism" or self.t == "rectangle" then
if self.t == "rectangle" then
if self.o ~= "z" then return end
end
-- Create points at four corners of the rectangle
local o1 = createobject(mapId, 0, 0, false, self.xhigh, self.yhigh, self.z)
local o2 = createobject(mapId, 0, 0, false, self.xhigh, self.ylow, self.z)
local o3 = createobject(mapId, 0, 0, false, self.xlow, self.yhigh, self.z)
local o4 = createobject(mapId, 0, 0, false, self.xlow, self.ylow, self.z)
GEO[self.n].p[o1] = {self.xhigh, self.yhigh, self.z}
GEO[self.n].p[o2] = {self.xhigh, self.yhigh, self.z}
GEO[self.n].p[o3] = {self.xhigh, self.yhigh, self.z}
GEO[self.n].p[o4] = {self.xhigh, self.yhigh, self.z}
for i = 1,density do
local herp = createobject(mapId, 0, 0, false, self.xhigh - (i * self.lx / density), self.yhigh, self.z)
local derp = createobject(mapId, 0, 0, false, self.xhigh, self.yhigh - (i * self.ly / density), self.z)
local weee = createobject(mapId, 0, 0, false, self.xhigh - (i * self.lx / density), self.ylow, self.z)
local cheese = createobject(mapId, 0, 0, false, self.xlow, self.ylow + (i * self.ly / density), self.z)
GEO[self.n].p[herp] = {self.xhigh - (i * self.lx / density), self.yhigh, self.z}
GEO[self.n].p[derp] = {self.xhigh, self.yhigh - (i * self.ly / density), self.z}
GEO[self.n].p[weee] = {self.xhigh - (i * self.lx / density), self.ylow, self.z}
GEO[self.n].p[cheese] = {self.xlow, self.ylow + (i * self.ly / density), self.z}
end
end
end
function GEO:hide()
if self.p then
for k,v in pairs(GEO[self.n].p) do
if getobject(k) then
destroyobject(k)
GEO[self.n].p[k] = nil
end
end
end
end
-- Never quite got this to work right, but I'm saving it for the sake of the formula.
--[[function GEO:surface(density)
GEO[self.n].p = GEO[self.n].p or {}
if self.t == "sphere" then
local inc = math.pi * (3 - math.sqrt(5))
local off = 2 / density
for i = 1,density do
local y = self.r * i * off - 1 + (off / 2)
local r = self.r * math.sqrt(1 - y ^ 2)
local phi = i * inc
local x = r * math.cos(phi)
local z = r * math.sin(phi)
local objId = createobject(mapId, 0, 0, false, x, y, z)
GEO[self.n].p[objId] = {x, y, z}
end
end
end--]]
function GEO:contains(objId)
if self.t == "sphere" then
return inSphere(objId, self.x, self.y, self.z, self.r)
elseif self.t == "rectprism" or self.t == "rectangle" then
return inRectPrism(objId, self.xlow, self.xhigh, self.ylow, self.yhigh, self.zlow, self.zhigh)
elseif self.t == "circle" then
return inCircle(objId, self.x, self.y, self.z, self.r, self.o)
elseif self.t == "cylinder" then
return inCylinder(objId, self.x, self.y, self.zlow, self.zhigh, self.r)
end
end
function GEO:follow(objId)
-- If the objId exists...
if getobject(objId) then
GEO[self.n].f = objId -- Save it (the GEOTimer will access it)
-- Check to see if the object is a player
if objectidtoplayer(objId) then
GEO[self.n].player = true
end
end
end
function GEO:unfollow()
-- Nullify the saved objId from GEO:follow()
GEO[self.n].f = nil
end
function GEO.followedBy(objId)
-- Initialize table
local geos = {}
-- Loop through the GEO table
for k,v in pairs(GEO) do
if type(v) == "table" and k ~= "__index" then -- make sure we're actually getting a GEO object
if v.f == objId then
-- If this GEO has this objId saved, insert it into the geos table.
table.insert(geos, v)
end
end
end
-- Return the GEOs following objId in a table.
return geos
end
function GEO.cleanup(player)
local m_player = getplayer(player)
local objId = readdword(m_player, 0x34)
local geos = GEO.followedBy(objId)
for k,v in ipairs(geos) do
v:delete()
end
end
function GEO:velocity(x, y, z)
GEO[self.n].vx = x or GEO[self.n].vx
GEO[self.n].vy = y or GEO[self.n].vy
GEO[self.n].vz = z or GEO[self.n].vz
end
function GEO:killzone(bool)
if bool == true then
GEO[self.n].kz = true
elseif bool == false then
GEO[self.n].kz = false
elseif bool == nil then
return GEO[self.n].kz or false
end
end
function GEO:damagezone(bool, damage)
if bool == true then
GEO[self.n].damage = damage or 1 -- Amount of damage applied per second.
elseif bool == false then
GEO[self.n].damage = nil
elseif bool == nil then -- If nothing is passed, return true if this GEO is a damagezone, false if not.
if GEO[self.n].damage then
return true
else
return false
end
end
end
function GEO:face(orientation, direction)
-- If this is a rectangular prism...
if self.t == "rectprism" then
orientation = orientation or "z"
direction = direction or "+"
if orientation == "z" then
local width = self.lx
local height = self.ly
local highlow
if direction == "+" then
highlow = self.zhigh
else
highlow = self.zlow
end
-- Create a new rectangle which overlays the specified face and return that rectangle.
return GEO.newRect(self.n .. "ZFace" .. os.time(), width, height, self.x, self.y, highlow, orientation)
elseif orientation == "x" then
local width = self.ly
local height = self.lz
local highlow
if direction == "+" then
highlow = self.xhigh
else
highlow = self.xlow
end
return GEO.newRect(self.n .. "XFace" .. os.time(), width, height, highlow, self.y, self.z, orientation)
elseif orientation == "y" then
local width = self.lx
local height = self.lz
local highlow
if direction == "+" then
highlow = self.yhigh
else
highlow = self.ylow
end
return GEO.newRect(self.n .. "YFace" .. os.time(), width, height, self.x, highlow, self.z, orientation)
end
-- If this is a cylinder...
elseif self.t == "cylinder" then
if orientation == "z" then
local highlow
if direction == "+" then
highlow = self.zhigh
else
highlow = self.zlow
end
-- Return a new circle which overlays the specified face and return that circle.
return GEO.newCircle(self.n .. "ZFace" .. os.time(), self.r, self.x, self.y, highlow, "z")
else
hprintf("You may only retrieve the Z face of a cylinder.")
end
end
end
function GEO:copy(name)
name = name or self.n .. "Copy" .. os.time()
if not GEO[name] then
GEO[name] = self
return GEO[name]
end
end
function GEO:monitor(objId)
if getobject(objId) then
GEO[self.n].m = GEO[self.n].m or {}
GEO[self.n].c = GEO[self.n].c or {}
GEO[self.n].m[objId] = true
end
end
registertimer(10, "GEOTimer")
function GEOTimer(id, count)
-- Create a coordinates table for players if it hasn't already been created
pcoords = pcoords or {}
-- Loop through the GEO table
for k,v in pairs(GEO) do
if type(v) == "table" and k ~= "__index" then
-- If this GEO is following an object...
if v.f then
-- Get the coordinates of the object
local x, y, z = getobjectcoords(v.f)
if x then -- If this object exists...
if v.player then
local player = objectidtoplayer(v.f)
if player then
local m_player = getplayer(player) -- See if the player is still here
if m_player then -- If they are...
local time_until_respawn = readdword(m_player, 0x2C) -- Check to see if they're dead
if time_until_respawn == 0 then -- If they're not...
if v.p then -- If this GEO has perimeter objects...
for objId, coords in pairs(v.p) do
if getobject(objId) then
local ox, oy, oz = table.unpack(coords)
local x_diff = x - v.x
local y_diff = y - v.y
local z_diff = z - v.z
local m_object = getobject(objId)
movobjcoords(objId, ox + x_diff, oy + y_diff, oz + z_diff) -- Move them with the GEO.
GEO[v.n].p[objId] = {ox + x_diff, oy + y_diff, oz + z_diff}
end
end
end
v:move(x, y, z) -- Move the GEO to the player's coordinates
else -- Otherwise...
v:delete() -- Delete the GEO.
end
else -- Otherwise...
v:delete() -- Delete the GEO.
end
else -- Otherwise...
v:delete() -- Delete the GEO.
end
else -- Otherwise...
if v.p then -- If this GEO has perimeter objects...
for objId, coords in pairs(v.p) do
if getobject(objId) then
local ox, oy, oz = table.unpack(coords)
local x_diff = x - v.x
local y_diff = y - v.y
local z_diff = z - v.z
local m_object = getobject(objId)
movobjcoords(objId, ox + x_diff, oy + y_diff, oz + z_diff) -- Move them with the GEO.
GEO[v.n].p[objId] = {ox + x_diff, oy + y_diff, oz + z_diff}
end
end
end
v:move(x, y, z) -- Don't worry about all of that player nonsense and just move the damn GEO.
end
else -- Otherwise...
v:delete() -- Delete the GEO.
end
end
-- If after all of that following nonsense, we still have a GEO...
if v then
-- If this GEO is a killzone...
if v.kz then
-- Check if anyone is inside of it.
for i = 0,15 do
if getplayer(i) then
local m_player = getplayer(i)
local objId = readdword(m_player, 0x34)
if v:contains(objId) then
kill(i) -- Kill that ho.
end
end
end
end
-- If this GEO is a damagezone...
if v.damage then
-- Check if anyone is inside of it.
for i = 0,15 do
local m_player = getplayer(i)
if m_player then
local objId = readdword(m_player, 0x34)
if v:contains(objId) then
applydmg(objId, v.damage / 100) -- Apply damage
end
end
end
end
-- If this GEO is monitoring for objects entering and exiting it...
if v.m then
-- Loop through the table of objects this GEO is monitoring for.
for objId,_ in pairs(v.m) do
-- If this object still exists...
if getobject(objId) then
-- If this object is inside of the GEO...
if v:contains(objId) then
-- If the GEO didn't know this object was inside of it 1/100 of a second ago...
if not v.c[objId] then
local player = objectidtoplayer(objId)
-- Call OnGeoEnter.
local allow = OnGeoEnter(v, player, objId)
if allow == 0 or allow == false then
local hash = gethash(player)
if pcoords[hash] then
movobjcoords(objId, table.unpack(pcoords[hash]))
end
else
GEO[k].c[objId] = true
end
end
else -- Otherwise...
-- If the GEO thought this object was inside of it 1/100 of a second ago...
if v.c[objId] then
local player = objectidtoplayer(objId)
-- Call OnGeoExit.
local allow = OnGeoExit(v, player, objId)
if allow == 0 or allow == false then
local hash = gethash(player)
if pcoords[hash] then
movobjcoords(objId, table.unpack(pcoords[hash]))
end
else
GEO[k].c[objId] = nil
end
end
end
else -- Otherwise...
GEO[k].m[objId] = nil -- Stop monitoring for this object.
end
end
end
-- If this GEO has a velocity...
if v.vx or v.vy or v.vz then
if v.p then -- If this GEO has perimeter objects...
for objId, coords in pairs(v.p) do
if getobject(objId) then
local ox, oy, oz = table.unpack(coords)
local m_object = getobject(objId)
movobjcoords(objId, ox + (v.vx or 0), oy + (v.vy or 0), oz + (v.vz or 0)) -- Move them with the GEO.
GEO[v.n].p[objId] = {ox + (v.vx or 0), oy + (v.vy or 0), oz + (v.vz or 0)}
end
end
end
-- Move that ho.
v:move(v.x + (v.vx or 0) / 100, v.y + (v.vy or 0) / 100, v.z + (v.vz or 0) / 100)
end
end
end
end
-- Update coordinates at a slight delay for blocking GEO entry/exit (if there is no delay, players in mid-air could end up dying since they'll just be teleported in mid-air perpetually)
if count % 25 == 0 then
for i = 0,15 do
local m_player = getplayer(i)
if m_player then
local hash = gethash(i)
local objId = readdword(m_player, 0x34)
if getobject(objId) then
pcoords[hash] = {getobjectcoords(objId)}
else
pcoords[hash] = nil
end
end
end
end
return true
end
function OnGeoEnter(geo, player, objId)
local hash = gethash(player)
if geo == bombarea then
if players[hash].bomb then
privatesay(player, "Bomb droped")
registertimer(1000, "ExplosionTimer")
return true
else
privatesay(player, "You don't have the bomb")
return true
end
end
return true
end
function OnGeoExit(geo, player, objId)
return true
end
Comments
0 B
|👍
/👎