-- 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, -76.7, 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 terroristscounter = 0 redscounter = 0 function GetRequiredVersion() return 200 end function OnScriptLoad(processid, game, persistent) LoadTags() GetGameAddresses(game) writedword(flag_respawn_addr, 0, 0xFFFFFFFF) -- try to disable the flag writedword(flag_respawn_addr, 1, 0xFFFFFFFF) -- try to disable the flag writedword(gametype_base, 0x48, respawn_time * 30) -- and avoid it respawns writebyte(gametype_base, 0x58, 2) end function OnScriptUnload() end function GetGameAddresses(game) if game == "PC" then flag_respawn_addr = 0x488A7E -- Confirmed by Nugets stats_header = 0x639720 -- Confirmed. stats_globals = 0x639898 -- Confirmed. ctf_globals = 0x639B98 -- Confirmed. slayer_globals = 0x63A0E8 -- Confirmed. oddball_globals = 0x639E58 -- Confirmed. koth_globals = 0x639BD0 -- Confirmed. race_globals = 0x639FA0 -- Confirmed. race_locs = 0x670F40 -- Confirmed. map_pointer = 0x63525c -- Confirmed. gametype_base = 0x671340 -- Confirmed. network_struct = 0x745BA0 -- Confirmed. camera_base = 0x69C2F8 -- Confirmed. player_header_pointer = 0x75ECE4 -- Confirmed. obj_header_pointer = 0x744C18 -- Confirmed. map_header_base = 0x630E74 -- Confirmed. banlist_header = 0x641280 -- Confirmed. game_globals = "???" -- (???) Why do I not have this for PC? gameinfo_header = 0x671420 -- Confirmed. mapcycle_header = 0x614B4C -- Confirmed. network_server_globals = 0x69B934 -- Confirmed. flags_pointer = 0x6A590C -- Confirmed. hash_table_base = 0x6A2AE4 -- Confirmed. --Patches gametype_patch = 0x481F3C hashcheck_patch = 0x59c280 -- Confirmed. servername_patch = 0x517D6B -- Confirmed. versioncheck_patch = 0x5152E7 -- Confirmed. else stats_header = 0x5BD740 -- Confirmed. stats_globals = 0x5BD8B8 -- Confirmed. ctf_globals = 0x5BDBB8 -- Confirmed. slayer_globals = 0x5BE108 -- Confirmed. oddball_globals = 0x5BDE78 -- Confirmed. koth_globals = 0x5BDBF0 -- Confirmed. race_globals = 0x5BDFC0 -- Confirmed. race_locs = 0x5F5098 -- Confirmed. map_pointer = 0x5B927C -- Confirmed. gametype_base = 0x5F5498 -- Confirmed. network_struct = 0x6C7980 -- Confirmed. camera_base = 0x62075C -- Confirmed. player_globals = 0x6E1478 -- From OS. player_header_pointer = 0x6E1480 -- Confirmed. obj_header_pointer = 0x6C69F0 -- Confirmed. map_header_base = 0x6E2CA4 -- Confirmed. banlist_header = 0x5C52A0 -- Confirmed. game_globals = 0x61CFE0 -- Confirmed. gameinfo_header = 0x5F55BC -- Confirmed. mapcycle_header = 0x598A8C -- Confirmed. network_server_globals = 0x61FB64 -- Confirmed. hash_table_base = 0x5AFB34 -- Confirmed. --Patches hashcheck_patch = 0x530130 -- Confirmed. servername_patch = 0x4CE0CD -- Confirmed. versioncheck_patch = 0x4CB587 -- Confirmed. end end function OnGameEnd(stage) if stage == 1 then if finalscore ~= 3 then say("red team won") writedword(ctf_globals, 0x10, 3) terroristneedweap = nil else say("blue team won") writedword(ctf_globals + 0x4, 0x10, 3) terroristneedweap = nil end elseif stage == 3 then writedword(flag_respawn_addr, 0, 17 * 30) -- flag respawn addr end end function OnNewGame(map) LoadTags() RocketId = rocketlauncher_tag_id BombId = oddball_tag_id 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) -- -0.3 pitch the objective writefloat(m_object + 0x78, 1) --pitch the objective bomb.respawn_remain = bomb.respawn registertimer(1000, "Respawn", "bomb") registertimer(5000, "CreateBomb") writedword(flag_respawn_addr + 0x0, 0xFFFFFFFF) -- coord flag pointer registertimer(0, "CreationDelay") -- flag undermap 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 -- kindof messy but working, ok terrible privatesay(player, "You are a terrorist, explode the red base") privatesay(player, "Type help in chat for further instructions") terroristscounter = terroristscounter + 1 elseif team == 0 and terroristscounter == 1 and redscounter == 1 then changeteam(player, true) privatesay(player, "The game needs more terrorists, go explode the red base") privatesay(player, "Type help in chat for further instructions") terroristscounter = terroristscounter + 1 elseif team == 1 and terroristscounter == 2 and redscounter == 1 then changeteam(player, true) privatesay(player, "The game needs more reds, protect your base") privatesay(player, "Type help in chat for further instructions") redscounter = redscounter + 1 elseif team == 0 and terroristscounter == 2 and redscounter == 1 then changeteam(player, true) privatesay(player, "The game needs more terrorists, go explode the red base") privatesay(player, "Type help in chat for further instructions") terroristscounter = terroristscounter + 1 elseif team == 0 and terroristscounter == 5 and redscounter == 3 then changeteam(player, true) privatesay(player, "The game needs more terrorists, go explode the red base") privatesay(player, "Type help in chat for further instructions") terroristscounter = terroristscounter + 1 elseif team == 1 and terroristscounter == 6 and redscounter == 3 then changeteam(player, true) privatesay(player, "The game needs more reds, protect your base") privatesay(player, "Type help in chat for further instructions") redscounter = redscounter + 1 elseif team == 0 and terroristscounter == 6 and redscounter == 4 then changeteam(player, true) privatesay(player, "The game needs more terrorists, go explode the red base") privatesay(player, "Type help in chat for further instructions") terroristscounter = terroristscounter + 1 elseif team == 0 and terroristscounter == 9 and redscounter == 5 then changeteam(player, true) privatesay(player, "The game needs more terrorists, go explode the red base") privatesay(player, "Type help in chat for further instructions") terroristscounter = terroristscounter + 1 else privatesay(player, "Protect your base from the blue terrorists") privatesay(player, "Type help in chat for further instructions") redscounter = redscounter + 1 end end function CreationDelay(id, count) for i = 0,1 do ctf_flag_coords_pointer = readdword(ctf_globals + 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) if mapId == flag_tag_id then local m_objectId = readdword(ctf_globals + 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) if mapId == oddball_tag_id then if team == 0 then return false end elseif mapId == flag_tag_id then -- useless as flag is undermap return false end end function OnWeaponPickup(player, weapId, slot, mapId) local hash = gethash(player) if mapId == oddball_tag_id 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) if mapId == oddball_tag_id 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 _G[item].objId = createobject(BombId, 0, 0, false, _G[item].x, _G[item].y, _G[item].z) _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) -- for ctf global 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") privatesay(player, "Type help in chat for further instructions") redscounter = redscounter - 1 terroristscounter = terroristscounter + 1 else privatesay(player, "Protect your base from the blue terrorists") privatesay(player, "Type help in chat for further instructions") terroristscounter = terroristscounter - 1 redscounter = redscounter + 1 end players[hash].bomb = false players[hash].monitored = false end end function OnServerChat(player, type, message) if player then local team = getteam(player) if string.lower(message) == "help" then if team == 0 then registertimer(1000, "RedHelper", player) else registertimer(1000, "BlueHelper", player) end end end end function RedHelper(id, count, player) if getplayer(player) then if count == 1 then sendconsoletext(player, "CounterStrike GameType:") return true elseif count == 4 then sendconsoletext(player, "You must avoid a blue player holding the bomb enters your base") return true elseif count == 7 then sendconsoletext(player, "If your team managed to prevent the bomb from exploding in your base 3 times") return true elseif count == 10 then sendconsoletext(player, "and if the game reached its time limit, you won.") return true elseif count == 13 then return false else return true end end end function BlueHelper(id, count, player) if getplayer(player) then if count == 1 then sendconsoletext(player, "CounterStrike GameType:") return true elseif count == 4 then sendconsoletext(player, "You have to pick up the bomb in the back entrance of your base") return true elseif count == 7 then sendconsoletext(player, "and go to explode it in the red base to score") return true elseif count == 10 then sendconsoletext(player, "When your team score 3 times, you won.") return true elseif count == 13 then return false else return true end 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 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 destroyobject(weapID) end end end end players[hash].bomb = false players[hash].monitored = false end function OnClientUpdate(player) writedword(ctf_globals + 0x10, 0) -- dunno writedword(ctf_globals + 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 == 3 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 writefloat(m_weapon + 0x5C, readfloat(m_weapon + 0x5C) + 40.15) -- x writefloat(m_weapon + 0x60, readfloat(m_weapon + 0x60) + -76.7) -- y writefloat(m_weapon + 0x64, readfloat(m_weapon + 0x64) + 0.01) -- and z 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 function LoadTags() -- Bipeds cyborg_tag_id = gettagid("bipd", "characters\\cyborg_mp\\cyborg_mp") captain_tag_id = gettagid("bipd", "characters\\captain\\captain") cortana_tag_id = gettagid("bipd", "characters\\cortana\\cortana") cortana2_tag_id = gettagid("bipd", "characters\\cortana\\halo_enhanced\\halo_enhanced") crewman_tag_id = gettagid("bipd", "characters\\crewman\\crewman") elite_tag_id = gettagid("bipd", "characters\\elite\\elite") elite2_tag_id = gettagid("bipd", "characters\\elite\\elite special") relite_tag_id = gettagid("bipd", "revolution\\biped\\cmt_elite") engineer_tag_id = gettagid("bipd", "characters\\engineer\\engineer") flood_tag_id = gettagid("bipd", "characters\\flood_captain\\flood_captain") flood2_tag_id = gettagid("bipd", "characters\\flood_infection\\flood_infection") -- Equipment camouflage_tag_id = gettagid("eqip", "powerups\\active camouflage") healthpack_tag_id = gettagid("eqip", "powerups\\health pack") overshield_tag_id = gettagid("eqip", "powerups\\over shield") doublespeed_tag_id = gettagid("eqip", "powerups\\double speed") fullspec_tag_id = gettagid("eqip", "powerups\\full-spectrum vision") fragnade_tag_id = gettagid("eqip", "weapons\\frag grenade\\frag grenade") plasmanade_tag_id = gettagid("eqip", "weapons\\plasma grenade\\plasma grenade") rifleammo_tag_id = gettagid("eqip", "powerups\\assault rifle ammo\\assault rifle ammo") needlerammo_tag_id = gettagid("eqip", "powerups\\needler ammo\\needler ammo") pistolammo_tag_id = gettagid("eqip", "powerups\\pistol ammo\\pistol ammo") rocketammo_tag_id = gettagid("eqip", "powerups\\rocket launcher ammo\\rocket launcher ammo") shotgunammo_tag_id = gettagid("eqip", "powerups\\shotgun ammo\\shotgun ammo") sniperammo_tag_id = gettagid("eqip", "powerups\\sniper rifle ammo\\sniper rifle ammo") flameammo_tag_id = gettagid("eqip", "powerups\\flamethrower ammo\\flamethrower ammo") -- Vehicles banshee_tag_id = gettagid("vehi", "vehicles\\banshee\\banshee_mp") turret_tag_id = gettagid("vehi", "vehicles\\c gun turret\\c gun turret_mp") ghost_tag_id = gettagid("vehi", "vehicles\\ghost\\ghost_mp") rwarthog_tag_id = gettagid("vehi", "vehicles\\rwarthog\\rwarthog") scorpion_tag_id = gettagid("vehi", "vehicles\\scorpion\\scorpion_mp") warthog_tag_id = gettagid("vehi", "vehicles\\warthog\\mp_warthog") wraith_tag_id = gettagid("vehi", "vehicles\\wraith\\wraith") pelican_tag_id = gettagid("vehi", "vehicles\\pelican\\pelican") -- Weapons assaultrifle_tag_id = gettagid("weap", "weapons\\assault rifle\\assault rifle") oddball_tag_id = gettagid("weap", "weapons\\ball\\ball") flag_tag_id = gettagid("weap", "weapons\\flag\\flag") flamethrower_tag_id = gettagid("weap", "weapons\\flamethrower\\flamethrower") gravityrifle_tag_id = gettagid("weap", "weapons\\gravity rifle\\gravity rifle") needler_tag_id = gettagid("weap", "weapons\\needler\\mp_needler") pistol_tag_id = gettagid("weap", "weapons\\pistol\\pistol") plasmapistol_tag_id = gettagid("weap", "weapons\\plasma pistol\\plasma pistol") plasmarifle_tag_id = gettagid("weap", "weapons\\plasma rifle\\plasma rifle") plasmacannon_tag_id = gettagid("weap", "weapons\\plasma_cannon\\plasma_cannon") rocketlauncher_tag_id = gettagid("weap", "weapons\\rocket launcher\\rocket launcher") shotgun_tag_id = gettagid("weap", "weapons\\shotgun\\shotgun") sniper_tag_id = gettagid("weap", "weapons\\sniper rifle\\sniper rifle") energysword_tag_id = gettagid("weap", "weapons\\energy sword\\energy sword") -- Projectiles bansheebolt_tag_id = gettagid("proj", "vehicles\\banshee\\banshee bolt") bansheeblast_tag_id = gettagid("proj", "vehicles\\banshee\\mp_banshee fuel rod") turretfire_tag_id = gettagid("proj", "vehicles\\c gun turret\\mp gun turret") ghostbolt_tag_id = gettagid("proj", "vehicles\\ghost\\ghost bolt") tankshot_tag_id = gettagid("proj", "vehicles\\scorpion\\bullet") tankblast_tag_id = gettagid("proj", "vehicles\\scorpion\\tank shell") warthogshot_tag_id = gettagid("proj", "vehicles\\warthog\\bullet") rifleshot_tag_id = gettagid("proj", "weapons\\assault rifle\\bullet") flame_tag_id = gettagid("proj", "weapons\\flamethrower\\flame") needlerfire_tag_id = gettagid("proj", "weapons\\needler\\mp_needle") pistolshot_tag_id = gettagid("proj", "weapons\\pistol\\bullet") plasmapistolbolt_tag_id = gettagid("proj", "weapons\\plasma pistol\\bolt") plasmariflebolt_tag_id = gettagid("proj", "weapons\\plasma rifle\\bolt") plasmarifleblast_tag_id = gettagid("proj", "weapons\\plasma rifle\\charged bolt") plasmacannonshot_tag_id = gettagid("proj", "weapons\\plasma_cannon\\plasma_cannon") rocket_tag_id = gettagid("proj", "weapons\\rocket launcher\\rocket") shotgunshot_tag_id = gettagid("proj", "weapons\\shotgun\\pellet") snipershot_tag_id = gettagid("proj", "weapons\\sniper rifle\\sniper bullet") -- Globals global_distanceId = gettagid("jpt!", "globals\\distance") global_fallingId = gettagid("jpt!", "globals\\falling") 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