- Joined
- Nov 17, 2010
- Messages
- 6,832
- Solutions
- 586
- Reaction score
- 5,414
Dungeon System
-> Multiple players can access a dungeon at a time, however only 1 player per sub-area.
-> Each dungeon can have unlimited sub-areas. Each sub-area can hold 1 player.
->-> If all sub-areas are full, players wanting to join this dungeon will have to wait until it's empty.
-> Each dungeon has their own reward scheme. (item and experience)
-> -> This means that every sub-area in that dungeon will have the same reward.
-> Everytime a player completes a dungeon, they get the reward. (They can access the dungeon infinite times, and get infinite rewards.)
-> Each dungeon is governed by a single actionid.
-> -> It controls the sub-areas, creature kill counting, storage values, reward details.. everything.
Here's my fabulous paint skills showcasing what a Dungeon with 3 sub-area's might look like.
Note: Each sub-area can be whatever size / shape you want, with multiple floors.
-> Just make sure that top_left_corner & bot_right_corner have the appropriate locations.
-> Multiple players can access a dungeon at a time, however only 1 player per sub-area.
-> Each dungeon can have unlimited sub-areas. Each sub-area can hold 1 player.
->-> If all sub-areas are full, players wanting to join this dungeon will have to wait until it's empty.
-> Each dungeon has their own reward scheme. (item and experience)
-> -> This means that every sub-area in that dungeon will have the same reward.
-> Everytime a player completes a dungeon, they get the reward. (They can access the dungeon infinite times, and get infinite rewards.)
-> Each dungeon is governed by a single actionid.
-> -> It controls the sub-areas, creature kill counting, storage values, reward details.. everything.
Here's my fabulous paint skills showcasing what a Dungeon with 3 sub-area's might look like.
Note: Each sub-area can be whatever size / shape you want, with multiple floors.
-> Just make sure that top_left_corner & bot_right_corner have the appropriate locations.
Lua:
--[[
data/lib/000-constant.lua [place anywhere. (I suggest very top or very bottom)]
--]]
dungeon_system_config = {
---------------------------
-- 45001 is a single dungeon, with multiple area's.
-- since it is a single dungeon, the reward for all area's of this dungeon is the same.
-- if area 1 is occupied, then player teleports to area 2.
-- if area 2 is occupied, then it tries to goto area 3. if area 3 doesn't exist, player must wait for a dungeon to be empty.
-- you can create only 1 area per dungeon if you want, or you can create infinite area's. Just depends on what you add into the table.
[45001] = {
timeout = 600, -- seconds until they timeout and teleport out of dungeon
reward_itemid = 1111,
reward_amount = 1,
experience = 1000,
area_info = {
---> {0} -- this holds player data to check if dungeon is empty or not.
---> {} -- this holds monster data to check if monsters in dungeon have been killed.
{ {0}, {}, -- area 1 start
{ {x = 1111, y = 1111, z = 7}, -- teleport_in_pos (where player starts the dungeon from)
{x = 2222, y = 2222, z = 7}, -- top_left_corner
{x = 3333, y = 3333, z = 7} -- bot_right_corner
},
{ {"rat", {x = 1111, y = 1111, z = 7}},
{"rat", {x = 2222, y = 2222, z = 7}}, -- you can add as many or as little monsters as you desire.
{"rat", {x = 3333, y = 3333, z = 7}},
{"rat", {x = 4444, y = 4444, z = 7}}
}
}, -- area 1 end
{ {0}, {}, -- area 2 start
{ {x = 1111, y = 1111, z = 7}, -- teleport_in_pos
{x = 2222, y = 2222, z = 7}, -- top_left_corner
{x = 3333, y = 3333, z = 7} -- bot_right_corner
},
{ {"rat", {x = 1111, y = 1111, z = 7}},
{"rat", {x = 2222, y = 2222, z = 7}},
{"rat", {x = 3333, y = 3333, z = 7}},
{"rat", {x = 4444, y = 4444, z = 7}}
}
} -- area 2 end
}
},
---------------------------
[45002] = {
timeout = 600, -- seconds until they timeout and teleport out of dungeon
reward_itemid = 2222,
reward_amount = 1,
experience = 2000,
area_info = {
{ {0}, {}, -- area 1 start
{ {x = 1111, y = 1111, z = 7}, -- teleport_in_pos
{x = 2222, y = 2222, z = 7}, -- top_left_corner
{x = 3333, y = 3333, z = 7} -- bot_right_corner
},
{ {"rat", {x = 1111, y = 1111, z = 7}},
{"rat", {x = 2222, y = 2222, z = 7}},
{"rat", {x = 3333, y = 3333, z = 7}},
{"rat", {x = 4444, y = 4444, z = 7}}
}
}, -- area 1 end
{ {0}, {}, -- area 2 start
{ {x = 1111, y = 1111, z = 7}, -- teleport_in_pos
{x = 2222, y = 2222, z = 7}, -- top_left_corner
{x = 3333, y = 3333, z = 7} -- bot_right_corner
},
{ {"rat", {x = 1111, y = 1111, z = 7}},
{"rat", {x = 2222, y = 2222, z = 7}},
{"rat", {x = 3333, y = 3333, z = 7}},
{"rat", {x = 4444, y = 4444, z = 7}}
}
} -- area 2 end
}
}
---------------------------
}
Lua:
--[[
actions.xml
<action actionid="45001-45002" event="script" value="onUse_xikini_dungeon_system.lua"/>
--]]
-- simple reward script, using actionid and the global table.
function onUse(cid, item, fromPosition, itemEx, toPosition)
local action_ID = item.actionid
local reward = dungeon_system_config[action_ID]
if not reward then
doPlayerSendTextMessage(cid, MESSAGE_STATUS_WARNING, "LUA ERROR: Contact Administrator. Error code: Xikini_2") -- actionid on tile is incorrect or not in table.
return true
end
-- if storage == -1, then we know that all monsters are dead, and reward has been obtained.
-- if storage > 0 then monsters are still alive, since we count backwards to 0 monsters alive, when then allows the player to get their reward.
local cur_storage = getPlayerStorageValue(cid, action_ID)
if cur_storage == -1 then
doPlayerSendTextMessage(cid, MESSAGE_STATUS_WARNING, "You've already obtained the reward. Please enter the teleport to exit the dungeon.")
return true
elseif cur_storage > 0 then
doPlayerSendTextMessage(cid, MESSAGE_STATUS_WARNING, "There is still " .. cur_storage .. " monsters that need to be killed in this dungeon.")
return true
end
if getItemWeightById(reward.reward_itemid, reward.reward_amount) > getPlayerFreeCap(cid) then
doPlayerSendTextMessage(cid, MESSAGE_STATUS_WARNING, "You do not have enough capacity to obtain this reward.")
return true
end
if reward.experience > 0 then
doPlayerAddExperience(cid, reward.experience)
end
doPlayerAddItem(cid, reward.reward_itemid, reward.reward_amount, true)
setPlayerStorageValue(cid, action_ID, -1)
doPlayerSendTextMessage(cid, MESSAGE_STATUS_WARNING, "Congratulations! Enter the teleport to exit the dungeon.")
return true
end
Lua:
--[[
creaturescripts.xml
<event type="login" name="onLogin_xikini_dungeon_system" event="script" value="onLogin_xikini_dungeon_system.lua"/>
login.lua [near bottom with other registered events]
registerCreatureEvent(cid, "onLogin_xikini_dungeon_system")
--]]
-- if server shut down, player logged out, or player died in a dungeon.. reset the dungeon storage and teleport player to temple.
function onLogin(cid)
local teleport = 0
for v, k in pairs(dungeon_system_config) do
if getPlayerStorageValue(cid, v) ~= -1 then
teleport = 1
setPlayerStorageValue(cid, v, -1)
end
end
if teleport == 1 then
doTeleportThing(cid, getTownTemplePosition(getPlayerTown(cid)))
end
return true
end
Lua:
--[[
movements.xml
<movevent type="StepIn" actionid="45001-45002" event="script" value="onStepIn_xikini_dungeon_system.lua"/>
--]]
local function dungeon_system_updater(cid, storage, timer, index)
if not isCreature(cid) then
if cid == index[1][1] then
index[1][1] = 0 -- if player dies or logs out, reset player data to indicate dungeon is empty.
end
return true
end
-- checks if the player is still inside the dungeon (so if player has completed dungeon but not yet left the dungeon, we can continue timer until auto-kick)
local creature_pos = getPlayerPosition(cid)
if creature_pos.x >= index[3][2].x and creature_pos.x <= index[3][3].x and creature_pos.y >= index[3][2].y and creature_pos.y <= index[3][3].y and creature_pos.z >= index[3][2].z and creature_pos.z <= index[3][3].z then
else
if cid == index[1][1] then
index[1][1] = 0 -- if player leaves the dungeon, reset player data to indicate dungeon is empty.
end
return true
end
-- check if any monsters have died, and update player storage.
local new_count = -1
for i = #index[2], 1, -1 do
if not isCreature(index[2][i]) then
new_count = getPlayerStorageValue(cid, storage) - 1
setPlayerStorageValue(cid, storage, new_count)
table.remove(index[2], i)
end
end
-- tell player that monsters have died.
if new_count > 0 then
local monster_count = #index[4]
doPlayerSendTextMessage(cid, MESSAGE_STATUS_WARNING, "You have killed [" .. (monster_count - new_count) .. " / " .. monster_count .."]")
elseif new_count == 0 then
doPlayerSendTextMessage(cid, MESSAGE_STATUS_WARNING, "You have killed all the creatures in this dungeon. Go open the chest for your reward.")
end
-- timeout timer stuff
timer = timer + 0.5 -- timer counts every 0.5 seconds, to check if player has run out of time.
if timer < dungeon_system_config[storage].timeout then
addEvent(dungeon_system_updater, 500, cid, storage, timer, index)
else
doPlayerSendTextMessage(cid, MESSAGE_STATUS_WARNING, "Out of time! You've been removed from the Dungeon.")
doTeleportThing(cid, getTownTemplePosition(getPlayerTown(cid)))
setPlayerStorageValue(cid, storage, -1)
index[1][1] = 0
end
end
function onStepIn(cid, item, position, lastPosition, fromPosition, toPosition, actor)
local storage = item.actionid
local dungeon = dungeon_system_config[storage]
if not dungeon then
doPlayerSendTextMessage(cid, MESSAGE_STATUS_WARNING, "LUA ERROR: Contact Administrator. Error code: Xikini_1") -- actionid on tile is incorrect or not in table.
return true
end
dungeon = dungeon.area_info -- re-using local when possible, to make script cleaner
-- check if player is already in a dungeon, and teleport them out.
for i = 1, #dungeon do
if dungeon[i][1][1] == cid then
local cur_storage = getPlayerStorageValue(cid, storage)
if cur_storage == -1 then
doTeleportThing(cid, getTownTemplePosition(getPlayerTown(cid)))
doPlayerSendTextMessage(cid, MESSAGE_STATUS_WARNING, "Dungeon Completed Successfully.")
return true
else
if cur_storage == 0 then
doPlayerSendTextMessage(cid, MESSAGE_STATUS_WARNING, "You must collect your reward before exiting the dungeon.")
else
doPlayerSendTextMessage(cid, MESSAGE_STATUS_WARNING, "There is still " .. cur_storage .. " monsters that need to be killed in this dungeon.")
end
doTeleportThing(cid, fromPosition)
return true
end
end
end
-- find a dungeon that is empty.
local area = 0
for i = 1, #dungeon do
if not isCreature(dungeon[i][1][1]) then
area = i
break
end
local creature_pos = getPlayerPosition(dungeon[i][1][1])
if creature_pos.x >= dungeon[i][3][2].x and creature_pos.x <= dungeon[i][3][3].x and creature_pos.y >= dungeon[i][3][2].y and creature_pos.y <= dungeon[i][3][3].y and creature_pos.z >= dungeon[i][3][2].z and creature_pos.z <= dungeon[i][3][3].z then
else
area = i
break
end
end
-- if no dungeons empty
if area == 0 then
doPlayerSendTextMessage(cid, MESSAGE_STATUS_WARNING, "Sorry, no dungeons are empty. Try again later.")
doTeleportThing(cid, fromPosition)
return true
end
dungeon = dungeon[area]
dungeon[1][1] = cid -- hold player data for later checking if dungeon is empty
local monster_count = #dungeon[4]
setPlayerStorageValue(cid, storage, monster_count) -- player storage is set as max monsters, and count down to 0 later.
-- remove any monsters that are still alive in dungeon. (if a player died in the dungeon or timed out)
for i = #dungeon[2], 1, -1 do
if isCreature(dungeon[2][i]) then
doRemoveCreature(dungeon[2][i])
end
end
dungeon[2] = {}
-- add all monsters into the dungeon, and store creatureids in table.
for i = 1, monster_count do
local monster = doCreateMonster(dungeon[4][i][1], dungeon[4][i][2])
table.insert(dungeon[2], monster)
end
-- addEvent for timer and creature death tracking.
addEvent(dungeon_system_updater, 500, cid, storage, 0, dungeon)
doTeleportThing(cid, dungeon[3][1])
return true
end
Last edited: