mirror of
https://github.com/ornfelt/azerothcore_lua_scripts
synced 2026-08-22 06:26:03 -04:00
189 lines
8.6 KiB
Lua
189 lines
8.6 KiB
Lua
|
|
local AIO = AIO or require("AIO")
|
||
|
|
local APTHandlers = AIO.AddHandlers("APTStuff", {})
|
||
|
|
|
||
|
|
-- Owner: grimreapaa
|
||
|
|
|
||
|
|
-- how long should APTs last in seconds. default: 259200 (3 days)
|
||
|
|
APT_TIME_EXPIRED = 31536000
|
||
|
|
|
||
|
|
--how often the server should check for spawned APTs in ms(bigger value may be needed for slower servers). default 1800000 (30mins)
|
||
|
|
APT_TIME_CHECK = 1800000
|
||
|
|
|
||
|
|
-- Zones that APTs are disallowed in.
|
||
|
|
DISABLE_APT_ZONES = {
|
||
|
|
[5000]=true, -- spark
|
||
|
|
[1581]=true, -- darkmines outside spark
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
-- The player uses item before casting spell, so we define which item and the GUID.
|
||
|
|
local function APT_OnUse(event, player, item, target)
|
||
|
|
item_entry = tonumber(item:GetEntry())
|
||
|
|
item_guid = tonumber(item:GetGUIDLow())
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Registers item events to declare on use hooks.
|
||
|
|
-- Chronological order of these functions: APTStartUp -> APT_RegisterEvents -> APT_ReloadEvents -> APT_RegisterEvents
|
||
|
|
local function APT_RegisterEvents()
|
||
|
|
APT_Query1 = WorldDBQuery("SELECT item_id, gobject FROM apt_template")
|
||
|
|
if (APT_Query1 == nil) then
|
||
|
|
-- Create `apt_template` table if not exists. Print error to populate database.
|
||
|
|
PrintInfo("[APT]: Table `apt_template` is not populated with any entries. Please create some and restart your server to use the APT system. Afterwards, you may use `.reload apt_template.`")
|
||
|
|
return
|
||
|
|
else
|
||
|
|
APT_objects = {}
|
||
|
|
APT_items = {}
|
||
|
|
for x=1,APT_Query1:GetRowCount(),1 do
|
||
|
|
local APT_Query2 = WorldDBQuery("SELECT entry FROM gameobject_template WHERE entry = " ..APT_Query1:GetInt32(1).. ";")
|
||
|
|
if (APT_Query2 == nil) then -- Print error and do not insert into array if gobject entry does not exist in gameobject_template
|
||
|
|
PrintInfo("[APT]: Table `apt_template` has incorrect gameobject value: " ..APT_Query1:GetInt32(1).. ".")
|
||
|
|
else
|
||
|
|
APT_objects[APT_Query1:GetInt32(0)] = APT_Query1:GetInt32(1) -- Insert into array item_id = gobject
|
||
|
|
APT_items[APT_Query1:GetInt32(1)] = APT_Query1:GetInt32(0) -- Reverse array. gobject = item_id
|
||
|
|
RegisterItemEvent(APT_Query1:GetInt32(0), 2, APT_OnUse) -- Register item events ON_USE. If item does not exist, error prints.
|
||
|
|
APT_Query1:NextRow()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
-- On script load, run function.
|
||
|
|
local function APTStartUp(event)
|
||
|
|
APT_RegisterEvents()
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Deletes item events before re-registering them via `.reload apt_template`
|
||
|
|
local function APT_ReloadEvents(event, player, command)
|
||
|
|
if (command ~= "reload apt_template") then
|
||
|
|
return
|
||
|
|
else
|
||
|
|
for x in pairs(APT_items) do
|
||
|
|
ClearItemEvents(APT_items[x], 2) -- table[pos] [pos]=value
|
||
|
|
SendWorldMessage("DB table `apt_template` reloaded.")
|
||
|
|
end
|
||
|
|
APT_RegisterEvents()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
-- dummy event to return object if found
|
||
|
|
local function Dummy_Event()
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
-- TO DO: Create table if not exists without firing the spell hook every time. On reload apt_template?
|
||
|
|
-- Chronological order -> APT_OnUse -> APT_Spell
|
||
|
|
local function APT_Spell(event, player, spell, skipCheck)
|
||
|
|
-- This event is fired every time a spell is cast, so we must kill the function first.
|
||
|
|
if (spell:GetEntry() ~= 2000001) then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
local instanceid = player:GetInstanceId()
|
||
|
|
-- here we stop error spam from a nil instanceid
|
||
|
|
if (instanceid == nil) then
|
||
|
|
instanceid = 0
|
||
|
|
end
|
||
|
|
-- If player is placing APT in disabled zone, then stop the script from running.
|
||
|
|
if DISABLE_APT_ZONES[player:GetZoneId()] == true then
|
||
|
|
player:SendBroadcastMessage("You are not allowed to place APTs in this area.")
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
local spell_x, spell_y, spell_z = spell:GetTargetDest()
|
||
|
|
local APT_Query3 = WorldDBQuery("SELECT item_instance, gobject_guid, gobject_raw, map, x, y, z, o FROM apt_spawned WHERE item_instance = " ..item_guid.. ";")
|
||
|
|
-- spawn APT if item_guid does not have an entry. Spell cannot use GetNearestGameObject, so we get a little hacky by spawning an NPC that can use that method at the spell xyz.
|
||
|
|
if (APT_Query3 == nil) then
|
||
|
|
-- we put a cooldown here so players cannot spam spawn, as DB issues can happen this way.
|
||
|
|
-- if player:GetLuaCooldown(1998) == 0 then
|
||
|
|
-- player:SetLuaCooldown(0.025, 1998)
|
||
|
|
-- else
|
||
|
|
-- player:SendBroadcastMessage("You must wait a second or two before spawning again.")
|
||
|
|
-- return
|
||
|
|
-- end
|
||
|
|
|
||
|
|
PerformIngameSpawn(2, APT_objects[item_entry], player:GetMapId(), instanceid, spell_x, spell_y, spell_z, player:GetO(), true, 0, 1)
|
||
|
|
PerformIngameSpawn(1, 32277, player:GetMapId(), player:GetInstanceId(), spell_x, spell_y, spell_z, player:GetO(), false, 0, 3)
|
||
|
|
-- this is made to catch any overlap of GUIDs and attempts to fix them.
|
||
|
|
local dummy = player:GetNearestCreature(50, 32277, 0, 1)
|
||
|
|
local nearestobjects = dummy:GetGameObjectsInRange(10, APT_objects[item_entry], 0)
|
||
|
|
local WeaverQuery2 = WorldDBQuery("SELECT `gobject_guid` FROM `apt_spawned` WHERE `gobject_guid` = " ..nearestobjects[1]:GetDBTableGUIDLow().. ";")
|
||
|
|
for x=1,#nearestobjects,1 do
|
||
|
|
if WeaverQuery2 ~= nearestobjects[x] then
|
||
|
|
-- player:SendBroadcastMessage("Detecting break. Fixing?")
|
||
|
|
nearestobject_guid = nearestobjects[x]:GetDBTableGUIDLow()
|
||
|
|
nearestobject_raw = nearestobjects[x]:GetGUIDLow()
|
||
|
|
map = nearestobjects[x]:GetMapId()
|
||
|
|
break
|
||
|
|
end
|
||
|
|
end
|
||
|
|
-- local object_guid = dummy:GetNearestGameObject(5, APT_objects[item_entry])
|
||
|
|
WorldDBExecute("INSERT INTO `elunaworld`.`apt_spawned` (`item_instance`, `gobject_guid`, `gobject_raw`, `gobject_entry`, `map`, `x`, `y`, `z`, `o`, `timestamp`, `owner_character`, `owner_account`,`owner_guid`) VALUES ('" ..item_guid.. "', '" ..nearestobject_guid.. "', '" ..nearestobject_raw.. "', '" ..APT_objects[item_entry].. "', '" ..map.. "', '" ..spell_x.. "', '" ..spell_y.. "', '" ..spell_z.. "', '" ..player:GetO().. "', '" ..tostring(GetGameTime()).. "', '" ..player:GetName().. "', '" ..player:GetAccountName().. "', '" ..player:GetGUIDLow().. "');")
|
||
|
|
dummy:DespawnOrUnsummon(0)
|
||
|
|
AwardAchievement(player, 65498)
|
||
|
|
return
|
||
|
|
else
|
||
|
|
-- delete APT if already spawned
|
||
|
|
-- local low_guid = GetGUIDLow( APT_Query3:GetInt32(2) )
|
||
|
|
-- print(low_guid)
|
||
|
|
-- print(APT_Query3:GetInt32(2))
|
||
|
|
-- local map = GetMapById(APT_Query3:GetInt32(3))
|
||
|
|
-- local build = GetObjectGUID(APT_Query3:GetInt32(2), APT_objects[item_entry])
|
||
|
|
-- print(build)
|
||
|
|
-- gameObjectsInRange = player:GetGameObjectsInRange( 100, APT_objects[item_entry] )
|
||
|
|
-- for x=1,#gameObjectsInRange,1 do
|
||
|
|
-- if gameObjectsInRange[x]:GetDBTableGUIDLow() == APT_Query3:GetInt32(1) then
|
||
|
|
-- print(gameObjectsInRange[x]:GetGUID())
|
||
|
|
-- print(gameObjectsInRange[x]:GetGUIDLow())
|
||
|
|
-- end
|
||
|
|
-- end
|
||
|
|
-- local object = map:GetWorldObject(build)
|
||
|
|
if APT_Query3:GetInt32(3) == player:GetMapId() then
|
||
|
|
local x, y, z, o = player:GetLocation()
|
||
|
|
local range = player:GetDistance2d(APT_Query3:GetInt32(4), APT_Query3:GetInt32(5)) + 10
|
||
|
|
-- print("searching range: " ..range)
|
||
|
|
local gameObjectsInRange = player:GetGameObjectsInRange( range, APT_objects[item_entry] )
|
||
|
|
-- print(APT_Query3:GetInt32(1))
|
||
|
|
-- print("game objects in range " ..#gameObjectsInRange)
|
||
|
|
for x=1,#gameObjectsInRange,1 do
|
||
|
|
if gameObjectsInRange[x]:GetDBTableGUIDLow() == APT_Query3:GetInt32(1) then
|
||
|
|
--- print(APT_Query3:GetInt32(1))
|
||
|
|
--- print(gameObjectsInRange[x]:GetGUID())
|
||
|
|
--- print(gameObjectsInRange[x]:GetGUIDLow())
|
||
|
|
object = gameObjectsInRange[x]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
else
|
||
|
|
player:SendBroadcastMessage("[APT System]: The APT you are trying to pick up is not on the same map as you.")
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
PrintInfo("[APT]: Player " .. player:GetName() .. " just deleted APT with itemID " .. item_guid .. ".")
|
||
|
|
object:RemoveFromWorld(true)
|
||
|
|
WorldDBExecute("DELETE FROM apt_spawned WHERE item_instance = " ..item_guid.. ";")
|
||
|
|
return
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function APT_CleanUp(eventId, delay, repeats)
|
||
|
|
local APT_CleanUp_Query2 = WorldDBQuery("SELECT gobject_guid, gobject_raw, map, `timestamp`, `gobject_entry` FROM apt_spawned;")
|
||
|
|
GamerTime = GetGameTime()
|
||
|
|
if (APT_CleanUp_Query2 == nil) then
|
||
|
|
return false
|
||
|
|
else
|
||
|
|
for x=1,APT_CleanUp_Query2:GetRowCount(),1 do
|
||
|
|
-- if gametime - time apt was placed is bigger than 3 days, then remove.
|
||
|
|
if (GamerTime - APT_CleanUp_Query2:GetInt32(3) > APT_TIME_EXPIRED) then
|
||
|
|
local map = GetMapById(APT_CleanUp_Query2:GetInt32(2))
|
||
|
|
local build = GetObjectGUID(APT_CleanUp_Query2:GetInt32(1), APT_CleanUp_Query2:GetInt32(4))
|
||
|
|
-- print(APT_CleanUp_Query2:GetInt32(1).. ":" ..APT_CleanUp_Query2:GetInt32(4))
|
||
|
|
local object = map:GetWorldObject(build)
|
||
|
|
object:RemoveFromWorld(true)
|
||
|
|
WorldDBExecute("DELETE FROM apt_spawned WHERE gobject_guid = " ..APT_CleanUp_Query2:GetInt32(0).. ";")
|
||
|
|
APT_CleanUp_Query2:NextRow()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
CreateLuaEvent(APT_CleanUp, APT_TIME_CHECK, 0) -- every half hour we check for APTs over expired time before deleting. 1800000
|
||
|
|
RegisterPlayerEvent(5, APT_Spell)
|
||
|
|
RegisterPlayerEvent(42, APT_ReloadEvents)
|
||
|
|
RegisterServerEvent(33, APTStartUp)
|