Files
m2dev-server/share/locale/english/quest/snow_dungeon.quest
2026-01-18 09:01:11 +02:00

1341 lines
43 KiB
Plaintext

define DUNGEON_MAN 20397
define ENTRY_MAN 20395
define DUNGEON_MAP_INDEX 352
define ENTER_LIMIT_TIME 240
define ENTRY_MAP_INDEX 61
define FINAL_BOSS 6191
define LEVEL2_REALKEY 30331
define LEVEL2_STONE 20386
define LEVEL4_TARGET_GROUP 6062
define LEVEL5_REALKEY 30332
define LEVEL5_STONE 20398
define LEVEL5_GEN_LIMIT 100
define LEVEL6_TARGET 8058
define LEVEL7_BOSSMOB 6151
define LEVEL8_REALKEY 30333
define LEVEL8_STONE 20386
define LEVEL9_TARGET 20399
define MOB_REGEN_FILE_PATH = "data/dungeon/snow_dungeon/"
define PASS_TICKET 71095
define HOSIN_BUFF 94
define GICHEON_BUFF 96
quest snow_dungeon begin
state start begin
function setting()
return
{
["dungeon_entry_pos"] = { 5291, 1814 },
["DUNGEON_MAN_pos"] = { 172, 261 },
["WARP_pos"] = {
{ 5291, 1814 },
{ 5540, 1797 },
{ 5882, 1800 },
{ 5293, 2071 },
{ 5540, 2074 },
{ 5866, 2076 },
{ 5423, 2244 },
{ 5689, 2237 },
{ 5969, 2229 },
{ 6047, 1924 }
},
["LEVEL2_STONE_pos"] = { 421, 191 },
["LEVEL4_TARGET_pos"] = { 171, 496 },
["LEVEL5_STONE_pos"] = {
{ 449, 488 },
{ 455, 445 },
{ 419, 422 },
{ 382, 444 },
{ 389, 488 }
},
["LEVEL6_TARGET_pos"] = { 747, 494 },
["LEVEL7_BOSSMOB_pos"] = {
{ 302, 678 },
{ 281, 657 },
{ 303, 635 },
{ 324, 656 }
},
["LEVEL8_STONE_pos"] = {
{ 570, 650 }
},
["LEVEL9_TARGET_pos"] = {
{ 849, 660 }
},
["boss_pos"] = { 927, 333 },
["outside_entry_pos"] = { 4322, 1655 }
}
end
function make_dungeon()
local setting = snow_dungeon.setting()
d.new_jump_party(DUNGEON_MAP_INDEX, setting.dungeon_entry_pos[1], setting.dungeon_entry_pos[2])
d.set_item_group("fd_pass_ticket", 1, PASS_TICKET, 1)
d.spawn_mob_ac_dir(DUNGEON_MAN, setting.DUNGEON_MAN_pos[1], setting.DUNGEON_MAN_pos[2], 1)
d.setf("tickets_consumed", 0)
end
function start_dungeon_at_stage(stage)
local setting = snow_dungeon.setting()
local map_idx = 0
if party.is_party() then
map_idx = party.getf("dungeon_index")
end
-- Create dungeon if needed
if map_idx == 0 or not d.find(map_idx) then
-- Create dungeon and jump to appropriate position based on stage
local warp_x = setting.dungeon_entry_pos[1]
local warp_y = setting.dungeon_entry_pos[2]
if stage > 1 then
warp_x = setting.WARP_pos[stage][1]
warp_y = setting.WARP_pos[stage][2]
end
d.new_jump_party(DUNGEON_MAP_INDEX, warp_x, warp_y)
d.set_item_group("fd_pass_ticket", 1, PASS_TICKET, 1)
if stage == 1 then
d.spawn_mob_ac_dir(DUNGEON_MAN, setting.DUNGEON_MAN_pos[1], setting.DUNGEON_MAN_pos[2], 1)
end
d.setf("tickets_consumed", 0)
map_idx = d.get_map_index()
notice("DEBUG: Created dungeon at map_idx " .. map_idx)
if party.is_party() then
party.setf("dungeon_index", map_idx)
end
else
notice("DEBUG: Using existing dungeon at map_idx " .. map_idx)
end
if not d.select(map_idx) then
notice("DEBUG: d.select failed for map_idx " .. map_idx)
return
end
notice("DEBUG: Selected map_idx " .. map_idx .. ", setting stage to " .. stage)
snow_dungeon.clear_timer(map_idx)
local s = stage
if s < 1 then
s = 1
elseif s > 10 then
s = 10
end
-- Stage 1: Don't auto-start, wait for DUNGEON_MAN chat
if s == 1 then
d.setf("level", 0)
d.jump_all(setting.WARP_pos[1][1], setting.WARP_pos[1][2])
-- Stages 2-10: Auto-start with proper setup
else
d.setf("dungeon_enter", 1)
d.setf("dungeon_start_time", get_global_time())
d.setf("party_leader_pid", party.is_party() and party.get_leader_pid() or 0)
if d.getf("tickets_consumed") == 0 then
d.delete_item_in_item_group_from_all("fd_pass_ticket")
d.setqf2("snow_dungeon", "ticket_delete", 1)
d.setf("tickets_consumed", 1)
end
d.setf("level4_boss_gen", 0)
d.setf("stonekill", 0)
d.setf("level8_clear", 0)
d.say_diff_by_item_group("fd_pass_ticket", gameforge.snow_dungeon._070_say, gameforge.snow_dungeon._080_say)
server_timer("snow_dungeon_30m_left_timer", 15 * 60, map_idx)
server_timer("snow_dungeon_45m_left_timer", 15 * 60, map_idx)
if s == 2 then
d.setf("level", 2)
d.jump_all(setting.WARP_pos[2][1], setting.WARP_pos[2][2])
d.set_regen_file(MOB_REGEN_FILE_PATH .. "id_2f.txt")
notice_multiline(gameforge.snow_dungeon._220_notice, d.notice)
elseif s == 3 then
d.setf("level", 3)
d.jump_all(setting.WARP_pos[3][1], setting.WARP_pos[3][2])
d.regen_file(MOB_REGEN_FILE_PATH .. "id_3f.txt")
server_timer("snow_dungeon_killed_A_1", 6, map_idx)
notice_multiline(gameforge.snow_dungeon._260_notice, d.notice)
elseif s == 4 then
d.setf("level", 4)
d.jump_all(setting.WARP_pos[4][1], setting.WARP_pos[4][2])
d.regen_file(MOB_REGEN_FILE_PATH .. "id_4f.txt")
d.setf("level4_boss_gen", 0)
server_timer("snow_dungeon_killed_A_1", 6, map_idx)
notice_multiline(gameforge.snow_dungeon._270_notice, d.notice)
elseif s == 5 then
d.setf("level", 5)
d.jump_all(setting.WARP_pos[5][1], setting.WARP_pos[5][2])
d.set_regen_file(MOB_REGEN_FILE_PATH .. "id_5f.txt")
notice_multiline(gameforge.snow_dungeon._280_notice, d.notice)
notice_multiline(gameforge.snow_dungeon._290_notice, d.notice)
local vis = { 0, 0, 0, 0, 0 }
for i = 1, 5 do
local ran = number(1, 5)
local st = 0
for j = 1, 50 do
st = st + 1
if st > 5 then
st = 1
end
if vis[st] == 0 then
ran = ran - 1
if ran == 0 then
vis[st] = 1
d.set_unique("stone5_" .. st, d.spawn_mob(LEVEL5_STONE, setting.LEVEL5_STONE_pos[i][1], setting.LEVEL5_STONE_pos[i][2]))
break
end
end
end
end
elseif s == 6 then
d.setf("level", 6)
d.jump_all(setting.WARP_pos[6][1], setting.WARP_pos[6][2])
d.regen_file(MOB_REGEN_FILE_PATH .. "id_6f.txt")
d.set_unique("stage6_npc", d.spawn_mob(20379, 747, 517))
server_timer("snow_dungeon_stage6_npc_guard", 10, map_idx)
server_timer("snow_dungeon_killed_A_1", 6, map_idx)
notice_multiline(gameforge.snow_dungeon._360_notice, d.notice)
elseif s == 7 then
d.setf("level", 7)
d.jump_all(setting.WARP_pos[7][1], setting.WARP_pos[7][2])
d.set_regen_file(MOB_REGEN_FILE_PATH .. "id_7f.txt")
notice_multiline(gameforge.snow_dungeon._380_notice, d.notice)
notice_multiline(gameforge.snow_dungeon._390_notice, d.notice)
local vis = { 0, 0, 0, 0 }
for i = 1, 3 do
vis[i] = 0
end
for i = 1, 4 do
local ran = number(1, 4)
local st = 0
for j = 1, 50 do
st = st + 1
if st > 4 then
st = 1
end
if vis[st] == 0 then
ran = ran - 1
if ran == 0 then
vis[st] = 1
d.set_unique("boss7_" .. st, d.spawn_mob(LEVEL7_BOSSMOB, setting.LEVEL7_BOSSMOB_pos[i][1], setting.LEVEL7_BOSSMOB_pos[i][2]))
break
end
end
end
end
for i = 1, 4 do
local vid = d.get_unique_vid('boss7_' .. i)
if vid ~= 0 then
npc.set_damage_immunity_with_conditions(vid, {{ type = 0, value = GICHEON_BUFF }})
end
end
server_timer("snow_dungeon_killed_B_1", 6, map_idx)
elseif s == 8 then
d.setf("level", 8)
d.jump_all(setting.WARP_pos[8][1], setting.WARP_pos[8][2])
d.set_regen_file(MOB_REGEN_FILE_PATH .. "id_8f.txt")
notice_multiline(gameforge.snow_dungeon._420_notice, d.notice)
elseif s == 9 then
d.setf("level", 9)
d.jump_all(setting.WARP_pos[9][1], setting.WARP_pos[9][2])
d.set_regen_file(MOB_REGEN_FILE_PATH .. "id_9f.txt")
d.spawn_mob_with_immunity(LEVEL9_TARGET, setting.LEVEL9_TARGET_pos[1][1], setting.LEVEL9_TARGET_pos[1][2], {{ type = 6, value = 1 }, { type = 6, value = 3 }})
notice_multiline(gameforge.snow_dungeon._450_notice, d.notice)
else
d.setf("level", 10)
d.jump_all(setting.WARP_pos[10][1], setting.WARP_pos[10][2])
d.set_regen_file(MOB_REGEN_FILE_PATH .. "id_boss.txt")
d.spawn_mob(FINAL_BOSS, setting.boss_pos[1], setting.boss_pos[2])
notice_multiline(gameforge.snow_dungeon._490_notice, d.notice)
end
end
end
function clear_timer(inx)
clear_server_timer("snow_dungeon_ticket_remove", inx)
clear_server_timer("snow_dungeon_0m_left_timer", inx)
clear_server_timer("snow_dungeon_1m_left_timer", inx)
clear_server_timer("snow_dungeon_5m_left_timer", inx)
clear_server_timer("snow_dungeon_10m_left_timer", inx)
clear_server_timer("snow_dungeon_15m_left_timer", inx)
clear_server_timer("snow_dungeon_30m_left_timer", inx)
clear_server_timer("snow_dungeon_45m_left_timer", inx)
clear_server_timer("snow_dungeon_end_timer", inx)
clear_server_timer("snow_dungeon_level2_start", inx)
clear_server_timer("snow_dungeon_level3_start", inx)
clear_server_timer("snow_dungeon_level4_start", inx)
clear_server_timer("snow_dungeon_level5_start", inx)
clear_server_timer("snow_dungeon_level6_start", inx)
clear_server_timer("snow_dungeon_level7_start", inx)
clear_server_timer("snow_dungeon_level8_start", inx)
clear_server_timer("snow_dungeon_level9_start", inx)
clear_server_timer("snow_dungeon_killed_A_1", inx)
clear_server_timer("snow_dungeon_killed_A_2", inx)
clear_server_timer("snow_dungeon_killed_B_1", inx)
clear_server_timer("snow_dungeon_killed_B_2", inx)
clear_server_timer("snow_dungeon_leader_out_timer", inx)
end
function is_snowd(idx)
return idx >= DUNGEON_MAP_INDEX * 10000 and idx < (DUNGEON_MAP_INDEX + 1) * 10000
end
function level_clear()
d.clear_regen()
d.purge_area(520000, 155000, 612000, 228600)
end
when login begin
local idx = pc.get_map_index()
local setting = snow_dungeon.setting()
if idx == DUNGEON_MAP_INDEX then
timer("snow_dungeon_warp_timer", 5)
elseif snow_dungeon.is_snowd(idx) then
pc.set_warp_location(ENTRY_MAP_INDEX, setting.outside_entry_pos[1] , setting.outside_entry_pos[2])
if d.getf("dungeon_enter") == 0 then
if get_global_time() - pc.getf("snow_dungeon", "exit_time") < ENTER_LIMIT_TIME * 60 then
notice_multiline(gameforge.snow_dungeon._010_notice, d.notice)
say(gameforge.snow_dungeon._020_say)
timer("snow_dungeon_warp_timer", 5)
elseif pc.count_item(PASS_TICKET) < 1 then
notice_multiline(gameforge.snow_dungeon._030_notice, d.notice)
say(gameforge.snow_dungeon._040_say)
timer("snow_dungeon_warp_timer", 5)
elseif pc.get_level() < 100 then
notice_multiline(string.format(gameforge.snow_dungeon._050_notice, 100), d.notice)
say(string.format(gameforge.snow_dungeon._060_say, 100))
timer("snow_dungeon_warp_timer", 5)
end
else
-- Clear leader timeout if they're back
if party.is_party() and party.is_leader() then
clear_server_timer("snow_dungeon_leader_out_timer", idx)
end
end
end
end
when logout begin
local idx = pc.get_map_index()
if snow_dungeon.is_snowd(idx) then
if d.getf("dungeon_enter") == 1 then
pc.setf("snow_dungeon", "exit_time", get_global_time())
end
if party.is_leader() then
server_timer("snow_dungeon_leader_out_timer", 5 * 60, d.get_map_index())
end
end
end
when snow_dungeon_warp_timer.timer begin
local setting = snow_dungeon.setting()
pc.warp(setting.outside_entry_pos[1] * 100, setting.outside_entry_pos[2] * 100, ENTRY_MAP_INDEX)
end
when DUNGEON_MAN.chat.gameforge.snow_dungeon._590_npcChat with pc.get_map_index() >= DUNGEON_MAP_INDEX * 10000 and pc.get_map_index() < (DUNGEON_MAP_INDEX + 1) * 10000 and d.getf("level") == 0 begin
if party.is_leader() then
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "STARTED")
d.setf("level", 1)
d.regen_file(MOB_REGEN_FILE_PATH .. "id_1f.txt")
-- Consume the initial entry ticket for everyone inside right when the run starts
if d.getf("tickets_consumed") == 0 then
d.delete_item_in_item_group_from_all("fd_pass_ticket")
d.setqf2("snow_dungeon", "ticket_delete", 1)
d.setf("tickets_consumed", 1)
end
server_timer("snow_dungeon_30m_left_timer", 15 * 60, get_server_timer_arg())
server_timer("snow_dungeon_killed_A_1", 6, d.get_map_index())
server_timer("snow_dungeon_45m_left_timer", 15 * 60, d.get_map_index())
d.say_diff_by_item_group("fd_pass_ticket", gameforge.snow_dungeon._070_say, gameforge.snow_dungeon._080_say)
server_timer("snow_dungeon_ticket_remove", 5, d.get_map_index())
party.setf("dungeon_index", d.get_map_index())
d.setf("party_leader_pid", party.get_leader_pid())
else
say(gameforge.snow_dungeon._090_say)
end
end
when snow_dungeon_ticket_remove.server_timer begin
if d.select(get_server_timer_arg()) then
-- Fallback cleanup in case the start NPC path did not consume tickets
if d.getf("tickets_consumed") == 0 then
d.exit_all_by_item_group("fd_pass_ticket")
d.delete_item_in_item_group_from_all("fd_pass_ticket")
d.setqf2("snow_dungeon", "ticket_delete", 1)
d.setf("tickets_consumed", 1)
end
d.setf("dungeon_enter", 1)
d.setf("dungeon_start_time", get_global_time())
notice_multiline(gameforge.snow_dungeon._120_notice, d.notice)
end
end
when ENTRY_MAN.chat."GM: Reset timers" with pc.is_gm() begin
-- GM-only quick reset option
say_title(mob_name(ENTRY_MAN) .. ": ")
say("Reset timers for Nemere Watchtower?")
local gm_sel = select("Reset", "Cancel")
if gm_sel == 1 then
if party.is_party() then
local map_idx = party.getf("dungeon_index")
if d.find(map_idx) then
-- Clear all dungeon timers for this party instance
snow_dungeon.clear_timer(map_idx)
if d.select(map_idx) then
-- Reset dungeon flags to idle
d.setf("level", 0)
d.setf("dungeon_enter", 0)
-- Unset tracked leader if any
d.setf("party_leader_pid", 0)
end
end
-- Reset per-player flags for all party members
local pids = { party.get_member_pids() }
for i = 1, table.getn(pids) do
q.begin_other_pc_block(pids[i])
pc.setf("snow_dungeon", "ticket_delete", 0)
pc.setf("snow_dungeon", "exit_time", 0)
q.end_other_pc_block()
end
-- Clear party reference to existing dungeon
party.setf("dungeon_index", 0)
say_title(mob_name(ENTRY_MAN) .. ": ")
say("Party dungeon state has been reset by GM.")
else
-- Solo GM reset
pc.setf("snow_dungeon", "ticket_delete", 0)
pc.setf("snow_dungeon", "exit_time", 0)
say_title(mob_name(ENTRY_MAN) .. ": ")
say("Your dungeon state has been reset.")
end
end
end
when ENTRY_MAN.chat."GM: Start at stage" with pc.is_gm() begin
say_title(mob_name(ENTRY_MAN) .. ": ")
say("Select stage to start:")
local sel = select(
"1. Clear room",
"2. Frost Keys",
"3. Clear room",
"4. Dual-wave (Blessing)",
"5. Arctic Cubes",
"6. Metin of Cold (Shaman)",
"7. Szel (Dragon's Aid)",
"8. Frostflower Key",
"9. Pillar (Ninja/Shaman)",
"10. Nemere",
"Cancel"
)
if sel >= 1 and sel <= 10 then
snow_dungeon.start_dungeon_at_stage(sel)
end
end
when ENTRY_MAN.chat.gameforge.snow_dungeon._100_npcChat with pc.get_map_index() == ENTRY_MAP_INDEX begin
local setting = snow_dungeon.setting()
-- Try to find the dungeon instance player belongs to
local dungeon_map_idx = 0
local is_valid_dungeon = false
-- Check if player is in party and party has a dungeon
if party.is_party() then
dungeon_map_idx = party.getf("dungeon_index")
if dungeon_map_idx > 0 and d.find(dungeon_map_idx) then
-- Verify this is the same party that created the dungeon
if d.getf_from_map_index("party_leader_pid", dungeon_map_idx) == party.get_leader_pid() then
is_valid_dungeon = true
end
end
end
-- If no valid party dungeon, check if player has solo re-entry eligibility
if not is_valid_dungeon and pc.getf("snow_dungeon", "initial_entry") == 1 then
-- Player was in a dungeon previously, try to find it
for test_idx = DUNGEON_MAP_INDEX * 10000, (DUNGEON_MAP_INDEX + 1) * 10000 - 1 do
if d.find(test_idx) and d.getf_from_map_index("dungeon_enter", test_idx) == 1 then
-- Found active dungeon, allow re-entry
dungeon_map_idx = test_idx
is_valid_dungeon = true
break
end
end
end
-- Handle re-entry into active dungeon
if is_valid_dungeon and dungeon_map_idx > 0 then
local map_idx = dungeon_map_idx
local current_time = get_global_time()
local dungeon_enter = d.getf_from_map_index("dungeon_enter", map_idx)
local dungeon_start_time = d.getf_from_map_index("dungeon_start_time", map_idx)
-- Dungeon has been started; check 5-minute windows
if dungeon_enter == 1 then
-- True re-entry requires both ticket consumed AND having actually entered before
local is_reentry = pc.getf("snow_dungeon", "ticket_delete") == 1 and pc.getf("snow_dungeon", "initial_entry") == 1
local allow = false
if pc.get_level() < 100 then
say_title(mob_name(ENTRY_MAN) .. ": ")
say(string.format(gameforge.snow_dungeon._050_notice, 100))
return
elseif pc.is_riding() then
say_title(mob_name(ENTRY_MAN) .. ": ")
say(gameforge.snow_dungeon._620_say)
return
elseif is_reentry then
-- Per-player re-entry window from last exit
if current_time - pc.getf("snow_dungeon", "exit_time") < 5 * 60 then
allow = true
end
else
-- Late entry window from dungeon start; requires ticket
if current_time - dungeon_start_time < 5 * 60 then
if pc.count_item(PASS_TICKET) < 1 then
say_title(mob_name(ENTRY_MAN) .. ": ")
say(gameforge.snow_dungeon._040_say)
return
else
allow = true
end
end
end
if allow then
local dungeon_level = d.getf_from_map_index("level", map_idx)
if dungeon_level == 0 then
dungeon_level = 1
end
-- Consume ticket for late entries right here (before warp)
-- Re-entries already have ticket_delete = 1 from their initial entry
if not is_reentry and pc.getf("snow_dungeon", "ticket_delete") == 0 then
pc.remove_item(PASS_TICKET, 1)
pc.setf("snow_dungeon", "ticket_delete", 1)
end
-- Count player back into the instance if not already counted
if pc.getf("snow_dungeon", "counted") == 0 then
if d.find(map_idx) and d.select(map_idx) then
d.setf("party_member_count", d.getf("party_member_count") + 1)
pc.setf("snow_dungeon", "counted", 1)
end
end
-- Mark as having entered if this is first time
if pc.getf("snow_dungeon", "initial_entry") == 0 then
pc.setqf("snow_dungeon", "initial_entry", 1)
end
pc.warp(setting.WARP_pos[dungeon_level][1] * 100, setting.WARP_pos[dungeon_level][2] * 100, map_idx)
else
say_title(mob_name(ENTRY_MAN) .. ": ")
say(gameforge.snow_dungeon._110_say)
return
end
elseif dungeon_enter == 0 and party.is_party() and party.is_leader() then
-- Dungeon not started yet, only party leader can request entry
local dungeon_level = d.getf_from_map_index("level", map_idx)
if dungeon_level == 0 then
dungeon_level = 1
end
pc.warp(setting.WARP_pos[dungeon_level][1] * 100, setting.WARP_pos[dungeon_level][2] * 100, map_idx)
elseif dungeon_enter == 0 then
-- Dungeon not started and player not leader
say_title(mob_name(ENTRY_MAN) .. ": ")
say(gameforge.snow_dungeon._160_say)
return
else
-- Re-entry/late entry window expired
say_title(mob_name(ENTRY_MAN) .. ": ")
say(gameforge.snow_dungeon._110_say)
return
end
-- Handle initial dungeon creation (only for party leaders)
elseif party.is_party() then
if party.is_leader() then
-- Check all party members have passage tickets
local pids = { party.get_member_pids() }
-- Check all party members are level 100+
local min_level = party.get_near_count(pc.get_level(), 0, 1000000)
local total_members = party.get_near_count(1, 0, 1000000)
if party.get_near_count(100, 0, 1000000) < total_members then
say_title(mob_name(ENTRY_MAN) .. ": ")
say(string.format(gameforge.snow_dungeon._050_notice, 100))
return
end
if pc.is_riding() then
say_title(mob_name(ENTRY_MAN) .. ": ")
say(gameforge.snow_dungeon._620_say)
return
end
-- Check for ninja and shaman in party (no nested other_pc_block)
local has_ninja = false
local has_shaman = false
for i = 1, table.getn(pids) do
q.begin_other_pc_block(pids[i])
local job = pc.get_job()
if job == 1 then
has_ninja = true
end
if job == 3 and pc.get_skill_group() == 1 then
has_shaman = true
end
q.end_other_pc_block()
end
if not has_ninja or not has_shaman then
say_title(mob_name(ENTRY_MAN) .. ": ")
say(gameforge.snow_dungeon._170_say)
return
end
say_title(mob_name(ENTRY_MAN) .. ": ")
say(gameforge.snow_dungeon._130_say)
local warp = select(gameforge.snow_dungeon._140_select, gameforge.snow_dungeon._150_select)
if warp == 1 then
local members_without_ticket = {}
local members_riding = {}
for i = 1, table.getn(pids) do
q.begin_other_pc_block(pids[i])
if pc.is_riding() then
table.insert(members_riding, pc.get_name())
end
if pc.count_item(PASS_TICKET) < 1 then
table.insert(members_without_ticket, pc.get_name())
end
q.end_other_pc_block()
end
if table.getn(members_riding) > 0 then
say_title(mob_name(ENTRY_MAN) .. ": ")
say(gameforge.snow_dungeon._630_say)
return
elseif table.getn(members_without_ticket) > 0 then
say_title(mob_name(ENTRY_MAN) .. ": ")
say(gameforge.snow_dungeon._610_notice)
say("")
for i = 1, table.getn(members_without_ticket) do
say(string.format(" - %s", members_without_ticket[i]))
end
say("")
elseif party.is_map_member_flag_lt("exit_time", get_global_time() - ENTER_LIMIT_TIME * 60) then
party.setf("snow_dungeon_boss_kill_count", 0)
snow_dungeon.make_dungeon()
else
say_title(mob_name(ENTRY_MAN) .. ": ")
say(gameforge.snow_dungeon._600_say)
end
end
else
say_title(mob_name(ENTRY_MAN) .. ": ")
say(gameforge.snow_dungeon._160_say)
end
else
say_title(mob_name(ENTRY_MAN) .. ": ")
say(gameforge.snow_dungeon._170_say)
end
end
when snow_dungeon_killed_A_1.server_timer begin
if d.select(get_server_timer_arg()) then
local setting = snow_dungeon.setting()
if d.count_monster() <= 0 then
if d.getf("level") == 1 then
notice_multiline(gameforge.snow_dungeon._180_notice, d.notice)
server_timer("snow_dungeon_level2_start", 10, d.get_map_index())
elseif d.getf("level") == 3 then
notice_multiline(gameforge.snow_dungeon._190_notice, d.notice)
server_timer("snow_dungeon_level4_start", 10, d.get_map_index())
elseif d.getf("level") == 4 then
if d.getf("level4_boss_gen") == 0 then
-- First clear: trigger second wave with boss group 6062 that requires Hosin buff to break immunity
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "LEVEL4 second wave (boss) STARTED")
d.setf("level4_boss_gen", 1)
-- Spawn boss group with Hosin-only immunity
d.spawn_group_with_immunity(LEVEL4_TARGET_GROUP, setting.LEVEL4_TARGET_pos[1], setting.LEVEL4_TARGET_pos[2], 1, true, 1, {{ type = 0, value = HOSIN_BUFF }})
-- Re-run stage mobs for the second wave (no immunity on regular mobs)
d.regen_file(MOB_REGEN_FILE_PATH .. "id_4f.txt")
server_timer("snow_dungeon_killed_A_2", 6, get_server_timer_arg())
elseif d.getf("level4_boss_gen") == 1 then
d.setf("level4_boss_gen", 0)
notice_multiline(gameforge.snow_dungeon._200_notice, d.notice)
server_timer("snow_dungeon_level5_start", 10, d.get_map_index())
end
elseif d.getf("level") == 6 then
notice_multiline(gameforge.snow_dungeon._210_notice, d.notice)
d.spawn_mob_with_immunity(LEVEL6_TARGET, setting.LEVEL6_TARGET_pos[1], setting.LEVEL6_TARGET_pos[2], { { type = 6, value = 3 } })
end
else
server_timer("snow_dungeon_killed_A_2", 6, get_server_timer_arg())
end
end
end
when snow_dungeon_killed_A_2.server_timer begin
if d.select(get_server_timer_arg()) then
local setting = snow_dungeon.setting()
if d.count_monster() <= 0 then
if d.getf("level") == 1 then
notice_multiline(gameforge.snow_dungeon._180_notice, d.notice)
server_timer("snow_dungeon_level2_start", 10, d.get_map_index())
elseif d.getf("level") == 3 then
notice_multiline(gameforge.snow_dungeon._190_notice, d.notice)
server_timer("snow_dungeon_level4_start", 10, d.get_map_index())
elseif d.getf("level") == 4 then
if d.getf("level4_boss_gen") == 0 then
-- First clear: trigger second wave with boss group 6062 that requires Hosin buff to break immunity
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "LEVEL4 second wave (boss) STARTED")
d.setf("level4_boss_gen", 1)
d.spawn_group_with_immunity(LEVEL4_TARGET_GROUP, setting.LEVEL4_TARGET_pos[1], setting.LEVEL4_TARGET_pos[2], 1, true, 1, {{ type = 0, value = HOSIN_BUFF }})
d.regen_file(MOB_REGEN_FILE_PATH .. "id_4f.txt")
server_timer("snow_dungeon_killed_A_1", 6, get_server_timer_arg())
elseif d.getf("level4_boss_gen") == 1 then
d.setf("level4_boss_gen", 0)
notice_multiline(gameforge.snow_dungeon._200_notice, d.notice)
server_timer("snow_dungeon_level5_start", 10, d.get_map_index())
end
elseif d.getf("level") == 6 then
notice_multiline(gameforge.snow_dungeon._210_notice, d.notice)
d.spawn_mob_with_immunity(LEVEL6_TARGET, setting.LEVEL6_TARGET_pos[1], setting.LEVEL6_TARGET_pos[2], { { type = 6, value = 3 } })
end
else
server_timer("snow_dungeon_killed_A_1", 6, get_server_timer_arg())
end
end
end
when snow_dungeon_level2_start.server_timer begin
if d.select(get_server_timer_arg()) then
local setting = snow_dungeon.setting()
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "LEVEL 2 started")
d.setf("level", 2)
d.jump_all(setting.WARP_pos[2][1], setting.WARP_pos[2][2])
d.set_regen_file(MOB_REGEN_FILE_PATH .. "id_2f.txt")
notice_multiline(gameforge.snow_dungeon._220_notice, d.notice)
end
end
when kill with snow_dungeon.is_snowd(pc.get_map_index()) and d.getf("level") == 2 begin
local i = number(1, 100)
if i == 1 then
game.drop_item(LEVEL2_REALKEY, 1)
end
end
when LEVEL2_REALKEY.use with d.getf("level") == 2 and snow_dungeon.is_snowd(pc.get_map_index()) begin
if pc.get_job() == 3 then
if d.getf("level2_clear") == 0 then
local j = number(1, 5)
if j == 1 then
item.remove()
snow_dungeon.level_clear()
notice_multiline(gameforge.snow_dungeon._230_notice, d.notice)
server_timer("snow_dungeon_level3_start", 10, d.get_map_index())
d.setf("level2_clear", 1)
else
say(gameforge.snow_dungeon._240_say)
item.remove()
end
end
else
say(gameforge.snow_dungeon._250_say)
end
end
when snow_dungeon_level3_start.server_timer begin
if d.select(get_server_timer_arg()) then
local setting = snow_dungeon.setting()
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "LEVEL 3 started")
d.setf("level", 3)
d.jump_all(setting.WARP_pos[3][1], setting.WARP_pos[3][2])
d.regen_file(MOB_REGEN_FILE_PATH .. "id_3f.txt")
server_timer("snow_dungeon_killed_A_1", 6, d.get_map_index())
notice_multiline(gameforge.snow_dungeon._260_notice, d.notice)
end
end
when snow_dungeon_level4_start.server_timer begin
if d.select(get_server_timer_arg()) then
local setting = snow_dungeon.setting()
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "LEVEL 4 started")
d.setf("level", 4)
d.jump_all(setting.WARP_pos[4][1], setting.WARP_pos[4][2])
d.regen_file(MOB_REGEN_FILE_PATH .. "id_4f.txt")
server_timer("snow_dungeon_killed_A_1", 6, d.get_map_index())
notice_multiline(gameforge.snow_dungeon._270_notice, d.notice)
end
end
when snow_dungeon_level5_start.server_timer begin
if d.select(get_server_timer_arg()) then
local setting = snow_dungeon.setting()
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "LEVEL 5 started")
d.setf("level", 5)
d.jump_all(setting.WARP_pos[5][1], setting.WARP_pos[5][2])
d.set_regen_file(MOB_REGEN_FILE_PATH .. "id_5f.txt")
notice_multiline(gameforge.snow_dungeon._280_notice, d.notice)
notice_multiline(gameforge.snow_dungeon._290_notice, d.notice)
local vis = { 0, 0, 0, 0, 0 }
for i = 1, 5 do
local ran = number(1, 5)
local st = 0
for j = 1, 50 do
st = st + 1
if st > 5 then
st = 1
end
if vis[st] == 0 then
ran = ran - 1
if ran == 0 then
vis[st] = 1
d.set_unique("stone5_" .. st, d.spawn_mob(LEVEL5_STONE, setting.LEVEL5_STONE_pos[i][1], setting.LEVEL5_STONE_pos[i][2]))
break
end
end
end
end
end
end
when kill with snow_dungeon.is_snowd(pc.get_map_index()) and d.getf("level") == 5 begin
local i = number(1, 100)
if i == 1 then
game.drop_item(LEVEL5_REALKEY, 1)
end
end
when LEVEL5_STONE.take with snow_dungeon.is_snowd(d.get_map_index()) and item.vnum == LEVEL5_REALKEY and d.getf("level") == 5 begin
local setting = snow_dungeon.setting()
if npc.get_vid() == d.get_unique_vid("stone5_1") then
npc.purge()
item.remove()
say(gameforge.snow_dungeon._300_say)
d.setf("stonekill", 2)
if d.count_monster() < LEVEL5_GEN_LIMIT then
d.regen_file(MOB_REGEN_FILE_PATH .. "id_5f.txt")
end
elseif npc.get_vid() == d.get_unique_vid("stone5_2") then
if d.getf("stonekill") == 2 then
npc.purge()
item.remove()
say(gameforge.snow_dungeon._310_say)
d.setf("stonekill", 3)
if d.count_monster() < LEVEL5_GEN_LIMIT then
d.regen_file(MOB_REGEN_FILE_PATH .. "id_5f.txt")
end
else
item.remove()
say(gameforge.snow_dungeon._320_say)
end
elseif npc.get_vid() == d.get_unique_vid("stone5_3") then
if d.getf("stonekill") == 3 then
npc.purge()
item.remove()
say(gameforge.snow_dungeon._330_say)
d.setf("stonekill", 4)
if d.count_monster() < LEVEL5_GEN_LIMIT then
d.regen_file(MOB_REGEN_FILE_PATH .. "id_5f.txt")
end
else
item.remove()
say(gameforge.snow_dungeon._320_say)
end
elseif npc.get_vid() == d.get_unique_vid("stone5_4") then
if d.getf("stonekill") == 4 then
npc.purge()
item.remove()
say(gameforge.snow_dungeon._340_say)
d.setf("stonekill", 5)
if d.count_monster() < LEVEL5_GEN_LIMIT then
d.regen_file(MOB_REGEN_FILE_PATH .. "id_5f.txt")
end
else
item.remove()
say(gameforge.snow_dungeon._320_say)
end
else
if d.getf("stonekill") == 5 then
npc.purge()
item.remove()
notice_multiline(gameforge.snow_dungeon._350_notice, d.notice)
snow_dungeon.level_clear()
server_timer("snow_dungeon_level6_start", 10, d.get_map_index())
else
item.remove()
say(gameforge.snow_dungeon._320_say)
end
end
end
when snow_dungeon_level6_start.server_timer begin
if d.select(get_server_timer_arg()) then
local setting = snow_dungeon.setting()
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "LEVEL 6 started")
d.setf("level", 6)
d.jump_all(setting.WARP_pos[6][1], setting.WARP_pos[6][2])
d.regen_file(MOB_REGEN_FILE_PATH .. "id_6f.txt")
d.set_unique("stage6_npc", d.spawn_mob(20379, 747, 517))
server_timer("snow_dungeon_stage6_npc_guard", 10, d.get_map_index())
server_timer("snow_dungeon_killed_A_1", 6, d.get_map_index())
notice_multiline(gameforge.snow_dungeon._360_notice, d.notice)
end
end
when LEVEL6_TARGET.kill with snow_dungeon.is_snowd(d.get_map_index()) and d.getf("level") == 6 begin
notice_multiline(gameforge.snow_dungeon._370_notice, d.notice)
snow_dungeon.level_clear()
server_timer("snow_dungeon_level7_start", 10, d.get_map_index())
end
when snow_dungeon_level7_start.server_timer begin
if d.select(get_server_timer_arg()) then
local setting = snow_dungeon.setting()
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "LEVEL 7 started")
d.setf("level", 7)
d.jump_all(setting.WARP_pos[7][1], setting.WARP_pos[7][2])
d.set_regen_file(MOB_REGEN_FILE_PATH .. "id_7f.txt")
notice_multiline(gameforge.snow_dungeon._380_notice, d.notice)
notice_multiline(gameforge.snow_dungeon._390_notice, d.notice)
local vis = { 0, 0, 0, 0 }
for i = 1, 3 do
vis[i] = 0
end
for i = 1, 4 do
local ran = number(1, 4)
local st = 0
for j = 1, 50 do
st = st + 1
if st > 4 then
st = 1
end
if vis[st] == 0 then
ran = ran - 1
if ran == 0 then
vis[st] = 1
d.set_unique("boss7_" .. st, d.spawn_mob(LEVEL7_BOSSMOB, setting.LEVEL7_BOSSMOB_pos[i][1], setting.LEVEL7_BOSSMOB_pos[i][2]))
break
end
end
end
end
-- Apply Dragon's Aid requirement (Gicheon buff) to all stage 7 bosses
for i = 1, 4 do
local vid = d.get_unique_vid('boss7_' .. i)
if vid ~= 0 then
npc.set_damage_immunity_with_conditions(vid, {{ type = 0, value = GICHEON_BUFF }})
end
end
server_timer("snow_dungeon_killed_B_1", 6, d.get_map_index())
end
end
when snow_dungeon_killed_B_1.server_timer begin
if d.select(get_server_timer_arg()) then
for i = 1, 4 do
if not d.is_unique_dead("boss7_" .. i) then
if d.unique_get_hp_perc("boss7_" .. i) < 50 then
d.purge_unique("boss7_" .. i)
notice_multiline(gameforge.snow_dungeon._400_notice, d.notice)
end
end
end
if d.is_unique_dead("boss7_4") then
snow_dungeon.level_clear()
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "LEVEL7_BOSSMOB KILLED")
notice_multiline(gameforge.snow_dungeon._410_notice, d.notice)
server_timer("snow_dungeon_level8_start", 10, d.get_map_index())
else
server_timer("snow_dungeon_killed_B_2", 3, get_server_timer_arg())
end
end
end
when snow_dungeon_killed_B_2.server_timer begin
if d.select(get_server_timer_arg()) then
for i = 1, 4 do
if not d.is_unique_dead("boss7_" .. i) then
if d.unique_get_hp_perc("boss7_" .. i) < 50 then
d.purge_unique("boss7_" .. i)
notice_multiline(gameforge.snow_dungeon._400_notice, d.notice)
end
end
end
if d.is_unique_dead("boss7_4") then
snow_dungeon.level_clear()
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "LEVEL7_BOSSMOB KILLED")
notice_multiline(gameforge.snow_dungeon._410_notice, d.notice)
server_timer("snow_dungeon_level8_start", 10, d.get_map_index())
else
server_timer("snow_dungeon_killed_B_1", 3, get_server_timer_arg())
end
end
end
when snow_dungeon_stage6_npc_guard.server_timer begin
if d.select(get_server_timer_arg()) then
-- Keep NPC 20379 present during stage 6; respawn if purged
if d.getf("level") == 6 then
local vid = d.get_unique_vid("stage6_npc")
if vid == 0 then
local new_vid = d.spawn_mob(20379, 747, 517)
d.set_unique("stage6_npc", new_vid)
end
server_timer("snow_dungeon_stage6_npc_guard", 10, d.get_map_index())
end
end
end
when snow_dungeon_level8_start.server_timer begin
if d.select(get_server_timer_arg()) then
local setting = snow_dungeon.setting()
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "LEVEL 8 started")
d.setf("level", 8)
d.jump_all(setting.WARP_pos[8][1], setting.WARP_pos[8][2])
d.set_regen_file(MOB_REGEN_FILE_PATH .. "id_8f.txt")
notice_multiline(gameforge.snow_dungeon._420_notice, d.notice)
end
end
when kill with snow_dungeon.is_snowd(pc.get_map_index()) and d.getf("level") == 8 begin
local i = number(1, 100)
if i == 1 then
game.drop_item(LEVEL8_REALKEY, 1)
end
end
when LEVEL8_REALKEY.use with snow_dungeon.is_snowd(d.get_map_index()) and d.getf("level") == 8 begin
if pc.get_job() == 1 or pc.get_job() == 3 then
if d.getf("level8_clear") == 0 then
if number(1, 5) == 1 then
item.remove()
snow_dungeon.level_clear()
notice_multiline(gameforge.snow_dungeon._430_notice, d.notice)
server_timer("snow_dungeon_level9_start", 10, d.get_map_index())
d.setf("level8_clear", 1)
if party.is_party() then
party.setf("snow_dungeon_room_enter", 9)
end
else
say(gameforge.snow_dungeon._240_say)
item.remove()
end
end
else
say(gameforge.snow_dungeon._440_say)
end
end
when snow_dungeon_level9_start.server_timer begin
if d.select(get_server_timer_arg()) then
local setting = snow_dungeon.setting()
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "LEVEL 9 started")
d.setf("level", 9)
d.jump_all(setting.WARP_pos[9][1], setting.WARP_pos[9][2])
d.set_regen_file(MOB_REGEN_FILE_PATH .. "id_9f.txt")
d.spawn_mob_with_immunity(LEVEL9_TARGET, setting.LEVEL9_TARGET_pos[1][1], setting.LEVEL9_TARGET_pos[1][2], {{ type = 6, value = 1 }, { type = 6, value = 3 }})
notice_multiline(gameforge.snow_dungeon._450_notice, d.notice)
end
end
when LEVEL9_TARGET.kill with snow_dungeon.is_snowd(pc.get_map_index()) and d.getf("level") == 9 begin
local setting = snow_dungeon.setting()
snow_dungeon.level_clear()
d.spawn_mob_ac_dir(DUNGEON_MAN, 849, 641, 1)
end
when DUNGEON_MAN.chat.gameforge.snow_dungeon._460_npcChat with d.getf("level") == 9 and pc.get_map_index() >= DUNGEON_MAP_INDEX * 10000 and pc.get_map_index() < (DUNGEON_MAP_INDEX + 1) * 10000 begin
local setting = snow_dungeon.setting()
if not party.is_leader() then
say(gameforge.snow_dungeon._090_say)
else
--if pc.get_level() < 104 then
--say(gameforge.snow_dungeon._470_say)
--server_timer("snow_dungeon_end_timer", 10, d.get_map_index())
--else
--if pc.getf("main_quest_flame_lv103", "__status")==main_quest_flame_lv103.__COMPLETE__ then
--if pc.getf("main_quest_lv1", "__status")==main_quest_lv1.__COMPLETE__ then
say(gameforge.snow_dungeon._480_say)
local warp = select(gameforge.snow_dungeon._140_select, gameforge.snow_dungeon._150_select)
if warp == 1 then
d.setf("level", 10)
d.jump_all(setting.WARP_pos[10][1], setting.WARP_pos[10][2])
d.set_regen_file(MOB_REGEN_FILE_PATH .. "id_boss.txt")
d.spawn_mob(FINAL_BOSS, setting.boss_pos[1], setting.boss_pos[2])
notice_multiline(gameforge.snow_dungeon._490_notice, d.notice)
end
--else
--say(gameforge.snow_dungeon._500_say)
--notice_multiline(gameforge.snow_dungeon._510_notice, d.notice)
--server_timer("snow_dungeon_end_timer", 10, d.get_map_index())
--end
--end
end
end
when FINAL_BOSS.kill with snow_dungeon.is_snowd(d.get_map_index()) and d.getf("level") == 10 begin
char_log(pc.get_channel_id() .. "" .. d.get_map_index(), "NW", "BOSS KILLED")
notice_multiline(gameforge.snow_dungeon._520_notice, d.notice)
notice_multiline(gameforge.snow_dungeon._530_notice, d.notice)
server_timer("snow_dungeon_end_timer", 60, d.get_map_index())
snow_dungeon.level_clear()
if party.is_party() then
party.setf("snow_dungeon_boss_kill_count", 1)
end
end
when snow_dungeon_45m_left_timer.server_timer begin
if d.select(get_server_timer_arg()) then
notice_multiline(string.format(gameforge.snow_dungeon._540_notice, 45), d.notice)
notice_multiline(gameforge.snow_dungeon._550_notice, d.notice)
server_timer("snow_dungeon_30m_left_timer", 15 * 60, get_server_timer_arg())
end
end
when snow_dungeon_30m_left_timer.server_timer begin
if d.select(get_server_timer_arg()) then
notice_multiline(string.format(gameforge.snow_dungeon._540_notice, 30), d.notice)
notice_multiline(gameforge.snow_dungeon._550_notice, d.notice)
server_timer("snow_dungeon_15m_left_timer", 15 * 60, get_server_timer_arg())
end
end
when snow_dungeon_15m_left_timer.server_timer begin
if d.select(get_server_timer_arg()) then
notice_multiline(string.format(gameforge.snow_dungeon._540_notice, 15), d.notice)
notice_multiline(gameforge.snow_dungeon._550_notice, d.notice)
server_timer("snow_dungeon_5m_left_timer", 10 * 60, get_server_timer_arg())
end
end
when snow_dungeon_5m_left_timer.server_timer begin
if d.select(get_server_timer_arg()) then
notice_multiline(string.format(gameforge.snow_dungeon._540_notice, 5), d.notice)
notice_multiline(gameforge.snow_dungeon._550_notice, d.notice)
server_timer("snow_dungeon_1m_left_timer", 4 * 60, get_server_timer_arg())
end
end
when snow_dungeon_1m_left_timer.server_timer begin
if d.select(get_server_timer_arg()) then
notice_multiline(string.format(gameforge.snow_dungeon._540_notice, 1), d.notice)
notice_multiline(gameforge.snow_dungeon._550_notice, d.notice)
server_timer("snow_dungeon_0m_left_timer", 60, get_server_timer_arg())
end
end
when snow_dungeon_0m_left_timer.server_timer begin
local setting = snow_dungeon.setting()
if d.select(get_server_timer_arg()) then
notice_multiline(gameforge.snow_dungeon._560_notice, d.notice)
notice_multiline(gameforge.snow_dungeon._510_notice, d.notice)
server_timer("snow_dungeon_end_timer", 10, d.get_map_index())
end
end
when snow_dungeon_end_timer.server_timer begin
local setting = snow_dungeon.setting()
if d.select(get_server_timer_arg()) then
d.setf("party_leader_pid", 0)
snow_dungeon.clear_timer(d.get_map_index())
d.set_warp_location(ENTRY_MAP_INDEX, setting.outside_entry_pos[1] , setting.outside_entry_pos[2])
d.exit_all()
end
end
when snow_dungeon_leader_out_timer.server_timer begin
local setting = snow_dungeon.setting()
if d.select(get_server_timer_arg()) then
say_in_map(get_server_timer_arg(), gameforge.snow_dungeon._570_say .. gameforge.snow_dungeon._580_say)
server_timer("snow_dungeon_end_timer", 10, d.get_map_index())
end
end
end
end