- Joined
- Apr 1, 2012
- Messages
- 1,249
- Solutions
- 71
- Reaction score
- 621
- Location
- Hell
- GitHub
- idontreallywolf
How can I find the amount of a specific monster in a specific area?
Game.getSpectators
Will find any alive creatures in the configured area around specified position.
The map spawn.xml file should contain information about spawns:
forgottenserver/data/world/forgotten-spawn.xml at master · otland/forgottenserver
A free and open-source MMORPG server emulator written in C++ - otland/forgottenservergithub.com
Which you could do some math on to figure out nearly creatures of a given position.
Edit:
Ohh, 0.4. :/ Sorry, didnt knew we were back in 2009. Just look for the 0.4 equivalent of getspectators, see if it grabs creatures as well, or if you can configure it to do so.
5x5
function countMonster(name, startPos, endPos)
local counter = 0
for i = startPos.y, endPos.y, 1 do
for j = startPos.x, endPos.x, 1 do
local topMonster = getTopCreature({x = j, y = i, z = 7}).uid
if(isMonster(topMonster) and getCreatureName(topMonster) == name) then
counter = counter + 1
end
end
end
return counter
end
function getCreatures(fromPos, toPos)
-- No matter what corner from and to is, we want to make
-- life easier by calculating north-west and south-east (before we start looping)
local zone = {
northWest = {
x = (fromPos.x < toPos.x and fromPos.x or toPos.x),
y = (fromPos.y < toPos.y and fromPos.y or toPos.y),
z = (fromPos.z < toPos.z and fromPos.z or toPos.z)
},
southEast = {
x = (toPos.x > fromPos.x and toPos.x or fromPos.x),
y = (toPos.y > fromPos.y and toPos.y or fromPos.y),
z = (toPos.z > fromPos.z and toPos.z or fromPos.z)
}
}
-- data to be returned once populated
local data = {
count = {
creatures = 0,
monsters = 0,
players = 0,
npcs = 0
},
keys = {
monsters = {},
players = {},
npcs = {}
},
creatures = {}
}
-- scan area and populate the data table above
local i = 1
for pz = zone.northWest.z, zone.southEast.z, 1 do
for py = zone.northWest.y, zone.southEast.y, 1 do
for px = zone.northWest.x, zone.southEast.x, 1 do
local creature = getTopCreature({x = px, y = py, z = pz}).uid
if creature then
data.count.creatures = data.count.creatures + 1
data.creatures[i] = creature
if isMonster(creature) then
data.count.monsters = data.count.monsters + 1
data.keys.monsters[#data.keys.monsters+1] = i
elseif isPlayer(creature) then
data.count.creatures = data.count.creatures + 1
data.keys.players[#data.keys.players+1] = i
else -- its an NPC
data.count.npcs = data.count.npcs + 1
data.keys.npcs[#data.keys.npcs+1] = i
end
i = i + 1 -- Increment key index of creature
end
end
end
end
return data
end
local fromPos = {x = 95 , y = 95 , z = 6} -- doesn't have to be lowest values
local toPos = {x = 105, y = 105, z = 8} -- doesn't have to be highest values
local data = getCreatures(fromPos, toPos)
print("Found ".. data.count.players .." players between ["..fromPos.x..","..fromPos.y..","..fromPos.z.."] and ["..toPos.x..","..toPos.y..","..toPos.z.."]")
if data.count.players > 0 then
for i, key in pairs(data.keys.players) do
local cid = data.creatures[key]
local pos = getCreaturePosition(cid)
print(i..": Found player: "..getCreatureName(cid).." at position: ["..pos.x..","..pos.y..","..pos.z.."].")
end
end
function getCreatures(centerPos, x, y, multifloor)
local data = {
monsters = {},
players = {},
npcs = {},
creatures = getSpectators(centerPos, x, y, multifloor)
}
for _, creature_id in ipairs(data.creatures) do
if isMonster(creature_id) then
data.monsters[#data.monsters + 1] = creature_id
elseif isPlayer(creature_id) then
data.players[#data.players + 1] = creature_id
elseif isNpc(creature_id) then
data.npcs[#data.npcs + 1] = creature_id
end
end
return data
end
-- Get all creature data within a 10x10 square from center position
local area_data = getCreatures({x = 1000, y = 1000, z = 7}, 10, 10, false)
print(#area_data.monsters) -- Prints the amount of monsters in that area
@Snavy Nice, but you forgot to loop through z. You might wanna use that function for something else than groun floor (z = 7).
Had some fun and made a more "generic" multi-purpose getCreatures function based on your code:
Lua:function getCreatures(fromPos, toPos) -- No matter what corner from and to is, we want to make -- life easier by calculating north-west and south-east (before we start looping) local zone = { northWest = { x = (fromPos.x < toPos.x and fromPos.x or toPos.x), y = (fromPos.y < toPos.y and fromPos.y or toPos.y), z = (fromPos.z < toPos.z and fromPos.z or toPos.z) }, southEast = { x = (toPos.x > fromPos.x and toPos.x or fromPos.x), y = (toPos.y > fromPos.y and toPos.y or fromPos.y), z = (toPos.z > fromPos.z and toPos.z or fromPos.z) } } -- data to be returned once populated local data = { count = { creatures = 0, monsters = 0, players = 0, npcs = 0 }, keys = { monsters = {}, players = {}, npcs = {} }, creatures = {} } -- scan area and populate the data table above local i = 1 for pz = zone.northWest.z, zone.southEast.z, 1 do for py = zone.northWest.y, zone.southEast.y, 1 do for px = zone.northWest.x, zone.southEast.x, 1 do local creature = getTopCreature({x = px, y = py, z = pz}).uid if creature then data.count.creatures = data.count.creatures + 1 data.creatures[i] = creature if isMonster(creature) then data.count.monsters = data.count.monsters + 1 data.keys.monsters[#data.keys.monsters+1] = i elseif isPlayer(creature) then data.count.creatures = data.count.creatures + 1 data.keys.players[#data.keys.players+1] = i else -- its an NPC data.count.npcs = data.count.npcs + 1 data.keys.npcs[#data.keys.npcs+1] = i end i = i + 1 -- Increment key index of creature end end end end return data end
Returns the populated version of the data table initialized in the start of the function. Counts creatures, which of them are monsters, players, npcs. Return a creature table with all the cids incase you want to do something else with them. As well as filter/index tables. (the keys tables) which you can look to specifically grab the group you are interested in.
Etc loop through all players in a 5x5x3 area:
Lua:local fromPos = {x = 95 , y = 95 , z = 6} -- doesn't have to be lowest values local toPos = {x = 105, y = 105, z = 8} -- doesn't have to be highest values local data = getCreatures(fromPos, toPos) print("Found ".. data.count.players .." players between ["..fromPos.x..","..fromPos.y..","..fromPos.z.."] and ["..toPos.x..","..toPos.y..","..toPos.z.."]") if data.count.players > 0 then for i, key in pairs(data.keys.players) do local cid = data.creatures[key] local pos = getCreaturePosition(cid) print(i..": Found player: "..getCreatureName(cid).." at position: ["..pos.x..","..pos.y..","..pos.z.."].") end end
Could be done much simpler using getSpectators which actually gets every creature in the case they are stacked
Lua:function getCreatures(centerPos, x, y, multifloor) local data = { monsters = {}, players = {}, npcs = {}, creatures = getSpectators(centerPos, x, y, multifloor) } for _, creature_id in ipairs(data.creatures) do if isMonster(creature_id) then data.monsters[#data.monsters + 1] = creature_id elseif isPlayer(creature_id) then data.players[#data.players + 1] = creature_id elseif isNpc(creature_id) then data.npcs[#data.npcs + 1] = creature_id end end return data end -- Get all creature data within a 10x10 square from center position local area_data = getCreatures({x = 1000, y = 1000, z = 7}, 10, 10, false) print(#area_data.monsters) -- Prints the amount of monsters in that area
Yes 0.4 has getSpectators and works the exact same as 1.X does, it gets all creatures in a specified range starting from a center position.Does TFS 0.4 have getSpectators? and does it work the same way as in newer tfs's?