mirror of
https://github.com/HerculesWS/Hercules
synced 2026-08-15 12:23:13 -04:00
Memory Slasher - May 30 Patch
http://hercules.ws/board/topic/928-memory-slasher-may-30-patch/ Signed-off-by: shennetsind <ind@henn.et>
This commit is contained in:
parent
21bbfad480
commit
20bdc01fa6
41 changed files with 3077 additions and 1413 deletions
101
conf/battlegrounds.conf
Normal file
101
conf/battlegrounds.conf
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
//====================================================
|
||||
//= _ _ _
|
||||
//= | | | | | |
|
||||
//= | |_| | ___ _ __ ___ _ _| | ___ ___
|
||||
//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
|
||||
//= | | | | __/ | | (__| |_| | | __/\__ \
|
||||
//= \_| |_/\___|_| \___|\__,_|_|\___||___/
|
||||
//=
|
||||
//= http://hercules.ws/board/
|
||||
//====================================================
|
||||
//= Link~u! <description> <link to wiki/topic>
|
||||
//= http://hercules.ws/board/topic/928-memory-slasher-may-30-patch/
|
||||
battlegrounds: (
|
||||
{
|
||||
/* feature is not complete */
|
||||
feature_off:true
|
||||
/* character variable for global bg delay */
|
||||
global_delay_var: "BG_Delay_Tick"
|
||||
/* how many seconds to consider a player "afk" and kick him out? */
|
||||
maximum_afk_seconds: 30
|
||||
|
||||
/* one can add as many as he wishes */
|
||||
/* for custom ones, need to edit "lua files/entryqueue/entryqueuelist.lua" [Ind/Hercules] */
|
||||
arenas: ({
|
||||
name: "Tierra Gorge" //must match the name in client files
|
||||
event: "Tierra_BG2::OnPlayerListReady"
|
||||
minLevel: 80
|
||||
maxLevel: 150
|
||||
reward: {/* amount of badges awarded on each case */
|
||||
win: 3
|
||||
loss: 1
|
||||
draw: 1
|
||||
}
|
||||
minPlayers: 6 /* minimum amount of players to start */
|
||||
maxPlayers: 60 /* maximum amount of players */
|
||||
minTeamPlayers: 6 /* minimum amount of team members required for a team (party or guild) to join */
|
||||
delay_var: "Tierra_BG_Tick" /* npc variable name that will store the delay for this match */
|
||||
maxDuration: 30 /* maximum duration in minutes, if reached game ends and highest score wins (or calls a draw if scores are equal) */
|
||||
},{
|
||||
name: "Flavius" //must match the name in client files
|
||||
event: "Flavius_BG1::OnPlayerListReady"
|
||||
minLevel: 80
|
||||
maxLevel: 150
|
||||
reward: {/* amount of badges awarded on each case */
|
||||
win: 9
|
||||
loss: 3
|
||||
draw: 3
|
||||
}
|
||||
minPlayers: 6 /* minimum amount of players to start */
|
||||
maxPlayers: 60 /* maximum amount of players */
|
||||
minTeamPlayers: 6 /* minimum amount of team members required for a team (party or guild) to join */
|
||||
delay_var: "Flavius_BG_Tick" /* npc variable name that will store the delay for this match */
|
||||
maxDuration: 30 /* maximum duration in minutes, if reached game ends and highest score wins (or calls a draw if scores are equal) */
|
||||
},{
|
||||
name: "KVM (Level 80 and up)" //must match the name in client files
|
||||
event: "KvM03_BG::OnPlayerListReady"
|
||||
minLevel: 80
|
||||
maxLevel: 150
|
||||
reward: {/* amount of badges awarded on each case */
|
||||
win: 5
|
||||
loss: 1
|
||||
draw: 1
|
||||
}
|
||||
minPlayers: 4 /* minimum amount of players to start */
|
||||
maxPlayers: 60 /* maximum amount of players */
|
||||
minTeamPlayers: 5 /* minimum amount of team members required for a team (party or guild) to join */
|
||||
delay_var: "KVM_BG_Tick" /* npc variable name that will store the delay for this match */
|
||||
maxDuration: 30 /* maximum duration in minutes, if reached game ends and highest score wins (or calls a draw if scores are equal) */
|
||||
},{
|
||||
name: "KVM (Level 60~79)" //must match the name in client files
|
||||
event: "KvM03_BG::OnPlayerListReady"
|
||||
minLevel: 60
|
||||
maxLevel: 79
|
||||
reward: {/* amount of badges awarded on each case */
|
||||
win: 2
|
||||
loss: 0
|
||||
draw: 1
|
||||
}
|
||||
minPlayers: 4 /* minimum amount of players to start */
|
||||
maxPlayers: 60 /* maximum amount of players */
|
||||
minTeamPlayers: 5 /* minimum amount of team members required for a team (party or guild) to join */
|
||||
delay_var: "KVM_BG_Tick" /* npc variable name that will store the delay for this match */
|
||||
maxDuration: 30 /* maximum duration in minutes, if reached game ends and highest score wins (or calls a draw if scores are equal) */
|
||||
},{
|
||||
name: "KVM (Level 59 and below)" //must match the name in client files
|
||||
event: "KvM03_BG::OnPlayerListReady"
|
||||
minLevel: 1
|
||||
maxLevel: 59
|
||||
reward: {/* amount of badges awarded on each case */
|
||||
win: 1
|
||||
loss: 0
|
||||
draw: 0
|
||||
}
|
||||
minPlayers: 4 /* minimum amount of players to start */
|
||||
maxPlayers: 60 /* maximum amount of players */
|
||||
minTeamPlayers: 5 /* minimum amount of team members required for a team (party or guild) to join */
|
||||
delay_var: "KVM_BG_Tick" /* npc variable name that will store the delay for this match */
|
||||
maxDuration: 30 /* maximum duration in minutes, if reached game ends and highest score wins (or calls a draw if scores are equal) */
|
||||
}
|
||||
)
|
||||
})
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1811,7 +1811,7 @@ OnEnable:
|
|||
monster "1@nyd",255,255,"Nidhoggur's Guardian#10",2021,1,instance_npcname("nyd_call_mon_1", instance_id())+"::OnMyMobDead";
|
||||
monster "1@nyd",225,245,"Nidhoggur's Guardian#11",2021,1,instance_npcname("nyd_call_mon_1", instance_id())+"::OnMyMobDead";
|
||||
monster "1@nyd",230,280,"Nidhoggur's Guardian#12",2021,1,instance_npcname("nyd_call_mon_1", instance_id())+"::OnMyMobDead";
|
||||
instance_announce 0, "Nidhoggur's Guardian : Protect the Guardian's Sanctuary. Get rid of the intruders.",bc_map,"0x00ff99";
|
||||
instance_announce -1, "Nidhoggur's Guardian : Protect the Guardian's Sanctuary. Get rid of the intruders.",bc_map,"0x00ff99";
|
||||
end;
|
||||
|
||||
OnDisable:
|
||||
|
|
@ -1822,7 +1822,7 @@ OnDisable:
|
|||
OnMyMobDead:
|
||||
set .@mob_dead_num,mobcount("1@nyd", instance_npcname("nyd_call_mon_1", instance_id())+"::OnMyMobDead");
|
||||
if (.@mob_dead_num < 1) {
|
||||
instance_announce 0, "All of Nidhoggur's Guardians have been defeated!",bc_map,"0x00ff99";
|
||||
instance_announce -1, "All of Nidhoggur's Guardians have been defeated!",bc_map,"0x00ff99";
|
||||
donpcevent instance_npcname("ins_nyd_1f_timer", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_to2f_warp", instance_id())+"::OnEnable";
|
||||
set 'ins_nyd2,2;
|
||||
|
|
@ -1848,23 +1848,23 @@ OnDisable:
|
|||
end;
|
||||
|
||||
OnTimer900000:
|
||||
instance_announce 0, "World Tree Yggdrasil : There's not much time left. Please hurry.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "World Tree Yggdrasil : There's not much time left. Please hurry.",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer1200000:
|
||||
instance_announce 0, "World Tree Yggdrasil : My powers are slowly disappearing. Please hurry.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "World Tree Yggdrasil : My powers are slowly disappearing. Please hurry.",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer1500000:
|
||||
instance_announce 0, "World Tree Yggdrasil : I'm... almost at my limit... please hurry up." ,bc_map,"0xFFFF00";
|
||||
instance_announce -1, "World Tree Yggdrasil : I'm... almost at my limit... please hurry up." ,bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer1800000:
|
||||
instance_announce 0, "World Tree Yggdrasil : You've failed... but I will use what power I have left... to send you out of here.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "World Tree Yggdrasil : You've failed... but I will use what power I have left... to send you out of here.",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer1830000:
|
||||
instance_announce 0, "Opening of the Gate has failed.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Opening of the Gate has failed.",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer1850000:
|
||||
|
|
@ -1933,15 +1933,15 @@ OnDisable:
|
|||
end;
|
||||
|
||||
OnTimer12000:
|
||||
instance_announce 0, "Nidhoggur's Shadow : No more...I can't stand this anymore...",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : No more...I can't stand this anymore...",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer15000:
|
||||
instance_announce 0, "Nidhoggur's Shadow : I need...I need the World Tree Yggdrasil's powers...",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I need...I need the World Tree Yggdrasil's powers...",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer18000:
|
||||
instance_announce 0, "Nidhoggur's Shadow : Destroy...everything...",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : Destroy...everything...",bc_map,"0xFFFF00";
|
||||
end;
|
||||
/*
|
||||
stopnpctimer;
|
||||
|
|
@ -1983,7 +1983,7 @@ OnInstanceInit:
|
|||
OnEnable:
|
||||
enablenpc instance_npcname("nyd_2f_boss_enter_call", instance_id());
|
||||
monster "2@nyd",199,327,"Nidhoggur's Shadow#",2022,1,instance_npcname("nyd_2f_boss_enter_call", instance_id())+"::OnMyMobDead";
|
||||
instance_announce 0, "Nidhoggur's Shadow : I will devour all of you...you and the World Tree Yggdrasil.",bc_map,"0x00ff99";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I will devour all of you...you and the World Tree Yggdrasil.",bc_map,"0x00ff99";
|
||||
//donpcevent instance_npcname("nyd_2f_boss_enter_call", instance_id())+"::Ongo";
|
||||
initnpctimer;
|
||||
end;
|
||||
|
|
@ -1996,7 +1996,7 @@ OnDisable:
|
|||
OnTimer180000:
|
||||
set .@rullet,rand(1,4);
|
||||
if (.@rullet == 1) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : In this chaos... your blood is just what I need.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : In this chaos... your blood is just what I need.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2005,7 +2005,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 2) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : I will freeze every last drop of your blood.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I will freeze every last drop of your blood.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2014,7 +2014,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 3) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : Sleep for eternity in an empty illusion.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : Sleep for eternity in an empty illusion.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2023,7 +2023,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 4) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : I'll let you enjoy the pain of dying slowly.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I'll let you enjoy the pain of dying slowly.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
|
|
@ -2037,7 +2037,7 @@ OnTimer180000:
|
|||
OnMyMobDead:
|
||||
set .@mob_dead_num,mobcount("2@nyd",instance_npcname("nyd_2f_boss_enter_call", instance_id())+"::OnMyMobDead");
|
||||
if (.@mob_dead_num < 1) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : World Tree Yggdrasil's guardian... his powers are disappearing...",bc_map,"0x00ff99";
|
||||
instance_announce -1, "Nidhoggur's Shadow : World Tree Yggdrasil's guardian... his powers are disappearing...",bc_map,"0x00ff99";
|
||||
donpcevent instance_npcname("World Tree Yggdrasil#2F", instance_id())+"::OnEnable";
|
||||
donpcevent instance_npcname("nyd_2f_boss_enter_call", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_boss_enter_logic", instance_id())+"::OnDisable";
|
||||
|
|
@ -2070,7 +2070,7 @@ OnDisable:
|
|||
OnTimer180000:
|
||||
set .@rullet,rand(1,4);
|
||||
if (.@rullet == 1) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : In this chaos... your blood is just what I need.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : In this chaos... your blood is just what I need.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2079,7 +2079,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 2) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : I will freeze every last drop of your blood.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I will freeze every last drop of your blood.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2088,7 +2088,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 3) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : Sleep for eternity in an empty illusion.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : Sleep for eternity in an empty illusion.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2097,7 +2097,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 4) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : I'll let you enjoy the pain of dying slowly.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I'll let you enjoy the pain of dying slowly.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
|
|
@ -2149,7 +2149,7 @@ OnInstanceInit:
|
|||
|
||||
OnEnable:
|
||||
enablenpc instance_npcname("World Tree Yggdrasil#2F", instance_id());
|
||||
instance_announce 0, "World Tree Yggdrasil : You did good. Have everyone go to the Magic Circle in the middle, and get ready for the destruction of the nest.",bc_map,"0x00ff99";
|
||||
instance_announce -1, "World Tree Yggdrasil : You did good. Have everyone go to the Magic Circle in the middle, and get ready for the destruction of the nest.",bc_map,"0x00ff99";
|
||||
end;
|
||||
|
||||
OnDisable:
|
||||
|
|
@ -2208,7 +2208,7 @@ OnEnable:
|
|||
OnMyMobDead:
|
||||
set .@mob_dead_num,mobcount("2@nyd",instance_npcname("nyd_2f_red_c", instance_id())+"::OnMyMobDead");
|
||||
if (.@mob_dead_num < 1) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : You're not bad... but I will be your opponent this time.",bc_map,"0x00ff99";
|
||||
instance_announce -1, "Nidhoggur's Shadow : You're not bad... but I will be your opponent this time.",bc_map,"0x00ff99";
|
||||
donpcevent instance_npcname("nyd_2f_red_c", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_boss_enter_logic", instance_id())+"::OnEnable";
|
||||
end;
|
||||
|
|
@ -2226,7 +2226,7 @@ OnTimer180000:
|
|||
stopnpctimer;
|
||||
set .@rullet,rand(1,4);
|
||||
if (.@rullet == 1) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : In this chaos... your blood is just what I need.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : In this chaos... your blood is just what I need.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2235,7 +2235,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 2) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : I will freeze every last drop of your blood.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I will freeze every last drop of your blood.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2244,7 +2244,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 3) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : Sleep for eternity in an empty illusion.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : Sleep for eternity in an empty illusion.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2253,7 +2253,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 4) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : I'll let you enjoy the pain of dying slowly.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I'll let you enjoy the pain of dying slowly.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
|
|
@ -2368,7 +2368,7 @@ OnEnable:
|
|||
OnMyMobDead:
|
||||
set .@mob_dead_num,mobcount("2@nyd",instance_npcname("nyd_2f_white_c", instance_id())+"::OnMyMobDead");
|
||||
if (.@mob_dead_num < 1) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : You're not bad... but I will be your opponent this time.",bc_map,"0x00ff99";
|
||||
instance_announce -1, "Nidhoggur's Shadow : You're not bad... but I will be your opponent this time.",bc_map,"0x00ff99";
|
||||
donpcevent instance_npcname("nyd_2f_white_c", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_boss_enter_logic", instance_id())+"::OnEnable";
|
||||
end;
|
||||
|
|
@ -2386,7 +2386,7 @@ OnTimer180000:
|
|||
stopnpctimer;
|
||||
set .@rullet,rand(1,4);
|
||||
if (.@rullet == 1) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : In this chaos... your blood is just what I need.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : In this chaos... your blood is just what I need.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2395,7 +2395,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 2) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : I will freeze every last drop of your blood.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I will freeze every last drop of your blood.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2404,7 +2404,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 3) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : Sleep for eternity in an empty illusion.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : Sleep for eternity in an empty illusion.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2413,7 +2413,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 4) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : I'll let you enjoy the pain of dying slowly.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I'll let you enjoy the pain of dying slowly.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
|
|
@ -2529,7 +2529,7 @@ OnEnable:
|
|||
OnMyMobDead:
|
||||
set .@mob_dead_num,mobcount("2@nyd",instance_npcname("nyd_2f_yellow_c", instance_id())+"::OnMyMobDead");
|
||||
if (.@mob_dead_num < 1) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : You're not bad...but I will be your opponent this time.",bc_map,"0x00ff99";
|
||||
instance_announce -1, "Nidhoggur's Shadow : You're not bad...but I will be your opponent this time.",bc_map,"0x00ff99";
|
||||
donpcevent instance_npcname("nyd_2f_yellow_c", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_boss_enter_logic", instance_id())+"::OnEnable";
|
||||
end;
|
||||
|
|
@ -2554,7 +2554,7 @@ OnTimer180000:
|
|||
stopnpctimer;
|
||||
set .@rullet,rand(1,4);
|
||||
if (.@rullet == 1) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : In this chaos... your blood is just what I need.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : In this chaos... your blood is just what I need.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2563,7 +2563,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 2) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : I will freeze every last drop of your blood.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I will freeze every last drop of your blood.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2572,7 +2572,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 3) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : Sleep for eternity in an empty illusion.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : Sleep for eternity in an empty illusion.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2581,7 +2581,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 4) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : I'll let you enjoy the pain of dying slowly.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I'll let you enjoy the pain of dying slowly.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
|
|
@ -2696,7 +2696,7 @@ OnEnable:
|
|||
OnMyMobDead:
|
||||
set .@mob_dead_num,mobcount("2@nyd",instance_npcname("nyd_2f_green_c", instance_id())+"::OnMyMobDead");
|
||||
if (.@mob_dead_num < 1) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : You're not bad... but I will be your opponent this time.",bc_map,"0x00ff99";
|
||||
instance_announce -1, "Nidhoggur's Shadow : You're not bad... but I will be your opponent this time.",bc_map,"0x00ff99";
|
||||
donpcevent instance_npcname("nyd_2f_green_c", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_boss_enter_logic", instance_id())+"::OnEnable";
|
||||
end;
|
||||
|
|
@ -2721,7 +2721,7 @@ OnTimer180000:
|
|||
stopnpctimer;
|
||||
set .@rullet,rand(1,4);
|
||||
if (.@rullet == 1) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : In this chaos... your blood is just what I need.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : In this chaos... your blood is just what I need.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2730,7 +2730,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 2) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : I will freeze every last drop of your blood.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I will freeze every last drop of your blood.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2739,7 +2739,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 3) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : Sleep for eternity in an empty illusion.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : Sleep for eternity in an empty illusion.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_green", instance_id())+"::OnDisable";
|
||||
|
|
@ -2748,7 +2748,7 @@ OnTimer180000:
|
|||
end;
|
||||
}
|
||||
else if (.@rullet == 4) {
|
||||
instance_announce 0, "Nidhoggur's Shadow : I'll let you enjoy the pain of dying slowly.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Nidhoggur's Shadow : I'll let you enjoy the pain of dying slowly.",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("nyd_2f_red", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_white", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("nyd_2f_yellow", instance_id())+"::OnDisable";
|
||||
|
|
|
|||
|
|
@ -309,19 +309,19 @@ OnMyMobDead:
|
|||
else if ((.@mob_ran > 28) && (.@mob_ran < 30)) {
|
||||
monster "1@orcs",0,0,"High Orc",1213,.@mob_dead_num,instance_npcname("#Resurrect Monsters1", instance_id())+"::OnMyMobDead";
|
||||
if (rand(1,10) == 9) {
|
||||
instance_announce 0, "High Orc: We need more defenses! Get more people here!",bc_map,"0xff4444";
|
||||
instance_announce -1, "High Orc: We need more defenses! Get more people here!",bc_map,"0xff4444";
|
||||
}
|
||||
}
|
||||
else if ((.@mob_ran > 26) && (.@mob_ran < 29)) {
|
||||
areamonster "1@orcs",41,91,51,81,"High Orc",1213,.@mob_dead_num,instance_npcname("#Resurrect Monsters1", instance_id())+"::OnMyMobDead";
|
||||
if (rand(1,10) == 9) {
|
||||
instance_announce 0, "Where are the High Orcs!? Get them to stop the enemies!",bc_map,"0xff4444";
|
||||
instance_announce -1, "Where are the High Orcs!? Get them to stop the enemies!",bc_map,"0xff4444";
|
||||
}
|
||||
}
|
||||
else {
|
||||
areamonster "1@orcs",17,187,27,177,"High Orc",1213,.@mob_dead_num,instance_npcname("#Resurrect Monsters1", instance_id())+"::OnMyMobDead";
|
||||
if (rand(1,5) == 3) {
|
||||
instance_announce 0, "Caution: The army's starting to concentrate at Zone No. 4.",bc_map,"0x77ff77";
|
||||
instance_announce -1, "Caution: The army's starting to concentrate at Zone No. 4.",bc_map,"0x77ff77";
|
||||
}
|
||||
if (rand(1,100) == 50) {
|
||||
initnpctimer;
|
||||
|
|
@ -331,11 +331,11 @@ OnMyMobDead:
|
|||
end;
|
||||
|
||||
OnTimer10:
|
||||
instance_announce 0, "Shouts of the Chief Orc of Safeguards: Looks like this will take longer than expected. Summon the Stalactic Golems!",bc_map,"0xff4444";
|
||||
instance_announce -1, "Shouts of the Chief Orc of Safeguards: Looks like this will take longer than expected. Summon the Stalactic Golems!",bc_map,"0xff4444";
|
||||
end;
|
||||
|
||||
OnTimer4010:
|
||||
instance_announce 0, "Stalactic Golems are digging out of the deep underground.",bc_map,"0x77ff77";
|
||||
instance_announce -1, "Stalactic Golems are digging out of the deep underground.",bc_map,"0x77ff77";
|
||||
areamonster "1@orcs",17,187,27,177,"Stalactic Golem",1278,20,instance_npcname("#Resurrect Monsters1", instance_id())+"::OnMyMobDead";
|
||||
stopnpctimer;
|
||||
end;
|
||||
|
|
@ -432,7 +432,7 @@ OnMyMobDead:
|
|||
if (.@mob_dead_num > 0) {
|
||||
areamonster "1@orcs",43,155,47,159,"Orc Archer",1189,.@mob_dead_num,instance_npcname("#Resurrect Monsters3", instance_id())+"::OnMyMobDead";
|
||||
if (rand(1,3) == 3) {
|
||||
instance_announce 0, "High Orc: Attack them from behind! Cut off their support!",bc_map,"0xff4444";
|
||||
instance_announce -1, "High Orc: Attack them from behind! Cut off their support!",bc_map,"0xff4444";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -490,39 +490,39 @@ OnEnable:
|
|||
end;
|
||||
|
||||
OnTimer10:
|
||||
instance_announce 0, "Kruger: Damn... What took you so long!! I don't have all day!!",bc_map,"0xffff00";
|
||||
instance_announce -1, "Kruger: Damn... What took you so long!! I don't have all day!!",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer5710:
|
||||
instance_announce 0, "Kruger: My plan was to let our comrades open the gate, but it's all ruined since I got busted by the Orc Shaman.",bc_map,"0xffff00";
|
||||
instance_announce -1, "Kruger: My plan was to let our comrades open the gate, but it's all ruined since I got busted by the Orc Shaman.",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer14610:
|
||||
instance_announce 0, "Shouts of the Chief Orc of Safeguards: I smell a rat.. Send some patrols to the entrance!!",bc_map,"0xff4444";
|
||||
instance_announce -1, "Shouts of the Chief Orc of Safeguards: I smell a rat.. Send some patrols to the entrance!!",bc_map,"0xff4444";
|
||||
end;
|
||||
|
||||
OnTimer20210:
|
||||
instance_announce 0, "Kruger: Darn it.. They'll be here any minute. Ok. Listen to me now.",bc_map,"0xffff00";
|
||||
instance_announce -1, "Kruger: Darn it.. They'll be here any minute. Ok. Listen to me now.",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer24910:
|
||||
instance_announce 0, "Kruger: The Orc Shaman has sealed the 1st basement by dividing it into 4 zones. Each zone has one Enchanted Orc who has the power to unseal the next zone.",bc_map,"0xffff00";
|
||||
instance_announce -1, "Kruger: The Orc Shaman has sealed the 1st basement by dividing it into 4 zones. Each zone has one Enchanted Orc who has the power to unseal the next zone.",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer34310:
|
||||
instance_announce 0, "Kruger: Find those Enchanted Orcs and get rid of them to move to the next zone.",bc_map,"0xffff00";
|
||||
instance_announce -1, "Kruger: Find those Enchanted Orcs and get rid of them to move to the next zone.",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer39710:
|
||||
instance_announce 0, "Kruger: Try to avoid encountering Orcs other then the Enchanted ones. Everytime you kill a normal Orc, High Orcs will gather at the last path to the 2nd floor.",bc_map,"0xffff00";
|
||||
instance_announce -1, "Kruger: Try to avoid encountering Orcs other then the Enchanted ones. Everytime you kill a normal Orc, High Orcs will gather at the last path to the 2nd floor.",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer49210:
|
||||
instance_announce 0, "Kruger: In the worst case, the path to the 2nd floor could be completely blocked. For your own sake, you should be as sneaky as possible.",bc_map,"0xffff00";
|
||||
instance_announce -1, "Kruger: In the worst case, the path to the 2nd floor could be completely blocked. For your own sake, you should be as sneaky as possible.",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer56310:
|
||||
instance_announce 0, "Mission: Sneak in and get rid of the 'Enchanted Orcs'. Avoiding battles with other Orcs is the best way of getting into the 2nd floor.",bc_map,"0x44ffff";
|
||||
instance_announce -1, "Mission: Sneak in and get rid of the 'Enchanted Orcs'. Avoiding battles with other Orcs is the best way of getting into the 2nd floor.",bc_map,"0x44ffff";
|
||||
donpcevent instance_npcname("#Resurrect Monsters1", instance_id())+"::OnEnable";
|
||||
donpcevent instance_npcname("#Resurrect Monsters2", instance_id())+"::OnEnable";
|
||||
donpcevent instance_npcname("#Resurrect Monsters3", instance_id())+"::OnEnable";
|
||||
|
|
@ -556,11 +556,11 @@ OnContinue:
|
|||
end;
|
||||
|
||||
OnTimer10300:
|
||||
instance_announce 0, "Kruger's Whisper: The Orcs here used to be my companions. They just lost their will ever since the Orc Shaman started to control them with her magic.",bc_map,"0xff4499";
|
||||
instance_announce -1, "Kruger's Whisper: The Orcs here used to be my companions. They just lost their will ever since the Orc Shaman started to control them with her magic.",bc_map,"0xff4499";
|
||||
end;
|
||||
|
||||
OnTimer18700:
|
||||
instance_announce 0, "Kruger's Whisper: There's nothing we can do but to defeat the Orc Shaman if we want to save the remaining tribes.",bc_map,"0xff4499";
|
||||
instance_announce -1, "Kruger's Whisper: There's nothing we can do but to defeat the Orc Shaman if we want to save the remaining tribes.",bc_map,"0xff4499";
|
||||
stopnpctimer;
|
||||
end;
|
||||
}
|
||||
|
|
@ -585,11 +585,11 @@ OnContinue:
|
|||
end;
|
||||
|
||||
OnTimer30300:
|
||||
instance_announce 0, "Kruger's Whisper: I saw the bodies of our tribe. It seems that the Orc Shaman used those Orcs for her rituals.",bc_map,"0xff4499";
|
||||
instance_announce -1, "Kruger's Whisper: I saw the bodies of our tribe. It seems that the Orc Shaman used those Orcs for her rituals.",bc_map,"0xff4499";
|
||||
end;
|
||||
|
||||
OnTimer37600:
|
||||
instance_announce 0, "Kruger's Whisper: ... It all has to do with me. I am responsible for this evil.",bc_map,"0xff4499";
|
||||
instance_announce -1, "Kruger's Whisper: ... It all has to do with me. I am responsible for this evil.",bc_map,"0xff4499";
|
||||
stopnpctimer;
|
||||
end;
|
||||
}
|
||||
|
|
@ -614,11 +614,11 @@ OnContinue:
|
|||
end;
|
||||
|
||||
OnTimer30300:
|
||||
instance_announce 0, "Please, hang in there!",bc_map,"0xff4499";
|
||||
instance_announce -1, "Please, hang in there!",bc_map,"0xff4499";
|
||||
end;
|
||||
|
||||
OnTimer32700:
|
||||
instance_announce 0, "We'll get some rest when we get to the 2nd basement after passing through here.",bc_map,"0xff4499";
|
||||
instance_announce -1, "We'll get some rest when we get to the 2nd basement after passing through here.",bc_map,"0xff4499";
|
||||
stopnpctimer;
|
||||
end;
|
||||
}
|
||||
|
|
@ -724,13 +724,13 @@ OnMyMobDead:
|
|||
else if ((.@mob_ran > 26) && (.@mob_ran < 29)) {
|
||||
areamonster "2@orcs",157,112,167,122,"High Orc",1213,.@mob_dead_num,instance_npcname("#2Resurrect Monsters1", instance_id())+"::OnMyMobDead";
|
||||
if (rand(1,10) == 9) {
|
||||
instance_announce 0, "Warning: High Orcs are gathering near area 3.",bc_map,"0xff4444";
|
||||
instance_announce -1, "Warning: High Orcs are gathering near area 3.",bc_map,"0xff4444";
|
||||
}
|
||||
}
|
||||
else {
|
||||
areamonster "2@orcs",173,13,183,23,"High Orc",1213,.@mob_dead_num,instance_npcname("#2Resurrect Monsters1", instance_id())+"::OnMyMobDead";
|
||||
if (rand(1,5) == 3) {
|
||||
instance_announce 0, "Caution: The Forces have started to concentrate at the Shaman's Altar.",bc_map,"0x77ff77";
|
||||
instance_announce -1, "Caution: The Forces have started to concentrate at the Shaman's Altar.",bc_map,"0x77ff77";
|
||||
}
|
||||
if (rand(1,70) == 50) {
|
||||
initnpctimer;
|
||||
|
|
@ -740,11 +740,11 @@ OnMyMobDead:
|
|||
end;
|
||||
|
||||
OnTimer10:
|
||||
instance_announce 0, "Voice from somewhere: Foolish... Do you really think the altar would fall like that?",bc_map,"0xff4444";
|
||||
instance_announce -1, "Voice from somewhere: Foolish... Do you really think the altar would fall like that?",bc_map,"0xff4444";
|
||||
end;
|
||||
|
||||
OnTimer4010:
|
||||
instance_announce 0, "[ Wraiths were summoned by an unknown power ]",bc_map,"0x77ff77";
|
||||
instance_announce -1, "[ Wraiths were summoned by an unknown power ]",bc_map,"0x77ff77";
|
||||
areamonster "2@orcs",167,25,177,35,"Wraith",1475,30,instance_npcname("#2Resurrect Monsters1", instance_id())+"::OnMyMobDead";
|
||||
stopnpctimer;
|
||||
end;
|
||||
|
|
@ -790,7 +790,7 @@ OnMyMobDead:
|
|||
if (.@mob_dead_num > 0) {
|
||||
areamonster "2@orcs",168,10,184,26,"Orc Archer",1189,.@mob_dead_num,instance_npcname("#2Resurrect Monsters3", instance_id())+"::OnMyMobDead";
|
||||
if (rand(1,15) == 3) {
|
||||
instance_announce 0, "Warning: Orc Archer teams are gathering near the altar.",bc_map,"0xff4444";
|
||||
instance_announce -1, "Warning: Orc Archer teams are gathering near the altar.",bc_map,"0xff4444";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -848,27 +848,27 @@ OnEnable:
|
|||
end;
|
||||
|
||||
OnTimer10:
|
||||
instance_announce 0, "Kruger's Whisper: I'll tell you how to get to the Shaman's altar.",bc_map,"0xffff00";
|
||||
instance_announce -1, "Kruger's Whisper: I'll tell you how to get to the Shaman's altar.",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer3510:
|
||||
instance_announce 0, "Kruger's Whisper: Do you see the braziers that light the path? Unseal the next zone by strengthening their flames.",bc_map,"0xffff00";
|
||||
instance_announce -1, "Kruger's Whisper: Do you see the braziers that light the path? Unseal the next zone by strengthening their flames.",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer10710:
|
||||
instance_announce 0, "Kruger's Whisper: Of course those monsters won't let you touch the braziers that easily.",bc_map,"0xffff00";
|
||||
instance_announce -1, "Kruger's Whisper: Of course those monsters won't let you touch the braziers that easily.",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer16310:
|
||||
instance_announce 0, "Kruger's Whisper: But still, try keep the battles not too noticable so the Shaman won't guard the altar with her army squad.",bc_map,"0xffff00";
|
||||
instance_announce -1, "Kruger's Whisper: But still, try keep the battles not too noticable so the Shaman won't guard the altar with her army squad.",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer21910:
|
||||
instance_announce 0, "Kruger's Whisper: Only the Party Leader can strengthen the flames, so protect your leader.",bc_map,"0xffff00";
|
||||
instance_announce -1, "Kruger's Whisper: Only the Party Leader can strengthen the flames, so protect your leader.",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer23910:
|
||||
instance_announce 0, "Mission: Unseal the zone by lighting the braziers. They can only be lit in a certain order, so be careful.",bc_map,"0x4444ff";
|
||||
instance_announce -1, "Mission: Unseal the zone by lighting the braziers. They can only be lit in a certain order, so be careful.",bc_map,"0x4444ff";
|
||||
donpcevent instance_npcname("#2Resurrect Monsters1", instance_id())+"::OnEnable";
|
||||
donpcevent instance_npcname("#2Resurrect Monsters3", instance_id())+"::OnEnable";
|
||||
donpcevent instance_npcname("Torch#1-1", instance_id())+"::OnEnable";
|
||||
|
|
@ -987,7 +987,7 @@ OnInstanceInit:
|
|||
|
||||
OnEnable:
|
||||
monster "2@orcs",109,156,"Safeguard Chief",1981,1,instance_npcname("#Mobs Control", instance_id())+"::OnMyMobDead1";
|
||||
instance_announce 0, "The Chief Orc of Safeguards: Oh!! Looks like I have company. Defeat me if you can!!",bc_map,"0xff8888";
|
||||
instance_announce -1, "The Chief Orc of Safeguards: Oh!! Looks like I have company. Defeat me if you can!!",bc_map,"0xff8888";
|
||||
end;
|
||||
|
||||
OnContinue:
|
||||
|
|
@ -1108,7 +1108,7 @@ OnInstanceInit:
|
|||
|
||||
OnEnable:
|
||||
monster "2@orcs",67,64,"Orc Sniper",1982,1,instance_npcname("#Mobs Control", instance_id())+"::OnMyMobDead2";
|
||||
instance_announce 0, "Orc Sniper: Hah! Pretty impressive that you made it this far, but your foolish little trip ends here...",bc_map,"0xff8888";
|
||||
instance_announce -1, "Orc Sniper: Hah! Pretty impressive that you made it this far, but your foolish little trip ends here...",bc_map,"0xff8888";
|
||||
end;
|
||||
|
||||
OnContinue:
|
||||
|
|
@ -1229,7 +1229,7 @@ OnInstanceInit:
|
|||
|
||||
OnEnable:
|
||||
monster "2@orcs",152,147,"Depraved Orc Spirit",1983,1,instance_npcname("#Mobs Control", instance_id())+"::OnMyMobDead3";
|
||||
instance_announce 0, "Depraved Orc Spirit: I smell flesh! Hungry! Wanna try some human meat!!",bc_map,"0xff8888";
|
||||
instance_announce -1, "Depraved Orc Spirit: I smell flesh! Hungry! Wanna try some human meat!!",bc_map,"0xff8888";
|
||||
end;
|
||||
|
||||
OnContinue:
|
||||
|
|
@ -1240,19 +1240,19 @@ OnContinue:
|
|||
end;
|
||||
|
||||
OnTimer10:
|
||||
instance_announce 0, "Shaman Cargalache: Hahaha!! So, you finally made it here. The assassin you sent was just terrible. That stupid Orc is getting cold under my feet.",bc_map,"0xffff00";
|
||||
instance_announce -1, "Shaman Cargalache: Hahaha!! So, you finally made it here. The assassin you sent was just terrible. That stupid Orc is getting cold under my feet.",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer6810:
|
||||
instance_announce 0, "Shaman Cargalache: My loyal slave, go get those intruders!",bc_map,"0xffff00";
|
||||
instance_announce -1, "Shaman Cargalache: My loyal slave, go get those intruders!",bc_map,"0xffff00";
|
||||
end;
|
||||
|
||||
OnTimer10310:
|
||||
instance_announce 0, "Depraved Orc Hero: Whatever you say, my lord.",bc_map,"0xff7777";
|
||||
instance_announce -1, "Depraved Orc Hero: Whatever you say, my lord.",bc_map,"0xff7777";
|
||||
end;
|
||||
|
||||
OnTimer13110:
|
||||
instance_announce 0, "Caution: You have been discovered by Shaman Cargalache. Kruger's plan to assassinate the Shaman has failed. You must defeat Cargalache and find traces of Kruger.",bc_map,"0x8888ff";
|
||||
instance_announce -1, "Caution: You have been discovered by Shaman Cargalache. Kruger's plan to assassinate the Shaman has failed. You must defeat Cargalache and find traces of Kruger.",bc_map,"0x8888ff";
|
||||
stopnpctimer;
|
||||
end;
|
||||
|
||||
|
|
@ -1278,19 +1278,19 @@ OnMyMobDead:
|
|||
donpcevent instance_npcname("Kruger#", instance_id())+"::OnEnable";
|
||||
set .@mob_ran,rand(1,5);
|
||||
if (.@mob_ran == 1) {
|
||||
instance_announce 0, "Shaman Cargalache: How... How could this be... How could someone like you...!!",bc_map,"0xffff00";
|
||||
instance_announce -1, "Shaman Cargalache: How... How could this be... How could someone like you...!!",bc_map,"0xffff00";
|
||||
}
|
||||
else if (.@mob_ran == 2) {
|
||||
instance_announce 0, "Shaman Cargalache: How is it that I've been overpowered by mere humans!",bc_map,"0xffff00";
|
||||
instance_announce -1, "Shaman Cargalache: How is it that I've been overpowered by mere humans!",bc_map,"0xffff00";
|
||||
}
|
||||
else if (.@mob_ran == 3) {
|
||||
instance_announce 0, "Shaman Cargalache: This... This can't be the end...",bc_map,"0xffff00";
|
||||
instance_announce -1, "Shaman Cargalache: This... This can't be the end...",bc_map,"0xffff00";
|
||||
}
|
||||
else if (.@mob_ran == 4) {
|
||||
instance_announce 0, "Shaman Cargalache: I... Can't die... Yet...!",bc_map,"0xffff00";
|
||||
instance_announce -1, "Shaman Cargalache: I... Can't die... Yet...!",bc_map,"0xffff00";
|
||||
}
|
||||
else {
|
||||
instance_announce 0, "Shaman Cargalache: Defeated by these fools... It can't be happening...!",bc_map,"0xffff00";
|
||||
instance_announce -1, "Shaman Cargalache: Defeated by these fools... It can't be happening...!",bc_map,"0xffff00";
|
||||
}
|
||||
donpcevent instance_npcname("#2Resurrect Monsters1", instance_id())+"::OnDisable";
|
||||
donpcevent instance_npcname("#2Resurrect Monsters3", instance_id())+"::OnDisable";
|
||||
|
|
|
|||
|
|
@ -263,8 +263,6 @@ monk_test,306,151,3 script Grave of Baphomet#edq 111,{
|
|||
switch(select("Touch the stone.:Step back.")) {
|
||||
case 1:
|
||||
set .@party_id,getcharid(1);
|
||||
set .@instance, instance_id(1);
|
||||
instance_attach(.@instance);
|
||||
|
||||
// 12 hour cooldown
|
||||
set .@ins_bapho_check,checkquest(3040,PLAYTIME);
|
||||
|
|
@ -726,7 +724,7 @@ OnDisable:
|
|||
|
||||
OnMyMobDead:
|
||||
if (mobcount("1@cata",instance_npcname("ins_baphomet_lotto3", instance_id())+"::OnMyMobDead") < 1) {
|
||||
instance_announce 0, "All apostles of Baphomet are dead!",bc_map,"0x00ff99";
|
||||
instance_announce -1, "All apostles of Baphomet are dead!",bc_map,"0x00ff99";
|
||||
}
|
||||
getitem 6002,1; //Token_Of_Apostle
|
||||
end;
|
||||
|
|
@ -807,7 +805,7 @@ OnMyMobDead:
|
|||
mes "[Voice of the Gravestone]";
|
||||
mes "Now I can substantialize my soul. I'll wait for you in front of the altar of fire located at the center of this grave. Let's meet there.";
|
||||
next;
|
||||
instance_announce 0, "Ancient Hero's Soul : I'll wait for you in front of the altar of fire located at the center",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : I'll wait for you in front of the altar of fire located at the center",bc_map,"0xFFFF00";
|
||||
mes "I can feel the voice becoming faint.";
|
||||
close;
|
||||
}
|
||||
|
|
@ -1023,7 +1021,7 @@ OnTouch:
|
|||
mes "[Ancient Hero's Soul]";
|
||||
mes "Go ahead, warriors.";
|
||||
cutin "",255;
|
||||
instance_announce 0, "Ancient Hero's Soul : Now you can go to the Main Altar's gate. It is located in the Southeast",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : Now you can go to the Main Altar's gate. It is located in the Southeast",bc_map,"0xFFFF00";
|
||||
close;
|
||||
}
|
||||
else if ('ins_baphomet == 4) {
|
||||
|
|
@ -1178,23 +1176,23 @@ OnDisable:;
|
|||
end;
|
||||
|
||||
OnTimer1800000:
|
||||
instance_announce 0, "Ancient Hero's Soul : We don't have enough time! Hurry up!",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : We don't have enough time! Hurry up!",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer2400000:
|
||||
instance_announce 0, "Ancient Hero's Soul : My body is disappearing... Hurry up!",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : My body is disappearing... Hurry up!",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer3000000:
|
||||
instance_announce 0, "Ancient Hero's Soul : Everything is over... There is no other way but to wait for the next chance...",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : Everything is over... There is no other way but to wait for the next chance...",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer3050000:
|
||||
instance_announce 0, "Ancient Hero's Soul : We failed... However... We still have a chance. I hope you will train yourselves until the time comes.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : We failed... However... We still have a chance. I hope you will train yourselves until the time comes.",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer3100000:
|
||||
instance_announce 0, "You've failed to open the seal of main altar.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "You've failed to open the seal of main altar.",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer3500000:
|
||||
|
|
@ -1221,19 +1219,19 @@ OnDisable:
|
|||
end;
|
||||
|
||||
OnTimer10000:
|
||||
instance_announce 0, "Baphomet : Humans... interfering again...",bc_map,"0xdb7093";
|
||||
instance_announce -1, "Baphomet : Humans... interfering again...",bc_map,"0xdb7093";
|
||||
end;
|
||||
|
||||
OnTimer13000:
|
||||
instance_announce 0, "Apostle of Baphomet : Humans! Humans have invaded our sanctum!",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Apostle of Baphomet : Humans! Humans have invaded our sanctum!",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer16000:
|
||||
instance_announce 0, "Apostle of Baphomet : Kill the humans! Do not stop the revival of our Master!",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Apostle of Baphomet : Kill the humans! Do not stop the revival of our Master!",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer18000:
|
||||
instance_announce 0, "Apostle of Baphomet : Hurry up and release the seals of the altars! Our Master's return is upon us!",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Apostle of Baphomet : Hurry up and release the seals of the altars! Our Master's return is upon us!",bc_map,"0xFFFF00";
|
||||
stopnpctimer;
|
||||
disablenpc instance_npcname("ins_2f_enter_broad", instance_id());
|
||||
end;
|
||||
|
|
@ -1242,7 +1240,7 @@ OnTimer18000:
|
|||
2@cata,50,67,0 script slave_left -1,5,5,{
|
||||
OnTouch:
|
||||
disablenpc instance_npcname("slave_left", instance_id());
|
||||
instance_announce 0, "Apostle of Baphomet : Kill the humans! Don't let them interrupt the revival of our Master!",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Apostle of Baphomet : Kill the humans! Don't let them interrupt the revival of our Master!",bc_map,"0xFFFF00";
|
||||
monster "2@cata",55,67,"Apostle of Baphomet",1869,1;
|
||||
monster "2@cata",51,67,"Apostle of Baphomet",1291,1;
|
||||
monster "2@cata",58,67,"Apostle of Baphomet",1292,1;
|
||||
|
|
@ -1265,7 +1263,7 @@ OnTouch:
|
|||
2@cata,109,67,0 script slave_right -1,5,5,{
|
||||
OnTouch:
|
||||
disablenpc instance_npcname("slave_right", instance_id());
|
||||
instance_announce 0, "Apostle of Baphomet : Kill the humans! Don't let them interrupt the revival of our Master!",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Apostle of Baphomet : Kill the humans! Don't let them interrupt the revival of our Master!",bc_map,"0xFFFF00";
|
||||
monster "2@cata",105,67,"Apostle of Baphomet",1869,1;
|
||||
monster "2@cata",104,67,"Apostle of Baphomet",1291,1;
|
||||
monster "2@cata",107,67,"Apostle of Baphomet",1869,1;
|
||||
|
|
@ -1288,7 +1286,7 @@ OnTouch:
|
|||
2@cata,79,39,0 script slave_down -1,5,5,{
|
||||
OnTouch:
|
||||
disablenpc instance_npcname("slave_down", instance_id());
|
||||
instance_announce 0, "Apostle of Baphomet : Kill the humans! Don't let them interrupt the revival of our Master!",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Apostle of Baphomet : Kill the humans! Don't let them interrupt the revival of our Master!",bc_map,"0xFFFF00";
|
||||
monster "2@cata",78,41,"Apostle of Baphomet",1869,1;
|
||||
monster "2@cata",79,42,"Apostle of Baphomet",1291,1;
|
||||
monster "2@cata",78,46,"Apostle of Baphomet",1869,1;
|
||||
|
|
@ -1330,7 +1328,7 @@ OnTouch:
|
|||
percentheal -50,0;
|
||||
sc_start Eff_Stone,20000,0;
|
||||
setquest 3041;
|
||||
instance_announce 0, "The seal activated by putting magical power into the altar.",bc_map,"0x87ceeb";
|
||||
instance_announce -1, "The seal activated by putting magical power into the altar.",bc_map,"0x87ceeb";
|
||||
mes "I can feel the power of the altar came back by adding magical power.";
|
||||
next;
|
||||
mes "But you can't use your magic for 3 minutes because you used your SP on the altar.";
|
||||
|
|
@ -1414,27 +1412,27 @@ OnDisable:
|
|||
end;
|
||||
|
||||
OnTimer3000:
|
||||
instance_announce 0, "Ancient Hero's Soul : My God! The seal of the Main Altar is weakening!",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : My God! The seal of the Main Altar is weakening!",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer6000:
|
||||
instance_announce 0, "Ancient Hero's Soul : My descendants... Listen carefully to what I'm going to say.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : My descendants... Listen carefully to what I'm going to say.",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer9000:
|
||||
instance_announce 0, "Ancient Hero's Soul : The altars that control the Main Altar's power are located in the Northeast, Southeast, Southwest and Northwest corners of this room.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : The altars that control the Main Altar's power are located in the Northeast, Southeast, Southwest and Northwest corners of this room.",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer12000:
|
||||
instance_announce 0, "Ancient Hero's Soul : Find these altars and activate their seals before Baphomet revives.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : Find these altars and activate their seals before Baphomet revives.",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer15000:
|
||||
instance_announce 0, "Baphomet : It's too late, weaklings... Now, you'll feel the despair of death!",bc_map,"0xdb7093";
|
||||
instance_announce -1, "Baphomet : It's too late, weaklings... Now, you'll feel the despair of death!",bc_map,"0xdb7093";
|
||||
end;
|
||||
|
||||
OnTimer17000:
|
||||
instance_announce 0, "Baphomet : No one can harm me here. You will be my first sacrifice.",bc_map,"0xdb7093";
|
||||
instance_announce -1, "Baphomet : No one can harm me here. You will be my first sacrifice.",bc_map,"0xdb7093";
|
||||
donpcevent instance_npcname("control_baphomet", instance_id())+"::OnEnable";
|
||||
donpcevent instance_npcname("ins_2f_hero_broad2", instance_id())+"::OnEnable";
|
||||
stopnpctimer;
|
||||
|
|
@ -1457,7 +1455,7 @@ OnMyMobDead:
|
|||
if (mobcount("2@cata",instance_npcname("control_baphomet", instance_id())+"::OnMyMobDead") < 1) {
|
||||
set 'ins_baphomet,7;
|
||||
erasequest 3041;
|
||||
instance_announce 0, "Baphomet : No! Nonono! How dare these weaklings defeat me!... No!!...",bc_map,"0xdb7093";
|
||||
instance_announce -1, "Baphomet : No! Nonono! How dare these weaklings defeat me!... No!!...",bc_map,"0xdb7093";
|
||||
enablenpc instance_npcname("Ancient Hero's Soul#2F", instance_id());
|
||||
disablenpc instance_npcname("slave_down", instance_id());
|
||||
disablenpc instance_npcname("slave_left", instance_id());
|
||||
|
|
@ -1486,31 +1484,31 @@ OnDisable:
|
|||
end;
|
||||
|
||||
OnTimer8000:
|
||||
instance_announce 0, "Ancient Hero's Soul : Don't be discouraged, Baphomet can still be defeated!",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : Don't be discouraged, Baphomet can still be defeated!",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer11000:
|
||||
instance_announce 0, "Ancient Hero's Soul : Go to the altars and activate their seals.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : Go to the altars and activate their seals.",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer13000:
|
||||
instance_announce 0, "Ancient Hero's Soul : Once the seals recover their power, Baphomet will be vulnerable.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : Once the seals recover their power, Baphomet will be vulnerable.",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer16000:
|
||||
instance_announce 0, "Ancient Hero's Soul : You should lure Baphomet to the unsealed Altars. Otherwise, your efforts will be futile.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : You should lure Baphomet to the unsealed Altars. Otherwise, your efforts will be futile.",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer19000:
|
||||
instance_announce 0, "Ancient Hero's Soul : We have only 1 hour to stop Baphomet. If time runs out, the power of the seals will be useless.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : We have only 1 hour to stop Baphomet. If time runs out, the power of the seals will be useless.",bc_map,"0xFFFF00";
|
||||
end;
|
||||
|
||||
OnTimer22000:
|
||||
instance_announce 0, "Baphomet : It's useless. Make more seals. I'll crush them all. None of you will survive!",bc_map,"0xdb7093";
|
||||
instance_announce -1, "Baphomet : It's useless. Make more seals. I'll crush them all. None of you will survive!",bc_map,"0xdb7093";
|
||||
end;
|
||||
|
||||
OnTimer26000:
|
||||
instance_announce 0, "Ancient Hero's Soul : The magical power of the central seal is running out. Go to the central seal and put the magical power.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : The magical power of the central seal is running out. Go to the central seal and put the magical power.",bc_map,"0xFFFF00";
|
||||
enablenpc instance_npcname("Magical Seal#0", instance_id());
|
||||
disablenpc instance_npcname("Magical Seal#2", instance_id());
|
||||
disablenpc instance_npcname("Magical Seal#4", instance_id());
|
||||
|
|
@ -1586,11 +1584,11 @@ OnDisable:
|
|||
end;
|
||||
|
||||
OnTimer3600000:
|
||||
instance_announce 0, "Baphomet : krrrr... Now you can't stop me with the seals. All you can do is wait for death!",bc_map,"0xdb7093";
|
||||
instance_announce -1, "Baphomet : krrrr... Now you can't stop me with the seals. All you can do is wait for death!",bc_map,"0xdb7093";
|
||||
end;
|
||||
|
||||
OnTimer3605000:
|
||||
instance_announce 0, "Ancient Hero's Soul : We can't stop Baphomet with the magical power of the seals anymore. Now everything depends on God...",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : We can't stop Baphomet with the magical power of the seals anymore. Now everything depends on God...",bc_map,"0xFFFF00";
|
||||
donpcevent instance_npcname("ins_2f_hero_pattern_c", instance_id())+"::OnDisable";
|
||||
end;
|
||||
}
|
||||
|
|
@ -1609,7 +1607,7 @@ OnDisable:
|
|||
OnTimer70000:
|
||||
switch(rand(1,5)) {
|
||||
case 1:
|
||||
instance_announce 0, "Ancient Hero's Soul : The seal of the Main Altar is running out. Strengthen the Main Altar's seal!",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : The seal of the Main Altar is running out. Strengthen the Main Altar's seal!",bc_map,"0xFFFF00";
|
||||
enablenpc instance_npcname("Magical Seal#0", instance_id());
|
||||
disablenpc instance_npcname("Magical Seal#2", instance_id());
|
||||
disablenpc instance_npcname("Magical Seal#4", instance_id());
|
||||
|
|
@ -1617,7 +1615,7 @@ OnTimer70000:
|
|||
disablenpc instance_npcname("Magical Seal#10", instance_id());
|
||||
break;
|
||||
case 2:
|
||||
instance_announce 0, "Ancient Hero's Soul : The magical power of the seal at 2 o'clock is running out. Go to 2 o'clock and put the magical power in the seal.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : The magical power of the seal at 2 o'clock is running out. Go to 2 o'clock and put the magical power in the seal.",bc_map,"0xFFFF00";
|
||||
disablenpc instance_npcname("Magical Seal#0", instance_id());
|
||||
enablenpc instance_npcname("Magical Seal#2", instance_id());
|
||||
disablenpc instance_npcname("Magical Seal#4", instance_id());
|
||||
|
|
@ -1625,7 +1623,7 @@ OnTimer70000:
|
|||
disablenpc instance_npcname("Magical Seal#10", instance_id());
|
||||
break;
|
||||
case 3:
|
||||
instance_announce 0, "Ancient Hero's Soul : The magical power of the seal at 4 o'clock is running out. Go to 4 o'clock and put the magical power in the seal.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : The magical power of the seal at 4 o'clock is running out. Go to 4 o'clock and put the magical power in the seal.",bc_map,"0xFFFF00";
|
||||
disablenpc instance_npcname("Magical Seal#0", instance_id());
|
||||
disablenpc instance_npcname("Magical Seal#2", instance_id());
|
||||
enablenpc instance_npcname("Magical Seal#4", instance_id());
|
||||
|
|
@ -1633,7 +1631,7 @@ OnTimer70000:
|
|||
disablenpc instance_npcname("Magical Seal#10", instance_id());
|
||||
break;
|
||||
case 4:
|
||||
instance_announce 0, "Ancient Hero's Soul : The magical power of the seal at 8 o'clock is running out. Go to 8 o'clock and put the magical power in the seal.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : The magical power of the seal at 8 o'clock is running out. Go to 8 o'clock and put the magical power in the seal.",bc_map,"0xFFFF00";
|
||||
disablenpc instance_npcname("Magical Seal#0", instance_id());
|
||||
disablenpc instance_npcname("Magical Seal#2", instance_id());
|
||||
disablenpc instance_npcname("Magical Seal#4", instance_id());
|
||||
|
|
@ -1641,7 +1639,7 @@ OnTimer70000:
|
|||
disablenpc instance_npcname("Magical Seal#10", instance_id());
|
||||
break;
|
||||
case 5:
|
||||
instance_announce 0, "Ancient Hero's Soul : The magical power of the seal at 10 o'clock is running out. Go to 10 o'clock and put the magical power in the seal.",bc_map,"0xFFFF00";
|
||||
instance_announce -1, "Ancient Hero's Soul : The magical power of the seal at 10 o'clock is running out. Go to 10 o'clock and put the magical power in the seal.",bc_map,"0xFFFF00";
|
||||
disablenpc instance_npcname("Magical Seal#0", instance_id());
|
||||
disablenpc instance_npcname("Magical Seal#2", instance_id());
|
||||
disablenpc instance_npcname("Magical Seal#4", instance_id());
|
||||
|
|
|
|||
|
|
@ -81,7 +81,8 @@ struct mmo_map_server {
|
|||
uint32 ip;
|
||||
uint16 port;
|
||||
int users;
|
||||
unsigned short map[MAX_MAP_PER_SERVER];
|
||||
unsigned short *map;
|
||||
unsigned short maps;
|
||||
} server[MAX_MAP_SERVERS];
|
||||
|
||||
int char_fd=-1;
|
||||
|
|
@ -2628,7 +2629,7 @@ int search_mapserver(unsigned short map, uint32 ip, uint16 port);
|
|||
/// Initializes a server structure.
|
||||
void mapif_server_init(int id)
|
||||
{
|
||||
memset(&server[id], 0, sizeof(server[id]));
|
||||
//memset(&server[id], 0, sizeof(server[id]));
|
||||
server[id].fd = -1;
|
||||
}
|
||||
|
||||
|
|
@ -2655,7 +2656,7 @@ void mapif_server_reset(int id)
|
|||
WBUFL(buf,4) = htonl(server[id].ip);
|
||||
WBUFW(buf,8) = htons(server[id].port);
|
||||
j = 0;
|
||||
for(i = 0; i < MAX_MAP_PER_SERVER; i++)
|
||||
for(i = 0; i < server[id].maps; i++)
|
||||
if (server[id].map[i])
|
||||
WBUFW(buf,10+(j++)*4) = server[id].map[i];
|
||||
if (j > 0) {
|
||||
|
|
@ -2725,8 +2726,11 @@ int parse_frommap(int fd)
|
|||
case 0x2afa: // Receiving map names list from the map-server
|
||||
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
|
||||
return 0;
|
||||
|
||||
memset(server[id].map, 0, sizeof(server[id].map));
|
||||
if( server[id].map != NULL ) { aFree(server[id].map); server[id].map = NULL; }
|
||||
|
||||
server[id].maps = ( RFIFOW(fd, 2) - 4 ) / 4;
|
||||
CREATE(server[id].map, unsigned short, server[id].maps);
|
||||
|
||||
j = 0;
|
||||
for(i = 4; i < RFIFOW(fd,2); i += 4) {
|
||||
server[id].map[j] = RFIFOW(fd,i);
|
||||
|
|
@ -3392,10 +3396,14 @@ int parse_frommap(int fd)
|
|||
if( RFIFOREST(fd) < RFIFOW(fd,4) )
|
||||
return 0;/* packet wasn't fully received yet (still fragmented) */
|
||||
else {
|
||||
int sfd;/* stat server fd */
|
||||
int sfd;/* stat server fd */
|
||||
struct hSockOpt opt;
|
||||
RFIFOSKIP(fd, 2);/* we skip first 2 bytes which are the 0x3008, so we end up with a buffer equal to the one we send */
|
||||
|
||||
if( (sfd = make_connection(host2ip("stats.hercules.ws"),(uint16)25427,true) ) == -1 ) {
|
||||
opt.silent = 1;
|
||||
opt.setTimeo = 1;
|
||||
|
||||
if( (sfd = make_connection(host2ip("stats.hercules.ws"),(uint16)25427,&opt) ) == -1 ) {
|
||||
RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */
|
||||
RFIFOFLUSH(fd);
|
||||
break;/* connection not possible, we drop the report */
|
||||
|
|
@ -4275,7 +4283,6 @@ int parse_char(int fd)
|
|||
server[i].ip = ntohl(RFIFOL(fd,54));
|
||||
server[i].port = ntohs(RFIFOW(fd,58));
|
||||
server[i].users = 0;
|
||||
memset(server[i].map, 0, sizeof(server[i].map));
|
||||
session[fd]->func_parse = parse_frommap;
|
||||
session[fd]->flag.server = 1;
|
||||
realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
|
||||
|
|
@ -4486,12 +4493,12 @@ int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data
|
|||
return 0;
|
||||
|
||||
ShowInfo("Attempt to connect to login-server...\n");
|
||||
login_fd = make_connection(login_ip, login_port, false);
|
||||
if (login_fd == -1)
|
||||
{ //Try again later. [Skotlex]
|
||||
|
||||
if ( (login_fd = make_connection(login_ip, login_port, NULL)) == -1) { //Try again later. [Skotlex]
|
||||
login_fd = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
session[login_fd]->func_parse = parse_fromlogin;
|
||||
session[login_fd]->flag.server = 1;
|
||||
realloc_fifo(login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
|
||||
|
|
@ -4858,8 +4865,8 @@ int char_config_read(const char* cfgName)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void do_final(void)
|
||||
{
|
||||
void do_final(void) {
|
||||
int i;
|
||||
ShowStatus("Terminating...\n");
|
||||
|
||||
set_all_offline(-1);
|
||||
|
|
@ -4879,8 +4886,7 @@ void do_final(void)
|
|||
online_char_db->destroy(online_char_db, NULL);
|
||||
auth_db->destroy(auth_db, NULL);
|
||||
|
||||
if( char_fd != -1 )
|
||||
{
|
||||
if( char_fd != -1 ) {
|
||||
do_close(char_fd);
|
||||
char_fd = -1;
|
||||
}
|
||||
|
|
@ -4888,6 +4894,10 @@ void do_final(void)
|
|||
SQL->Free(sql_handle);
|
||||
mapindex_final();
|
||||
|
||||
for(i = 0; i < MAX_MAP_SERVERS; i++ )
|
||||
if( server[i].map )
|
||||
aFree(server[i].map);
|
||||
|
||||
ShowStatus("Finished.\n");
|
||||
}
|
||||
|
||||
|
|
@ -4923,11 +4933,17 @@ void do_shutdown(void)
|
|||
|
||||
|
||||
int do_init(int argc, char **argv) {
|
||||
int i;
|
||||
memset(&skillid2idx, 0, sizeof(skillid2idx));
|
||||
|
||||
for(i = 0; i < MAX_MAP_SERVERS; i++ )
|
||||
server[i].map = NULL;
|
||||
|
||||
//Read map indexes
|
||||
mapindex_init();
|
||||
start_point.map = mapindex_name2id("new_zone01");
|
||||
|
||||
|
||||
pincode_defaults();
|
||||
|
||||
char_config_read((argc < 2) ? CHAR_CONF_NAME : argv[1]);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ struct online_char_data {
|
|||
|
||||
DBMap* online_char_db; // int account_id -> struct online_char_data*
|
||||
|
||||
#define MAX_MAP_SERVERS 30
|
||||
#define MAX_MAP_SERVERS 2
|
||||
|
||||
#define DEFAULT_AUTOSAVE_INTERVAL 300*1000
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ CPCMD(exit) {
|
|||
CPCMD(ers_report) {
|
||||
ers_report();
|
||||
}
|
||||
CPCMD(mem_report) {
|
||||
memmgr_report(line?atoi(line):0);
|
||||
}
|
||||
CPCMD(help) {
|
||||
unsigned int i = 0;
|
||||
for ( i = 0; i < console->cmd_list_count; i++ ) {
|
||||
|
|
@ -115,6 +118,7 @@ void console_load_defaults(void) {
|
|||
CP_DEF(help),
|
||||
CP_DEF_C(server),
|
||||
CP_DEF_S(ers_report,server),
|
||||
CP_DEF_S(mem_report,server),
|
||||
CP_DEF_S(malloc_usage,server),
|
||||
CP_DEF_S(exit,server),
|
||||
};
|
||||
|
|
@ -227,8 +231,10 @@ void console_parse_sub(char *line) {
|
|||
char *tok;
|
||||
char sublist[CP_CMD_LENGTH * 5];
|
||||
unsigned int i, len = 0;
|
||||
|
||||
memcpy(bline, line, 200);
|
||||
tok = strtok(line, " ");
|
||||
|
||||
for ( i = 0; i < console->cmd_list_count; i++ ) {
|
||||
if( strcmpi(tok,console->cmd_list[i]->cmd) == 0 )
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -200,6 +200,8 @@ static struct unit_head_large *unit_head_large_first = NULL;
|
|||
static struct block* block_malloc(unsigned short hash);
|
||||
static void block_free(struct block* p);
|
||||
static size_t memmgr_usage_bytes;
|
||||
static size_t memmgr_usage_bytes_t;
|
||||
|
||||
|
||||
#define block2unit(p, n) ((struct unit_head*)(&(p)->data[ p->unit_size * (n) ]))
|
||||
#define memmgr_assert(v) do { if(!(v)) { ShowError("Memory manager: assertion '" #v "' failed!\n"); } } while(0)
|
||||
|
|
@ -245,6 +247,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func )
|
|||
/* At that time, the distinction by assigning NULL to unit_head.block */
|
||||
if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
|
||||
struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func);
|
||||
memmgr_usage_bytes_t += size+sizeof(struct unit_head_large);
|
||||
if(p != NULL) {
|
||||
p->size = size;
|
||||
p->unit_head.block = NULL;
|
||||
|
|
@ -401,6 +404,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func )
|
|||
head_large->next->prev = head_large->prev;
|
||||
}
|
||||
memmgr_usage_bytes -= head_large->size;
|
||||
memmgr_usage_bytes_t -= head_large->size + sizeof(struct unit_head_large);
|
||||
#ifdef DEBUG_MEMMGR
|
||||
// set freed memory to 0xfd
|
||||
memset(ptr, 0xfd, head_large->size);
|
||||
|
|
@ -457,6 +461,7 @@ static struct block* block_malloc(unsigned short hash)
|
|||
} else {
|
||||
/* Newly allocated space for the block */
|
||||
p = (struct block*)MALLOC(sizeof(struct block) * (BLOCK_ALLOC), __FILE__, __LINE__, __func__ );
|
||||
memmgr_usage_bytes_t += sizeof(struct block) * (BLOCK_ALLOC);
|
||||
if(p == NULL) {
|
||||
ShowFatalError("Memory manager::block_alloc failed.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -650,6 +655,86 @@ static void memmgr_final (void)
|
|||
}
|
||||
#endif /* LOG_MEMMGR */
|
||||
}
|
||||
/* [Ind/Hercules] */
|
||||
void memmgr_report (int extra) {
|
||||
struct block *block = block_first;
|
||||
struct unit_head_large *large = unit_head_large_first;
|
||||
unsigned int count = 0, size = 0;
|
||||
int j;
|
||||
unsigned short msize = 1024;
|
||||
struct {
|
||||
const char *file;
|
||||
unsigned short line;
|
||||
unsigned int size;
|
||||
unsigned int count;
|
||||
} data[100];
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
if( extra != 0 )
|
||||
msize = extra;
|
||||
|
||||
while (block) {
|
||||
if (block->unit_used) {
|
||||
int i;
|
||||
for (i = 0; i < block->unit_maxused; i++) {
|
||||
struct unit_head *head = block2unit(block, i);
|
||||
if( head->block != NULL && head->size > msize ) {
|
||||
for( j = 0; j < 100; j++ ) {
|
||||
if( data[j].file == head->file && data[j].line == head->line ) {
|
||||
data[j].size += head->size;
|
||||
data[j].count += 1;
|
||||
break;
|
||||
} else if( data[j].size == 0 ) {
|
||||
data[j].file = head->file;
|
||||
data[j].line = head->line;
|
||||
data[j].size = head->size;
|
||||
data[j].count += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
size += (unsigned int)head->size;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
block = block->block_next;
|
||||
}
|
||||
|
||||
while(large) {
|
||||
if( large->size > msize ) {
|
||||
for( j = 0; j < 100; j++ ) {
|
||||
if( data[j].file == large->unit_head.file && data[j].line == large->unit_head.line ) {
|
||||
data[j].size += large->size;
|
||||
data[j].count += 1;
|
||||
break;
|
||||
} else if( data[j].size == 0 ) {
|
||||
data[j].file = large->unit_head.file;
|
||||
data[j].line = large->unit_head.line;
|
||||
data[j].size = large->size;
|
||||
data[j].count += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
size += (unsigned int)large->size;
|
||||
count++;
|
||||
}
|
||||
large = large->next;
|
||||
}
|
||||
for( j = 0; j < 100; j++ ) {
|
||||
if( data[j].size != 0 ) {
|
||||
ShowMessage("[malloc] : "CL_WHITE"%s"CL_RESET":"CL_WHITE"%d"CL_RESET" %d instances => %.2f MB\n",data[j].file,data[j].line,data[j].count,(double)((data[j].size)/1024)/1024);
|
||||
}
|
||||
}
|
||||
ShowMessage("[malloc] : reporting %u instances | %.2f MB\n",count,(double)((size)/1024)/1024);
|
||||
ShowMessage("[malloc] : internal usage %.2f MB | %.2f MB\n",(double)((memmgr_usage_bytes_t-memmgr_usage_bytes)/1024)/1024,(double)((memmgr_usage_bytes_t)/1024)/1024);
|
||||
|
||||
if( extra ) {
|
||||
ShowMessage("[malloc] : unit_head_large: %d bytes\n",sizeof(struct unit_head_large));
|
||||
ShowMessage("[malloc] : unit_head: %d bytes\n",sizeof(struct unit_head));
|
||||
ShowMessage("[malloc] : block: %d bytes\n",sizeof(struct block));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void memmgr_init (void)
|
||||
{
|
||||
|
|
@ -677,8 +762,7 @@ void malloc_memory_check(void)
|
|||
|
||||
/// Returns true if a pointer is valid.
|
||||
/// The check is best-effort, false positives are possible.
|
||||
bool malloc_verify_ptr(void* ptr)
|
||||
{
|
||||
bool malloc_verify_ptr(void* ptr) {
|
||||
#ifdef USE_MEMMGR
|
||||
return memmgr_verify(ptr) && MEMORY_VERIFY(ptr);
|
||||
#else
|
||||
|
|
@ -687,8 +771,7 @@ bool malloc_verify_ptr(void* ptr)
|
|||
}
|
||||
|
||||
|
||||
size_t malloc_usage (void)
|
||||
{
|
||||
size_t malloc_usage (void) {
|
||||
#ifdef USE_MEMMGR
|
||||
return memmgr_usage ();
|
||||
#else
|
||||
|
|
@ -696,16 +779,16 @@ size_t malloc_usage (void)
|
|||
#endif
|
||||
}
|
||||
|
||||
void malloc_final (void)
|
||||
{
|
||||
void malloc_final (void) {
|
||||
#ifdef USE_MEMMGR
|
||||
memmgr_final ();
|
||||
#endif
|
||||
MEMORY_CHECK();
|
||||
}
|
||||
|
||||
void malloc_init (void)
|
||||
{
|
||||
void malloc_init (void) {
|
||||
memmgr_usage_bytes_t = 0;
|
||||
memmgr_usage_bytes = 0;
|
||||
#if defined(DMALLOC) && defined(CYGWIN)
|
||||
// http://dmalloc.com/docs/latest/online/dmalloc_19.html
|
||||
dmalloc_debug_setup(getenv("DMALLOC_OPTIONS"));
|
||||
|
|
@ -720,8 +803,7 @@ void malloc_init (void)
|
|||
#endif
|
||||
}
|
||||
|
||||
void malloc_defaults()
|
||||
{
|
||||
void malloc_defaults(void) {
|
||||
malloclib = &malloclib_s;
|
||||
malloclib->init = malloc_init;
|
||||
malloclib->final = malloc_final;
|
||||
|
|
|
|||
|
|
@ -80,5 +80,7 @@ struct malloc_interface {
|
|||
void (*final) (void);
|
||||
} malloclib_s;
|
||||
|
||||
void memmgr_report (int extra);
|
||||
|
||||
struct malloc_interface *malloclib;
|
||||
#endif /* _MALLOC_H_ */
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@
|
|||
#define MAX_HOTKEYS 38
|
||||
#endif
|
||||
|
||||
#define MAX_MAP_PER_SERVER 1500 // Increased to allow creation of Instance Maps
|
||||
#define MAX_INVENTORY 100
|
||||
//Max number of characters per account. Note that changing this setting alone is not enough if the client is not hexed to support more characters as well.
|
||||
#define MAX_CHARS 9
|
||||
|
|
@ -526,6 +525,10 @@ struct guild {
|
|||
|
||||
/* TODO: still used for something?|: */
|
||||
unsigned short save_flag; // for TXT saving
|
||||
|
||||
unsigned short *instance;
|
||||
unsigned short instances;
|
||||
|
||||
void *channel;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -280,9 +280,10 @@ void set_nonblocking(int fd, unsigned long yes)
|
|||
ShowError("set_nonblocking: Failed to set socket #%d to non-blocking mode (%s) - Please report this!!!\n", fd, error_msg());
|
||||
}
|
||||
|
||||
void setsocketopts(int fd)
|
||||
{
|
||||
void setsocketopts(int fd, struct hSockOpt *opt) {
|
||||
int yes = 1; // reuse fix
|
||||
struct linger lopt;
|
||||
|
||||
#if !defined(WIN32)
|
||||
// set SO_REAUSEADDR to true, unix only. on windows this option causes
|
||||
// the previous owner of the socket to give up, which is not desirable
|
||||
|
|
@ -297,15 +298,22 @@ void setsocketopts(int fd)
|
|||
// The RO protocol is mainly single-packet request/response, plus the FIFO model already does packet grouping anyway.
|
||||
sSetsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof(yes));
|
||||
|
||||
if( opt && opt->setTimeo ) {
|
||||
struct timeval timeout;
|
||||
|
||||
timeout.tv_sec = 5;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
sSetsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout));
|
||||
sSetsockopt(fd,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(timeout));
|
||||
}
|
||||
|
||||
// force the socket into no-wait, graceful-close mode (should be the default, but better make sure)
|
||||
//(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/closesocket_2.asp)
|
||||
{
|
||||
struct linger opt;
|
||||
opt.l_onoff = 0; // SO_DONTLINGER
|
||||
opt.l_linger = 0; // Do not care
|
||||
if( sSetsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&opt, sizeof(opt)) )
|
||||
lopt.l_onoff = 0; // SO_DONTLINGER
|
||||
lopt.l_linger = 0; // Do not care
|
||||
if( sSetsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&lopt, sizeof(lopt)) )
|
||||
ShowWarning("setsocketopts: Unable to set SO_LINGER mode for connection #%d!\n", fd);
|
||||
}
|
||||
}
|
||||
|
||||
/*======================================
|
||||
|
|
@ -404,8 +412,7 @@ void flush_fifos(void)
|
|||
/*======================================
|
||||
* CORE : Connection functions
|
||||
*--------------------------------------*/
|
||||
int connect_client(int listen_fd)
|
||||
{
|
||||
int connect_client(int listen_fd) {
|
||||
int fd;
|
||||
struct sockaddr_in client_address;
|
||||
socklen_t len;
|
||||
|
|
@ -417,20 +424,18 @@ int connect_client(int listen_fd)
|
|||
ShowError("connect_client: accept failed (%s)!\n", error_msg());
|
||||
return -1;
|
||||
}
|
||||
if( fd == 0 )
|
||||
{// reserved
|
||||
if( fd == 0 ) { // reserved
|
||||
ShowError("connect_client: Socket #0 is reserved - Please report this!!!\n");
|
||||
sClose(fd);
|
||||
return -1;
|
||||
}
|
||||
if( fd >= FD_SETSIZE )
|
||||
{// socket number too big
|
||||
if( fd >= FD_SETSIZE ) { // socket number too big
|
||||
ShowError("connect_client: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
|
||||
sClose(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
setsocketopts(fd);
|
||||
setsocketopts(fd,NULL);
|
||||
set_nonblocking(fd, 1);
|
||||
|
||||
#ifndef MINICORE
|
||||
|
|
@ -457,25 +462,22 @@ int make_listen_bind(uint32 ip, uint16 port)
|
|||
|
||||
fd = sSocket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if( fd == -1 )
|
||||
{
|
||||
if( fd == -1 ) {
|
||||
ShowError("make_listen_bind: socket creation failed (%s)!\n", error_msg());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if( fd == 0 )
|
||||
{// reserved
|
||||
if( fd == 0 ) { // reserved
|
||||
ShowError("make_listen_bind: Socket #0 is reserved - Please report this!!!\n");
|
||||
sClose(fd);
|
||||
return -1;
|
||||
}
|
||||
if( fd >= FD_SETSIZE )
|
||||
{// socket number too big
|
||||
if( fd >= FD_SETSIZE ) { // socket number too big
|
||||
ShowError("make_listen_bind: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
|
||||
sClose(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
setsocketopts(fd);
|
||||
setsocketopts(fd,NULL);
|
||||
set_nonblocking(fd, 1);
|
||||
|
||||
server_address.sin_family = AF_INET;
|
||||
|
|
@ -503,7 +505,7 @@ int make_listen_bind(uint32 ip, uint16 port)
|
|||
return fd;
|
||||
}
|
||||
|
||||
int make_connection(uint32 ip, uint16 port, bool silent) {
|
||||
int make_connection(uint32 ip, uint16 port, struct hSockOpt *opt) {
|
||||
struct sockaddr_in remote_address;
|
||||
int fd;
|
||||
int result;
|
||||
|
|
@ -514,31 +516,29 @@ int make_connection(uint32 ip, uint16 port, bool silent) {
|
|||
ShowError("make_connection: socket creation failed (%s)!\n", error_msg());
|
||||
return -1;
|
||||
}
|
||||
if( fd == 0 )
|
||||
{// reserved
|
||||
if( fd == 0 ) {// reserved
|
||||
ShowError("make_connection: Socket #0 is reserved - Please report this!!!\n");
|
||||
sClose(fd);
|
||||
return -1;
|
||||
}
|
||||
if( fd >= FD_SETSIZE )
|
||||
{// socket number too big
|
||||
if( fd >= FD_SETSIZE ) {// socket number too big
|
||||
ShowError("make_connection: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
|
||||
sClose(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
setsocketopts(fd);
|
||||
setsocketopts(fd,opt);
|
||||
|
||||
remote_address.sin_family = AF_INET;
|
||||
remote_address.sin_addr.s_addr = htonl(ip);
|
||||
remote_address.sin_port = htons(port);
|
||||
|
||||
if( !silent )
|
||||
if( !( opt && opt->silent ) )
|
||||
ShowStatus("Connecting to %d.%d.%d.%d:%i\n", CONVIP(ip), port);
|
||||
|
||||
result = sConnect(fd, (struct sockaddr *)(&remote_address), sizeof(struct sockaddr_in));
|
||||
if( result == SOCKET_ERROR ) {
|
||||
if( !silent )
|
||||
if( !( opt && opt->silent ) )
|
||||
ShowError("make_connection: connect failed (socket #%d, %s)!\n", fd, error_msg());
|
||||
do_close(fd);
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
|
||||
// For more information, see LICENCE in the main folder
|
||||
// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
|
||||
// See the LICENSE file
|
||||
// Portions Copyright (c) Athena Dev Teams
|
||||
|
||||
#ifndef _SOCKET_H_
|
||||
#define _SOCKET_H_
|
||||
|
|
@ -48,6 +49,9 @@
|
|||
} \
|
||||
} while(0)
|
||||
|
||||
/* [Ind/Hercules] */
|
||||
#define RFIFO2PTR(fd,len) (void*)(session[fd]->rdata + len)
|
||||
|
||||
// buffer I/O macros
|
||||
#define RBUFP(p,pos) (((uint8*)(p)) + (pos))
|
||||
#define RBUFB(p,pos) (*(uint8*)RBUFP((p),(pos)))
|
||||
|
|
@ -94,6 +98,10 @@ struct socket_data
|
|||
void* session_data; // stores application-specific data related to the session
|
||||
};
|
||||
|
||||
struct hSockOpt {
|
||||
unsigned int silent : 1;
|
||||
unsigned int setTimeo : 1;
|
||||
};
|
||||
|
||||
// Data prototype declaration
|
||||
|
||||
|
|
@ -113,7 +121,7 @@ extern bool session_isActive(int fd);
|
|||
// Function prototype declaration
|
||||
|
||||
int make_listen_bind(uint32 ip, uint16 port);
|
||||
int make_connection(uint32 ip, uint16 port, bool silent);
|
||||
int make_connection(uint32 ip, uint16 port, struct hSockOpt *opt);
|
||||
int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size);
|
||||
int realloc_writefifo(int fd, size_t addition);
|
||||
int WFIFOSET(int fd, size_t len);
|
||||
|
|
|
|||
|
|
@ -3940,7 +3940,7 @@ ACMD(mapinfo) {
|
|||
for (i = 0; i < map[m_id].npc_num;)
|
||||
{
|
||||
nd = map[m_id].npc[i];
|
||||
switch(nd->ud.dir) {
|
||||
switch(nd->dir) {
|
||||
case 0: strcpy(direction, msg_txt(1101)); break; // North
|
||||
case 1: strcpy(direction, msg_txt(1102)); break; // North West
|
||||
case 2: strcpy(direction, msg_txt(1103)); break; // West
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "../common/showmsg.h"
|
||||
#include "../common/socket.h"
|
||||
#include "../common/strlib.h"
|
||||
#include "../common/conf.h"
|
||||
|
||||
#include "battleground.h"
|
||||
#include "battle.h"
|
||||
|
|
@ -16,6 +17,7 @@
|
|||
#include "map.h"
|
||||
#include "npc.h"
|
||||
#include "pc.h"
|
||||
#include "party.h"
|
||||
#include "pet.h"
|
||||
#include "homunculus.h"
|
||||
#include "mercenary.h"
|
||||
|
|
@ -26,14 +28,12 @@
|
|||
static DBMap* bg_team_db; // int bg_id -> struct battleground_data*
|
||||
static unsigned int bg_team_counter = 0; // Next bg_id
|
||||
|
||||
struct battleground_data* bg_team_search(int bg_id)
|
||||
{ // Search a BG Team using bg_id
|
||||
struct battleground_data* bg_team_search(int bg_id) { // Search a BG Team using bg_id
|
||||
if( !bg_id ) return NULL;
|
||||
return (struct battleground_data *)idb_get(bg_team_db, bg_id);
|
||||
}
|
||||
|
||||
struct map_session_data* bg_getavailablesd(struct battleground_data *bg)
|
||||
{
|
||||
struct map_session_data* bg_getavailablesd(struct battleground_data *bg) {
|
||||
int i;
|
||||
nullpo_retr(NULL, bg);
|
||||
ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd != NULL);
|
||||
|
|
@ -95,8 +95,7 @@ int bg_team_join(int bg_id, struct map_session_data *sd)
|
|||
|
||||
guild->send_dot_remove(sd);
|
||||
|
||||
for( i = 0; i < MAX_BG_MEMBERS; i++ )
|
||||
{
|
||||
for( i = 0; i < MAX_BG_MEMBERS; i++ ) {
|
||||
if( (pl_sd = bg->members[i].sd) != NULL && pl_sd != sd )
|
||||
clif->hpmeter_single(sd->fd, pl_sd->bl.id, pl_sd->battle_status.hp, pl_sd->battle_status.max_hp);
|
||||
}
|
||||
|
|
@ -152,8 +151,7 @@ int bg_member_respawn(struct map_session_data *sd)
|
|||
return 1; // Warped
|
||||
}
|
||||
|
||||
int bg_create(unsigned short mapindex, short rx, short ry, const char *ev, const char *dev)
|
||||
{
|
||||
int bg_create(unsigned short mapindex, short rx, short ry, const char *ev, const char *dev) {
|
||||
struct battleground_data *bg;
|
||||
bg_team_counter++;
|
||||
|
||||
|
|
@ -226,12 +224,10 @@ int bg_send_xy_timer_sub(DBKey key, DBData *data, va_list ap)
|
|||
struct map_session_data *sd;
|
||||
int i;
|
||||
nullpo_ret(bg);
|
||||
for( i = 0; i < MAX_BG_MEMBERS; i++ )
|
||||
{
|
||||
for( i = 0; i < MAX_BG_MEMBERS; i++ ) {
|
||||
if( (sd = bg->members[i].sd) == NULL )
|
||||
continue;
|
||||
if( sd->bl.x != bg->members[i].x || sd->bl.y != bg->members[i].y )
|
||||
{ // xy update
|
||||
if( sd->bl.x != bg->members[i].x || sd->bl.y != bg->members[i].y ) { // xy update
|
||||
bg->members[i].x = sd->bl.x;
|
||||
bg->members[i].y = sd->bl.y;
|
||||
clif->bg_xy(sd);
|
||||
|
|
@ -240,20 +236,496 @@ int bg_send_xy_timer_sub(DBKey key, DBData *data, va_list ap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int bg_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
{
|
||||
int bg_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
bg_team_db->foreach(bg_team_db, bg_send_xy_timer_sub, tick);
|
||||
return 0;
|
||||
}
|
||||
void bg_config_read(void) {
|
||||
config_t bg_conf;
|
||||
config_setting_t *data = NULL;
|
||||
const char *config_filename = "conf/battlegrounds.conf"; // FIXME hardcoded name
|
||||
|
||||
if (conf_read_file(&bg_conf, config_filename))
|
||||
return;
|
||||
|
||||
data = config_lookup(&bg_conf, "battlegrounds");
|
||||
|
||||
if (data != NULL) {
|
||||
config_setting_t *settings = config_setting_get_elem(data, 0);
|
||||
config_setting_t *arenas;
|
||||
const char *delay_var;
|
||||
int i, arena_count = 0, total = 0, offline = 0;
|
||||
|
||||
if( !config_setting_lookup_string(settings, "global_delay_var", &delay_var) )
|
||||
delay_var = "BG_Delay_Tick";
|
||||
|
||||
safestrncpy(bg->gdelay_var, delay_var, BG_DELAY_VAR_LENGTH);
|
||||
|
||||
config_setting_lookup_int(settings, "maximum_afk_seconds", &bg->mafksec);
|
||||
|
||||
config_setting_lookup_bool(settings, "feature_off", &offline);
|
||||
|
||||
if( offline == 0 )
|
||||
bg->queue_on = true;
|
||||
|
||||
void do_init_battleground(void)
|
||||
{
|
||||
if( (arenas = config_setting_get_member(settings, "arenas")) != NULL ) {
|
||||
arena_count = config_setting_length(arenas);
|
||||
CREATE( bg->arena, struct bg_arena *, arena_count );
|
||||
for(i = 0; i < arena_count; i++) {
|
||||
config_setting_t *arena = config_setting_get_elem(arenas, i);
|
||||
config_setting_t *reward;
|
||||
const char *aName, *aEvent, *aDelayVar;
|
||||
int minLevel = 0, maxLevel = 0;
|
||||
int prizeWin, prizeLoss, prizeDraw;
|
||||
int minPlayers, maxPlayers, minTeamPlayers;
|
||||
int maxDuration;
|
||||
int fillup_duration, pregame_duration;
|
||||
|
||||
bg->arena[i] = NULL;
|
||||
|
||||
if( !config_setting_lookup_string(arena, "name", &aName) ) {
|
||||
ShowError("bg_config_read: failed to find 'name' for arena #%d\n",i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !config_setting_lookup_string(arena, "event", &aEvent) ) {
|
||||
ShowError("bg_config_read: failed to find 'event' for arena #%d\n",i);
|
||||
continue;
|
||||
}
|
||||
|
||||
config_setting_lookup_int(arena, "minLevel", &minLevel);
|
||||
config_setting_lookup_int(arena, "maxLevel", &maxLevel);
|
||||
|
||||
if( minLevel < 0 ) {
|
||||
ShowWarning("bg_config_read: invalid %d value for arena '%s' minLevel\n",minLevel,aName);
|
||||
minLevel = 0;
|
||||
}
|
||||
if( maxLevel > MAX_LEVEL ) {
|
||||
ShowWarning("bg_config_read: invalid %d value for arena '%s' maxLevel\n",maxLevel,aName);
|
||||
maxLevel = MAX_LEVEL;
|
||||
}
|
||||
|
||||
if( !(reward = config_setting_get_member(settings, "reward")) ) {
|
||||
ShowError("bg_config_read: failed to find 'reward' for arena '%s'/#%d\n",aName,i);
|
||||
continue;
|
||||
}
|
||||
|
||||
config_setting_lookup_int(reward, "win", &prizeWin);
|
||||
config_setting_lookup_int(reward, "loss", &prizeLoss);
|
||||
config_setting_lookup_int(reward, "draw", &prizeDraw);
|
||||
|
||||
if( prizeWin < 0 ) {
|
||||
ShowWarning("bg_config_read: invalid %d value for arena '%s' reward:win\n",prizeWin,aName);
|
||||
prizeWin = 0;
|
||||
}
|
||||
if( prizeLoss < 0 ) {
|
||||
ShowWarning("bg_config_read: invalid %d value for arena '%s' reward:loss\n",prizeLoss,aName);
|
||||
prizeLoss = 0;
|
||||
}
|
||||
if( prizeDraw < 0 ) {
|
||||
ShowWarning("bg_config_read: invalid %d value for arena '%s' reward:draw\n",prizeDraw,aName);
|
||||
prizeDraw = 0;
|
||||
}
|
||||
|
||||
config_setting_lookup_int(arena, "minPlayers", &minPlayers);
|
||||
config_setting_lookup_int(arena, "maxPlayers", &maxPlayers);
|
||||
config_setting_lookup_int(arena, "minTeamPlayers", &minTeamPlayers);
|
||||
|
||||
if( minPlayers < 0 ) {
|
||||
ShowWarning("bg_config_read: invalid %d value for arena '%s' minPlayers\n",minPlayers,aName);
|
||||
minPlayers = 0;
|
||||
}
|
||||
if( maxPlayers > MAX_BG_MEMBERS * 2 ) {
|
||||
ShowWarning("bg_config_read: invalid %d value for arena '%s' maxPlayers, change #define MAX_BG_MEMBERS\n",maxPlayers,aName);
|
||||
maxPlayers = 0;
|
||||
}
|
||||
if( minTeamPlayers < 0 ) {
|
||||
ShowWarning("bg_config_read: invalid %d value for arena '%s' minTeamPlayers\n",minTeamPlayers,aName);
|
||||
minTeamPlayers = 0;
|
||||
}
|
||||
|
||||
if( !config_setting_lookup_string(arena, "delay_var", &aDelayVar) ) {
|
||||
ShowError("bg_config_read: failed to find 'delay_var' for arena '%s'/#%d\n",aName,i);
|
||||
continue;
|
||||
}
|
||||
|
||||
config_setting_lookup_int(arena, "maxDuration", &maxDuration);
|
||||
|
||||
if( maxDuration < 0 ) {
|
||||
ShowWarning("bg_config_read: invalid %d value for arena '%s' maxDuration\n",maxDuration,aName);
|
||||
maxDuration = 30;
|
||||
}
|
||||
|
||||
config_setting_lookup_int(arena, "fillDuration", &fillup_duration);
|
||||
config_setting_lookup_int(arena, "pGameDuration", &pregame_duration);
|
||||
|
||||
if( fillup_duration < 20 ) {
|
||||
ShowWarning("bg_config_read: invalid %d value for arena '%s' fillDuration, minimum has to be 20, defaulting to 20.\n",fillup_duration,aName);
|
||||
fillup_duration = 20;
|
||||
}
|
||||
|
||||
if( pregame_duration < 20 ) {
|
||||
ShowWarning("bg_config_read: invalid %d value for arena '%s' pGameDuration, minimum has to be 20, defaulting to 20.\n",pregame_duration,aName);
|
||||
pregame_duration = 20;
|
||||
}
|
||||
|
||||
|
||||
CREATE( bg->arena[i], struct bg_arena, 1 );
|
||||
|
||||
bg->arena[i]->id = i;
|
||||
safestrncpy(bg->arena[i]->name, aName, NAME_LENGTH);
|
||||
safestrncpy(bg->arena[i]->npc_event, aEvent, EVENT_NAME_LENGTH);
|
||||
bg->arena[i]->min_level = minLevel;
|
||||
bg->arena[i]->max_level = maxLevel;
|
||||
bg->arena[i]->prize_win = prizeWin;
|
||||
bg->arena[i]->prize_loss = prizeLoss;
|
||||
bg->arena[i]->prize_draw = prizeDraw;
|
||||
bg->arena[i]->min_players = minPlayers;
|
||||
bg->arena[i]->max_players = maxPlayers;
|
||||
bg->arena[i]->min_team_players = minTeamPlayers;
|
||||
safestrncpy(bg->arena[i]->delay_var, aDelayVar, NAME_LENGTH);
|
||||
bg->arena[i]->maxDuration = maxDuration;
|
||||
bg->arena[i]->queue_id = -1;
|
||||
bg->arena[i]->begin_timer = INVALID_TIMER;
|
||||
bg->arena[i]->fillup_timer = INVALID_TIMER;
|
||||
bg->arena[i]->pregame_duration = pregame_duration;
|
||||
bg->arena[i]->fillup_duration = fillup_duration;
|
||||
|
||||
total++;
|
||||
}
|
||||
bg->arenas = arena_count;
|
||||
}
|
||||
|
||||
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' arenas in '"CL_WHITE"%s"CL_RESET"'.\n", total, config_filename);
|
||||
config_destroy(&bg_conf);
|
||||
}
|
||||
}
|
||||
struct bg_arena *bg_name2arena (char *name) {
|
||||
int i;
|
||||
for(i = 0; i < bg->arenas; i++) {
|
||||
if( strcmpi(bg->arena[i]->name,name) == 0 )
|
||||
return bg->arena[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
int bg_id2pos ( int queue_id, int account_id ) {
|
||||
struct hQueue *queue = script->queue(queue_id);
|
||||
if( queue ) {
|
||||
int i;
|
||||
for(i = 0; i < queue->items; i++ ) {
|
||||
if( queue->item[i] == account_id ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void bg_queue_player_cleanup(struct map_session_data *sd) {
|
||||
if ( sd->bg_queue.client_has_bg_data ) {
|
||||
clif->bgqueue_notice_delete(sd,BGQND_CLOSEWINDOW, sd->bg_queue.arena->id);
|
||||
}
|
||||
script->queue_remove(sd->bg_queue.arena->queue_id,sd->status.account_id);
|
||||
sd->bg_queue.arena = NULL;
|
||||
sd->bg_queue.ready = 0;
|
||||
sd->bg_queue.client_has_bg_data = 0;
|
||||
sd->bg_queue.type = 0;
|
||||
}
|
||||
void bg_match_over(struct bg_arena *arena, bool canceled) {
|
||||
struct hQueue *queue = &script->hq[arena->queue_id];
|
||||
int i;//, count = 0;
|
||||
|
||||
/* if( !canceled ) <check time/score> */
|
||||
|
||||
for( i = 0; i < queue->items; i++ ) {
|
||||
struct map_session_data * sd = NULL;
|
||||
|
||||
if( ( sd = map_id2sd(queue->item[i]) ) ) {
|
||||
bg->queue_pc_cleanup(sd);
|
||||
clif->colormes(sd->fd,COLOR_RED,"BG Match Cancelled: not enough players");
|
||||
}
|
||||
}
|
||||
|
||||
bg->arena[i]->begin_timer = INVALID_TIMER;
|
||||
bg->arena[i]->fillup_timer = INVALID_TIMER;
|
||||
/* reset queue */
|
||||
}
|
||||
void bg_begin(struct bg_arena *arena) {
|
||||
struct hQueue *queue = &script->hq[arena->queue_id];
|
||||
int i, count = 0;
|
||||
|
||||
for( i = 0; i < queue->items; i++ ) {
|
||||
struct map_session_data * sd = NULL;
|
||||
|
||||
if( ( sd = map_id2sd(queue->item[i]) ) ) {
|
||||
if( sd->bg_queue.ready == 1 )
|
||||
count++;
|
||||
else
|
||||
bg->queue_pc_cleanup(sd);
|
||||
}
|
||||
}
|
||||
|
||||
if( count < arena->min_players ) {
|
||||
bg_match_over(arena,true);
|
||||
} else {
|
||||
;
|
||||
/* we split evenly? */
|
||||
/* but if a party of say 10 joins, it cant be split evenly unless by luck there are 10 soloers in the queue besides them */
|
||||
/* not sure how to split T_T needs more info */
|
||||
}
|
||||
}
|
||||
int bg_begin_timer(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
bg->begin(bg->arena[id]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bg_queue_pregame(struct bg_arena *arena) {
|
||||
struct hQueue *queue = &script->hq[arena->queue_id];
|
||||
int i;
|
||||
|
||||
for( i = 0; i < queue->items; i++ ) {
|
||||
struct map_session_data * sd = NULL;
|
||||
|
||||
if( ( sd = map_id2sd(queue->item[i]) ) ) {
|
||||
clif->bgqueue_battlebegins(sd,arena->id,SELF);
|
||||
}
|
||||
}
|
||||
arena->begin_timer = add_timer( gettick() + (arena->pregame_duration*1000), bg->begin_timer, arena->id, 0 );
|
||||
}
|
||||
int bg_fillup_timer(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
bg->queue_pregame(bg->arena[id]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bg_queue_check(struct bg_arena *arena) {
|
||||
int count = script->hq[arena->queue_id].items;
|
||||
|
||||
if( count == arena->max_players ) {
|
||||
if( arena->fillup_timer != INVALID_TIMER ) {
|
||||
delete_timer(arena->fillup_timer,bg_fillup_timer);
|
||||
arena->fillup_timer = INVALID_TIMER;
|
||||
}
|
||||
bg->queue_pregame(arena);
|
||||
} else if( count >= arena->min_players && arena->fillup_timer == INVALID_TIMER ) {
|
||||
arena->fillup_timer = add_timer( gettick() + (arena->fillup_duration*1000), bg->fillup_timer, arena->id, 0 );
|
||||
}
|
||||
}
|
||||
void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type) {
|
||||
enum BATTLEGROUNDS_QUEUE_ACK result = bg->can_queue(sd,arena,type);
|
||||
struct hQueue *queue;
|
||||
int i, count = 0;
|
||||
|
||||
if( arena->begin_timer != INVALID_TIMER ) {
|
||||
clif->bgqueue_ack(sd,BGQA_FAIL_QUEUING_FINISHED,arena->id);
|
||||
return;
|
||||
}
|
||||
|
||||
if( result != BGQA_SUCCESS ) {
|
||||
clif->bgqueue_ack(sd,result,arena->id);
|
||||
return;
|
||||
}
|
||||
|
||||
switch( type ) { /* guild/party already validated in can_queue */
|
||||
case BGQT_PARTY: {
|
||||
struct party_data *p = party_search(sd->status.party_id);
|
||||
for( i = 0; i < MAX_PARTY; i++ ) {
|
||||
if( !p->data[i].sd || p->data[i].sd->bg_queue.arena != NULL ) continue;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BGQT_GUILD:
|
||||
for ( i=0; i<sd->guild->max_member; i++ ) {
|
||||
if ( !sd->guild->member[i].sd || sd->guild->member[i].sd->bg_queue.arena != NULL )
|
||||
continue;
|
||||
count++;
|
||||
}
|
||||
break;
|
||||
case BGQT_INDIVIDUAL:
|
||||
count = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if( !(queue = script->queue(arena->queue_id)) || (queue->items+count) >= arena->max_players ) {
|
||||
clif->bgqueue_ack(sd,BGQA_FAIL_PPL_OVERAMOUNT,arena->id);
|
||||
return;
|
||||
}
|
||||
|
||||
switch( type ) {
|
||||
case BGQT_INDIVIDUAL:
|
||||
sd->bg_queue.type = type;
|
||||
sd->bg_queue.arena = arena;
|
||||
sd->bg_queue.ready = 0;
|
||||
script->queue_add(arena->queue_id,sd->status.account_id);
|
||||
clif->bgqueue_joined(sd,script->hq[arena->queue_id].items);
|
||||
clif->bgqueue_update_info(sd,arena->id,script->hq[arena->queue_id].items);
|
||||
break;
|
||||
case BGQT_PARTY: {
|
||||
struct party_data *p = party_search(sd->status.party_id);
|
||||
for( i = 0; i < MAX_PARTY; i++ ) {
|
||||
if( !p->data[i].sd || p->data[i].sd->bg_queue.arena != NULL ) continue;
|
||||
p->data[i].sd->bg_queue.type = type;
|
||||
p->data[i].sd->bg_queue.arena = arena;
|
||||
p->data[i].sd->bg_queue.ready = 0;
|
||||
script->queue_add(arena->queue_id,p->data[i].sd->status.account_id);
|
||||
clif->bgqueue_joined(p->data[i].sd,script->hq[arena->queue_id].items);
|
||||
clif->bgqueue_update_info(p->data[i].sd,arena->id,script->hq[arena->queue_id].items);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BGQT_GUILD:
|
||||
for ( i=0; i<sd->guild->max_member; i++ ) {
|
||||
if ( !sd->guild->member[i].sd || sd->guild->member[i].sd->bg_queue.arena != NULL )
|
||||
continue;
|
||||
sd->guild->member[i].sd->bg_queue.type = type;
|
||||
sd->guild->member[i].sd->bg_queue.arena = arena;
|
||||
sd->guild->member[i].sd->bg_queue.ready = 0;
|
||||
script->queue_add(arena->queue_id,sd->guild->member[i].sd->status.account_id);
|
||||
clif->bgqueue_joined(sd->guild->member[i].sd,script->hq[arena->queue_id].items);
|
||||
clif->bgqueue_update_info(sd->guild->member[i].sd,arena->id,script->hq[arena->queue_id].items);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
clif->bgqueue_ack(sd,BGQA_SUCCESS,arena->id);
|
||||
|
||||
}
|
||||
enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type) {
|
||||
int tick;
|
||||
unsigned int tsec;
|
||||
if ( sd->status.base_level > arena->max_level || sd->status.base_level < arena->max_level )
|
||||
return BGQA_FAIL_LEVEL_INCORRECT;
|
||||
|
||||
if ( !(sd->class_&JOBL_2) ) /* TODO: maybe make this a per-arena setting, so users may make custom arenas like baby-only,whatever. */
|
||||
return BGQA_FAIL_CLASS_INVALID;
|
||||
|
||||
tsec = time(NULL);
|
||||
|
||||
if ( ( tick = pc_readglobalreg(sd, bg->gdelay_var) ) && tsec < tick ) {
|
||||
char response[100];
|
||||
if( (tick-tsec) > 60 )
|
||||
sprintf(response, "You are a deserter! Wait %d minute(s) before you can apply again",(tick-tsec)/60);
|
||||
else
|
||||
sprintf(response, "You are a deserter! Wait %d seconds before you can apply again",(tick-tsec));
|
||||
clif->colormes(sd->fd,COLOR_RED,response);
|
||||
return BGQA_FAIL_DESERTER;
|
||||
}
|
||||
|
||||
if ( ( tick = pc_readglobalreg(sd, arena->cooldown_variable) ) && tsec < tick ) {
|
||||
char response[100];
|
||||
if( (tick-tsec) > 60 )
|
||||
sprintf(response, "You can't reapply to this arena so fast. Apply to the different arena or wait %d minute(s)",(tick-tsec)/60);
|
||||
else
|
||||
sprintf(response, "You can't reapply to this arena so fast. Apply to the different arena or wait %d seconds",(tick-tsec));
|
||||
clif->colormes(sd->fd,COLOR_RED,response);
|
||||
return BGQA_FAIL_COOLDOWN;
|
||||
}
|
||||
|
||||
if( sd->bg_queue.arena != NULL )
|
||||
return BGQA_DUPLICATE_REQUEST;
|
||||
|
||||
switch(type) {
|
||||
case BGQT_GUILD:
|
||||
if( !sd->guild || !sd->state.gmaster_flag )
|
||||
return BGQA_NOT_PARTY_GUILD_LEADER;
|
||||
else {
|
||||
int i, count = 0;
|
||||
for ( i=0; i<sd->guild->max_member; i++ ) {
|
||||
if ( !sd->guild->member[i].sd || sd->guild->member[i].sd->bg_queue.arena != NULL )
|
||||
continue;
|
||||
count++;
|
||||
}
|
||||
if ( count < arena->min_team_players ) {
|
||||
char response[100];
|
||||
if( count != sd->guild->connect_member && sd->guild->connect_member >= arena->min_team_players )
|
||||
sprintf(response, "Can't apply: not enough members in your team/guild that have not entered the queue in individual mode, minimum is %d",arena->min_team_players);
|
||||
else
|
||||
sprintf(response, "Can't apply: not enough members in your team/guild, minimum is %d",arena->min_team_players);
|
||||
clif->colormes(sd->fd,COLOR_RED,response);
|
||||
return BGQA_FAIL_TEAM_COUNT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BGQT_PARTY:
|
||||
if( !sd->status.party_id )
|
||||
return BGQA_NOT_PARTY_GUILD_LEADER;
|
||||
else {
|
||||
struct party_data *p;
|
||||
if( (p = party_search(sd->status.party_id) ) ) {
|
||||
int i, count = 0;
|
||||
bool is_leader = false;
|
||||
|
||||
for(i = 0; i < MAX_PARTY; i++) {
|
||||
if( !p->data[i].sd )
|
||||
continue;
|
||||
if( p->party.member[i].leader && sd == p->data[i].sd )
|
||||
is_leader = true;
|
||||
if( p->data[i].sd->bg_queue.arena == NULL )
|
||||
count++;
|
||||
}
|
||||
|
||||
if( !is_leader )
|
||||
return BGQA_NOT_PARTY_GUILD_LEADER;
|
||||
|
||||
if( count < arena->min_team_players ) {
|
||||
char response[100];
|
||||
if( count != p->party.count && p->party.count >= arena->min_team_players )
|
||||
sprintf(response, "Can't apply: not enough members in your team/party that have not entered the queue in individual mode, minimum is %d",arena->min_team_players);
|
||||
else
|
||||
sprintf(response, "Can't apply: not enough members in your team/party, minimum is %d",arena->min_team_players);
|
||||
clif->colormes(sd->fd,COLOR_RED,response);
|
||||
return BGQA_FAIL_TEAM_COUNT;
|
||||
}
|
||||
|
||||
} else
|
||||
return BGQA_NOT_PARTY_GUILD_LEADER;
|
||||
}
|
||||
break;
|
||||
case BGQT_INDIVIDUAL:/* already did */
|
||||
break;
|
||||
default:
|
||||
ShowDebug("bg_canqueue: unknown/unsupported type %d\n",type);
|
||||
return BGQA_DUPLICATE_REQUEST;
|
||||
}
|
||||
|
||||
return BGQA_SUCCESS;
|
||||
}
|
||||
void do_init_battleground(void) {
|
||||
bg_team_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||
add_timer_func_list(bg_send_xy_timer, "bg_send_xy_timer");
|
||||
add_timer_interval(gettick() + battle_config.bg_update_interval, bg_send_xy_timer, 0, 0, battle_config.bg_update_interval);
|
||||
}
|
||||
|
||||
void do_final_battleground(void)
|
||||
{
|
||||
void do_final_battleground(void) {
|
||||
int i;
|
||||
|
||||
bg_team_db->destroy(bg_team_db, NULL);
|
||||
|
||||
for( i = 0; i < bg->arenas; i++ ) {
|
||||
if( bg->arena[i] )
|
||||
aFree(bg->arena[i]);
|
||||
}
|
||||
|
||||
if( bg->arena )
|
||||
aFree(bg->arena);
|
||||
}
|
||||
void battleground_defaults(void) {
|
||||
bg = &bg_s;
|
||||
|
||||
bg->queue_on = false;
|
||||
|
||||
bg->mafksec = 0;
|
||||
bg->arena = NULL;
|
||||
bg->arenas = 0;
|
||||
/* */
|
||||
bg->name2arena = bg_name2arena;
|
||||
bg->queue_add = bg_queue_add;
|
||||
bg->can_queue = bg_canqueue;
|
||||
bg->id2pos = bg_id2pos;
|
||||
bg->queue_pc_cleanup = bg_queue_player_cleanup;
|
||||
bg->begin = bg_begin;
|
||||
bg->begin_timer = bg_begin_timer;
|
||||
bg->queue_pregame = bg_queue_pregame;
|
||||
bg->fillup_timer = bg_fillup_timer;
|
||||
/* */
|
||||
bg->config_read = bg_config_read;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
|
||||
// For more information, see LICENCE in the main folder
|
||||
// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
|
||||
// See the LICENSE file
|
||||
// Portions Copyright (c) Athena Dev Teams
|
||||
|
||||
#ifndef _BATTLEGROUND_H_
|
||||
#define _BATTLEGROUND_H_
|
||||
|
|
@ -7,7 +8,21 @@
|
|||
#include "../common/mmo.h" // struct party
|
||||
#include "guild.h"
|
||||
|
||||
/**
|
||||
* Defines
|
||||
**/
|
||||
#define MAX_BG_MEMBERS 30
|
||||
#define BG_DELAY_VAR_LENGTH 30
|
||||
|
||||
/**
|
||||
* Enumerations
|
||||
**/
|
||||
enum bg_queue_types {
|
||||
BGQT_INVALID,
|
||||
BGQT_INDIVIDUAL,
|
||||
BGQT_PARTY,
|
||||
BGQT_GUILD
|
||||
};
|
||||
|
||||
struct battleground_member_data {
|
||||
unsigned short x, y;
|
||||
|
|
@ -42,4 +57,51 @@ int bg_team_warp(int bg_id, unsigned short mapindex, short x, short y);
|
|||
int bg_member_respawn(struct map_session_data *sd);
|
||||
int bg_send_message(struct map_session_data *sd, const char *mes, int len);
|
||||
|
||||
struct bg_arena {
|
||||
char name[NAME_LENGTH];
|
||||
unsigned char id;
|
||||
char npc_event[EVENT_NAME_LENGTH];
|
||||
short min_level, max_level;
|
||||
short prize_win, prize_loss, prize_draw;
|
||||
short min_players;
|
||||
short max_players;
|
||||
short min_team_players;
|
||||
char cooldown_variable[NAME_LENGTH];
|
||||
char delay_var[NAME_LENGTH];
|
||||
unsigned short maxDuration;
|
||||
int queue_id;
|
||||
int begin_timer;
|
||||
int fillup_timer;
|
||||
int game_timer;
|
||||
unsigned short fillup_duration;
|
||||
unsigned short pregame_duration;
|
||||
};
|
||||
|
||||
/* battleground.c interface (incomplete) */
|
||||
struct battleground_interface {
|
||||
bool queue_on;
|
||||
/* */
|
||||
int mafksec;
|
||||
char gdelay_var[BG_DELAY_VAR_LENGTH];
|
||||
/* */
|
||||
struct bg_arena **arena;
|
||||
unsigned char arenas;
|
||||
/* */
|
||||
struct bg_arena *(*name2arena) (char *name);
|
||||
void (*queue_add) (struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type);
|
||||
enum BATTLEGROUNDS_QUEUE_ACK (*can_queue) (struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type);
|
||||
int (*id2pos) (int queue_id, int account_id);
|
||||
void (*queue_pc_cleanup) (struct map_session_data *sd);
|
||||
void (*begin) (struct bg_arena *arena);
|
||||
int (*begin_timer) (int tid, unsigned int tick, int id, intptr_t data);
|
||||
void (*queue_pregame) (struct bg_arena *arena);
|
||||
int (*fillup_timer) (int tid, unsigned int tick, int id, intptr_t data);
|
||||
/* */
|
||||
void (*config_read) (void);
|
||||
} bg_s;
|
||||
|
||||
struct battleground_interface *bg;
|
||||
|
||||
void battleground_defaults(void);
|
||||
|
||||
#endif /* _BATTLEGROUND_H_ */
|
||||
|
|
|
|||
|
|
@ -344,9 +344,9 @@ int chrif_sendmap(int fd) {
|
|||
ShowStatus("Sending maps to char server...\n");
|
||||
|
||||
// Sending normal maps, not instances
|
||||
WFIFOHEAD(fd, 4 + instance_start * 4);
|
||||
WFIFOHEAD(fd, 4 + instance->start_id * 4);
|
||||
WFIFOW(fd,0) = 0x2afa;
|
||||
for(i = 0; i < instance_start; i++)
|
||||
for(i = 0; i < instance->start_id; i++)
|
||||
WFIFOW(fd,4+i*4) = map[i].index;
|
||||
WFIFOW(fd,2) = 4 + i * 4;
|
||||
WFIFOSET(fd,WFIFOW(fd,2));
|
||||
|
|
@ -1537,9 +1537,8 @@ static int check_connect_char_server(int tid, unsigned int tick, int id, intptr_
|
|||
}
|
||||
|
||||
chrif_state = 0;
|
||||
char_fd = make_connection(char_ip, char_port,false);
|
||||
|
||||
if (char_fd == -1)//Attempt to connect later. [Skotlex]
|
||||
if ( ( char_fd = make_connection(char_ip, char_port,NULL) ) == -1) //Attempt to connect later. [Skotlex]
|
||||
return 0;
|
||||
|
||||
session[char_fd]->func_parse = chrif_parse;
|
||||
|
|
|
|||
248
src/map/clif.c
248
src/map/clif.c
|
|
@ -1333,7 +1333,7 @@ int clif_spawn(struct block_list *bl)
|
|||
/**
|
||||
* Hide NPC from maya purple card.
|
||||
**/
|
||||
if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE))
|
||||
if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->option&OPTION_INVISIBLE))
|
||||
return 0;
|
||||
|
||||
clif->spawn_unit(bl,AREA_WOS);
|
||||
|
|
@ -1612,7 +1612,7 @@ void clif_move(struct unit_data *ud)
|
|||
/**
|
||||
* Hide NPC from maya purple card.
|
||||
**/
|
||||
if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE))
|
||||
if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->option&OPTION_INVISIBLE))
|
||||
return;
|
||||
|
||||
if (ud->state.speed_changed) {
|
||||
|
|
@ -1666,15 +1666,14 @@ void clif_quitsave(int fd,struct map_session_data *sd) {
|
|||
|
||||
/// Notifies the client of a position change to coordinates on given map (ZC_NPCACK_MAPMOVE).
|
||||
/// 0091 <map name>.16B <x>.W <y>.W
|
||||
void clif_changemap(struct map_session_data *sd, short map, int x, int y)
|
||||
{
|
||||
void clif_changemap(struct map_session_data *sd, short m, int x, int y) {
|
||||
int fd;
|
||||
nullpo_retv(sd);
|
||||
fd = sd->fd;
|
||||
|
||||
WFIFOHEAD(fd,packet_len(0x91));
|
||||
WFIFOW(fd,0) = 0x91;
|
||||
mapindex_getmapname_ext(mapindex_id2name(map), (char*)WFIFOP(fd,2));
|
||||
mapindex_getmapname_ext(map[m].cName ? map[m].cName : map[m].name, (char*)WFIFOP(fd,2));
|
||||
WFIFOW(fd,18) = x;
|
||||
WFIFOW(fd,20) = y;
|
||||
WFIFOSET(fd,packet_len(0x91));
|
||||
|
|
@ -1683,8 +1682,7 @@ void clif_changemap(struct map_session_data *sd, short map, int x, int y)
|
|||
|
||||
/// Notifies the client of a position change to coordinates on given map, which is on another map-server (ZC_NPCACK_SERVERMOVE).
|
||||
/// 0092 <map name>.16B <x>.W <y>.W <ip>.L <port>.W
|
||||
void clif_changemapserver(struct map_session_data* sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port)
|
||||
{
|
||||
void clif_changemapserver(struct map_session_data* sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port) {
|
||||
int fd;
|
||||
nullpo_retv(sd);
|
||||
fd = sd->fd;
|
||||
|
|
@ -4344,7 +4342,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
|
|||
/**
|
||||
* Hide NPC from maya purple card.
|
||||
**/
|
||||
if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE))
|
||||
if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->option&OPTION_INVISIBLE))
|
||||
return;
|
||||
|
||||
if ( ( ud = unit_bl2ud(bl) ) && ud->walktimer != INVALID_TIMER )
|
||||
|
|
@ -4601,16 +4599,13 @@ void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_targe
|
|||
WBUFW(buf,2) = x;
|
||||
WBUFW(buf,4) = y;
|
||||
WBUFW(buf,6) = type;
|
||||
mapindex_getmapname_ext(map[m].name,(char*)WBUFP(buf,8));
|
||||
mapindex_getmapname_ext(map[m].cName ? map[m].cName : map[m].name,(char*)WBUFP(buf,8));
|
||||
|
||||
if( fd )
|
||||
{
|
||||
if( fd ) {
|
||||
WFIFOHEAD(fd,packet_len(0x192));
|
||||
memcpy(WFIFOP(fd,0), buf, packet_len(0x192));
|
||||
WFIFOSET(fd,packet_len(0x192));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
struct block_list dummy_bl;
|
||||
dummy_bl.type = BL_NUL;
|
||||
dummy_bl.x = x;
|
||||
|
|
@ -4799,7 +4794,7 @@ int clif_outsight(struct block_list *bl,va_list ap)
|
|||
clif->clearchar_skillunit((struct skill_unit *)bl,tsd->fd);
|
||||
break;
|
||||
case BL_NPC:
|
||||
if( !(((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE) )
|
||||
if( !(((TBL_NPC*)bl)->option&OPTION_INVISIBLE) )
|
||||
clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -4810,7 +4805,7 @@ int clif_outsight(struct block_list *bl,va_list ap)
|
|||
}
|
||||
if (sd && sd->fd) { //sd is watching tbl go out of view.
|
||||
if (((vd=status_get_viewdata(tbl)) && vd->class_ != INVISIBLE_CLASS) &&
|
||||
!(tbl->type == BL_NPC && (((TBL_NPC*)tbl)->sc.option&OPTION_INVISIBLE)))
|
||||
!(tbl->type == BL_NPC && (((TBL_NPC*)tbl)->option&OPTION_INVISIBLE)))
|
||||
clif->clearunit_single(tbl->id,CLR_OUTSIGHT,sd->fd);
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -6529,7 +6524,7 @@ void clif_party_member_info(struct party_data *p, struct map_session_data *sd)
|
|||
WBUFB(buf,14) = (p->party.member[i].online)?0:1;
|
||||
memcpy(WBUFP(buf,15), p->party.name, NAME_LENGTH);
|
||||
memcpy(WBUFP(buf,39), sd->status.name, NAME_LENGTH);
|
||||
mapindex_getmapname_ext(map[sd->bl.m].name, (char*)WBUFP(buf,63));
|
||||
mapindex_getmapname_ext(map[sd->bl.m].cName ? map[sd->bl.m].cName : map[sd->bl.m].name, (char*)WBUFP(buf,63));
|
||||
WBUFB(buf,79) = (p->party.item&1)?1:0;
|
||||
WBUFB(buf,80) = (p->party.item&2)?1:0;
|
||||
clif->send(buf,packet_len(0x1e9),&sd->bl,PARTY);
|
||||
|
|
@ -8485,7 +8480,7 @@ void clif_refresh(struct map_session_data *sd)
|
|||
int i;
|
||||
nullpo_retv(sd);
|
||||
|
||||
clif->changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y);
|
||||
clif->changemap(sd,sd->bl.m,sd->bl.x,sd->bl.y);
|
||||
clif->inventorylist(sd);
|
||||
if(pc_iscarton(sd)) {
|
||||
clif->cartlist(sd);
|
||||
|
|
@ -9328,7 +9323,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
|
|||
|
||||
if (sd->state.rewarp) { //Rewarp player.
|
||||
sd->state.rewarp = 0;
|
||||
clif->changemap(sd, sd->mapindex, sd->bl.x, sd->bl.y);
|
||||
clif->changemap(sd, sd->bl.m, sd->bl.x, sd->bl.y);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -9372,9 +9367,9 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
|
|||
if( !(sd->sc.option&OPTION_INVISIBLE) ) { // increment the number of pvp players on the map
|
||||
map[sd->bl.m].users_pvp++;
|
||||
}
|
||||
if( map[sd->bl.m].instance_id ) {
|
||||
instance[map[sd->bl.m].instance_id].users++;
|
||||
instance_check_idle(map[sd->bl.m].instance_id);
|
||||
if( map[sd->bl.m].instance_id >= 0 ) {
|
||||
instances[map[sd->bl.m].instance_id].users++;
|
||||
instance->check_idle(map[sd->bl.m].instance_id);
|
||||
}
|
||||
sd->state.debug_remove_map = 0; // temporary state to track double remove_map's [FlavioJS]
|
||||
|
||||
|
|
@ -15573,48 +15568,61 @@ void clif_font(struct map_session_data *sd)
|
|||
/*==========================================
|
||||
* Instancing Window
|
||||
*------------------------------------------*/
|
||||
int clif_instance(int instance_id, int type, int flag)
|
||||
{
|
||||
int clif_instance(int instance_id, int type, int flag) {
|
||||
struct map_session_data *sd;
|
||||
struct party_data *p;
|
||||
unsigned char buf[255];
|
||||
enum send_target target = PARTY;
|
||||
|
||||
switch( instances[instance_id].owner_type ) {
|
||||
case IOT_NONE:
|
||||
return 0;
|
||||
case IOT_GUILD:
|
||||
target = GUILD;
|
||||
sd = guild->getavailablesd(guild->search(instances[instance_id].owner_id));
|
||||
break;
|
||||
case IOT_PARTY:
|
||||
/* default is already PARTY */
|
||||
sd = party_getavailablesd(party_search(instances[instance_id].owner_id));
|
||||
break;
|
||||
case IOT_CHAR:
|
||||
target = SELF;
|
||||
sd = map_id2sd(instances[instance_id].owner_id);
|
||||
break;
|
||||
}
|
||||
|
||||
if( (p = party_search(instance[instance_id].party_id)) == NULL || (sd = party_getavailablesd(p)) == NULL )
|
||||
if( !sd )
|
||||
return 0;
|
||||
|
||||
|
||||
switch( type ) {
|
||||
case 1:
|
||||
// S 0x2cb <Instance name>.61B <Standby Position>.W
|
||||
// Required to start the instancing information window on Client
|
||||
// This window re-appear each "refresh" of client automatically until type 4 is send to client.
|
||||
WBUFW(buf,0) = 0x02CB;
|
||||
memcpy(WBUFP(buf,2),instance[instance_id].name,INSTANCE_NAME_LENGTH);
|
||||
memcpy(WBUFP(buf,2),instances[instance_id].name,INSTANCE_NAME_LENGTH);
|
||||
WBUFW(buf,63) = flag;
|
||||
clif->send(buf,packet_len(0x02CB),&sd->bl,PARTY);
|
||||
clif->send(buf,packet_len(0x02CB),&sd->bl,target);
|
||||
break;
|
||||
case 2:
|
||||
// S 0x2cc <Standby Position>.W
|
||||
// To announce Instancing queue creation if no maps available
|
||||
WBUFW(buf,0) = 0x02CC;
|
||||
WBUFW(buf,2) = flag;
|
||||
clif->send(buf,packet_len(0x02CC),&sd->bl,PARTY);
|
||||
clif->send(buf,packet_len(0x02CC),&sd->bl,target);
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
// S 0x2cd <Instance Name>.61B <Instance Remaining Time>.L <Instance Noplayers close time>.L
|
||||
WBUFW(buf,0) = 0x02CD;
|
||||
memcpy(WBUFP(buf,2),instance[instance_id].name,61);
|
||||
if( type == 3 )
|
||||
{
|
||||
WBUFL(buf,63) = (uint32)instance[instance_id].progress_timeout;
|
||||
memcpy(WBUFP(buf,2),instances[instance_id].name,61);
|
||||
if( type == 3 ) {
|
||||
WBUFL(buf,63) = instances[instance_id].progress_timeout;
|
||||
WBUFL(buf,67) = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
WBUFL(buf,63) = 0;
|
||||
WBUFL(buf,67) = (uint32)instance[instance_id].idle_timeout;
|
||||
WBUFL(buf,67) = instances[instance_id].idle_timeout;
|
||||
}
|
||||
clif->send(buf,packet_len(0x02CD),&sd->bl,PARTY);
|
||||
clif->send(buf,packet_len(0x02CD),&sd->bl,target);
|
||||
break;
|
||||
case 5:
|
||||
// S 0x2ce <Message ID>.L
|
||||
|
|
@ -15626,7 +15634,7 @@ int clif_instance(int instance_id, int type, int flag)
|
|||
WBUFW(buf,0) = 0x02CE;
|
||||
WBUFL(buf,2) = flag;
|
||||
//WBUFL(buf,6) = EnterLimitDate;
|
||||
clif->send(buf,packet_len(0x02CE),&sd->bl,PARTY);
|
||||
clif->send(buf,packet_len(0x02CE),&sd->bl,target);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -15634,24 +15642,24 @@ int clif_instance(int instance_id, int type, int flag)
|
|||
|
||||
void clif_instance_join(int fd, int instance_id)
|
||||
{
|
||||
if( instance[instance_id].idle_timer != INVALID_TIMER ) {
|
||||
if( instances[instance_id].idle_timer != INVALID_TIMER ) {
|
||||
WFIFOHEAD(fd,packet_len(0x02CD));
|
||||
WFIFOW(fd,0) = 0x02CD;
|
||||
memcpy(WFIFOP(fd,2),instance[instance_id].name,61);
|
||||
memcpy(WFIFOP(fd,2),instances[instance_id].name,61);
|
||||
WFIFOL(fd,63) = 0;
|
||||
WFIFOL(fd,67) = (uint32)instance[instance_id].idle_timeout;
|
||||
WFIFOL(fd,67) = instances[instance_id].idle_timeout;
|
||||
WFIFOSET(fd,packet_len(0x02CD));
|
||||
} else if( instance[instance_id].progress_timer != INVALID_TIMER ) {
|
||||
} else if( instances[instance_id].progress_timer != INVALID_TIMER ) {
|
||||
WFIFOHEAD(fd,packet_len(0x02CD));
|
||||
WFIFOW(fd,0) = 0x02CD;
|
||||
memcpy(WFIFOP(fd,2),instance[instance_id].name,61);
|
||||
WFIFOL(fd,63) = (uint32)instance[instance_id].progress_timeout;;
|
||||
memcpy(WFIFOP(fd,2),instances[instance_id].name,61);
|
||||
WFIFOL(fd,63) = instances[instance_id].progress_timeout;
|
||||
WFIFOL(fd,67) = 0;
|
||||
WFIFOSET(fd,packet_len(0x02CD));
|
||||
} else {
|
||||
WFIFOHEAD(fd,packet_len(0x02CB));
|
||||
WFIFOW(fd,0) = 0x02CB;
|
||||
memcpy(WFIFOP(fd,2),instance[instance_id].name,61);
|
||||
memcpy(WFIFOP(fd,2),instances[instance_id].name,61);
|
||||
WFIFOW(fd,63) = 0;
|
||||
WFIFOSET(fd,packet_len(0x02CB));
|
||||
}
|
||||
|
|
@ -16949,6 +16957,124 @@ void clif_status_change_end(struct block_list *bl, int tid, enum send_target tar
|
|||
clif->send(&p,sizeof(p), bl, target);
|
||||
}
|
||||
|
||||
void clif_bgqueue_ack(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK response, unsigned char arena_id) {
|
||||
|
||||
switch (response) {
|
||||
case BGQA_FAIL_COOLDOWN:
|
||||
case BGQA_FAIL_DESERTER:
|
||||
case BGQA_FAIL_TEAM_COUNT:
|
||||
break;
|
||||
default: {
|
||||
struct packet_bgqueue_ack p;
|
||||
|
||||
p.PacketType = bgqueue_ackType;
|
||||
p.type = response;
|
||||
safestrncpy(p.bg_name, bg->arena[arena_id]->name, sizeof(p.bg_name));
|
||||
|
||||
clif->send(&p,sizeof(p), &sd->bl, SELF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, unsigned char arena_id) {
|
||||
struct packet_bgqueue_notice_delete p;
|
||||
|
||||
p.PacketType = bgqueue_notice_deleteType;
|
||||
p.type = response;
|
||||
safestrncpy(p.bg_name, bg->arena[arena_id]->name, sizeof(p.bg_name));
|
||||
|
||||
clif->send(&p,sizeof(p), &sd->bl, SELF);
|
||||
}
|
||||
|
||||
void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) {
|
||||
struct packet_bgqueue_register *p = P2PTR(fd, bgqueue_registerType);
|
||||
struct bg_arena *arena = NULL;
|
||||
|
||||
if( !bg->queue_on ) return; /* temp, until feature is complete */
|
||||
|
||||
if( !(arena = bg->name2arena(p->bg_name)) ) {
|
||||
clif->bgqueue_ack(sd,BGQA_FAIL_BGNAME_INVALID,0);
|
||||
return;
|
||||
}
|
||||
|
||||
switch( (enum bg_queue_types)p->type ) {
|
||||
case BGQT_INDIVIDUAL:
|
||||
case BGQT_PARTY:
|
||||
case BGQT_GUILD:
|
||||
break;
|
||||
default:
|
||||
clif->bgqueue_ack(sd,BGQA_FAIL_TYPE_INVALID, arena->id);
|
||||
return;
|
||||
}
|
||||
|
||||
bg->queue_add(sd, arena, (enum bg_queue_types)p->type);
|
||||
}
|
||||
|
||||
void clif_bgqueue_update_info(struct map_session_data *sd, unsigned char arena_id, int position) {
|
||||
struct packet_bgqueue_update_info p;
|
||||
|
||||
p.PacketType = bgqueue_updateinfoType;
|
||||
safestrncpy(p.bg_name, bg->arena[arena_id]->name, sizeof(p.bg_name));
|
||||
p.position = position;
|
||||
|
||||
sd->bg_queue.client_has_bg_data = true; // Client creates bg data when this packet arrives
|
||||
|
||||
clif->send(&p,sizeof(p), &sd->bl, SELF);
|
||||
}
|
||||
|
||||
void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd) {
|
||||
//struct packet_bgqueue_checkstate *p = P2PTR(fd, bgqueue_checkstateType); /* TODO: bgqueue_notice_delete should use this p->bg_name */
|
||||
if( !bg->queue_on ) return; /* temp, until feature is complete */
|
||||
if ( sd->bg_queue.arena && sd->bg_queue.type ) {
|
||||
sd->bg_queue.client_has_bg_data = true;
|
||||
clif->bgqueue_update_info(sd,sd->bg_queue.arena->id,bg->id2pos(sd->bg_queue.arena->queue_id,sd->status.account_id));
|
||||
} else
|
||||
clif->bgqueue_notice_delete(sd, BGQND_FAIL_NOT_QUEUING,0);/* TODO: wrong response, should respond with p->bg_name not id 0 */
|
||||
}
|
||||
|
||||
void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) {
|
||||
//struct packet_bgqueue_revoke_req *p = P2PTR(fd, bgqueue_revokereqType);
|
||||
return;
|
||||
//bg->queue_leave(sd, p->bg_name);
|
||||
}
|
||||
|
||||
void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd) {
|
||||
//struct packet_bgqueue_battlebegin_ack *p = P2PTR(fd, bgqueue_checkstateType);
|
||||
return;
|
||||
//if ( p->result == 1 )
|
||||
// bg->queue_pc_ready(sd);
|
||||
//else
|
||||
// bg->queue_leave(sd, p->bg_name);
|
||||
}
|
||||
|
||||
void clif_bgqueue_joined(struct map_session_data *sd, int pos) {
|
||||
struct packet_bgqueue_notify_entry p;
|
||||
|
||||
p.PacketType = bgqueue_notify_entryType;
|
||||
safestrncpy(p.name,sd->status.name,sizeof(p.name));
|
||||
p.position = pos;
|
||||
|
||||
clif->send(&p,sizeof(p), &sd->bl, BG_QUEUE);
|
||||
}
|
||||
|
||||
void clif_bgqueue_pcleft(struct map_session_data *sd) {
|
||||
/* no idea */
|
||||
return;
|
||||
}
|
||||
|
||||
// Sends BG ready req to all with same bg arena/type as sd
|
||||
void clif_bgqueue_battlebegins(struct map_session_data *sd, unsigned char arena_id, enum send_target target) {
|
||||
struct packet_bgqueue_battlebegins p;
|
||||
|
||||
p.PacketType = bgqueue_battlebegins;
|
||||
safestrncpy(p.bg_name, bg->arena[arena_id]->name, sizeof(p.bg_name));
|
||||
safestrncpy(p.game_name, bg->arena[arena_id]->name, sizeof(p.game_name));
|
||||
|
||||
clif->send(&p,sizeof(p), &sd->bl, target);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Main client packet processing function
|
||||
*------------------------------------------*/
|
||||
|
|
@ -17124,6 +17250,7 @@ void clif_bc_ready(void) {
|
|||
int do_init_clif(void) {
|
||||
const char* colors[COLOR_MAX] = { "0xFF0000", "0x00ff00", "0xffffff" };
|
||||
int i;
|
||||
|
||||
/**
|
||||
* Setup Color Table (saves unnecessary load of strtoul on every call)
|
||||
**/
|
||||
|
|
@ -17613,13 +17740,7 @@ void clif_defaults(void) {
|
|||
/* elemental-related */
|
||||
clif->elemental_info = clif_elemental_info;
|
||||
clif->elemental_updatestatus = clif_elemental_updatestatus;
|
||||
/* misc-handling */
|
||||
clif->adopt_reply = clif_Adopt_reply;
|
||||
clif->adopt_request = clif_Adopt_request;
|
||||
clif->readbook = clif_readbook;
|
||||
clif->notify_time = clif_notify_time;
|
||||
clif->user_count = clif_user_count;
|
||||
clif->noask_sub = clif_noask_sub;
|
||||
/* Hercules Channel System */
|
||||
clif->chsys_create = clif_hercules_chsys_create;
|
||||
clif->chsys_msg = clif_hercules_chsys_msg;
|
||||
clif->chsys_msg2 = clif_hercules_chsys_msg2;
|
||||
|
|
@ -17632,6 +17753,20 @@ void clif_defaults(void) {
|
|||
clif->chsys_quitg = clif_hercules_chsys_quitg;
|
||||
clif->chsys_gjoin = clif_hercules_chsys_gjoin;
|
||||
clif->chsys_gleave = clif_hercules_chsys_gleave;
|
||||
/* bgqueue */
|
||||
clif->bgqueue_ack = clif_bgqueue_ack;
|
||||
clif->bgqueue_notice_delete = clif_bgqueue_notice_delete;
|
||||
clif->bgqueue_update_info = clif_bgqueue_update_info;
|
||||
clif->bgqueue_joined = clif_bgqueue_joined;
|
||||
clif->bgqueue_pcleft = clif_bgqueue_pcleft;
|
||||
clif->bgqueue_battlebegins = clif_bgqueue_battlebegins;
|
||||
/* misc-handling */
|
||||
clif->adopt_reply = clif_Adopt_reply;
|
||||
clif->adopt_request = clif_Adopt_request;
|
||||
clif->readbook = clif_readbook;
|
||||
clif->notify_time = clif_notify_time;
|
||||
clif->user_count = clif_user_count;
|
||||
clif->noask_sub = clif_noask_sub;
|
||||
clif->cashshop_load = clif_cashshop_db;
|
||||
clif->bc_ready = clif_bc_ready;
|
||||
clif->undisguise_timer = clif_undisguise_timer;
|
||||
|
|
@ -17837,6 +17972,11 @@ void clif_defaults(void) {
|
|||
clif->pCashShopReqTab = clif_parse_CashShopReqTab;
|
||||
clif->pCashShopSchedule = clif_parse_CashShopSchedule;
|
||||
clif->pCashShopBuy = clif_parse_CashShopBuy;
|
||||
/* BGQueue */
|
||||
clif->pBGQueueRegister = clif_parse_bgqueue_register;
|
||||
clif->pBGQueueCheckState = clif_parse_bgqueue_checkstate;
|
||||
clif->pBGQueueRevokeReq = clif_parse_bgqueue_revoke_req;
|
||||
clif->pBGQueueBattleBeginAck = clif_parse_bgqueue_battlebegin_ack;
|
||||
/* */
|
||||
clif->pPartyTick = clif_parse_PartyTick;
|
||||
clif->pGuildInvite2 = clif_parse_GuildInvite2;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "../common/cbasetypes.h"
|
||||
#include "../common/db.h"
|
||||
#include "../common/mmo.h"
|
||||
#include "../common/socket.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
|
|
@ -42,6 +43,7 @@ struct eri;
|
|||
* Defines
|
||||
**/
|
||||
#define packet_len(cmd) packet_db[cmd].len
|
||||
#define P2PTR(fd,cmd) RFIFO2PTR(fd,packet_db[cmd].len)
|
||||
#define clif_menuskill_clear(sd) (sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0;
|
||||
#define HCHSYS_NAME_LENGTH 20
|
||||
|
||||
|
|
@ -86,6 +88,8 @@ typedef enum send_target {
|
|||
BG_SAMEMAP_WOS,
|
||||
BG_AREA,
|
||||
BG_AREA_WOS,
|
||||
|
||||
BG_QUEUE,
|
||||
} send_target;
|
||||
|
||||
typedef enum emotion_type {
|
||||
|
|
@ -365,6 +369,29 @@ enum CASH_SHOP_BUY_RESULT {
|
|||
CSBR_UNKNOWN = 0xb,
|
||||
};
|
||||
|
||||
enum BATTLEGROUNDS_QUEUE_ACK {
|
||||
BGQA_SUCCESS = 1,
|
||||
BGQA_FAIL_QUEUING_FINISHED,
|
||||
BGQA_FAIL_BGNAME_INVALID,
|
||||
BGQA_FAIL_TYPE_INVALID,
|
||||
BGQA_FAIL_PPL_OVERAMOUNT,
|
||||
BGQA_FAIL_LEVEL_INCORRECT,
|
||||
BGQA_DUPLICATE_REQUEST,
|
||||
BGQA_PLEASE_RELOGIN,
|
||||
BGQA_NOT_PARTY_GUILD_LEADER,
|
||||
BGQA_FAIL_CLASS_INVALID,
|
||||
/* not official way to respond (gotta find packet?) */
|
||||
BGQA_FAIL_DESERTER,
|
||||
BGQA_FAIL_COOLDOWN,
|
||||
BGQA_FAIL_TEAM_COUNT,
|
||||
};
|
||||
|
||||
enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED {
|
||||
BGQND_CLOSEWINDOW = 1,
|
||||
BGQND_FAIL_BGNAME_WRONG = 3,
|
||||
BGQND_FAIL_NOT_QUEUING = 11,
|
||||
};
|
||||
|
||||
/**
|
||||
* Structures
|
||||
**/
|
||||
|
|
@ -499,7 +526,7 @@ struct clif_interface {
|
|||
/* main unit spawn */
|
||||
int (*spawn) (struct block_list *bl);
|
||||
/* map-related */
|
||||
void (*changemap) (struct map_session_data *sd, short map, int x, int y);
|
||||
void (*changemap) (struct map_session_data *sd, short m, int x, int y);
|
||||
void (*changemapcell) (int fd, int16 m, int x, int y, int type, enum send_target target);
|
||||
void (*map_property) (struct map_session_data* sd, enum map_property property);
|
||||
void (*pvpset) (struct map_session_data *sd, int pvprank, int pvpnum,int type);
|
||||
|
|
@ -860,6 +887,13 @@ struct clif_interface {
|
|||
/* elemental-related */
|
||||
void (*elemental_info) (struct map_session_data *sd);
|
||||
void (*elemental_updatestatus) (struct map_session_data *sd, int type);
|
||||
/* bgqueue */
|
||||
void (*bgqueue_ack) (struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK response, unsigned char arena_id);
|
||||
void (*bgqueue_notice_delete) (struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, unsigned char arena_id);
|
||||
void (*bgqueue_update_info) (struct map_session_data *sd, unsigned char arena_id, int position);
|
||||
void (*bgqueue_joined) (struct map_session_data *sd, int pos);
|
||||
void (*bgqueue_pcleft) (struct map_session_data *sd);
|
||||
void (*bgqueue_battlebegins) (struct map_session_data *sd, unsigned char arena_id, enum send_target target);
|
||||
/* misc-handling */
|
||||
void (*adopt_reply) (struct map_session_data *sd, int type);
|
||||
void (*adopt_request) (struct map_session_data *sd, struct map_session_data *src, int p_id);
|
||||
|
|
@ -1078,6 +1112,11 @@ struct clif_interface {
|
|||
void (*pSkillSelectMenu) (int fd, struct map_session_data *sd);
|
||||
void (*pMoveItem) (int fd, struct map_session_data *sd);
|
||||
void (*pDull) (int fd, struct map_session_data *sd);
|
||||
/* BGQueue */
|
||||
void (*pBGQueueRegister) (int fd, struct map_session_data *sd);
|
||||
void (*pBGQueueCheckState) (int fd, struct map_session_data *sd);
|
||||
void (*pBGQueueRevokeReq) (int fd, struct map_session_data *sd);
|
||||
void (*pBGQueueBattleBeginAck) (int fd, struct map_session_data *sd);
|
||||
/* RagExe Cash Shop [Ind/Hercules] */
|
||||
void (*pCashShopOpen) (int fd, struct map_session_data *sd);
|
||||
void (*pCashShopClose) (int fd, struct map_session_data *sd);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "clif.h"
|
||||
#include "skill.h"
|
||||
#include "log.h"
|
||||
#include "instance.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -503,6 +504,8 @@ int guild_recv_info(struct guild *sg) {
|
|||
if((g = (struct guild*)idb_get(guild_db,sg->guild_id))==NULL) {
|
||||
guild_new = true;
|
||||
g=(struct guild *)aCalloc(1,sizeof(struct guild));
|
||||
g->instance = NULL;
|
||||
g->instances = 0;
|
||||
idb_put(guild_db,sg->guild_id,g);
|
||||
if( hChSys.ally ) {
|
||||
struct hChSysCh *channel;
|
||||
|
|
@ -926,7 +929,8 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c
|
|||
sd->status.guild_id = 0;
|
||||
sd->guild = NULL;
|
||||
sd->guild_emblem_id = 0;
|
||||
|
||||
if( g->instances )
|
||||
instance->check_kick(sd);
|
||||
clif->charnameupdate(sd); //Update display name [Skotlex]
|
||||
//TODO: send emblem update to self and people around
|
||||
}
|
||||
|
|
@ -2211,6 +2215,10 @@ void do_final_guild(void) {
|
|||
for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) ) {
|
||||
if( g->channel != NULL )
|
||||
clif->chsys_delete((struct hChSysCh *)g->channel);
|
||||
if( g->instance != NULL ) {
|
||||
aFree(g->instance);
|
||||
g->instance = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
dbi_destroy(iter);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
|
||||
// For more information, see LICENCE in the main folder
|
||||
// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
|
||||
// See the LICENSE file
|
||||
// Portions Copyright (c) Athena Dev Teams
|
||||
|
||||
#include "../common/cbasetypes.h"
|
||||
#include "../common/socket.h"
|
||||
|
|
@ -24,20 +25,13 @@
|
|||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
int instance_start = 0; // To keep the last index + 1 of normal map inserted in the map[ARRAY]
|
||||
struct s_instance instance[MAX_INSTANCE];
|
||||
|
||||
|
||||
/// Checks whether given instance id is valid or not.
|
||||
static bool instance_is_valid(int instance_id)
|
||||
{
|
||||
if( instance_id < 1 || instance_id >= ARRAYLENGTH(instance) )
|
||||
{// out of range
|
||||
bool instance_is_valid(int instance_id) {
|
||||
if( instance_id < 0 || instance_id >= instance->instances ) {// out of range
|
||||
return false;
|
||||
}
|
||||
|
||||
if( instance[instance_id].state == INSTANCE_FREE )
|
||||
{// uninitialized/freed instance slot
|
||||
if( instances[instance_id].state == INSTANCE_FREE ) {// uninitialized/freed instance slot
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -48,56 +42,104 @@ static bool instance_is_valid(int instance_id)
|
|||
/*--------------------------------------
|
||||
* name : instance name
|
||||
* Return value could be
|
||||
* -4 = already exists | -3 = no free instances | -2 = party not found | -1 = invalid type
|
||||
* -4 = already exists | -3 = no free instances | -2 = owner not found | -1 = invalid type
|
||||
* On success return instance_id
|
||||
*--------------------------------------*/
|
||||
int instance_create(int party_id, const char *name)
|
||||
{
|
||||
int i;
|
||||
struct party_data* p;
|
||||
|
||||
if( ( p = party_search(party_id) ) == NULL )
|
||||
{
|
||||
ShowError("instance_create: party %d not found for instance '%s'.\n", party_id, name);
|
||||
return -2;
|
||||
int instance_create(int owner_id, const char *name, enum instance_owner_type type) {
|
||||
unsigned short *iptr = NULL, *icptr = NULL;
|
||||
struct map_session_data *sd = NULL;
|
||||
struct party_data *p = NULL;
|
||||
struct guild *g = NULL;
|
||||
int i, j;
|
||||
|
||||
switch ( type ) {
|
||||
case IOT_NONE:
|
||||
break;
|
||||
case IOT_CHAR:
|
||||
if( ( sd = map_id2sd(owner_id) ) == NULL ) {
|
||||
ShowError("instance_create: character %d not found for instance '%s'.\n", owner_id, name);
|
||||
return -2;
|
||||
}
|
||||
iptr = sd->instance;
|
||||
icptr = &sd->instances;
|
||||
break;
|
||||
case IOT_PARTY:
|
||||
if( ( p = party_search(owner_id) ) == NULL ) {
|
||||
ShowError("instance_create: party %d not found for instance '%s'.\n", owner_id, name);
|
||||
return -2;
|
||||
}
|
||||
iptr = p->instance;
|
||||
icptr = &p->instances;
|
||||
break;
|
||||
case IOT_GUILD:
|
||||
if( ( g = guild->search(owner_id) ) == NULL ) {
|
||||
ShowError("instance_create: guild %d not found for instance '%s'.\n", owner_id, name);
|
||||
return -2;
|
||||
}
|
||||
iptr = g->instance;
|
||||
icptr = &g->instances;
|
||||
break;
|
||||
default:
|
||||
ShowError("instance_create: unknown type %d for owner_id %d and name %s.\n", type,owner_id,name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( p->instance_id )
|
||||
return -4; // Party already instancing
|
||||
|
||||
// Searching a Free Instance
|
||||
// 0 is ignored as this mean "no instance" on maps
|
||||
ARR_FIND(1, MAX_INSTANCE, i, instance[i].state == INSTANCE_FREE);
|
||||
if( i == MAX_INSTANCE )
|
||||
{
|
||||
ShowError("instance_create: no free instances, consider increasing MAX_INSTANCE.\n");
|
||||
return -3;
|
||||
|
||||
if( type != IOT_NONE && *icptr ) {
|
||||
ARR_FIND(0, *icptr, i, strcmp(instances[iptr[i]].name,name) == 0 );
|
||||
if( i != *icptr )
|
||||
return -4;/* already got this instance */
|
||||
}
|
||||
|
||||
ARR_FIND(0, instance->instances, i, instances[i].state == INSTANCE_FREE);
|
||||
|
||||
if( i == instance->instances )
|
||||
RECREATE(instances, struct instance_data, ++instance->instances);
|
||||
|
||||
instance[i].state = INSTANCE_IDLE;
|
||||
instance[i].instance_id = i;
|
||||
instance[i].idle_timer = INVALID_TIMER;
|
||||
instance[i].idle_timeout = instance[i].idle_timeoutval = 0;
|
||||
instance[i].progress_timer = INVALID_TIMER;
|
||||
instance[i].progress_timeout = 0;
|
||||
instance[i].users = 0;
|
||||
instance[i].party_id = party_id;
|
||||
instance[i].vars = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||
|
||||
safestrncpy( instance[i].name, name, sizeof(instance[i].name) );
|
||||
memset( instance[i].map, 0x00, sizeof(instance[i].map) );
|
||||
p->instance_id = i;
|
||||
instances[i].state = INSTANCE_IDLE;
|
||||
instances[i].id = i;
|
||||
instances[i].idle_timer = INVALID_TIMER;
|
||||
instances[i].idle_timeout = instances[i].idle_timeoutval = 0;
|
||||
instances[i].progress_timer = INVALID_TIMER;
|
||||
instances[i].progress_timeout = 0;
|
||||
instances[i].users = 0;
|
||||
instances[i].map = NULL;
|
||||
instances[i].num_map = 0;
|
||||
instances[i].owner_id = owner_id;
|
||||
instances[i].owner_type = type;
|
||||
instances[i].vars = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||
|
||||
safestrncpy( instances[i].name, name, sizeof(instances[i].name) );
|
||||
instances[i].map = NULL;
|
||||
|
||||
if( type != IOT_NONE ) {
|
||||
ARR_FIND(0, *icptr, j, iptr[j] == 0);
|
||||
if( j == *icptr ) {
|
||||
switch( type ) {
|
||||
case IOT_CHAR:
|
||||
RECREATE(sd->instance, unsigned short, ++*icptr);
|
||||
sd->instance[sd->instances-1] = i;
|
||||
break;
|
||||
case IOT_PARTY:
|
||||
RECREATE(p->instance, unsigned short, ++*icptr);
|
||||
p->instance[p->instances-1] = i;
|
||||
break;
|
||||
case IOT_GUILD:
|
||||
RECREATE(g->instance, unsigned short, ++*icptr);
|
||||
g->instance[g->instances-1] = i;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
iptr[j] = i;
|
||||
}
|
||||
|
||||
clif->instance(i, 1, 0); // Start instancing window
|
||||
ShowInfo("[Instance] Created: %s.\n", name);
|
||||
return i;
|
||||
}
|
||||
|
||||
/*--------------------------------------
|
||||
* Add a map to the instance using src map "name"
|
||||
*--------------------------------------*/
|
||||
int instance_add_map(const char *name, int instance_id, bool usebasename)
|
||||
{
|
||||
int instance_add_map(const char *name, int instance_id, bool usebasename, const char *map_name) {
|
||||
int16 m = map_mapname2mapid(name);
|
||||
int i, im = -1;
|
||||
size_t num_cell, size;
|
||||
|
|
@ -105,42 +147,49 @@ int instance_add_map(const char *name, int instance_id, bool usebasename)
|
|||
if( m < 0 )
|
||||
return -1; // source map not found
|
||||
|
||||
if( !instance_is_valid(instance_id) )
|
||||
{
|
||||
if( !instance->valid(instance_id) ) {
|
||||
ShowError("instance_add_map: trying to attach '%s' map to non-existing instance %d.\n", name, instance_id);
|
||||
return -1;
|
||||
}
|
||||
if( instance[instance_id].num_map >= MAX_MAP_PER_INSTANCE )
|
||||
{
|
||||
ShowError("instance_add_map: trying to add '%s' map to instance %d (%s) failed. Please increase MAX_MAP_PER_INSTANCE.\n", name, instance_id, instance[instance_id].name);
|
||||
|
||||
if( map_name != NULL && strdb_iget(mapindex_db, map_name) ) {
|
||||
ShowError("instance_add_map: trying to create instanced map with existent name '%s'\n", map_name);
|
||||
return -2;
|
||||
}
|
||||
if( map[m].instance_id != 0 )
|
||||
{ // Source map already belong to a Instance.
|
||||
|
||||
if( map[m].instance_id >= 0 ) { // Source map already belong to a Instance.
|
||||
ShowError("instance_add_map: trying to instance already instanced map %s.\n", name);
|
||||
return -4;
|
||||
}
|
||||
|
||||
ARR_FIND( instance->start_id, map_num, i, !map[i].name[0] ); // Searching for a Free Map
|
||||
|
||||
ARR_FIND( instance_start, map_num, i, !map[i].name[0] ); // Searching for a Free Map
|
||||
if( i < map_num ) im = i; // Unused map found (old instance)
|
||||
else if( map_num - 1 >= MAX_MAP_PER_SERVER )
|
||||
{ // No more free maps
|
||||
ShowError("instance_add_map: no more free space to create maps on this server.\n");
|
||||
return -5;
|
||||
if( i < map_num )
|
||||
im = i; // Unused map found (old instance)
|
||||
else {
|
||||
im = map_num; // Using next map index
|
||||
RECREATE(map,struct map_data,++map_num);
|
||||
}
|
||||
else im = map_num++; // Using next map index
|
||||
|
||||
if( map[m].cell == (struct mapcell *)0xdeadbeaf )
|
||||
map_cellfromcache(&map[m]);
|
||||
|
||||
memcpy( &map[im], &map[m], sizeof(struct map_data) ); // Copy source map
|
||||
snprintf(map[im].name, MAP_NAME_LENGTH, (usebasename ? "%.3d#%s" : "%.3d%s"), instance_id, name); // Generate Name for Instance Map
|
||||
if( map_name != NULL ) {
|
||||
snprintf(map[im].name, MAP_NAME_LENGTH, "%s", map_name);
|
||||
map[im].cName = map[m].name;
|
||||
} else
|
||||
snprintf(map[im].name, MAP_NAME_LENGTH, (usebasename ? "%.3d#%s" : "%.3d%s"), instance_id, name); // Generate Name for Instance Map
|
||||
map[im].index = mapindex_addmap(-1, map[im].name); // Add map index
|
||||
|
||||
if( !map[im].index )
|
||||
{
|
||||
map[im].channel = NULL;
|
||||
|
||||
if( !map[im].index ) {
|
||||
map[im].name[0] = '\0';
|
||||
ShowError("instance_add_map: no more free map indexes.\n");
|
||||
return -3; // No free map index
|
||||
}
|
||||
|
||||
|
||||
// Reallocate cells
|
||||
num_cell = map[im].xs * map[im].ys;
|
||||
CREATE( map[im].cell, struct mapcell, num_cell );
|
||||
|
|
@ -161,9 +210,11 @@ int instance_add_map(const char *name, int instance_id, bool usebasename)
|
|||
map[im].instance_src_map = m;
|
||||
map[m].flag.src4instance = 1; // Flag this map as a src map for instances
|
||||
|
||||
instance[instance_id].map[instance[instance_id].num_map++] = im; // Attach to actual instance
|
||||
map_addmap2db(&map[im]);
|
||||
RECREATE(instances[instance_id].map, unsigned short, ++instances[instance_id].num_map);
|
||||
|
||||
instances[instance_id].map[instances[instance_id].num_map - 1] = im; // Attach to actual instance
|
||||
map_addmap2db(&map[im]);
|
||||
|
||||
return im;
|
||||
}
|
||||
|
||||
|
|
@ -172,19 +223,16 @@ int instance_add_map(const char *name, int instance_id, bool usebasename)
|
|||
* party_id : source party of this instance
|
||||
* type : result (0 = map id | 1 = instance id)
|
||||
*--------------------------------------*/
|
||||
int instance_map2imap(int16 m, int instance_id)
|
||||
{
|
||||
int instance_map2imap(int16 m, int instance_id) {
|
||||
int i;
|
||||
|
||||
if( !instance_is_valid(instance_id) )
|
||||
{
|
||||
if( !instance->valid(instance_id) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for( i = 0; i < instance[instance_id].num_map; i++ )
|
||||
{
|
||||
if( instance[instance_id].map[i] && map[instance[instance_id].map[i]].instance_src_map == m )
|
||||
return instance[instance_id].map[i];
|
||||
for( i = 0; i < instances[instance_id].num_map; i++ ) {
|
||||
if( instances[instance_id].map[i] && map[instances[instance_id].map[i]].instance_src_map == m )
|
||||
return instances[instance_id].map[i];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -194,59 +242,56 @@ int instance_map2imap(int16 m, int instance_id)
|
|||
* instance_id : where to search
|
||||
* result : mapid of map "m" in this instance
|
||||
*--------------------------------------*/
|
||||
int instance_mapid2imapid(int16 m, int instance_id)
|
||||
{
|
||||
int instance_mapid2imapid(int16 m, int instance_id) {
|
||||
if( map[m].flag.src4instance == 0 )
|
||||
return m; // not instances found for this map
|
||||
else if( map[m].instance_id )
|
||||
{ // This map is a instance, not a src map instance
|
||||
else if( map[m].instance_id >= 0 ) { // This map is a instance, not a src map instance
|
||||
ShowError("map_instance_mapid2imapid: already instanced (%d / %d)\n", m, instance_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( !instance_is_valid(instance_id) )
|
||||
if( !instance->valid(instance_id) )
|
||||
return -1;
|
||||
|
||||
return instance_map2imap(m, instance_id);
|
||||
return instance->map2imap(m, instance_id);
|
||||
}
|
||||
|
||||
/*--------------------------------------
|
||||
* map_instance_map_npcsub
|
||||
* Used on Init instance. Duplicates each script on source map
|
||||
*--------------------------------------*/
|
||||
int instance_map_npcsub(struct block_list* bl, va_list args)
|
||||
{
|
||||
int instance_map_npcsub(struct block_list* bl, va_list args) {
|
||||
struct npc_data* nd = (struct npc_data*)bl;
|
||||
int16 m = va_arg(args, int); // Destination Map
|
||||
|
||||
npc_duplicate4instance(nd, m);
|
||||
if ( npc_duplicate4instance(nd, m) )
|
||||
ShowDebug("instance_map_npcsub:npc_duplicate4instance failed (%s/%d)\n",nd->name,m);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*--------------------------------------
|
||||
* Init all map on the instance. Npcs are created here
|
||||
*--------------------------------------*/
|
||||
void instance_init(int instance_id)
|
||||
{
|
||||
void instance_init(int instance_id) {
|
||||
int i;
|
||||
|
||||
if( !instance_is_valid(instance_id) )
|
||||
if( !instance->valid(instance_id) )
|
||||
return; // nothing to do
|
||||
|
||||
for( i = 0; i < instance[instance_id].num_map; i++ )
|
||||
map_foreachinmap(instance_map_npcsub, map[instance[instance_id].map[i]].instance_src_map, BL_NPC, instance[instance_id].map[i]);
|
||||
for( i = 0; i < instances[instance_id].num_map; i++ )
|
||||
map_foreachinmap(instance_map_npcsub, map[instances[instance_id].map[i]].instance_src_map, BL_NPC, instances[instance_id].map[i]);
|
||||
|
||||
instance[instance_id].state = INSTANCE_BUSY;
|
||||
ShowInfo("[Instance] Initialized %s.\n", instance[instance_id].name);
|
||||
instances[instance_id].state = INSTANCE_BUSY;
|
||||
}
|
||||
|
||||
/*--------------------------------------
|
||||
* Used on instance deleting process.
|
||||
* Warps all players on each instance map to its save points.
|
||||
*--------------------------------------*/
|
||||
int instance_del_load(struct map_session_data* sd, va_list args)
|
||||
{
|
||||
int instance_del_load(struct map_session_data* sd, va_list args) {
|
||||
int16 m = va_arg(args,int);
|
||||
|
||||
if( !sd || sd->bl.m != m )
|
||||
return 0;
|
||||
|
||||
|
|
@ -285,12 +330,11 @@ int instance_cleanup_sub(struct block_list *bl, va_list ap) {
|
|||
/*--------------------------------------
|
||||
* Removes a simple instance map
|
||||
*--------------------------------------*/
|
||||
void instance_del_map(int16 m)
|
||||
{
|
||||
void instance_del_map(int16 m) {
|
||||
int i;
|
||||
if( m <= 0 || !map[m].instance_id )
|
||||
{
|
||||
ShowError("Tried to remove non-existing instance map (%d)\n", m);
|
||||
|
||||
if( m <= 0 || map[m].instance_id == -1 ) {
|
||||
ShowError("instance_del_map: tried to remove non-existing instance map (%d)\n", m);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -299,116 +343,145 @@ void instance_del_map(int16 m)
|
|||
|
||||
if( map[m].mob_delete_timer != INVALID_TIMER )
|
||||
delete_timer(map[m].mob_delete_timer, map_removemobs_timer);
|
||||
|
||||
|
||||
mapindex_removemap( map[m].index );
|
||||
|
||||
// Free memory
|
||||
aFree(map[m].cell);
|
||||
aFree(map[m].block);
|
||||
aFree(map[m].block_mob);
|
||||
|
||||
|
||||
// Remove from instance
|
||||
for( i = 0; i < instance[map[m].instance_id].num_map; i++ )
|
||||
{
|
||||
if( instance[map[m].instance_id].map[i] == m )
|
||||
{
|
||||
instance[map[m].instance_id].num_map--;
|
||||
for( ; i < instance[map[m].instance_id].num_map; i++ )
|
||||
instance[map[m].instance_id].map[i] = instance[map[m].instance_id].map[i+1];
|
||||
for( i = 0; i < instances[map[m].instance_id].num_map; i++ ) {
|
||||
if( instances[map[m].instance_id].map[i] == m ) {
|
||||
instances[map[m].instance_id].num_map--;
|
||||
for( ; i < instances[map[m].instance_id].num_map; i++ )
|
||||
instances[map[m].instance_id].map[i] = instances[map[m].instance_id].map[i+1];
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( i == instance[map[m].instance_id].num_map )
|
||||
ShowError("map_instance_del: failed to remove %s from instance list (%s): %d\n", map[m].name, instance[map[m].instance_id].name, m);
|
||||
|
||||
if( i == instances[map[m].instance_id].num_map )
|
||||
ShowError("map_instance_del: failed to remove %s from instance list (%s): %d\n", map[m].name, instances[map[m].instance_id].name, m);
|
||||
|
||||
if( map[m].channel )
|
||||
clif->chsys_delete(map[m].channel);
|
||||
|
||||
map_removemapdb(&map[m]);
|
||||
memset(&map[m], 0x00, sizeof(map[0]));
|
||||
|
||||
/* for it is default and makes it not try to delete a non-existent timer since we did not delete this entry. */
|
||||
map[m].instance_id = -1;
|
||||
map[m].mob_delete_timer = INVALID_TIMER;
|
||||
}
|
||||
|
||||
/*--------------------------------------
|
||||
* Timer to destroy instance by process or idle
|
||||
*--------------------------------------*/
|
||||
int instance_destroy_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
{
|
||||
instance_destroy(id);
|
||||
int instance_destroy_timer(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
instance->destroy(id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*--------------------------------------
|
||||
* Removes a instance, all its maps and npcs.
|
||||
*--------------------------------------*/
|
||||
void instance_destroy(int instance_id)
|
||||
{
|
||||
int last = 0, type;
|
||||
struct party_data *p;
|
||||
time_t now = time(NULL);
|
||||
void instance_destroy(int instance_id) {
|
||||
unsigned short *iptr = NULL, *icptr = NULL;
|
||||
struct map_session_data *sd = NULL;
|
||||
struct party_data *p = NULL;
|
||||
struct guild *g = NULL;
|
||||
int last = 0, type, j;
|
||||
unsigned int now = (unsigned int)time(NULL);
|
||||
|
||||
if( !instance_is_valid(instance_id) )
|
||||
if( !instance->valid(instance_id) )
|
||||
return; // nothing to do
|
||||
|
||||
if( instance[instance_id].progress_timeout && instance[instance_id].progress_timeout <= now )
|
||||
if( instances[instance_id].progress_timeout && instances[instance_id].progress_timeout <= now )
|
||||
type = 1;
|
||||
else if( instance[instance_id].idle_timeout && instance[instance_id].idle_timeout <= now )
|
||||
else if( instances[instance_id].idle_timeout && instances[instance_id].idle_timeout <= now )
|
||||
type = 2;
|
||||
else
|
||||
type = 3;
|
||||
|
||||
clif->instance(instance_id, 5, type); // Report users this instance has been destroyed
|
||||
|
||||
while( instance[instance_id].num_map && last != instance[instance_id].map[0] )
|
||||
{ // Remove all maps from instance
|
||||
last = instance[instance_id].map[0];
|
||||
instance_del_map( instance[instance_id].map[0] );
|
||||
switch ( instances[instance_id].owner_type ) {
|
||||
case IOT_NONE:
|
||||
break;
|
||||
case IOT_CHAR:
|
||||
if( ( sd = map_id2sd(instances[instance_id].owner_id) ) == NULL ) {
|
||||
break;
|
||||
}
|
||||
iptr = sd->instance;
|
||||
icptr = &sd->instances;
|
||||
break;
|
||||
case IOT_PARTY:
|
||||
if( ( p = party_search(instances[instance_id].owner_id) ) == NULL ) {
|
||||
break;
|
||||
}
|
||||
iptr = p->instance;
|
||||
icptr = &p->instances;
|
||||
break;
|
||||
case IOT_GUILD:
|
||||
if( ( g = guild->search(instances[instance_id].owner_id) ) == NULL ) {
|
||||
break;
|
||||
}
|
||||
iptr = g->instance;
|
||||
icptr = &g->instances;
|
||||
break;
|
||||
default:
|
||||
ShowError("instance_destroy: unknown type %d for owner_id %d and name %s.\n", instances[instance_id].owner_type,instances[instance_id].owner_id,instances[instance_id].name);
|
||||
break;
|
||||
}
|
||||
|
||||
if( iptr != NULL ) {
|
||||
ARR_FIND(0, *icptr, j, iptr[j] == instance_id);
|
||||
if( j != *icptr )
|
||||
iptr[j] = 0;
|
||||
}
|
||||
|
||||
while( instances[instance_id].num_map && last != instances[instance_id].map[0] ) { // Remove all maps from instance
|
||||
last = instances[instance_id].map[0];
|
||||
instance->del_map( instances[instance_id].map[0] );
|
||||
}
|
||||
|
||||
if( instance[instance_id].vars )
|
||||
db_destroy(instance[instance_id].vars);
|
||||
if( instances[instance_id].vars )
|
||||
db_destroy(instances[instance_id].vars);
|
||||
|
||||
if( instance[instance_id].progress_timer != INVALID_TIMER )
|
||||
delete_timer( instance[instance_id].progress_timer, instance_destroy_timer);
|
||||
if( instance[instance_id].idle_timer != INVALID_TIMER )
|
||||
delete_timer( instance[instance_id].idle_timer, instance_destroy_timer);
|
||||
if( instances[instance_id].progress_timer != INVALID_TIMER )
|
||||
delete_timer( instances[instance_id].progress_timer, instance_destroy_timer);
|
||||
if( instances[instance_id].idle_timer != INVALID_TIMER )
|
||||
delete_timer( instances[instance_id].idle_timer, instance_destroy_timer);
|
||||
|
||||
instance[instance_id].vars = NULL;
|
||||
instances[instance_id].vars = NULL;
|
||||
|
||||
if( instance[instance_id].party_id && (p = party_search(instance[instance_id].party_id)) != NULL )
|
||||
p->instance_id = 0; // Update Party information
|
||||
aFree(instances[instance_id].map);
|
||||
|
||||
memset( &instances[instance_id], 0x00, sizeof(struct instance_data) );
|
||||
|
||||
ShowInfo("[Instance] Destroyed %s.\n", instance[instance_id].name);
|
||||
memset( &instance[instance_id], 0x00, sizeof(instance[0]) );
|
||||
|
||||
instance[instance_id].state = INSTANCE_FREE;
|
||||
}
|
||||
|
||||
/*--------------------------------------
|
||||
* Checks if there are users in the instance or not to start idle timer
|
||||
*--------------------------------------*/
|
||||
void instance_check_idle(int instance_id)
|
||||
{
|
||||
void instance_check_idle(int instance_id) {
|
||||
bool idle = true;
|
||||
time_t now = time(NULL);
|
||||
unsigned int now = (unsigned int)time(NULL);
|
||||
|
||||
if( !instance_is_valid(instance_id) || instance[instance_id].idle_timeoutval == 0 )
|
||||
if( !instance->valid(instance_id) || instances[instance_id].idle_timeoutval == 0 )
|
||||
return;
|
||||
|
||||
if( instance[instance_id].users )
|
||||
if( instances[instance_id].users )
|
||||
idle = false;
|
||||
|
||||
if( instance[instance_id].idle_timer != INVALID_TIMER && !idle )
|
||||
{
|
||||
delete_timer(instance[instance_id].idle_timer, instance_destroy_timer);
|
||||
instance[instance_id].idle_timer = INVALID_TIMER;
|
||||
instance[instance_id].idle_timeout = 0;
|
||||
if( instances[instance_id].idle_timer != INVALID_TIMER && !idle ) {
|
||||
delete_timer(instances[instance_id].idle_timer, instance_destroy_timer);
|
||||
instances[instance_id].idle_timer = INVALID_TIMER;
|
||||
instances[instance_id].idle_timeout = 0;
|
||||
clif->instance(instance_id, 3, 0); // Notify instance users normal instance expiration
|
||||
}
|
||||
else if( instance[instance_id].idle_timer == INVALID_TIMER && idle )
|
||||
{
|
||||
instance[instance_id].idle_timeout = now + instance[instance_id].idle_timeoutval;
|
||||
instance[instance_id].idle_timer = add_timer( gettick() + (unsigned int)instance[instance_id].idle_timeoutval * 1000, instance_destroy_timer, instance_id, 0);
|
||||
} else if( instances[instance_id].idle_timer == INVALID_TIMER && idle ) {
|
||||
instances[instance_id].idle_timeout = now + instances[instance_id].idle_timeoutval;
|
||||
instances[instance_id].idle_timer = add_timer( gettick() + instances[instance_id].idle_timeoutval * 1000, instance_destroy_timer, instance_id, 0);
|
||||
clif->instance(instance_id, 4, 0); // Notify instance users it will be destroyed of no user join it again in "X" time
|
||||
}
|
||||
}
|
||||
|
|
@ -418,54 +491,46 @@ void instance_check_idle(int instance_id)
|
|||
*--------------------------------------*/
|
||||
void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsigned int idle_timeout)
|
||||
{
|
||||
time_t now = time(0);
|
||||
unsigned int now = time(0);
|
||||
|
||||
if( !instance_is_valid(instance_id) )
|
||||
if( !instance->valid(instance_id) )
|
||||
return;
|
||||
|
||||
if( instance[instance_id].progress_timer != INVALID_TIMER )
|
||||
delete_timer( instance[instance_id].progress_timer, instance_destroy_timer);
|
||||
if( instance[instance_id].idle_timer != INVALID_TIMER )
|
||||
delete_timer( instance[instance_id].idle_timer, instance_destroy_timer);
|
||||
if( instances[instance_id].progress_timer != INVALID_TIMER )
|
||||
delete_timer( instances[instance_id].progress_timer, instance_destroy_timer);
|
||||
if( instances[instance_id].idle_timer != INVALID_TIMER )
|
||||
delete_timer( instances[instance_id].idle_timer, instance_destroy_timer);
|
||||
|
||||
if( progress_timeout )
|
||||
{
|
||||
instance[instance_id].progress_timeout = now + progress_timeout;
|
||||
instance[instance_id].progress_timer = add_timer( gettick() + progress_timeout * 1000, instance_destroy_timer, instance_id, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
instance[instance_id].progress_timeout = 0;
|
||||
instance[instance_id].progress_timer = INVALID_TIMER;
|
||||
if( progress_timeout ) {
|
||||
instances[instance_id].progress_timeout = now + progress_timeout;
|
||||
instances[instance_id].progress_timer = add_timer( gettick() + progress_timeout * 1000, instance_destroy_timer, instance_id, 0);
|
||||
} else {
|
||||
instances[instance_id].progress_timeout = 0;
|
||||
instances[instance_id].progress_timer = INVALID_TIMER;
|
||||
}
|
||||
|
||||
if( idle_timeout )
|
||||
{
|
||||
instance[instance_id].idle_timeoutval = idle_timeout;
|
||||
instance[instance_id].idle_timer = INVALID_TIMER;
|
||||
if( idle_timeout ) {
|
||||
instances[instance_id].idle_timeoutval = idle_timeout;
|
||||
instances[instance_id].idle_timer = INVALID_TIMER;
|
||||
instance_check_idle(instance_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
instance[instance_id].idle_timeoutval = 0;
|
||||
instance[instance_id].idle_timeout = 0;
|
||||
instance[instance_id].idle_timer = INVALID_TIMER;
|
||||
} else {
|
||||
instances[instance_id].idle_timeoutval = 0;
|
||||
instances[instance_id].idle_timeout = 0;
|
||||
instances[instance_id].idle_timer = INVALID_TIMER;
|
||||
}
|
||||
|
||||
if( instance[instance_id].idle_timer == INVALID_TIMER && instance[instance_id].progress_timer != INVALID_TIMER )
|
||||
if( instances[instance_id].idle_timer == INVALID_TIMER && instances[instance_id].progress_timer != INVALID_TIMER )
|
||||
clif->instance(instance_id, 3, 0);
|
||||
}
|
||||
|
||||
/*--------------------------------------
|
||||
* Checks if sd in on a instance and should be kicked from it
|
||||
*--------------------------------------*/
|
||||
void instance_check_kick(struct map_session_data *sd)
|
||||
{
|
||||
void instance_check_kick(struct map_session_data *sd) {
|
||||
int16 m = sd->bl.m;
|
||||
|
||||
clif->instance_leave(sd->fd);
|
||||
if( map[m].instance_id )
|
||||
{ // User was on the instance map
|
||||
if( map[m].instance_id >= 0 ) { // User was on the instance map
|
||||
if( map[m].save.map )
|
||||
pc_setpos(sd, map[m].save.map, map[m].save.x, map[m].save.y, CLR_TELEPORT);
|
||||
else
|
||||
|
|
@ -473,16 +538,41 @@ void instance_check_kick(struct map_session_data *sd)
|
|||
}
|
||||
}
|
||||
|
||||
void do_final_instance(void)
|
||||
{
|
||||
void do_final_instance(void) {
|
||||
int i;
|
||||
|
||||
for( i = 1; i < MAX_INSTANCE; i++ )
|
||||
for(i = 0; i < instance->instances; i++) {
|
||||
instance_destroy(i);
|
||||
}
|
||||
|
||||
aFree(instances);
|
||||
}
|
||||
|
||||
void do_init_instance(void)
|
||||
{
|
||||
memset(instance, 0x00, sizeof(instance));
|
||||
void do_init_instance(void) {
|
||||
add_timer_func_list(instance_destroy_timer, "instance_destroy_timer");
|
||||
}
|
||||
|
||||
void instance_defaults(void) {
|
||||
instance = &instance_s;
|
||||
|
||||
instance->init = do_init_instance;
|
||||
instance->final = do_final_instance;
|
||||
|
||||
/* start point */
|
||||
instance->start_id = 0;
|
||||
/* count */
|
||||
instance->instances = 0;
|
||||
|
||||
/* */
|
||||
instance->create = instance_create;
|
||||
instance->add_map = instance_add_map;
|
||||
instance->del_map = instance_del_map;
|
||||
instance->map2imap = instance_map2imap;
|
||||
instance->mapid2imapid = instance_mapid2imapid;
|
||||
instance->destroy = instance_destroy;
|
||||
instance->start = instance_init;
|
||||
instance->check_idle = instance_check_idle;
|
||||
instance->check_kick = instance_check_kick;
|
||||
instance->set_timeout = instance_set_timeout;
|
||||
instance->valid = instance_is_valid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,51 +1,71 @@
|
|||
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
|
||||
// For more information, see LICENCE in the main folder
|
||||
// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
|
||||
// See the LICENSE file
|
||||
// Portions Copyright (c) Athena Dev Teams
|
||||
|
||||
#ifndef _INSTANCE_H_
|
||||
#define _INSTANCE_H_
|
||||
|
||||
#define MAX_MAP_PER_INSTANCE 10
|
||||
#define MAX_INSTANCE 500
|
||||
|
||||
#define INSTANCE_NAME_LENGTH (60+1)
|
||||
|
||||
typedef enum instance_state { INSTANCE_FREE, INSTANCE_IDLE, INSTANCE_BUSY } instance_state;
|
||||
typedef enum instance_state {
|
||||
INSTANCE_FREE,
|
||||
INSTANCE_IDLE,
|
||||
INSTANCE_BUSY
|
||||
} instance_state;
|
||||
|
||||
struct s_instance {
|
||||
enum instance_owner_type {
|
||||
IOT_NONE,
|
||||
IOT_CHAR,
|
||||
IOT_PARTY,
|
||||
IOT_GUILD,
|
||||
/* ... */
|
||||
IOT_MAX,
|
||||
};
|
||||
|
||||
struct instance_data {
|
||||
unsigned short id;
|
||||
char name[INSTANCE_NAME_LENGTH]; // Instance Name - required for clif functions.
|
||||
instance_state state;
|
||||
short instance_id;
|
||||
int party_id;
|
||||
enum instance_owner_type owner_type;
|
||||
int owner_id;
|
||||
|
||||
int map[MAX_MAP_PER_INSTANCE];
|
||||
int num_map;
|
||||
int users;
|
||||
unsigned short *map;
|
||||
unsigned short num_map;
|
||||
unsigned short users;
|
||||
|
||||
struct DBMap* vars; // Instance Variable for scripts
|
||||
|
||||
int progress_timer;
|
||||
time_t progress_timeout;
|
||||
unsigned int progress_timeout;
|
||||
|
||||
int idle_timer;
|
||||
time_t idle_timeout, idle_timeoutval;
|
||||
unsigned int idle_timeout, idle_timeoutval;
|
||||
};
|
||||
|
||||
extern int instance_start;
|
||||
extern struct s_instance instance[MAX_INSTANCE];
|
||||
struct instance_data *instances;
|
||||
|
||||
int instance_create(int party_id, const char *name);
|
||||
int instance_add_map(const char *name, int instance_id, bool usebasename);
|
||||
void instance_del_map(int16 m);
|
||||
int instance_map2imap(int16 m, int instance_id);
|
||||
int instance_mapid2imapid(int16 m, int instance_id);
|
||||
void instance_destroy(int instance_id);
|
||||
void instance_init(int instance_id);
|
||||
struct instance_interface {
|
||||
void (*init) (void);
|
||||
void (*final) (void);
|
||||
/* start point */
|
||||
unsigned short start_id;
|
||||
unsigned short instances;
|
||||
/* */
|
||||
int (*create) (int party_id, const char *name, enum instance_owner_type type);
|
||||
int (*add_map) (const char *name, int instance_id, bool usebasename, const char *map_name);
|
||||
void (*del_map) (int16 m);
|
||||
int (*map2imap) (int16 m, int instance_id);
|
||||
int (*mapid2imapid) (int16 m, int instance_id);
|
||||
void (*destroy) (int instance_id);
|
||||
void (*start) (int instance_id);
|
||||
void (*check_idle) (int instance_id);
|
||||
void (*check_kick) (struct map_session_data *sd);
|
||||
void (*set_timeout) (int instance_id, unsigned int progress_timeout, unsigned int idle_timeout);
|
||||
bool (*valid) (int instance_id);
|
||||
} instance_s;
|
||||
|
||||
void instance_check_idle(int instance_id);
|
||||
void instance_check_kick(struct map_session_data *sd);
|
||||
void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsigned int idle_timeout);
|
||||
struct instance_interface *instance;
|
||||
|
||||
void do_final_instance(void);
|
||||
void do_init_instance(void);
|
||||
void instance_defaults(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -467,7 +467,7 @@ int intif_party_changemap(struct map_session_data *sd,int online)
|
|||
if(!sd)
|
||||
return 0;
|
||||
|
||||
if( (m=map_mapindex2mapid(sd->mapindex)) >= 0 && map[m].instance_id )
|
||||
if( (m=map_mapindex2mapid(sd->mapindex)) >= 0 && map[m].instance_id >= 0 )
|
||||
mapindex = map[map[m].instance_src_map].index;
|
||||
else
|
||||
mapindex = sd->mapindex;
|
||||
|
|
|
|||
|
|
@ -22,12 +22,16 @@
|
|||
char send_string[200];
|
||||
|
||||
int irc_connect_timer(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
struct hSockOpt opt;
|
||||
if( ircbot->isOn || ++ircbot->fails >= 3 )
|
||||
return 0;
|
||||
|
||||
opt.silent = 1;
|
||||
opt.setTimeo = 0;
|
||||
|
||||
ircbot->last_try = gettick();
|
||||
|
||||
if( ( ircbot->fd = make_connection(ircbot->ip,hChSys.irc_server_port,true) ) > 0 ){
|
||||
if( ( ircbot->fd = make_connection(ircbot->ip,hChSys.irc_server_port,&opt) ) > 0 ){
|
||||
session[ircbot->fd]->func_parse = ircbot->parse;
|
||||
session[ircbot->fd]->flag.server = 1;
|
||||
add_timer(gettick() + 3000, ircbot->identify_timer, 0, 0);
|
||||
|
|
|
|||
467
src/map/map.c
467
src/map/map.c
|
|
@ -101,7 +101,7 @@ static DBMap* id_db=NULL; // int id -> struct block_list*
|
|||
static DBMap* pc_db=NULL; // int id -> struct map_session_data*
|
||||
static DBMap* mobid_db=NULL; // int id -> struct mob_data*
|
||||
static DBMap* bossid_db=NULL; // int id -> struct mob_data* (MVP db)
|
||||
static DBMap* map_db=NULL; // unsigned int mapindex -> struct map_data*
|
||||
static DBMap* map_db=NULL; // unsigned int mapindex -> struct map_data_other_server*
|
||||
static DBMap* nick_db=NULL; // int char_id -> struct charid2nick* (requested names of offline characters)
|
||||
static DBMap* charid_db=NULL; // int char_id -> struct map_session_data*
|
||||
static DBMap* regen_db=NULL; // int id -> struct block_list* (status_natural_heal processing)
|
||||
|
|
@ -150,6 +150,8 @@ struct map_cache_map_info {
|
|||
int32 len;
|
||||
};
|
||||
|
||||
uint16 index2mapid[MAX_MAPINDEX];
|
||||
|
||||
char db_path[256] = "db";
|
||||
char help_txt[256] = "conf/help.txt";
|
||||
char help2_txt[256] = "conf/help2.txt";
|
||||
|
|
@ -162,6 +164,7 @@ int enable_grf = 0; //To enable/disable reading maps from GRF files, bypassing m
|
|||
|
||||
/* [Ind/Hercules] */
|
||||
struct eri *map_iterator_ers;
|
||||
char *map_cache_buffer = NULL; // Has the uncompressed gat data of all maps, so just one allocation has to be made
|
||||
|
||||
/*==========================================
|
||||
* server player count (of all mapservers)
|
||||
|
|
@ -397,8 +400,7 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
|
|||
if (sc->data[SC_PROPERTYWALK] &&
|
||||
sc->data[SC_PROPERTYWALK]->val3 >= skill->get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) )
|
||||
status_change_end(bl,SC_PROPERTYWALK,INVALID_TIMER);
|
||||
} else
|
||||
if (bl->type == BL_NPC)
|
||||
} else if (bl->type == BL_NPC)
|
||||
npc_unsetcells((TBL_NPC*)bl);
|
||||
|
||||
if (moveblock) map_delblock(bl);
|
||||
|
|
@ -469,8 +471,7 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
|
|||
skill->unit_move_unit_group(skill->id2group(sc->data[SC_HAWKEYES]->val4), bl->m, x1-x0, y1-y0);
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (bl->type == BL_NPC)
|
||||
} else if (bl->type == BL_NPC)
|
||||
npc_setcells((TBL_NPC*)bl);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1194,8 +1195,7 @@ int map_foreachinpath(int (*func)(struct block_list*,va_list),int16 m,int16 x0,i
|
|||
}
|
||||
|
||||
// Copy of map_foreachincell, but applied to the whole map. [Skotlex]
|
||||
int map_foreachinmap(int (*func)(struct block_list*,va_list), int16 m, int type,...)
|
||||
{
|
||||
int map_foreachinmap(int (*func)(struct block_list*,va_list), int16 m, int type,...) {
|
||||
int b, bsize;
|
||||
int returnCount = 0; //total sum of returned values of func() [Skotlex]
|
||||
struct block_list *bl;
|
||||
|
|
@ -1233,6 +1233,52 @@ int map_foreachinmap(int (*func)(struct block_list*,va_list), int16 m, int type,
|
|||
bl_list_count = blockcount;
|
||||
return returnCount;
|
||||
}
|
||||
// Copy of map_foreachinmap, but applied to all maps in a instance id. [Ind/Hercules]
|
||||
int map_foreachininstance(int (*func)(struct block_list*,va_list), int16 instance_id, int type,...) {
|
||||
int b, bsize;
|
||||
int returnCount = 0; //total sum of returned values of func() [Skotlex]
|
||||
struct block_list *bl;
|
||||
int blockcount = bl_list_count, i, j;
|
||||
int16 m;
|
||||
va_list ap;
|
||||
|
||||
for( j = 0; j < instances[instance_id].num_map; j++ ) {
|
||||
|
||||
m = instances[instance_id].map[j];
|
||||
|
||||
bsize = map[ m ].bxs * map[ m ].bys;
|
||||
|
||||
if( type&~BL_MOB )
|
||||
for( b = 0; b < bsize; b++ )
|
||||
for( bl = map[ m ].block[ b ]; bl != NULL; bl = bl->next )
|
||||
if( bl->type&type && bl_list_count < BL_LIST_MAX )
|
||||
bl_list[ bl_list_count++ ] = bl;
|
||||
|
||||
if( type&BL_MOB )
|
||||
for( b = 0; b < bsize; b++ )
|
||||
for( bl = map[ m ].block_mob[ b ]; bl != NULL; bl = bl->next )
|
||||
if( bl_list_count < BL_LIST_MAX )
|
||||
bl_list[ bl_list_count++ ] = bl;
|
||||
|
||||
if( bl_list_count >= BL_LIST_MAX )
|
||||
ShowWarning("map_foreachininstance: block count too many!\n");
|
||||
|
||||
map_freeblock_lock();
|
||||
|
||||
for( i = blockcount; i < bl_list_count ; i++ )
|
||||
if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion.
|
||||
va_start(ap, type);
|
||||
returnCount += func(bl_list[ i ], ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
map_freeblock_unlock();
|
||||
|
||||
}
|
||||
|
||||
bl_list_count = blockcount;
|
||||
return returnCount;
|
||||
}
|
||||
|
||||
|
||||
/// Generates a new flooritem object id from the interval [MIN_FLOORITEM, MAX_FLOORITEM).
|
||||
|
|
@ -1637,8 +1683,19 @@ int map_quit(struct map_session_data *sd) {
|
|||
|
||||
pc_itemcd_do(sd,false);
|
||||
|
||||
for( i = 0; i < sd->queues_count; i++ ) {
|
||||
struct hQueue *queue;
|
||||
if( (queue = script->queue(sd->queues[i])) && queue->onLogOut[0] != '\0' ) {
|
||||
npc_event(sd, queue->onLogOut, 0);
|
||||
}
|
||||
}
|
||||
/* two times, the npc event above may assign a new one or delete others */
|
||||
for( i = 0; i < sd->queues_count; i++ ) {
|
||||
script->queue_remove(sd->queues[i],sd->status.account_id);
|
||||
}
|
||||
|
||||
npc_script_event(sd, NPCE_LOGOUT);
|
||||
|
||||
|
||||
//Unit_free handles clearing the player related data,
|
||||
//map_quit handles extra specific data which is related to quitting normally
|
||||
//(changing map-servers invokes unit_free but bypasses map_quit)
|
||||
|
|
@ -1712,7 +1769,7 @@ int map_quit(struct map_session_data *sd) {
|
|||
|
||||
unit_remove_map_pc(sd,CLR_TELEPORT);
|
||||
|
||||
if( map[sd->bl.m].instance_id ) { // Avoid map conflicts and warnings on next login
|
||||
if( map[sd->bl.m].instance_id >= 0 ) { // Avoid map conflicts and warnings on next login
|
||||
int16 m;
|
||||
struct point *pt;
|
||||
if( map[sd->bl.m].save.map )
|
||||
|
|
@ -1720,8 +1777,7 @@ int map_quit(struct map_session_data *sd) {
|
|||
else
|
||||
pt = &sd->status.save_point;
|
||||
|
||||
if( (m=map_mapindex2mapid(pt->map)) >= 0 )
|
||||
{
|
||||
if( (m=map_mapindex2mapid(pt->map)) >= 0 ) {
|
||||
sd->bl.m = m;
|
||||
sd->bl.x = pt->x;
|
||||
sd->bl.y = pt->y;
|
||||
|
|
@ -2160,8 +2216,7 @@ bool mapit_exists(struct s_mapiterator* mapit)
|
|||
/*==========================================
|
||||
* Add npc-bl to id_db, basically register npc to map
|
||||
*------------------------------------------*/
|
||||
bool map_addnpc(int16 m,struct npc_data *nd)
|
||||
{
|
||||
bool map_addnpc(int16 m,struct npc_data *nd) {
|
||||
nullpo_ret(nd);
|
||||
|
||||
if( m < 0 || m >= map_num )
|
||||
|
|
@ -2188,8 +2243,7 @@ int map_addmobtolist(unsigned short m, struct spawn_data *spawn)
|
|||
{
|
||||
size_t i;
|
||||
ARR_FIND( 0, MAX_MOB_LIST_PER_MAP, i, map[m].moblist[i] == NULL );
|
||||
if( i < MAX_MOB_LIST_PER_MAP )
|
||||
{
|
||||
if( i < MAX_MOB_LIST_PER_MAP ) {
|
||||
map[m].moblist[i] = spawn;
|
||||
return i;
|
||||
}
|
||||
|
|
@ -2250,13 +2304,11 @@ int map_removemobs_timer(int tid, unsigned int tick, int id, intptr_t data)
|
|||
int count;
|
||||
const int16 m = id;
|
||||
|
||||
if (m < 0 || m >= MAX_MAP_PER_SERVER)
|
||||
{ //Incorrect map id!
|
||||
if (m < 0 || m >= map_num) { //Incorrect map id!
|
||||
ShowError("map_removemobs_timer error: timer %d points to invalid map %d\n",tid, m);
|
||||
return 0;
|
||||
}
|
||||
if (map[m].mob_delete_timer != tid)
|
||||
{ //Incorrect timer call!
|
||||
if (map[m].mob_delete_timer != tid) { //Incorrect timer call!
|
||||
ShowError("map_removemobs_timer mismatch: %d != %d (map %s)\n",map[m].mob_delete_timer, tid, map[m].name);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2283,8 +2335,7 @@ void map_removemobs(int16 m)
|
|||
/*==========================================
|
||||
* Hookup, get map_id from map_name
|
||||
*------------------------------------------*/
|
||||
int16 map_mapname2mapid(const char* name)
|
||||
{
|
||||
int16 map_mapname2mapid(const char* name) {
|
||||
unsigned short map_index;
|
||||
map_index = mapindex_name2id(name);
|
||||
if (!map_index)
|
||||
|
|
@ -2295,24 +2346,18 @@ int16 map_mapname2mapid(const char* name)
|
|||
/*==========================================
|
||||
* Returns the map of the given mapindex. [Skotlex]
|
||||
*------------------------------------------*/
|
||||
int16 map_mapindex2mapid(unsigned short mapindex)
|
||||
{
|
||||
struct map_data *md=NULL;
|
||||
int16 map_mapindex2mapid(unsigned short mapindex) {
|
||||
|
||||
if (!mapindex)
|
||||
if (!mapindex || mapindex > MAX_MAPINDEX)
|
||||
return -1;
|
||||
|
||||
md = (struct map_data*)uidb_get(map_db,(unsigned int)mapindex);
|
||||
if(md==NULL || md->cell==NULL)
|
||||
return -1;
|
||||
return md->m;
|
||||
return index2mapid[mapindex] == 0 ? -1 : index2mapid[mapindex];
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Switching Ip, port ? (like changing map_server) get ip/port from map_name
|
||||
*------------------------------------------*/
|
||||
int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port)
|
||||
{
|
||||
int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port) {
|
||||
struct map_data_other_server *mdos;
|
||||
|
||||
mdos = (struct map_data_other_server*)uidb_get(map_db,(unsigned int)name);
|
||||
|
|
@ -2443,8 +2488,7 @@ inline static struct mapcell map_gat2cell(int gat) {
|
|||
return cell;
|
||||
}
|
||||
|
||||
static int map_cell2gat(struct mapcell cell)
|
||||
{
|
||||
static int map_cell2gat(struct mapcell cell) {
|
||||
if( cell.walkable == 1 && cell.shootable == 1 && cell.water == 0 ) return 0;
|
||||
if( cell.walkable == 0 && cell.shootable == 0 && cell.water == 0 ) return 1;
|
||||
if( cell.walkable == 1 && cell.shootable == 1 && cell.water == 1 ) return 3;
|
||||
|
|
@ -2453,17 +2497,42 @@ static int map_cell2gat(struct mapcell cell)
|
|||
ShowWarning("map_cell2gat: cell has no matching gat type\n");
|
||||
return 1; // default to 'wall'
|
||||
}
|
||||
int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk);
|
||||
void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag);
|
||||
void map_cellfromcache(struct map_data *m) {
|
||||
char decode_buffer[MAX_MAP_SIZE];
|
||||
struct map_cache_map_info *info = NULL;
|
||||
|
||||
if( (info = (struct map_cache_map_info *)m->cellPos) ) {
|
||||
unsigned long size, xy;
|
||||
int i;
|
||||
|
||||
size = (unsigned long)info->xs*(unsigned long)info->ys;
|
||||
|
||||
// TO-DO: Maybe handle the scenario, if the decoded buffer isn't the same size as expected? [Shinryo]
|
||||
decode_zip(decode_buffer, &size, m->cellPos+sizeof(struct map_cache_map_info), info->len);
|
||||
CREATE(m->cell, struct mapcell, size);
|
||||
|
||||
for( xy = 0; xy < size; ++xy )
|
||||
m->cell[xy] = map_gat2cell(decode_buffer[xy]);
|
||||
|
||||
m->getcellp = map_getcellp;
|
||||
m->setcell = map_setcell;
|
||||
|
||||
for(i = 0; i < m->npc_num; i++) {
|
||||
npc_setcells(m->npc[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Confirm if celltype in (m,x,y) match the one given in cellchk
|
||||
*------------------------------------------*/
|
||||
int map_getcell(int16 m,int16 x,int16 y,cell_chk cellchk)
|
||||
{
|
||||
return (m < 0 || m >= MAX_MAP_PER_SERVER) ? 0 : map_getcellp(&map[m],x,y,cellchk);
|
||||
int map_getcell(int16 m,int16 x,int16 y,cell_chk cellchk) {
|
||||
return (m < 0 || m >= map_num) ? 0 : map[m].getcellp(&map[m],x,y,cellchk);
|
||||
}
|
||||
|
||||
int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk)
|
||||
{
|
||||
int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) {
|
||||
struct mapcell cell;
|
||||
|
||||
nullpo_ret(m);
|
||||
|
|
@ -2474,8 +2543,7 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk)
|
|||
|
||||
cell = m->cell[x + y*m->xs];
|
||||
|
||||
switch(cellchk)
|
||||
{
|
||||
switch(cellchk) {
|
||||
// gat type retrieval
|
||||
case CELL_GETTYPE:
|
||||
return map_cell2gat(cell);
|
||||
|
|
@ -2534,13 +2602,19 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk)
|
|||
}
|
||||
}
|
||||
|
||||
/* [Ind/Hercules] */
|
||||
int map_sub_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) {
|
||||
map_cellfromcache(m);
|
||||
m->getcellp = map_getcellp;
|
||||
m->setcell = map_setcell;
|
||||
return m->getcellp(m,x,y,cellchk);
|
||||
}
|
||||
/*==========================================
|
||||
* Change the type/flags of a map cell
|
||||
* 'cell' - which flag to modify
|
||||
* 'flag' - true = on, false = off
|
||||
*------------------------------------------*/
|
||||
void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag)
|
||||
{
|
||||
void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag) {
|
||||
int j;
|
||||
|
||||
if( m < 0 || m >= map_num || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
|
||||
|
|
@ -2565,7 +2639,16 @@ void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void map_sub_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag) {
|
||||
|
||||
if( m < 0 || m >= map_num || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
|
||||
return;
|
||||
|
||||
map_cellfromcache(&map[m]);
|
||||
map[m].setcell = map_setcell;
|
||||
map[m].getcellp = map_getcellp;
|
||||
map[m].setcell(m,x,y,cell,flag);
|
||||
}
|
||||
void map_setgatcell(int16 m, int16 x, int16 y, int gat)
|
||||
{
|
||||
int j;
|
||||
|
|
@ -2635,8 +2718,8 @@ bool map_iwall_set(int16 m, int16 x, int16 y, int size, int8 dir, bool shootable
|
|||
if( map_getcell(m, x1, y1, CELL_CHKNOREACH) )
|
||||
break; // Collision
|
||||
|
||||
map_setcell(m, x1, y1, CELL_WALKABLE, false);
|
||||
map_setcell(m, x1, y1, CELL_SHOOTABLE, shootable);
|
||||
map[m].setcell(m, x1, y1, CELL_WALKABLE, false);
|
||||
map[m].setcell(m, x1, y1, CELL_SHOOTABLE, shootable);
|
||||
|
||||
clif->changemapcell(0, m, x1, y1, map_getcell(m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP);
|
||||
}
|
||||
|
|
@ -2682,8 +2765,8 @@ void map_iwall_remove(const char *wall_name)
|
|||
for( i = 0; i < iwall->size; i++ ) {
|
||||
map_iwall_nextxy(iwall->x, iwall->y, iwall->dir, i, &x1, &y1);
|
||||
|
||||
map_setcell(iwall->m, x1, y1, CELL_SHOOTABLE, true);
|
||||
map_setcell(iwall->m, x1, y1, CELL_WALKABLE, true);
|
||||
map[iwall->m].setcell(iwall->m, x1, y1, CELL_SHOOTABLE, true);
|
||||
map[iwall->m].setcell(iwall->m, x1, y1, CELL_WALKABLE, true);
|
||||
|
||||
clif->changemapcell(0, iwall->m, x1, y1, map_getcell(iwall->m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP);
|
||||
}
|
||||
|
|
@ -2740,8 +2823,7 @@ int map_eraseallipport_sub(DBKey key, DBData *data, va_list va)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int map_eraseallipport(void)
|
||||
{
|
||||
int map_eraseallipport(void) {
|
||||
map_db->foreach(map_db,map_eraseallipport_sub);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -2749,8 +2831,7 @@ int map_eraseallipport(void)
|
|||
/*==========================================
|
||||
* Delete mapindex from db of another map server
|
||||
*------------------------------------------*/
|
||||
int map_eraseipport(unsigned short mapindex, uint32 ip, uint16 port)
|
||||
{
|
||||
int map_eraseipport(unsigned short mapindex, uint32 ip, uint16 port) {
|
||||
struct map_data_other_server *mdos;
|
||||
|
||||
mdos = (struct map_data_other_server*)uidb_get(map_db,(unsigned int)mapindex);
|
||||
|
|
@ -2800,13 +2881,12 @@ static char *map_init_mapcache(FILE *fp)
|
|||
* Map cache reading
|
||||
* [Shinryo]: Optimized some behaviour to speed this up
|
||||
*==========================================*/
|
||||
int map_readfromcache(struct map_data *m, char *buffer, char *decode_buffer)
|
||||
{
|
||||
int map_readfromcache(struct map_data *m, char *buffer) {
|
||||
int i;
|
||||
struct map_cache_main_header *header = (struct map_cache_main_header *)buffer;
|
||||
struct map_cache_map_info *info = NULL;
|
||||
char *p = buffer + sizeof(struct map_cache_main_header);
|
||||
|
||||
|
||||
for(i = 0; i < header->map_count; i++) {
|
||||
info = (struct map_cache_map_info *)p;
|
||||
|
||||
|
|
@ -2818,8 +2898,8 @@ int map_readfromcache(struct map_data *m, char *buffer, char *decode_buffer)
|
|||
}
|
||||
|
||||
if( info && i < header->map_count ) {
|
||||
unsigned long size, xy;
|
||||
|
||||
unsigned long size;
|
||||
|
||||
if( info->xs <= 0 || info->ys <= 0 )
|
||||
return 0;// Invalid
|
||||
|
||||
|
|
@ -2831,51 +2911,30 @@ int map_readfromcache(struct map_data *m, char *buffer, char *decode_buffer)
|
|||
ShowWarning("map_readfromcache: %s exceeded MAX_MAP_SIZE of %d\n", info->name, MAX_MAP_SIZE);
|
||||
return 0; // Say not found to remove it from list.. [Shinryo]
|
||||
}
|
||||
|
||||
// TO-DO: Maybe handle the scenario, if the decoded buffer isn't the same size as expected? [Shinryo]
|
||||
decode_zip(decode_buffer, &size, p+sizeof(struct map_cache_map_info), info->len);
|
||||
|
||||
CREATE(m->cell, struct mapcell, size);
|
||||
|
||||
|
||||
for( xy = 0; xy < size; ++xy )
|
||||
m->cell[xy] = map_gat2cell(decode_buffer[xy]);
|
||||
|
||||
|
||||
m->cellPos = p;
|
||||
m->cell = (struct mapcell *)0xdeadbeaf;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0; // Not found
|
||||
}
|
||||
|
||||
int map_addmap(char* mapname)
|
||||
{
|
||||
if( strcmpi(mapname,"clear")==0 )
|
||||
{
|
||||
map_num = 0;
|
||||
instance_start = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( map_num >= MAX_MAP_PER_SERVER - 1 )
|
||||
{
|
||||
ShowError("Could not add map '"CL_WHITE"%s"CL_RESET"', the limit of maps has been reached.\n",mapname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
mapindex_getmapname(mapname, map[map_num].name);
|
||||
map_num++;
|
||||
int map_addmap(char* mapname) {
|
||||
map[map_num].instance_id = -1;
|
||||
mapindex_getmapname(mapname, map[map_num++].name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void map_delmapid(int id)
|
||||
{
|
||||
static void map_delmapid(int id) {
|
||||
ShowNotice("Removing map [ %s ] from maplist"CL_CLL"\n",map[id].name);
|
||||
memmove(map+id, map+id+1, sizeof(map[0])*(map_num-id-1));
|
||||
map_num--;
|
||||
}
|
||||
|
||||
int map_delmap(char* mapname)
|
||||
{
|
||||
int map_delmap(char* mapname) {
|
||||
int i;
|
||||
char map_name[MAP_NAME_LENGTH];
|
||||
|
||||
|
|
@ -2958,13 +3017,62 @@ void map_zone_db_clear(void) {
|
|||
}
|
||||
aFree(map_zone_all.capped_skills);
|
||||
}
|
||||
|
||||
void map_clean(int i) {
|
||||
int v;
|
||||
if(map[i].cell && map[i].cell != (struct mapcell *)0xdeadbeaf) aFree(map[i].cell);
|
||||
if(map[i].block) aFree(map[i].block);
|
||||
if(map[i].block_mob) aFree(map[i].block_mob);
|
||||
|
||||
if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random]
|
||||
int j;
|
||||
if(map[i].mob_delete_timer != INVALID_TIMER)
|
||||
delete_timer(map[i].mob_delete_timer, map_removemobs_timer);
|
||||
for (j=0; j<MAX_MOB_LIST_PER_MAP; j++)
|
||||
if (map[i].moblist[j]) aFree(map[i].moblist[j]);
|
||||
}
|
||||
|
||||
if( map[i].unit_count ) {
|
||||
for(v = 0; v < map[i].unit_count; v++) {
|
||||
aFree(map[i].units[v]);
|
||||
}
|
||||
if( map[i].units ) {
|
||||
aFree(map[i].units);
|
||||
map[i].units = NULL;
|
||||
}
|
||||
map[i].unit_count = 0;
|
||||
}
|
||||
|
||||
if( map[i].skill_count ) {
|
||||
for(v = 0; v < map[i].skill_count; v++) {
|
||||
aFree(map[i].skills[v]);
|
||||
}
|
||||
if( map[i].skills ) {
|
||||
aFree(map[i].skills);
|
||||
map[i].skills = NULL;
|
||||
}
|
||||
map[i].skill_count = 0;
|
||||
}
|
||||
|
||||
if( map[i].zone_mf_count ) {
|
||||
for(v = 0; v < map[i].zone_mf_count; v++) {
|
||||
aFree(map[i].zone_mf[v]);
|
||||
}
|
||||
if( map[i].zone_mf ) {
|
||||
aFree(map[i].zone_mf);
|
||||
map[i].zone_mf = NULL;
|
||||
}
|
||||
map[i].zone_mf_count = 0;
|
||||
}
|
||||
|
||||
if( map[i].channel )
|
||||
clif->chsys_delete(map[i].channel);
|
||||
}
|
||||
void do_final_maps(void) {
|
||||
int i, v = 0;
|
||||
|
||||
for( i = 0; i < map_num; i++ ) {
|
||||
|
||||
if(map[i].cell) aFree(map[i].cell);
|
||||
if(map[i].cell && map[i].cell != (struct mapcell *)0xdeadbeaf ) aFree(map[i].cell);
|
||||
if(map[i].block) aFree(map[i].block);
|
||||
if(map[i].block_mob) aFree(map[i].block_mob);
|
||||
|
||||
|
|
@ -3009,6 +3117,12 @@ void do_final_maps(void) {
|
|||
map[i].zone_mf_count = 0;
|
||||
}
|
||||
|
||||
if( map[i].drop_list_count ) {
|
||||
map[i].drop_list_count = 0;
|
||||
}
|
||||
if( map[i].drop_list != NULL )
|
||||
aFree(map[i].drop_list);
|
||||
|
||||
if( map[i].channel )
|
||||
clif->chsys_delete(map[i].channel);
|
||||
}
|
||||
|
|
@ -3028,7 +3142,10 @@ void map_flags_init(void) {
|
|||
map[i].nocommand = 0; // nocommand mapflag level
|
||||
map[i].bexp = 100; // per map base exp multiplicator
|
||||
map[i].jexp = 100; // per map job exp multiplicator
|
||||
memset(map[i].drop_list, 0, sizeof(map[i].drop_list)); // pvp nightmare drop list
|
||||
if( map[i].drop_list != NULL )
|
||||
aFree(map[i].drop_list);
|
||||
map[i].drop_list = NULL;
|
||||
map[i].drop_list_count = 0;
|
||||
|
||||
if( map[i].unit_count ) {
|
||||
for(v = 0; v < map[i].unit_count; v++) {
|
||||
|
|
@ -3153,14 +3270,12 @@ int map_readgat (struct map_data* m)
|
|||
/*======================================
|
||||
* Add/Remove map to the map_db
|
||||
*--------------------------------------*/
|
||||
void map_addmap2db(struct map_data *m)
|
||||
{
|
||||
uidb_put(map_db, (unsigned int)m->index, m);
|
||||
void map_addmap2db(struct map_data *m) {
|
||||
index2mapid[m->index] = m->m;
|
||||
}
|
||||
|
||||
void map_removemapdb(struct map_data *m)
|
||||
{
|
||||
uidb_remove(map_db, (unsigned int)m->index);
|
||||
void map_removemapdb(struct map_data *m) {
|
||||
index2mapid[m->index] = 0;
|
||||
}
|
||||
|
||||
/*======================================
|
||||
|
|
@ -3170,8 +3285,6 @@ int map_readallmaps (void) {
|
|||
int i;
|
||||
FILE* fp=NULL;
|
||||
int maps_removed = 0;
|
||||
char *map_cache_buffer = NULL; // Has the uncompressed gat data of all maps, so just one allocation has to be made
|
||||
char map_cache_decode_buffer[MAX_MAP_SIZE];
|
||||
|
||||
if( enable_grf )
|
||||
ShowStatus("Loading maps (using GRF files)...\n");
|
||||
|
|
@ -3203,7 +3316,7 @@ int map_readallmaps (void) {
|
|||
if( !
|
||||
(enable_grf?
|
||||
map_readgat(&map[i])
|
||||
:map_readfromcache(&map[i], map_cache_buffer, map_cache_decode_buffer))
|
||||
:map_readfromcache(&map[i], map_cache_buffer))
|
||||
) {
|
||||
map_delmapid(i);
|
||||
maps_removed++;
|
||||
|
|
@ -3213,10 +3326,9 @@ int map_readallmaps (void) {
|
|||
|
||||
map[i].index = mapindex_name2id(map[i].name);
|
||||
|
||||
if (uidb_get(map_db,(unsigned int)map[i].index) != NULL)
|
||||
{
|
||||
if ( index2mapid[map[i].index] != 0 ) {
|
||||
ShowWarning("Map %s already loaded!"CL_CLL"\n", map[i].name);
|
||||
if (map[i].cell) {
|
||||
if (map[i].cell && map[i].cell != (struct mapcell *)0xdeadbeaf) {
|
||||
aFree(map[i].cell);
|
||||
map[i].cell = NULL;
|
||||
}
|
||||
|
|
@ -3225,10 +3337,10 @@ int map_readallmaps (void) {
|
|||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
map[i].m = i;
|
||||
map_addmap2db(&map[i]);
|
||||
|
||||
map[i].m = i;
|
||||
memset(map[i].moblist, 0, sizeof(map[i].moblist)); //Initialize moblist [Skotlex]
|
||||
map[i].mob_delete_timer = INVALID_TIMER; //Initialize timer [Skotlex]
|
||||
|
||||
|
|
@ -3238,6 +3350,9 @@ int map_readallmaps (void) {
|
|||
size = map[i].bxs * map[i].bys * sizeof(struct block_list*);
|
||||
map[i].block = (struct block_list**)aCalloc(size, 1);
|
||||
map[i].block_mob = (struct block_list**)aCalloc(size, 1);
|
||||
|
||||
map[i].getcellp = map_sub_getcellp;
|
||||
map[i].setcell = map_sub_setcell;
|
||||
}
|
||||
|
||||
// intialization and configuration-dependent adjustments of mapflags
|
||||
|
|
@ -3245,14 +3360,11 @@ int map_readallmaps (void) {
|
|||
|
||||
if( !enable_grf ) {
|
||||
fclose(fp);
|
||||
|
||||
// The cache isn't needed anymore, so free it.. [Shinryo]
|
||||
aFree(map_cache_buffer);
|
||||
}
|
||||
|
||||
// finished map loading
|
||||
ShowInfo("Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps."CL_CLL"\n",map_num);
|
||||
instance_start = map_num; // Next Map Index will be instances
|
||||
instance->start_id = map_num; // Next Map Index will be instances
|
||||
|
||||
if (maps_removed)
|
||||
ShowNotice("Maps removed: '"CL_WHITE"%d"CL_RESET"'\n",maps_removed);
|
||||
|
|
@ -3267,20 +3379,17 @@ static int char_ip_set = 0;
|
|||
/*==========================================
|
||||
* Read map server configuration files (conf/map_server.conf...)
|
||||
*------------------------------------------*/
|
||||
int map_config_read(char *cfgName)
|
||||
{
|
||||
int map_config_read(char *cfgName) {
|
||||
char line[1024], w1[1024], w2[1024];
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(cfgName,"r");
|
||||
if( fp == NULL )
|
||||
{
|
||||
if( fp == NULL ) {
|
||||
ShowError("Map configuration file not found at: %s\n", cfgName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while( fgets(line, sizeof(line), fp) )
|
||||
{
|
||||
while( fgets(line, sizeof(line), fp) ) {
|
||||
char* ptr;
|
||||
|
||||
if( line[0] == '/' && line[1] == '/' )
|
||||
|
|
@ -3320,9 +3429,9 @@ int map_config_read(char *cfgName)
|
|||
clif->setport(atoi(w2));
|
||||
map_port = (atoi(w2));
|
||||
} else if (strcmpi(w1, "map") == 0)
|
||||
map_addmap(w2);
|
||||
map_num++;
|
||||
else if (strcmpi(w1, "delmap") == 0)
|
||||
map_delmap(w2);
|
||||
map_num--;
|
||||
else if (strcmpi(w1, "npc") == 0)
|
||||
npc_addsrcfile(w2);
|
||||
else if (strcmpi(w1, "delnpc") == 0)
|
||||
|
|
@ -3362,7 +3471,43 @@ int map_config_read(char *cfgName)
|
|||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int map_config_read_sub(char *cfgName) {
|
||||
char line[1024], w1[1024], w2[1024];
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(cfgName,"r");
|
||||
if( fp == NULL ) {
|
||||
ShowError("Map configuration file not found at: %s\n", cfgName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while( fgets(line, sizeof(line), fp) ) {
|
||||
char* ptr;
|
||||
|
||||
if( line[0] == '/' && line[1] == '/' )
|
||||
continue;
|
||||
if( (ptr = strstr(line, "//")) != NULL )
|
||||
*ptr = '\n'; //Strip comments
|
||||
if( sscanf(line, "%[^:]: %[^\t\r\n]", w1, w2) < 2 )
|
||||
continue;
|
||||
|
||||
//Strip trailing spaces
|
||||
ptr = w2 + strlen(w2);
|
||||
while (--ptr >= w2 && *ptr == ' ');
|
||||
ptr++;
|
||||
*ptr = '\0';
|
||||
|
||||
if (strcmpi(w1, "map") == 0)
|
||||
map_addmap(w2);
|
||||
else if (strcmpi(w1, "delmap") == 0)
|
||||
map_delmap(w2);
|
||||
else if (strcmpi(w1, "import") == 0)
|
||||
map_config_read_sub(w2);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
void map_reloadnpc_sub(char *cfgName)
|
||||
{
|
||||
char line[1024], w1[1024], w2[1024];
|
||||
|
|
@ -4849,11 +4994,12 @@ void read_map_zone_db(void) {
|
|||
/**
|
||||
* @see DBApply
|
||||
*/
|
||||
int map_db_final(DBKey key, DBData *data, va_list ap)
|
||||
{
|
||||
int map_db_final(DBKey key, DBData *data, va_list ap) {
|
||||
struct map_data_other_server *mdos = DB->data2ptr(data);
|
||||
if(mdos && mdos->cell == NULL)
|
||||
|
||||
if(mdos && malloclib->verify_ptr(mdos) && mdos->cell == NULL)
|
||||
aFree(mdos);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -4877,8 +5023,7 @@ int nick_db_final(DBKey key, DBData *data, va_list args)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int cleanup_sub(struct block_list *bl, va_list ap)
|
||||
{
|
||||
int cleanup_sub(struct block_list *bl, va_list ap) {
|
||||
nullpo_ret(bl);
|
||||
|
||||
switch(bl->type) {
|
||||
|
|
@ -4932,6 +5077,8 @@ void do_final(void)
|
|||
map_quit(sd);
|
||||
mapit->free(iter);
|
||||
|
||||
instance->final();
|
||||
|
||||
/* prepares npcs for a faster shutdown process */
|
||||
do_clear_npc();
|
||||
|
||||
|
|
@ -4954,7 +5101,6 @@ void do_final(void)
|
|||
clif->final();
|
||||
do_final_npc();
|
||||
script->final();
|
||||
do_final_instance();
|
||||
do_final_itemdb();
|
||||
do_final_storage();
|
||||
guild->final();
|
||||
|
|
@ -4993,6 +5139,9 @@ void do_final(void)
|
|||
|
||||
aFree(map);
|
||||
|
||||
if( !enable_grf )
|
||||
aFree(map_cache_buffer);
|
||||
|
||||
ShowStatus("Finished.\n");
|
||||
}
|
||||
|
||||
|
|
@ -5196,10 +5345,12 @@ void map_defaults(void) {
|
|||
void load_defaults(void) {
|
||||
atcommand_defaults();
|
||||
battle_defaults();
|
||||
battleground_defaults();
|
||||
buyingstore_defaults();
|
||||
clif_defaults();
|
||||
guild_defaults();
|
||||
homunculus_defaults();
|
||||
instance_defaults();
|
||||
ircbot_defaults();
|
||||
log_defaults();
|
||||
map_defaults();
|
||||
|
|
@ -5228,79 +5379,50 @@ int do_init(int argc, char *argv[])
|
|||
|
||||
rnd_init();
|
||||
|
||||
for( i = 1; i < argc ; i++ )
|
||||
{
|
||||
for( i = 1; i < argc ; i++ ) {
|
||||
const char* arg = argv[i];
|
||||
|
||||
if( arg[0] != '-' && ( arg[0] != '/' || arg[1] == '-' ) )
|
||||
{// -, -- and /
|
||||
if( arg[0] != '-' && ( arg[0] != '/' || arg[1] == '-' ) ) {// -, -- and /
|
||||
ShowError("Unknown option '%s'.\n", argv[i]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else if( (++arg)[0] == '-' )
|
||||
{// long option
|
||||
} else if( (++arg)[0] == '-' ) {// long option
|
||||
arg++;
|
||||
|
||||
if( strcmp(arg, "help") == 0 )
|
||||
{
|
||||
if( strcmp(arg, "help") == 0 ) {
|
||||
map_helpscreen(true);
|
||||
}
|
||||
else if( strcmp(arg, "version") == 0 )
|
||||
{
|
||||
} else if( strcmp(arg, "version") == 0 ) {
|
||||
map_versionscreen(true);
|
||||
}
|
||||
else if( strcmp(arg, "map-config") == 0 )
|
||||
{
|
||||
} else if( strcmp(arg, "map-config") == 0 ) {
|
||||
if( map_arg_next_value(arg, i, argc) )
|
||||
MAP_CONF_NAME = argv[++i];
|
||||
}
|
||||
else if( strcmp(arg, "battle-config") == 0 )
|
||||
{
|
||||
} else if( strcmp(arg, "battle-config") == 0 ) {
|
||||
if( map_arg_next_value(arg, i, argc) )
|
||||
BATTLE_CONF_FILENAME = argv[++i];
|
||||
}
|
||||
else if( strcmp(arg, "atcommand-config") == 0 )
|
||||
{
|
||||
} else if( strcmp(arg, "atcommand-config") == 0 ) {
|
||||
if( map_arg_next_value(arg, i, argc) )
|
||||
ATCOMMAND_CONF_FILENAME = argv[++i];
|
||||
}
|
||||
else if( strcmp(arg, "script-config") == 0 )
|
||||
{
|
||||
} else if( strcmp(arg, "script-config") == 0 ) {
|
||||
if( map_arg_next_value(arg, i, argc) )
|
||||
SCRIPT_CONF_NAME = argv[++i];
|
||||
}
|
||||
else if( strcmp(arg, "msg-config") == 0 )
|
||||
{
|
||||
} else if( strcmp(arg, "msg-config") == 0 ) {
|
||||
if( map_arg_next_value(arg, i, argc) )
|
||||
MSG_CONF_NAME = argv[++i];
|
||||
}
|
||||
else if( strcmp(arg, "grf-path-file") == 0 )
|
||||
{
|
||||
} else if( strcmp(arg, "grf-path-file") == 0 ) {
|
||||
if( map_arg_next_value(arg, i, argc) )
|
||||
GRF_PATH_FILENAME = argv[++i];
|
||||
}
|
||||
else if( strcmp(arg, "inter-config") == 0 )
|
||||
{
|
||||
} else if( strcmp(arg, "inter-config") == 0 ) {
|
||||
if( map_arg_next_value(arg, i, argc) )
|
||||
INTER_CONF_NAME = argv[++i];
|
||||
}
|
||||
else if( strcmp(arg, "log-config") == 0 )
|
||||
{
|
||||
} else if( strcmp(arg, "log-config") == 0 ) {
|
||||
if( map_arg_next_value(arg, i, argc) )
|
||||
LOG_CONF_NAME = argv[++i];
|
||||
}
|
||||
else if( strcmp(arg, "run-once") == 0 ) // close the map-server as soon as its done.. for testing [Celest]
|
||||
{
|
||||
} else if( strcmp(arg, "run-once") == 0 ) { // close the map-server as soon as its done.. for testing [Celest]
|
||||
runflag = CORE_ST_STOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
ShowError("Unknown option '%s'.\n", argv[i]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else switch( arg[0] )
|
||||
{// short option
|
||||
} else switch( arg[0] ) {// short option
|
||||
case '?':
|
||||
case 'h':
|
||||
map_helpscreen(true);
|
||||
|
|
@ -5313,12 +5435,13 @@ int do_init(int argc, char *argv[])
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
CREATE(map,struct map_data,MAX_MAP_PER_SERVER);
|
||||
|
||||
memset(&index2mapid, 0, sizeof(index2mapid));
|
||||
|
||||
load_defaults();
|
||||
|
||||
map_config_read(MAP_CONF_NAME);
|
||||
CREATE(map,struct map_data,map_num);
|
||||
map_num = 0;
|
||||
map_config_read_sub(MAP_CONF_NAME);
|
||||
// loads npcs
|
||||
map_reloadnpc(false);
|
||||
|
||||
|
|
@ -5384,7 +5507,7 @@ int do_init(int argc, char *argv[])
|
|||
|
||||
atcommand->init();
|
||||
battle->init();
|
||||
do_init_instance();
|
||||
instance->init();
|
||||
do_init_chrif();
|
||||
clif->init();
|
||||
ircbot->init();
|
||||
|
|
|
|||
|
|
@ -27,20 +27,18 @@ enum E_MAPSERVER_ST {
|
|||
MAPSERVER_ST_LAST
|
||||
};
|
||||
|
||||
|
||||
#define MAX_NPC_PER_MAP 512
|
||||
#define AREA_SIZE battle_config.area_size
|
||||
#define DAMAGELOG_SIZE 30
|
||||
#define LOOTITEM_SIZE 10
|
||||
#define MAX_MOBSKILL 50 //Max 128, see mob skill_idx type if need this higher
|
||||
#define MAX_MOB_LIST_PER_MAP 128
|
||||
#define MAX_MOB_LIST_PER_MAP 100
|
||||
#define MAX_EVENTQUEUE 2
|
||||
#define MAX_EVENTTIMER 32
|
||||
#define NATURAL_HEAL_INTERVAL 500
|
||||
#define MIN_FLOORITEM 2
|
||||
#define MAX_FLOORITEM START_ACCOUNT_NUM
|
||||
#define MAX_LEVEL 150
|
||||
#define MAX_DROP_PER_MAP 48
|
||||
#define MAX_IGNORE_LIST 20 // official is 14
|
||||
#define MAX_VENDING 12
|
||||
#define MAX_MAP_SIZE 512*512 // Wasn't there something like this already? Can't find it.. [Shinryo]
|
||||
|
|
@ -558,6 +556,12 @@ void map_zone_change2(int m, struct map_zone_data *zone);
|
|||
struct map_zone_data map_zone_all;/* used as a base on all maps */
|
||||
struct map_zone_data map_zone_pk;/* used for (pk_mode) */
|
||||
|
||||
struct map_drop_list {
|
||||
int drop_id;
|
||||
int drop_type;
|
||||
int drop_per;
|
||||
};
|
||||
|
||||
|
||||
struct map_data {
|
||||
char name[MAP_NAME_LENGTH];
|
||||
|
|
@ -625,11 +629,8 @@ struct map_data {
|
|||
} flag;
|
||||
struct point save;
|
||||
struct npc_data *npc[MAX_NPC_PER_MAP];
|
||||
struct {
|
||||
int drop_id;
|
||||
int drop_type;
|
||||
int drop_per;
|
||||
} drop_list[MAX_DROP_PER_MAP];
|
||||
struct map_drop_list *drop_list;
|
||||
unsigned short drop_list_count;
|
||||
|
||||
struct spawn_data *moblist[MAX_MOB_LIST_PER_MAP]; // [Wizputer]
|
||||
int mob_delete_timer; // [Skotlex]
|
||||
|
|
@ -676,6 +677,14 @@ struct map_data {
|
|||
unsigned short short_damage_rate;
|
||||
/* long_damage_rate mapflag */
|
||||
unsigned short long_damage_rate;
|
||||
|
||||
/* instance unique name */
|
||||
char *cName;
|
||||
|
||||
/* */
|
||||
int (*getcellp)(struct map_data* m,int16 x,int16 y,cell_chk cellchk);
|
||||
void (*setcell) (int16 m, int16 x, int16 y, cell_t cell, bool flag);
|
||||
char *cellPos;
|
||||
};
|
||||
|
||||
/// Stores information about a remote map (for multi-mapserver setups).
|
||||
|
|
@ -689,8 +698,6 @@ struct map_data_other_server {
|
|||
};
|
||||
|
||||
int map_getcell(int16 m,int16 x,int16 y,cell_chk cellchk);
|
||||
int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk);
|
||||
void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag);
|
||||
void map_setgatcell(int16 m, int16 x, int16 y, int gat);
|
||||
|
||||
struct map_data *map;
|
||||
|
|
@ -711,6 +718,8 @@ extern char charhelp_txt[];
|
|||
|
||||
extern char wisp_server_name[];
|
||||
|
||||
void map_cellfromcache(struct map_data *m);
|
||||
|
||||
// users
|
||||
void map_setusers(int);
|
||||
int map_getusers(void);
|
||||
|
|
@ -733,6 +742,7 @@ int map_foreachinmovearea(int (*func)(struct block_list*,va_list), struct block_
|
|||
int map_foreachincell(int (*func)(struct block_list*,va_list), int16 m, int16 x, int16 y, int type, ...);
|
||||
int map_foreachinpath(int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int16 range, int length, int type, ...);
|
||||
int map_foreachinmap(int (*func)(struct block_list*,va_list), int16 m, int type, ...);
|
||||
int map_foreachininstance(int (*func)(struct block_list*,va_list), int16 instance_id, int type,...);
|
||||
//blocklist nb in one cell
|
||||
int map_count_oncell(int16 m,int16 x,int16 y,int type);
|
||||
struct skill_unit *map_find_skill_unit_oncell(struct block_list *,int16 x,int16 y,uint16 skill_id,struct skill_unit *, int flag);
|
||||
|
|
@ -831,6 +841,7 @@ void map_removemobs(int16 m); // [Wizputer]
|
|||
void do_reconnect_map(void); //Invoked on map-char reconnection [Skotlex]
|
||||
void map_addmap2db(struct map_data *m);
|
||||
void map_removemapdb(struct map_data *m);
|
||||
void map_clean(int i);
|
||||
|
||||
extern char *INTER_CONF_NAME;
|
||||
extern char *LOG_CONF_NAME;
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time)
|
|||
|
||||
nd->bl.id = md->tomb_nid = npc_get_new_npc_id();
|
||||
|
||||
nd->ud.dir = md->ud.dir;
|
||||
nd->dir = md->ud.dir;
|
||||
nd->bl.m = md->bl.m;
|
||||
nd->bl.x = md->bl.x;
|
||||
nd->bl.y = md->bl.y;
|
||||
|
|
@ -262,8 +262,7 @@ int mob_parse_dataset(struct spawn_data *data)
|
|||
/*==========================================
|
||||
* Generates the basic mob data using the spawn_data provided.
|
||||
*------------------------------------------*/
|
||||
struct mob_data* mob_spawn_dataset(struct spawn_data *data)
|
||||
{
|
||||
struct mob_data* mob_spawn_dataset(struct spawn_data *data) {
|
||||
struct mob_data *md = (struct mob_data*)aCalloc(1, sizeof(struct mob_data));
|
||||
md->bl.id= npc_get_new_npc_id();
|
||||
md->bl.type = BL_MOB;
|
||||
|
|
@ -290,7 +289,7 @@ struct mob_data* mob_spawn_dataset(struct spawn_data *data)
|
|||
status_set_viewdata(&md->bl, md->class_);
|
||||
status_change_init(&md->bl);
|
||||
unit_dataset(&md->bl);
|
||||
|
||||
|
||||
map_addiddb(&md->bl);
|
||||
return md;
|
||||
}
|
||||
|
|
|
|||
323
src/map/npc.c
323
src/map/npc.c
|
|
@ -122,7 +122,7 @@ struct view_data* npc_get_viewdata(int class_)
|
|||
static int npc_isnear_sub(struct block_list* bl, va_list args) {
|
||||
struct npc_data *nd = (struct npc_data*)bl;
|
||||
|
||||
if( nd->sc.option & (OPTION_HIDE|OPTION_INVISIBLE) )
|
||||
if( nd->option & (OPTION_HIDE|OPTION_INVISIBLE) )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
|
@ -175,7 +175,7 @@ int npc_enable_sub(struct block_list *bl, va_list ap)
|
|||
{
|
||||
TBL_PC *sd = (TBL_PC*)bl;
|
||||
|
||||
if (nd->sc.option&OPTION_INVISIBLE)
|
||||
if (nd->option&OPTION_INVISIBLE)
|
||||
return 1;
|
||||
|
||||
if( npc_ontouch_event(sd,nd) > 0 && npc_ontouch2_event(sd,nd) > 0 )
|
||||
|
|
@ -204,20 +204,20 @@ int npc_enable(const char* name, int flag)
|
|||
}
|
||||
|
||||
if (flag&1) {
|
||||
nd->sc.option&=~OPTION_INVISIBLE;
|
||||
nd->option&=~OPTION_INVISIBLE;
|
||||
clif->spawn(&nd->bl);
|
||||
} else if (flag&2)
|
||||
nd->sc.option&=~OPTION_HIDE;
|
||||
nd->option&=~OPTION_HIDE;
|
||||
else if (flag&4)
|
||||
nd->sc.option|= OPTION_HIDE;
|
||||
nd->option|= OPTION_HIDE;
|
||||
else { //Can't change the view_data to invisible class because the view_data for all npcs is shared! [Skotlex]
|
||||
nd->sc.option|= OPTION_INVISIBLE;
|
||||
nd->option|= OPTION_INVISIBLE;
|
||||
clif->clearunit_area(&nd->bl,CLR_OUTSIGHT); // Hack to trick maya purple card [Xazax]
|
||||
}
|
||||
|
||||
if (nd->class_ == WARP_CLASS || nd->class_ == FLAG_CLASS)
|
||||
{ //Client won't display option changes for these classes [Toms]
|
||||
if (nd->sc.option&(OPTION_HIDE|OPTION_INVISIBLE))
|
||||
if (nd->option&(OPTION_HIDE|OPTION_INVISIBLE))
|
||||
clif->clearunit_area(&nd->bl, CLR_OUTSIGHT);
|
||||
else
|
||||
clif->spawn(&nd->bl);
|
||||
|
|
@ -385,8 +385,7 @@ static int npc_event_do_sub(DBKey key, DBData *data, va_list ap)
|
|||
nullpo_ret(c = va_arg(ap, int *));
|
||||
nullpo_ret(name = va_arg(ap, const char *));
|
||||
|
||||
if( p && strcmpi(name, p) == 0 )
|
||||
{
|
||||
if( p && strcmpi(name, p) == 0 ) {
|
||||
run_script(ev->nd->u.scr.script,ev->pos,0,ev->nd->bl.id);
|
||||
(*c)++;
|
||||
}
|
||||
|
|
@ -815,7 +814,7 @@ int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char
|
|||
ShowWarning("npc_event: player's event queue is full, can't add event '%s' !\n", eventname);
|
||||
return 1;
|
||||
}
|
||||
if( ev->nd->sc.option&OPTION_INVISIBLE )
|
||||
if( ev->nd->option&OPTION_INVISIBLE )
|
||||
{
|
||||
//Disabled npc, shouldn't trigger event.
|
||||
npc_event_dequeue(sd);
|
||||
|
|
@ -835,22 +834,20 @@ int npc_event(struct map_session_data* sd, const char* eventname, int ontouch)
|
|||
|
||||
nullpo_ret(sd);
|
||||
|
||||
if( ev == NULL || (nd = ev->nd) == NULL )
|
||||
{
|
||||
if( ev == NULL || (nd = ev->nd) == NULL ) {
|
||||
if( !ontouch )
|
||||
ShowError("npc_event: event not found [%s]\n", eventname);
|
||||
return ontouch;
|
||||
}
|
||||
|
||||
switch(ontouch)
|
||||
{
|
||||
case 1:
|
||||
nd->touching_id = sd->bl.id;
|
||||
sd->touching_id = nd->bl.id;
|
||||
break;
|
||||
case 2:
|
||||
sd->areanpc_id = nd->bl.id;
|
||||
break;
|
||||
switch(ontouch) {
|
||||
case 1:
|
||||
nd->touching_id = sd->bl.id;
|
||||
sd->touching_id = nd->bl.id;
|
||||
break;
|
||||
case 2:
|
||||
sd->areanpc_id = nd->bl.id;
|
||||
break;
|
||||
}
|
||||
|
||||
return npc_event_sub(sd,ev,eventname);
|
||||
|
|
@ -928,9 +925,8 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
|
|||
//if(sd->npc_id)
|
||||
// return 1;
|
||||
|
||||
for(i=0;i<map[m].npc_num;i++)
|
||||
{
|
||||
if (map[m].npc[i]->sc.option&OPTION_INVISIBLE) {
|
||||
for(i=0;i<map[m].npc_num;i++) {
|
||||
if (map[m].npc[i]->option&OPTION_INVISIBLE) {
|
||||
f=0; // a npc was found, but it is disabled; don't print warning
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1008,13 +1004,11 @@ int npc_touch_areanpc2(struct mob_data *md)
|
|||
struct event_data* ev;
|
||||
int xs, ys;
|
||||
|
||||
for( i = 0; i < map[m].npc_num; i++ )
|
||||
{
|
||||
if( map[m].npc[i]->sc.option&OPTION_INVISIBLE )
|
||||
for( i = 0; i < map[m].npc_num; i++ ) {
|
||||
if( map[m].npc[i]->option&OPTION_INVISIBLE )
|
||||
continue;
|
||||
|
||||
switch( map[m].npc[i]->subtype )
|
||||
{
|
||||
switch( map[m].npc[i]->subtype ) {
|
||||
case WARP:
|
||||
if( !( battle_config.mob_warp&1 ) )
|
||||
continue;
|
||||
|
|
@ -1087,27 +1081,25 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range)
|
|||
if (!i) return 0; //No NPC_CELLs.
|
||||
|
||||
//Now check for the actual NPC on said range.
|
||||
for(i=0;i<map[m].npc_num;i++)
|
||||
{
|
||||
if (map[m].npc[i]->sc.option&OPTION_INVISIBLE)
|
||||
for(i=0;i<map[m].npc_num;i++) {
|
||||
if (map[m].npc[i]->option&OPTION_INVISIBLE)
|
||||
continue;
|
||||
|
||||
switch(map[m].npc[i]->subtype)
|
||||
{
|
||||
case WARP:
|
||||
if (!(flag&1))
|
||||
switch(map[m].npc[i]->subtype) {
|
||||
case WARP:
|
||||
if (!(flag&1))
|
||||
continue;
|
||||
xs=map[m].npc[i]->u.warp.xs;
|
||||
ys=map[m].npc[i]->u.warp.ys;
|
||||
break;
|
||||
case SCRIPT:
|
||||
if (!(flag&2))
|
||||
continue;
|
||||
xs=map[m].npc[i]->u.scr.xs;
|
||||
ys=map[m].npc[i]->u.scr.ys;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
xs=map[m].npc[i]->u.warp.xs;
|
||||
ys=map[m].npc[i]->u.warp.ys;
|
||||
break;
|
||||
case SCRIPT:
|
||||
if (!(flag&2))
|
||||
continue;
|
||||
xs=map[m].npc[i]->u.scr.xs;
|
||||
ys=map[m].npc[i]->u.scr.ys;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if( x1 >= map[m].npc[i]->bl.x-xs && x0 <= map[m].npc[i]->bl.x+xs
|
||||
|
|
@ -1206,7 +1198,7 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd)
|
|||
if ((nd = npc_checknear(sd,&nd->bl)) == NULL)
|
||||
return 1;
|
||||
//Hidden/Disabled npc.
|
||||
if (nd->class_ < 0 || nd->sc.option&(OPTION_INVISIBLE|OPTION_HIDE))
|
||||
if (nd->class_ < 0 || nd->option&(OPTION_INVISIBLE|OPTION_HIDE))
|
||||
return 1;
|
||||
|
||||
switch(nd->subtype) {
|
||||
|
|
@ -1291,7 +1283,7 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type)
|
|||
sd->npc_id=0;
|
||||
return 1;
|
||||
}
|
||||
if (nd->sc.option & OPTION_INVISIBLE) // can't buy if npc is not visible (hack?)
|
||||
if (nd->option & OPTION_INVISIBLE) // can't buy if npc is not visible (hack?)
|
||||
return 1;
|
||||
if( nd->class_ < 0 && !sd->state.callshop )
|
||||
{// not called through a script and is not a visible NPC so an invalid call
|
||||
|
|
@ -1759,8 +1751,7 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list)
|
|||
|
||||
//Atempt to remove an npc from a map
|
||||
//This doesn't remove it from map_db
|
||||
int npc_remove_map(struct npc_data* nd)
|
||||
{
|
||||
int npc_remove_map(struct npc_data* nd) {
|
||||
int16 m,i;
|
||||
nullpo_retr(1, nd);
|
||||
|
||||
|
|
@ -1892,6 +1883,11 @@ int npc_unload(struct npc_data* nd, bool single) {
|
|||
guild->flag_remove(nd);
|
||||
}
|
||||
|
||||
if( nd->ud != &npc_base_ud ) {
|
||||
aFree(nd->ud);
|
||||
nd->ud = NULL;
|
||||
}
|
||||
|
||||
script_stop_sleeptimers(nd->bl.id);
|
||||
|
||||
aFree(nd);
|
||||
|
|
@ -2060,8 +2056,7 @@ static void npc_parsename(struct npc_data* nd, const char* name, const char* sta
|
|||
}
|
||||
|
||||
//Add then display an npc warp on map
|
||||
struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y)
|
||||
{
|
||||
struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y) {
|
||||
int i, flag = 0;
|
||||
struct npc_data *nd;
|
||||
|
||||
|
|
@ -2100,8 +2095,7 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
|
|||
npc_setcells(nd);
|
||||
map_addblock(&nd->bl);
|
||||
status_set_viewdata(&nd->bl, nd->class_);
|
||||
status_change_init(&nd->bl);
|
||||
unit_dataset(&nd->bl);
|
||||
nd->ud = &npc_base_ud;
|
||||
if( map[nd->bl.m].users )
|
||||
clif->spawn(&nd->bl);
|
||||
strdb_put(npcname_db, nd->exname, nd);
|
||||
|
|
@ -2166,8 +2160,7 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const
|
|||
npc_setcells(nd);
|
||||
map_addblock(&nd->bl);
|
||||
status_set_viewdata(&nd->bl, nd->class_);
|
||||
status_change_init(&nd->bl);
|
||||
unit_dataset(&nd->bl);
|
||||
nd->ud = &npc_base_ud;
|
||||
if( map[nd->bl.m].users )
|
||||
clif->spawn(&nd->bl);
|
||||
strdb_put(npcname_db, nd->exname, nd);
|
||||
|
|
@ -2275,18 +2268,15 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
|
|||
++npc_shop;
|
||||
nd->bl.type = BL_NPC;
|
||||
nd->subtype = type;
|
||||
if( m >= 0 )
|
||||
{// normal shop npc
|
||||
if( m >= 0 ) {// normal shop npc
|
||||
map_addnpc(m,nd);
|
||||
map_addblock(&nd->bl);
|
||||
status_set_viewdata(&nd->bl, nd->class_);
|
||||
status_change_init(&nd->bl);
|
||||
unit_dataset(&nd->bl);
|
||||
nd->ud.dir = dir;
|
||||
nd->ud = &npc_base_ud;
|
||||
nd->dir = dir;
|
||||
if( map[nd->bl.m].users )
|
||||
clif->spawn(&nd->bl);
|
||||
} else
|
||||
{// 'floating' shop?
|
||||
} else {// 'floating' shop?
|
||||
map_addiddb(&nd->bl);
|
||||
}
|
||||
strdb_put(npcname_db, nd->exname, nd);
|
||||
|
|
@ -2485,23 +2475,18 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons
|
|||
nd->bl.type = BL_NPC;
|
||||
nd->subtype = SCRIPT;
|
||||
|
||||
if( m >= 0 )
|
||||
{
|
||||
if( m >= 0 ) {
|
||||
map_addnpc(m, nd);
|
||||
status_change_init(&nd->bl);
|
||||
unit_dataset(&nd->bl);
|
||||
nd->ud.dir = dir;
|
||||
nd->ud = &npc_base_ud;
|
||||
nd->dir = dir;
|
||||
npc_setcells(nd);
|
||||
map_addblock(&nd->bl);
|
||||
if( class_ >= 0 )
|
||||
{
|
||||
if( class_ >= 0 ) {
|
||||
status_set_viewdata(&nd->bl, nd->class_);
|
||||
if( map[nd->bl.m].users )
|
||||
clif->spawn(&nd->bl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// we skip map_addnpc, but still add it to the list of ID's
|
||||
map_addiddb(&nd->bl);
|
||||
}
|
||||
|
|
@ -2576,13 +2561,10 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
|
|||
type = dnd->subtype;
|
||||
|
||||
// get placement
|
||||
if( (type==SHOP || type==CASHSHOP || type==SCRIPT) && strcmp(w1, "-") == 0 )
|
||||
{// floating shop/chashshop/script
|
||||
if( (type==SHOP || type==CASHSHOP || type==SCRIPT) && strcmp(w1, "-") == 0 ) {// floating shop/chashshop/script
|
||||
x = y = dir = 0;
|
||||
m = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 )// <map name>,<x>,<y>,<facing>
|
||||
{
|
||||
ShowError("npc_parse_duplicate: Invalid placement format for duplicate in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
|
||||
|
|
@ -2599,8 +2581,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
|
|||
if( type == WARP && sscanf(w4, "%d,%d", &xs, &ys) == 2 );// <spanx>,<spany>
|
||||
else if( type == SCRIPT && sscanf(w4, "%d,%d,%d", &class_, &xs, &ys) == 3);// <sprite id>,<triggerX>,<triggerY>
|
||||
else if( type != WARP ) class_ = atoi(w4);// <sprite id>
|
||||
else
|
||||
{
|
||||
else {
|
||||
ShowError("npc_parse_duplicate: Invalid span format for duplicate warp in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
|
||||
return end;// next line, try to continue
|
||||
}
|
||||
|
|
@ -2618,56 +2599,50 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
|
|||
nd->src_id = src_id;
|
||||
nd->bl.type = BL_NPC;
|
||||
nd->subtype = (enum npc_subtype)type;
|
||||
switch( type )
|
||||
{
|
||||
case SCRIPT:
|
||||
++npc_script;
|
||||
nd->u.scr.xs = xs;
|
||||
nd->u.scr.ys = ys;
|
||||
nd->u.scr.script = dnd->u.scr.script;
|
||||
nd->u.scr.label_list = dnd->u.scr.label_list;
|
||||
nd->u.scr.label_list_num = dnd->u.scr.label_list_num;
|
||||
break;
|
||||
switch( type ) {
|
||||
case SCRIPT:
|
||||
++npc_script;
|
||||
nd->u.scr.xs = xs;
|
||||
nd->u.scr.ys = ys;
|
||||
nd->u.scr.script = dnd->u.scr.script;
|
||||
nd->u.scr.label_list = dnd->u.scr.label_list;
|
||||
nd->u.scr.label_list_num = dnd->u.scr.label_list_num;
|
||||
break;
|
||||
|
||||
case SHOP:
|
||||
case CASHSHOP:
|
||||
++npc_shop;
|
||||
nd->u.shop.shop_item = dnd->u.shop.shop_item;
|
||||
nd->u.shop.count = dnd->u.shop.count;
|
||||
break;
|
||||
case SHOP:
|
||||
case CASHSHOP:
|
||||
++npc_shop;
|
||||
nd->u.shop.shop_item = dnd->u.shop.shop_item;
|
||||
nd->u.shop.count = dnd->u.shop.count;
|
||||
break;
|
||||
|
||||
case WARP:
|
||||
++npc_warp;
|
||||
if( !battle_config.warp_point_debug )
|
||||
nd->class_ = WARP_CLASS;
|
||||
else
|
||||
nd->class_ = WARP_DEBUG_CLASS;
|
||||
nd->u.warp.xs = xs;
|
||||
nd->u.warp.ys = ys;
|
||||
nd->u.warp.mapindex = dnd->u.warp.mapindex;
|
||||
nd->u.warp.x = dnd->u.warp.x;
|
||||
nd->u.warp.y = dnd->u.warp.y;
|
||||
break;
|
||||
case WARP:
|
||||
++npc_warp;
|
||||
if( !battle_config.warp_point_debug )
|
||||
nd->class_ = WARP_CLASS;
|
||||
else
|
||||
nd->class_ = WARP_DEBUG_CLASS;
|
||||
nd->u.warp.xs = xs;
|
||||
nd->u.warp.ys = ys;
|
||||
nd->u.warp.mapindex = dnd->u.warp.mapindex;
|
||||
nd->u.warp.x = dnd->u.warp.x;
|
||||
nd->u.warp.y = dnd->u.warp.y;
|
||||
break;
|
||||
}
|
||||
|
||||
//Add the npc to its location
|
||||
if( m >= 0 )
|
||||
{
|
||||
if( m >= 0 ) {
|
||||
map_addnpc(m, nd);
|
||||
status_change_init(&nd->bl);
|
||||
unit_dataset(&nd->bl);
|
||||
nd->ud.dir = dir;
|
||||
nd->ud = &npc_base_ud;
|
||||
nd->dir = dir;
|
||||
npc_setcells(nd);
|
||||
map_addblock(&nd->bl);
|
||||
if( class_ >= 0 )
|
||||
{
|
||||
if( class_ >= 0 ) {
|
||||
status_set_viewdata(&nd->bl, nd->class_);
|
||||
if( map[nd->bl.m].users )
|
||||
clif->spawn(&nd->bl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// we skip map_addnpc, but still add it to the list of ID's
|
||||
map_addiddb(&nd->bl);
|
||||
}
|
||||
|
|
@ -2694,25 +2669,21 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
|
|||
int npc_duplicate4instance(struct npc_data *snd, int16 m) {
|
||||
char newname[NAME_LENGTH];
|
||||
|
||||
if( map[m].instance_id == 0 )
|
||||
if( map[m].instance_id == -1 )
|
||||
return 1;
|
||||
|
||||
snprintf(newname, ARRAYLENGTH(newname), "dup_%d_%d", map[m].instance_id, snd->bl.id);
|
||||
if( npc_name2id(newname) != NULL )
|
||||
{ // Name already in use
|
||||
if( npc_name2id(newname) != NULL ) { // Name already in use
|
||||
ShowError("npc_duplicate4instance: the npcname (%s) is already in use while trying to duplicate npc %s in instance %d.\n", newname, snd->exname, map[m].instance_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( snd->subtype == WARP )
|
||||
{ // Adjust destination, if instanced
|
||||
if( snd->subtype == WARP ) { // Adjust destination, if instanced
|
||||
struct npc_data *wnd = NULL; // New NPC
|
||||
int dm = map_mapindex2mapid(snd->u.warp.mapindex), im;
|
||||
if( dm < 0 ) return 1;
|
||||
|
||||
im = instance_mapid2imapid(dm, map[m].instance_id);
|
||||
if( im == -1 )
|
||||
{
|
||||
if( ( im = instance->mapid2imapid(dm, map[m].instance_id) ) == -1 ) {
|
||||
ShowError("npc_duplicate4instance: warp (%s) leading to instanced map (%s), but instance map is not attached to current instance.\n", map[dm].name, snd->exname);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -2738,18 +2709,15 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
|
|||
npc_setcells(wnd);
|
||||
map_addblock(&wnd->bl);
|
||||
status_set_viewdata(&wnd->bl, wnd->class_);
|
||||
status_change_init(&wnd->bl);
|
||||
unit_dataset(&wnd->bl);
|
||||
wnd->ud = &npc_base_ud;
|
||||
if( map[wnd->bl.m].users )
|
||||
clif->spawn(&wnd->bl);
|
||||
strdb_put(npcname_db, wnd->exname, wnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
static char w1[50], w2[50], w3[50], w4[50];
|
||||
const char* stat_buf = "- call from instancing subsystem -\n";
|
||||
|
||||
snprintf(w1, sizeof(w1), "%s,%d,%d,%d", map[m].name, snd->bl.x, snd->bl.y, snd->ud.dir);
|
||||
snprintf(w1, sizeof(w1), "%s,%d,%d,%d", map[m].name, snd->bl.x, snd->bl.y, snd->dir);
|
||||
snprintf(w2, sizeof(w2), "duplicate(%s)", snd->exname);
|
||||
snprintf(w3, sizeof(w3), "%s::%s", snd->name, newname);
|
||||
|
||||
|
|
@ -2765,39 +2733,36 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
|
|||
}
|
||||
|
||||
//Set mapcell CELL_NPC to trigger event later
|
||||
void npc_setcells(struct npc_data* nd)
|
||||
{
|
||||
void npc_setcells(struct npc_data* nd) {
|
||||
int16 m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys;
|
||||
int i,j;
|
||||
|
||||
switch(nd->subtype)
|
||||
{
|
||||
case WARP:
|
||||
xs = nd->u.warp.xs;
|
||||
ys = nd->u.warp.ys;
|
||||
break;
|
||||
case SCRIPT:
|
||||
xs = nd->u.scr.xs;
|
||||
ys = nd->u.scr.ys;
|
||||
break;
|
||||
default:
|
||||
return; // Other types doesn't have touch area
|
||||
switch(nd->subtype) {
|
||||
case WARP:
|
||||
xs = nd->u.warp.xs;
|
||||
ys = nd->u.warp.ys;
|
||||
break;
|
||||
case SCRIPT:
|
||||
xs = nd->u.scr.xs;
|
||||
ys = nd->u.scr.ys;
|
||||
break;
|
||||
default:
|
||||
return; // Other types doesn't have touch area
|
||||
}
|
||||
|
||||
if (m < 0 || xs < 0 || ys < 0) //invalid range or map
|
||||
if (m < 0 || xs < 0 || ys < 0 || map[m].cell == (struct mapcell *)0xdeadbeaf) //invalid range or map
|
||||
return;
|
||||
|
||||
for (i = y-ys; i <= y+ys; i++) {
|
||||
for (j = x-xs; j <= x+xs; j++) {
|
||||
if (map_getcell(m, j, i, CELL_CHKNOPASS))
|
||||
continue;
|
||||
map_setcell(m, j, i, CELL_NPC, true);
|
||||
map[m].setcell(m, j, i, CELL_NPC, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int npc_unsetcells_sub(struct block_list* bl, va_list ap)
|
||||
{
|
||||
int npc_unsetcells_sub(struct block_list* bl, va_list ap) {
|
||||
struct npc_data *nd = (struct npc_data*)bl;
|
||||
int id = va_arg(ap,int);
|
||||
if (nd->bl.id == id) return 0;
|
||||
|
|
@ -2805,8 +2770,7 @@ int npc_unsetcells_sub(struct block_list* bl, va_list ap)
|
|||
return 1;
|
||||
}
|
||||
|
||||
void npc_unsetcells(struct npc_data* nd)
|
||||
{
|
||||
void npc_unsetcells(struct npc_data* nd) {
|
||||
int16 m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys;
|
||||
int i,j, x0, x1, y0, y1;
|
||||
|
||||
|
|
@ -2818,7 +2782,7 @@ void npc_unsetcells(struct npc_data* nd)
|
|||
ys = nd->u.scr.ys;
|
||||
}
|
||||
|
||||
if (m < 0 || xs < 0 || ys < 0)
|
||||
if (m < 0 || xs < 0 || ys < 0 || map[m].cell == (struct mapcell *)0xdeadbeaf)
|
||||
return;
|
||||
|
||||
//Locate max range on which we can locate npc cells
|
||||
|
|
@ -2831,7 +2795,7 @@ void npc_unsetcells(struct npc_data* nd)
|
|||
//Erase this npc's cells
|
||||
for (i = y-ys; i <= y+ys; i++)
|
||||
for (j = x-xs; j <= x+xs; j++)
|
||||
map_setcell(m, j, i, CELL_NPC, false);
|
||||
map[m].setcell(m, j, i, CELL_NPC, false);
|
||||
|
||||
//Re-deploy NPC cells for other nearby npcs.
|
||||
map_foreachinarea( npc_unsetcells_sub, m, x0, y0, x1, y1, BL_NPC, nd->bl.id );
|
||||
|
|
@ -2910,7 +2874,7 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
|
|||
return 1;
|
||||
}
|
||||
|
||||
if( ev->nd->sc.option&OPTION_INVISIBLE ) { // Disabled npc, shouldn't trigger event.
|
||||
if( ev->nd->option&OPTION_INVISIBLE ) { // Disabled npc, shouldn't trigger event.
|
||||
npc_event_dequeue(sd);
|
||||
return 2;
|
||||
}
|
||||
|
|
@ -2994,8 +2958,7 @@ void npc_parse_mob2(struct spawn_data* mob)
|
|||
{
|
||||
int i;
|
||||
|
||||
for( i = mob->active; i < mob->num; ++i )
|
||||
{
|
||||
for( i = mob->active; i < mob->num; ++i ) {
|
||||
struct mob_data* md = mob_spawn_dataset(mob);
|
||||
md->spawn = mob;
|
||||
md->spawn->active++;
|
||||
|
|
@ -3150,19 +3113,17 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
|
|||
memcpy(data, &mob, sizeof(struct spawn_data));
|
||||
|
||||
// spawn / cache the new mobs
|
||||
if( battle_config.dynamic_mobs && map_addmobtolist(data->m, data) >= 0 )
|
||||
{
|
||||
if( battle_config.dynamic_mobs && map_addmobtolist(data->m, data) >= 0 ) {
|
||||
data->state.dynamic = true;
|
||||
npc_cache_mob += data->num;
|
||||
|
||||
// check if target map has players
|
||||
// (usually shouldn't occur when map server is just starting,
|
||||
// but not the case when we do @reloadscript
|
||||
if( map[data->m].users > 0 )
|
||||
if( map[data->m].users > 0 ) {
|
||||
npc_parse_mob2(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
} else {
|
||||
data->state.dynamic = false;
|
||||
npc_parse_mob2(data);
|
||||
npc_delay_mob += data->num;
|
||||
|
|
@ -3282,16 +3243,11 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
|
|||
else if (!strcmpi(drop_arg2,"all"))
|
||||
drop_type = 3;
|
||||
|
||||
if (drop_id != 0){
|
||||
int i;
|
||||
for (i = 0; i < MAX_DROP_PER_MAP; i++) {
|
||||
if (map[m].drop_list[i].drop_id == 0){
|
||||
map[m].drop_list[i].drop_id = drop_id;
|
||||
map[m].drop_list[i].drop_type = drop_type;
|
||||
map[m].drop_list[i].drop_per = drop_per;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (drop_id != 0) {
|
||||
RECREATE(map[m].drop_list, struct map_drop_list, ++map[m].drop_list_count);
|
||||
map[m].drop_list[map[m].drop_list_count-1].drop_id = drop_id;
|
||||
map[m].drop_list[map[m].drop_list_count-1].drop_type = drop_type;
|
||||
map[m].drop_list[map[m].drop_list_count-1].drop_per = drop_per;
|
||||
map[m].flag.pvp_nightmaredrop = 1;
|
||||
}
|
||||
} else if (!state) //Disable
|
||||
|
|
@ -3892,10 +3848,7 @@ int npc_reload(void) {
|
|||
"\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n",
|
||||
npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
|
||||
|
||||
do_final_instance();
|
||||
|
||||
for( i = 0; i < ARRAYLENGTH(instance); ++i )
|
||||
instance_init(instance[i].instance_id);
|
||||
instance->final();
|
||||
|
||||
map_zone_init();
|
||||
|
||||
|
|
@ -4002,8 +3955,18 @@ int do_init_npc(void)
|
|||
struct npc_src_list *file;
|
||||
int i;
|
||||
|
||||
memset(&npc_base_ud, 0, sizeof( struct unit_data) );
|
||||
npc_base_ud.bl = NULL;
|
||||
npc_base_ud.walktimer = INVALID_TIMER;
|
||||
npc_base_ud.skilltimer = INVALID_TIMER;
|
||||
npc_base_ud.attacktimer = INVALID_TIMER;
|
||||
npc_base_ud.attackabletime =
|
||||
npc_base_ud.canact_tick =
|
||||
npc_base_ud.canmove_tick = gettick();
|
||||
|
||||
//Stock view data for normal npcs.
|
||||
memset(&npc_viewdb, 0, sizeof(npc_viewdb));
|
||||
|
||||
npc_viewdb[0].class_ = INVISIBLE_CLASS; //Invisible class is stored here.
|
||||
for( i = 1; i < MAX_NPC_CLASS; i++ )
|
||||
npc_viewdb[i].class_ = i;
|
||||
|
|
@ -4030,7 +3993,7 @@ int do_init_npc(void)
|
|||
"\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n"
|
||||
"\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n",
|
||||
npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
|
||||
|
||||
|
||||
map_zone_init();
|
||||
|
||||
npc->motd = npc_name2id("HerculesMOTD"); /* [Ind/Hercules] */
|
||||
|
|
@ -4068,6 +4031,6 @@ int do_init_npc(void)
|
|||
}
|
||||
void npc_defaults(void) {
|
||||
npc = &npc_s;
|
||||
|
||||
|
||||
npc->motd = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ struct block_list;
|
|||
struct npc_data;
|
||||
struct view_data;
|
||||
|
||||
struct unit_data npc_base_ud;
|
||||
|
||||
struct npc_timerevent_list {
|
||||
int timer,pos;
|
||||
|
|
@ -26,9 +27,9 @@ struct npc_item_list {
|
|||
|
||||
struct npc_data {
|
||||
struct block_list bl;
|
||||
struct unit_data ud; //Because they need to be able to move....
|
||||
struct unit_data *ud;
|
||||
struct view_data *vd;
|
||||
struct status_change sc; //They can't have status changes, but.. they want the visual opt values.
|
||||
unsigned int option;
|
||||
struct npc_data *master_nd;
|
||||
short class_;
|
||||
short speed;
|
||||
|
|
@ -37,12 +38,13 @@ struct npc_data {
|
|||
int chat_id;
|
||||
int touching_id;
|
||||
unsigned int next_walktime;
|
||||
|
||||
uint8 dir;
|
||||
|
||||
unsigned size : 2;
|
||||
|
||||
struct status_data status;
|
||||
unsigned int level;
|
||||
unsigned int stat_point;
|
||||
unsigned short level;
|
||||
unsigned short stat_point;
|
||||
|
||||
void* chatdb; // pointer to a npc_parse struct (see npc_chat.c)
|
||||
char* path;/* path dir */
|
||||
|
|
|
|||
|
|
@ -1869,6 +1869,10 @@ packet(0x020d,-1);
|
|||
packet(0x0838,6,clif->pSolveCharName,2);
|
||||
packet(0x0439,8,clif->pUseItem,2,4);
|
||||
packet(0x08d2,10);
|
||||
packet(0x08d7,28,clif->pBGQueueRegister,2);
|
||||
packet(0x090a,26,clif->pBGQueueCheckState,2);
|
||||
packet(0x08da,26,clif->pBGQueueRevokeReq,2);
|
||||
packet(0x08e0,51,clif->pBGQueueBattleBeginAck,2);
|
||||
#endif
|
||||
|
||||
//2011-11-02aRagexe
|
||||
|
|
@ -1985,7 +1989,6 @@ packet(0x020d,-1);
|
|||
packet(0x08FB,6,clif->pDull,2); //bookingcanceljoinparty
|
||||
packet(0x0907,5,clif->pMoveItem,2,4);
|
||||
packet(0x0908,5);
|
||||
packet(0x08D7,28,clif->pDull,2,4); //battlegroundreg
|
||||
packet(0x08CF,10);//Amulet spirits
|
||||
packet(0x0977,14);//Monster HP Bar
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -87,6 +87,15 @@ enum packet_headers {
|
|||
#else
|
||||
unit_walkingType = 0x914,
|
||||
#endif
|
||||
bgqueue_ackType = 0x8d8,
|
||||
bgqueue_notice_deleteType = 0x8db,
|
||||
bgqueue_registerType = 0x8d7,
|
||||
bgqueue_updateinfoType = 0x8d9,
|
||||
bgqueue_checkstateType = 0x90a,
|
||||
bgqueue_revokereqType = 0x8da,
|
||||
bgqueue_battlebeginackType = 0x8e0,
|
||||
bgqueue_notify_entryType = 0x8d9,
|
||||
bgqueue_battlebegins = 0x8df,
|
||||
#if PACKETVER > 20130000 /* not sure date */
|
||||
dropflooritemType = 0x84b,
|
||||
#else
|
||||
|
|
@ -391,6 +400,59 @@ struct packet_maptypeproperty2 {
|
|||
} flag;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct packet_bgqueue_ack {
|
||||
short PacketType;
|
||||
short type;
|
||||
char bg_name[NAME_LENGTH];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct packet_bgqueue_notice_delete {
|
||||
short PacketType;
|
||||
short type;
|
||||
char bg_name[NAME_LENGTH];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct packet_bgqueue_register {
|
||||
short PacketType;
|
||||
short type;
|
||||
char bg_name[NAME_LENGTH];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct packet_bgqueue_update_info {
|
||||
short PacketType;
|
||||
char bg_name[NAME_LENGTH];
|
||||
int position;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct packet_bgqueue_checkstate {
|
||||
short PacketType;
|
||||
char bg_name[NAME_LENGTH];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct packet_bgqueue_revoke_req {
|
||||
short PacketType;
|
||||
char bg_name[NAME_LENGTH];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct packet_bgqueue_battlebegin_ack {
|
||||
short PacketType;
|
||||
short result;
|
||||
char bg_name[NAME_LENGTH];
|
||||
char game_name[NAME_LENGTH];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct packet_bgqueue_notify_entry {
|
||||
short PacketType;
|
||||
char name[NAME_LENGTH];
|
||||
int position;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct packet_bgqueue_battlebegins {
|
||||
short PacketType;
|
||||
char bg_name[NAME_LENGTH];
|
||||
char game_name[NAME_LENGTH];
|
||||
} __attribute__((packed));
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif /* _PACKETS_STRUCT_H_ */
|
||||
|
|
|
|||
107
src/map/party.c
107
src/map/party.c
|
|
@ -50,8 +50,6 @@ static void party_fill_member(struct party_member* member, struct map_session_da
|
|||
member->online = 1;
|
||||
member->leader = leader;
|
||||
}
|
||||
|
||||
|
||||
/// Get the member_id of a party member.
|
||||
/// Return -1 if not in party.
|
||||
int party_getmemberid(struct party_data* p, struct map_session_data* sd)
|
||||
|
|
@ -101,14 +99,21 @@ static TBL_PC* party_sd_check(int party_id, int account_id, int char_id)
|
|||
|
||||
return sd;
|
||||
}
|
||||
|
||||
int party_db_final(DBKey key, DBData *data, va_list ap) {
|
||||
struct party_data *p;
|
||||
|
||||
if( ( p = DB->data2ptr(data) ) && p->instance )
|
||||
aFree(p->instance);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*==========================================
|
||||
* Destructor
|
||||
* Called in map shutdown, cleanup var
|
||||
*------------------------------------------*/
|
||||
void do_final_party(void)
|
||||
{
|
||||
party_db->destroy(party_db,NULL);
|
||||
party_db->destroy(party_db,party_db_final);
|
||||
party_booking_db->destroy(party_booking_db,NULL); // Party Booking [Spiria]
|
||||
}
|
||||
// Constructor, init vars
|
||||
|
|
@ -251,16 +256,14 @@ int party_recv_info(struct party* sp, int char_id)
|
|||
int removed_count = 0;
|
||||
int added[MAX_PARTY];// member_id in new data
|
||||
int added_count = 0;
|
||||
int i;
|
||||
int i,j;
|
||||
int member_id;
|
||||
|
||||
nullpo_ret(sp);
|
||||
|
||||
p = (struct party_data*)idb_get(party_db, sp->party_id);
|
||||
if( p != NULL )// diff members
|
||||
{
|
||||
for( member_id = 0; member_id < MAX_PARTY; ++member_id )
|
||||
{
|
||||
if( p != NULL ) {// diff members
|
||||
for( member_id = 0; member_id < MAX_PARTY; ++member_id ) {
|
||||
member = &p->party.member[member_id];
|
||||
if( member->char_id == 0 )
|
||||
continue;// empty
|
||||
|
|
@ -270,8 +273,7 @@ int party_recv_info(struct party* sp, int char_id)
|
|||
if( i == MAX_PARTY )
|
||||
removed[removed_count++] = member_id;
|
||||
}
|
||||
for( member_id = 0; member_id < MAX_PARTY; ++member_id )
|
||||
{
|
||||
for( member_id = 0; member_id < MAX_PARTY; ++member_id ) {
|
||||
member = &sp->member[member_id];
|
||||
if( member->char_id == 0 )
|
||||
continue;// empty
|
||||
|
|
@ -281,17 +283,16 @@ int party_recv_info(struct party* sp, int char_id)
|
|||
if( i == MAX_PARTY )
|
||||
added[added_count++] = member_id;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
for( member_id = 0; member_id < MAX_PARTY; ++member_id )
|
||||
if( sp->member[member_id].char_id != 0 )
|
||||
added[added_count++] = member_id;
|
||||
CREATE(p, struct party_data, 1);
|
||||
p->instance = NULL;
|
||||
p->instances = 0;
|
||||
idb_put(party_db, sp->party_id, p);
|
||||
}
|
||||
while( removed_count > 0 )// no longer in party
|
||||
{
|
||||
while( removed_count > 0 ) {// no longer in party
|
||||
member_id = removed[--removed_count];
|
||||
sd = p->data[member_id].sd;
|
||||
if( sd == NULL )
|
||||
|
|
@ -301,16 +302,14 @@ int party_recv_info(struct party* sp, int char_id)
|
|||
memcpy(&p->party, sp, sizeof(struct party));
|
||||
memset(&p->state, 0, sizeof(p->state));
|
||||
memset(&p->data, 0, sizeof(p->data));
|
||||
for( member_id = 0; member_id < MAX_PARTY; member_id++ )
|
||||
{
|
||||
for( member_id = 0; member_id < MAX_PARTY; member_id++ ) {
|
||||
member = &p->party.member[member_id];
|
||||
if ( member->char_id == 0 )
|
||||
continue;// empty
|
||||
p->data[member_id].sd = party_sd_check(sp->party_id, member->account_id, member->char_id);
|
||||
}
|
||||
party_check_state(p);
|
||||
while( added_count > 0 )// new in party
|
||||
{
|
||||
while( added_count > 0 ) { // new in party
|
||||
member_id = added[--added_count];
|
||||
sd = p->data[member_id].sd;
|
||||
if( sd == NULL )
|
||||
|
|
@ -319,8 +318,12 @@ int party_recv_info(struct party* sp, int char_id)
|
|||
clif->party_member_info(p,sd);
|
||||
clif->party_option(p,sd,0x100);
|
||||
clif->party_info(p,NULL);
|
||||
if( p->instance_id != 0 )
|
||||
clif->instance_join(sd->fd, p->instance_id);
|
||||
for( j = 0; j < p->instances; j++ ) {
|
||||
if( instances[p->instance[j]].idle_timer == INVALID_TIMER && instances[p->instance[j]].progress_timer == INVALID_TIMER )
|
||||
continue;
|
||||
clif->instance_join(sd->fd, p->instance[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( char_id != 0 )// requester
|
||||
{
|
||||
|
|
@ -429,19 +432,21 @@ void party_member_joined(struct map_session_data *sd)
|
|||
{
|
||||
struct party_data* p = party_search(sd->status.party_id);
|
||||
int i;
|
||||
if (!p)
|
||||
{
|
||||
if (!p) {
|
||||
party_request_info(sd->status.party_id, sd->status.char_id);
|
||||
return;
|
||||
}
|
||||
ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == sd->status.account_id && p->party.member[i].char_id == sd->status.char_id );
|
||||
if (i < MAX_PARTY)
|
||||
{
|
||||
if (i < MAX_PARTY) {
|
||||
int j;
|
||||
p->data[i].sd = sd;
|
||||
if( p->instance_id )
|
||||
clif->instance_join(sd->fd,p->instance_id);
|
||||
}
|
||||
else
|
||||
for( j = 0; j < p->instances; j++ ) {
|
||||
if( instances[p->instance[j]].idle_timer == INVALID_TIMER && instances[p->instance[j]].progress_timer == INVALID_TIMER )
|
||||
continue;
|
||||
clif->instance_join(sd->fd, p->instance[j]);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
sd->status.party_id = 0; //He does not belongs to the party really?
|
||||
}
|
||||
|
||||
|
|
@ -451,7 +456,7 @@ int party_member_added(int party_id,int account_id,int char_id, int flag)
|
|||
{
|
||||
struct map_session_data *sd = map_id2sd(account_id),*sd2;
|
||||
struct party_data *p = party_search(party_id);
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
if(sd == NULL || sd->status.char_id != char_id || !sd->party_joining ) {
|
||||
if (!flag) //Char logged off before being accepted into party.
|
||||
|
|
@ -496,9 +501,13 @@ int party_member_added(int party_id,int account_id,int char_id, int flag)
|
|||
clif->party_xy(sd);
|
||||
clif->charnameupdate(sd); //Update char name's display [Skotlex]
|
||||
|
||||
if( p->instance_id )
|
||||
clif->instance_join(sd->fd, p->instance_id);
|
||||
|
||||
for( j = 0; j < p->instances; j++ ) {
|
||||
if( instances[p->instance[j]].idle_timer == INVALID_TIMER && instances[p->instance[j]].progress_timer == INVALID_TIMER )
|
||||
continue;
|
||||
clif->instance_join(sd->fd, p->instance[j]);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -551,12 +560,10 @@ int party_member_withdraw(int party_id, int account_id, int char_id)
|
|||
struct map_session_data* sd = map_id2sd(account_id);
|
||||
struct party_data* p = party_search(party_id);
|
||||
|
||||
if( p )
|
||||
{
|
||||
if( p ) {
|
||||
int i;
|
||||
ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == account_id && p->party.member[i].char_id == char_id );
|
||||
if( i < MAX_PARTY )
|
||||
{
|
||||
if( i < MAX_PARTY ) {
|
||||
clif->party_withdraw(p,sd,account_id,p->party.member[i].name,0x0);
|
||||
memset(&p->party.member[i], 0, sizeof(p->party.member[0]));
|
||||
memset(&p->data[i], 0, sizeof(p->data[0]));
|
||||
|
|
@ -565,13 +572,12 @@ int party_member_withdraw(int party_id, int account_id, int char_id)
|
|||
}
|
||||
}
|
||||
|
||||
if( sd && sd->status.party_id == party_id && sd->status.char_id == char_id )
|
||||
{
|
||||
if( sd && sd->status.party_id == party_id && sd->status.char_id == char_id ) {
|
||||
sd->status.party_id = 0;
|
||||
clif->charnameupdate(sd); //Update name display [Skotlex]
|
||||
//TODO: hp bars should be cleared too
|
||||
if( p->instance_id )
|
||||
instance_check_kick(sd);
|
||||
if( p->instances )
|
||||
instance->check_kick(sd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -581,22 +587,19 @@ int party_member_withdraw(int party_id, int account_id, int char_id)
|
|||
int party_broken(int party_id)
|
||||
{
|
||||
struct party_data* p;
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
p = party_search(party_id);
|
||||
if( p == NULL )
|
||||
return 0;
|
||||
|
||||
if( p->instance_id )
|
||||
{
|
||||
instance[p->instance_id].party_id = 0;
|
||||
instance_destroy( p->instance_id );
|
||||
for( j = 0; j < p->instances; j++ ) {
|
||||
instance->destroy( p->instance[j] );
|
||||
instances[p->instance[j]].owner_id = 0;
|
||||
}
|
||||
|
||||
for( i = 0; i < MAX_PARTY; i++ )
|
||||
{
|
||||
if( p->data[i].sd!=NULL )
|
||||
{
|
||||
|
||||
for( i = 0; i < MAX_PARTY; i++ ) {
|
||||
if( p->data[i].sd!=NULL ) {
|
||||
clif->party_withdraw(p,p->data[i].sd,p->party.member[i].account_id,p->party.member[i].name,0x10);
|
||||
p->data[i].sd->status.party_id=0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ struct party_data {
|
|||
struct party party;
|
||||
struct party_member_data data[MAX_PARTY];
|
||||
uint8 itemc; //For item distribution, position of last picker in party
|
||||
unsigned int instance_id;
|
||||
unsigned short *instance;
|
||||
unsigned short instances;
|
||||
struct {
|
||||
unsigned monk : 1; //There's at least one monk in party?
|
||||
unsigned sg : 1; //There's at least one Star Gladiator in party?
|
||||
|
|
|
|||
|
|
@ -167,12 +167,10 @@ int path_blownpos(int16 m,int16 x0,int16 y0,int16 dx,int16 dy,int count)
|
|||
dy=(dy>0)?1:((dy<0)?-1:0);
|
||||
}
|
||||
|
||||
while( count > 0 && (dx != 0 || dy != 0) )
|
||||
{
|
||||
if( !map_getcellp(md,x0+dx,y0+dy,CELL_CHKPASS) )
|
||||
{// attempt partial movement
|
||||
int fx = ( dx != 0 && map_getcellp(md,x0+dx,y0,CELL_CHKPASS) );
|
||||
int fy = ( dy != 0 && map_getcellp(md,x0,y0+dy,CELL_CHKPASS) );
|
||||
while( count > 0 && (dx != 0 || dy != 0) ) {
|
||||
if( !md->getcellp(md,x0+dx,y0+dy,CELL_CHKPASS) ) {// attempt partial movement
|
||||
int fx = ( dx != 0 && md->getcellp(md,x0+dx,y0,CELL_CHKPASS) );
|
||||
int fy = ( dy != 0 && md->getcellp(md,x0,y0+dy,CELL_CHKPASS) );
|
||||
if( fx && fy )
|
||||
{
|
||||
if(rnd()&1)
|
||||
|
|
@ -225,7 +223,7 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16
|
|||
spd->x[0] = x0;
|
||||
spd->y[0] = y0;
|
||||
|
||||
if (map_getcellp(md,x1,y1,cell))
|
||||
if (md->getcellp(md,x1,y1,cell))
|
||||
return false;
|
||||
|
||||
if (dx > abs(dy)) {
|
||||
|
|
@ -238,7 +236,7 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16
|
|||
|
||||
while (x0 != x1 || y0 != y1)
|
||||
{
|
||||
if (map_getcellp(md,x0,y0,cell))
|
||||
if (md->getcellp(md,x0,y0,cell))
|
||||
return false;
|
||||
wx += dx;
|
||||
wy += dy;
|
||||
|
|
@ -290,10 +288,10 @@ bool path_search(struct walkpath_data *wpd,int16 m,int16 x0,int16 y0,int16 x1,in
|
|||
//Do not check starting cell as that would get you stuck.
|
||||
if( x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys )
|
||||
#else
|
||||
if( x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| map_getcellp(md,x0,y0,cell)*/ )
|
||||
if( x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| md->getcellp(md,x0,y0,cell)*/ )
|
||||
#endif
|
||||
return false;
|
||||
if( x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || map_getcellp(md,x1,y1,cell) )
|
||||
if( x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || md->getcellp(md,x1,y1,cell) )
|
||||
return false;
|
||||
|
||||
// calculate (sgn(x1-x0), sgn(y1-y0))
|
||||
|
|
@ -317,7 +315,7 @@ bool path_search(struct walkpath_data *wpd,int16 m,int16 x0,int16 y0,int16 x1,in
|
|||
|
||||
if( dx == 0 && dy == 0 )
|
||||
break; // success
|
||||
if( map_getcellp(md,x,y,cell) )
|
||||
if( md->getcellp(md,x,y,cell) )
|
||||
break; // obstacle = failure
|
||||
}
|
||||
|
||||
|
|
@ -365,29 +363,29 @@ bool path_search(struct walkpath_data *wpd,int16 m,int16 x0,int16 y0,int16 x1,in
|
|||
// dc[2] : y--
|
||||
// dc[3] : x++
|
||||
|
||||
if(y < ys && !map_getcellp(md,x ,y+1,cell)) {
|
||||
if(y < ys && !md->getcellp(md,x ,y+1,cell)) {
|
||||
f |= 1; dc[0] = (y >= y1 ? 20 : 0);
|
||||
e+=add_path(heap,tp,x ,y+1,dist,rp,cost+dc[0]); // (x, y+1)
|
||||
}
|
||||
if(x > 0 && !map_getcellp(md,x-1,y ,cell)) {
|
||||
if(x > 0 && !md->getcellp(md,x-1,y ,cell)) {
|
||||
f |= 2; dc[1] = (x <= x1 ? 20 : 0);
|
||||
e+=add_path(heap,tp,x-1,y ,dist,rp,cost+dc[1]); // (x-1, y )
|
||||
}
|
||||
if(y > 0 && !map_getcellp(md,x ,y-1,cell)) {
|
||||
if(y > 0 && !md->getcellp(md,x ,y-1,cell)) {
|
||||
f |= 4; dc[2] = (y <= y1 ? 20 : 0);
|
||||
e+=add_path(heap,tp,x ,y-1,dist,rp,cost+dc[2]); // (x , y-1)
|
||||
}
|
||||
if(x < xs && !map_getcellp(md,x+1,y ,cell)) {
|
||||
if(x < xs && !md->getcellp(md,x+1,y ,cell)) {
|
||||
f |= 8; dc[3] = (x >= x1 ? 20 : 0);
|
||||
e+=add_path(heap,tp,x+1,y ,dist,rp,cost+dc[3]); // (x+1, y )
|
||||
}
|
||||
if( (f & (2+1)) == (2+1) && !map_getcellp(md,x-1,y+1,cell))
|
||||
if( (f & (2+1)) == (2+1) && !md->getcellp(md,x-1,y+1,cell))
|
||||
e+=add_path(heap,tp,x-1,y+1,dist+4,rp,cost+dc[1]+dc[0]-6); // (x-1, y+1)
|
||||
if( (f & (2+4)) == (2+4) && !map_getcellp(md,x-1,y-1,cell))
|
||||
if( (f & (2+4)) == (2+4) && !md->getcellp(md,x-1,y-1,cell))
|
||||
e+=add_path(heap,tp,x-1,y-1,dist+4,rp,cost+dc[1]+dc[2]-6); // (x-1, y-1)
|
||||
if( (f & (8+4)) == (8+4) && !map_getcellp(md,x+1,y-1,cell))
|
||||
if( (f & (8+4)) == (8+4) && !md->getcellp(md,x+1,y-1,cell))
|
||||
e+=add_path(heap,tp,x+1,y-1,dist+4,rp,cost+dc[3]+dc[2]-6); // (x+1, y-1)
|
||||
if( (f & (8+1)) == (8+1) && !map_getcellp(md,x+1,y+1,cell))
|
||||
if( (f & (8+1)) == (8+1) && !md->getcellp(md,x+1,y+1,cell))
|
||||
e+=add_path(heap,tp,x+1,y+1,dist+4,rp,cost+dc[3]+dc[0]-6); // (x+1, y+1)
|
||||
tp[rp].flag=1;
|
||||
if(e || heap[0]>=MAX_HEAP-5)
|
||||
|
|
|
|||
148
src/map/pc.c
148
src/map/pc.c
|
|
@ -518,8 +518,7 @@ int pc_makesavestatus(struct map_session_data *sd)
|
|||
#else
|
||||
sd->status.option = sd->sc.option&(OPTION_INVISIBLE|OPTION_CART|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR);
|
||||
#endif
|
||||
if (sd->sc.data[SC_JAILED])
|
||||
{ //When Jailed, do not move last point.
|
||||
if (sd->sc.data[SC_JAILED]) { //When Jailed, do not move last point.
|
||||
if(pc_isdead(sd)){
|
||||
pc_setrestartvalue(sd,0);
|
||||
} else {
|
||||
|
|
@ -543,13 +542,25 @@ int pc_makesavestatus(struct map_session_data *sd)
|
|||
sd->status.last_point.y = sd->bl.y;
|
||||
}
|
||||
|
||||
if(map[sd->bl.m].flag.nosave){
|
||||
if(map[sd->bl.m].flag.nosave || map[sd->bl.m].instance_id >= 0){
|
||||
struct map_data *m=&map[sd->bl.m];
|
||||
if(m->save.map)
|
||||
memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point));
|
||||
else
|
||||
memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point));
|
||||
}
|
||||
if( sd->status.last_point.map == 0 ) {
|
||||
sd->status.last_point.map = 1;
|
||||
sd->status.last_point.x = 0;
|
||||
sd->status.last_point.y = 0;
|
||||
}
|
||||
|
||||
if( sd->status.save_point.map == 0 ) {
|
||||
sd->status.save_point.map = 1;
|
||||
sd->status.save_point.x = 0;
|
||||
sd->status.save_point.y = 0;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -905,8 +916,7 @@ int pc_isequip(struct map_session_data *sd,int n)
|
|||
* No problem with the session id
|
||||
* set the status that has been sent from char server
|
||||
*------------------------------------------*/
|
||||
bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers)
|
||||
{
|
||||
bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers) {
|
||||
int i;
|
||||
unsigned long tick = gettick();
|
||||
uint32 ip = session[sd->fd]->client_addr;
|
||||
|
|
@ -1014,6 +1024,17 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
|
|||
|
||||
sd->disguise = -1;
|
||||
|
||||
sd->instance = NULL;
|
||||
sd->instances = 0;
|
||||
|
||||
sd->bg_queue.arena = NULL;
|
||||
sd->bg_queue.ready = 0;
|
||||
sd->bg_queue.client_has_bg_data = 0;
|
||||
sd->bg_queue.type = 0;
|
||||
|
||||
sd->queues = NULL;
|
||||
sd->queues_count = 0;
|
||||
|
||||
// Event Timers
|
||||
for( i = 0; i < MAX_EVENTTIMER; i++ )
|
||||
sd->eventtimer[i] = INVALID_TIMER;
|
||||
|
|
@ -1075,7 +1096,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
|
|||
/**
|
||||
* Fixes login-without-aura glitch (the screen won't blink at this point, don't worry :P)
|
||||
**/
|
||||
clif->changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y);
|
||||
clif->changemap(sd,sd->bl.m,sd->bl.x,sd->bl.y);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -4680,36 +4701,62 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *target)
|
|||
* 1 - Invalid map index.
|
||||
* 2 - Map not in this map-server, and failed to locate alternate map-server.
|
||||
*------------------------------------------*/
|
||||
int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype)
|
||||
{
|
||||
struct party_data *p;
|
||||
int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype) {
|
||||
int16 m;
|
||||
|
||||
nullpo_ret(sd);
|
||||
|
||||
if( !mapindex || !mapindex_id2name(mapindex) )
|
||||
{
|
||||
if( !mapindex || !mapindex_id2name(mapindex) ) {
|
||||
ShowDebug("pc_setpos: Passed mapindex(%d) is invalid!\n", mapindex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( pc_isdead(sd) )
|
||||
{ //Revive dead people before warping them
|
||||
if( pc_isdead(sd) ) { //Revive dead people before warping them
|
||||
pc_setstand(sd);
|
||||
pc_setrestartvalue(sd,1);
|
||||
}
|
||||
|
||||
m = map_mapindex2mapid(mapindex);
|
||||
if( map[m].flag.src4instance && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id )
|
||||
{
|
||||
// Request the mapid of this src map into the instance of the party
|
||||
int im = instance_map2imap(m, p->instance_id);
|
||||
if( im < 0 )
|
||||
; // Player will enter the src map for instances
|
||||
else
|
||||
{ // Changes destiny to the instance map, not the source map
|
||||
m = im;
|
||||
mapindex = map_id2index(m);
|
||||
|
||||
if( map[m].flag.src4instance ) {
|
||||
struct party_data *p;
|
||||
bool stop = false;
|
||||
int i = 0, j = 0;
|
||||
|
||||
if( sd->instances ) {
|
||||
for( i = 0; i < sd->instances; i++ ) {
|
||||
ARR_FIND(0, instances[sd->instance[i]].num_map, j, map[instances[sd->instance[i]].map[j]].instance_src_map == m && !map[instances[sd->instance[i]].map[j]].cName);
|
||||
if( j != instances[sd->instance[i]].num_map )
|
||||
break;
|
||||
}
|
||||
if( i != sd->instances ) {
|
||||
m = instances[sd->instance[i]].map[j];
|
||||
mapindex = map[m].index;
|
||||
stop = true;
|
||||
}
|
||||
}
|
||||
if ( !stop && sd->status.party_id && (p = party_search(sd->status.party_id)) && p->instances ) {
|
||||
for( i = 0; i < p->instances; i++ ) {
|
||||
ARR_FIND(0, instances[p->instance[i]].num_map, j, map[instances[p->instance[i]].map[j]].instance_src_map == m && !map[instances[p->instance[i]].map[j]].cName);
|
||||
if( j != instances[p->instance[i]].num_map )
|
||||
break;
|
||||
}
|
||||
if( i != p->instances ) {
|
||||
m = instances[p->instance[i]].map[j];
|
||||
mapindex = map[m].index;
|
||||
stop = true;
|
||||
}
|
||||
}
|
||||
if ( !stop && sd->status.guild_id && sd->guild && sd->guild->instances ) {
|
||||
for( i = 0; i < sd->guild->instances; i++ ) {
|
||||
ARR_FIND(0, instances[sd->guild->instance[i]].num_map, j, map[instances[sd->guild->instance[i]].map[j]].instance_src_map == m && !map[instances[sd->guild->instance[i]].map[j]].cName);
|
||||
if( j != instances[sd->guild->instance[i]].num_map )
|
||||
break;
|
||||
}
|
||||
if( i != sd->guild->instances ) {
|
||||
m = instances[sd->guild->instance[i]].map[j];
|
||||
mapindex = map[m].index;
|
||||
stop = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4718,6 +4765,17 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
|
|||
if( sd->state.changemap ) { // Misc map-changing settings
|
||||
int i;
|
||||
sd->state.pmap = sd->bl.m;
|
||||
|
||||
for( i = 0; i < sd->queues_count; i++ ) {
|
||||
struct hQueue *queue;
|
||||
if( (queue = script->queue(sd->queues[i])) && queue->onMapChange[0] != '\0' ) {
|
||||
pc_setregstr(sd, add_str("QMapChangeTo"), map[m].name);
|
||||
npc_event(sd, queue->onMapChange, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if( map[m].cell == (struct mapcell *)0xdeadbeaf )
|
||||
map_cellfromcache(&map[m]);
|
||||
if (sd->sc.count) { // Cancel some map related stuff.
|
||||
if (sd->sc.data[SC_JAILED])
|
||||
return 1; //You may not get out!
|
||||
|
|
@ -4761,8 +4819,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
|
|||
|
||||
}
|
||||
|
||||
if( m < 0 )
|
||||
{
|
||||
if( m < 0 ) {
|
||||
uint32 ip;
|
||||
uint16 port;
|
||||
//if can't find any map-servers, just abort setting position.
|
||||
|
|
@ -4787,14 +4844,12 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
|
|||
return 0;
|
||||
}
|
||||
|
||||
if( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
|
||||
{
|
||||
if( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) {
|
||||
ShowError("pc_setpos: attempt to place player %s (%d:%d) on invalid coordinates (%s-%d,%d)\n", sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(mapindex),x,y);
|
||||
x = y = 0; // make it random
|
||||
}
|
||||
|
||||
if( x == 0 && y == 0 )
|
||||
{// pick a random walkable cell
|
||||
if( x == 0 && y == 0 ) {// pick a random walkable cell
|
||||
do {
|
||||
x=rnd()%(map[m].xs-2)+1;
|
||||
y=rnd()%(map[m].ys-2)+1;
|
||||
|
|
@ -4808,7 +4863,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
|
|||
|
||||
if(sd->bl.prev != NULL){
|
||||
unit_remove_map_pc(sd,clrtype);
|
||||
clif->changemap(sd,map[m].index,x,y); // [MouseJstr]
|
||||
clif->changemap(sd,m,x,y); // [MouseJstr]
|
||||
} else if(sd->state.active)
|
||||
//Tag player for rewarping after map-loading is done. [Skotlex]
|
||||
sd->state.rewarp = 1;
|
||||
|
|
@ -4818,31 +4873,27 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
|
|||
sd->bl.x = sd->ud.to_x = x;
|
||||
sd->bl.y = sd->ud.to_y = y;
|
||||
|
||||
if( sd->status.guild_id > 0 && map[m].flag.gvg_castle )
|
||||
{ // Increased guild castle regen [Valaris]
|
||||
if( sd->status.guild_id > 0 && map[m].flag.gvg_castle ) { // Increased guild castle regen [Valaris]
|
||||
struct guild_castle *gc = guild->mapindex2gc(sd->mapindex);
|
||||
if(gc && gc->guild_id == sd->status.guild_id)
|
||||
sd->regen.state.gc = 1;
|
||||
}
|
||||
|
||||
if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 )
|
||||
{
|
||||
if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 ) {
|
||||
sd->pd->bl.m = m;
|
||||
sd->pd->bl.x = sd->pd->ud.to_x = x;
|
||||
sd->pd->bl.y = sd->pd->ud.to_y = y;
|
||||
sd->pd->ud.dir = sd->ud.dir;
|
||||
}
|
||||
|
||||
if( homun_alive(sd->hd) )
|
||||
{
|
||||
if( homun_alive(sd->hd) ) {
|
||||
sd->hd->bl.m = m;
|
||||
sd->hd->bl.x = sd->hd->ud.to_x = x;
|
||||
sd->hd->bl.y = sd->hd->ud.to_y = y;
|
||||
sd->hd->ud.dir = sd->ud.dir;
|
||||
}
|
||||
|
||||
if( sd->md )
|
||||
{
|
||||
if( sd->md ) {
|
||||
sd->md->bl.m = m;
|
||||
sd->md->bl.x = sd->md->ud.to_x = x;
|
||||
sd->md->bl.y = sd->md->ud.to_y = y;
|
||||
|
|
@ -6588,15 +6639,22 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
|
|||
pc_setglobalreg(sd,"PC_DIE_COUNTER",sd->die_counter+1);
|
||||
pc_setparam(sd, SP_KILLERRID, src?src->id:0);
|
||||
|
||||
if( sd->bg_id ) {
|
||||
if( sd->bg_id ) {/* TODO: purge when bgqueue is deemed ok */
|
||||
struct battleground_data *bg;
|
||||
if( (bg = bg_team_search(sd->bg_id)) != NULL && bg->die_event[0] )
|
||||
npc_event(sd, bg->die_event, 0);
|
||||
}
|
||||
|
||||
|
||||
for( i = 0; i < sd->queues_count; i++ ) {
|
||||
struct hQueue *queue;
|
||||
if( (queue = script->queue(sd->queues[i])) && queue->onDeath[0] != '\0' )
|
||||
npc_event(sd, queue->onDeath, 0);
|
||||
}
|
||||
|
||||
npc_script_event(sd,NPCE_DIE);
|
||||
|
||||
// Clear anything NPC-related when you die and was interacting with one.
|
||||
if (sd->npc_id)
|
||||
{
|
||||
if (sd->npc_id) {
|
||||
if (sd->state.using_fake_npc) {
|
||||
clif->clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd);
|
||||
sd->state.using_fake_npc = 0;
|
||||
|
|
@ -6611,8 +6669,6 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
|
|||
sd->st->state = END;
|
||||
}
|
||||
|
||||
npc_script_event(sd,NPCE_DIE);
|
||||
|
||||
/* e.g. not killed thru pc_damage */
|
||||
if( pc_issit(sd) ) {
|
||||
clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_SIT);
|
||||
|
|
@ -6788,7 +6844,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
|
|||
|
||||
if(map[sd->bl.m].flag.pvp_nightmaredrop)
|
||||
{ // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker]
|
||||
for(j=0;j<MAX_DROP_PER_MAP;j++){
|
||||
for(j=0;j<map[sd->bl.m].drop_list_count;j++){
|
||||
int id = map[sd->bl.m].drop_list[j].drop_id;
|
||||
int type = map[sd->bl.m].drop_list[j].drop_type;
|
||||
int per = map[sd->bl.m].drop_list[j].drop_per;
|
||||
|
|
|
|||
15
src/map/pc.h
15
src/map/pc.h
|
|
@ -10,6 +10,7 @@
|
|||
#include "../common/timer.h" // INVALID_TIMER
|
||||
#include "atcommand.h" // AtCommandType
|
||||
#include "battle.h" // battle_config
|
||||
#include "battleground.h"
|
||||
#include "buyingstore.h" // struct s_buyingstore
|
||||
#include "itemdb.h" // MAX_ITEMGROUP
|
||||
#include "map.h" // RC_MAX
|
||||
|
|
@ -519,6 +520,20 @@ struct map_session_data {
|
|||
struct sc_display_entry **sc_display;
|
||||
unsigned char sc_display_count;
|
||||
|
||||
unsigned short *instance;
|
||||
unsigned short instances;
|
||||
|
||||
/* Possible Thanks to Yommy~! */
|
||||
struct {
|
||||
unsigned int ready : 1;/* did he accept the 'match is about to start, enter' dialog? */
|
||||
unsigned int client_has_bg_data : 1; /* flags whether the client has the "in queue" window (aka the client knows it is in a queue) */
|
||||
struct bg_arena *arena;
|
||||
enum bg_queue_types type;
|
||||
} bg_queue;
|
||||
|
||||
int *queues;
|
||||
unsigned int queues_count;
|
||||
|
||||
// temporary debugging of bug #3504
|
||||
const char* delunit_prevfile;
|
||||
int delunit_prevline;
|
||||
|
|
|
|||
709
src/map/script.c
709
src/map/script.c
File diff suppressed because it is too large
Load diff
|
|
@ -4,6 +4,8 @@
|
|||
#ifndef _SCRIPT_H_
|
||||
#define _SCRIPT_H_
|
||||
|
||||
#include "map.h" //EVENT_NAME_LENGTH
|
||||
|
||||
#define NUM_WHISPER_VAR 10
|
||||
|
||||
struct map_session_data;
|
||||
|
|
@ -110,6 +112,30 @@ struct script_stack {
|
|||
struct DBMap* var_function;// scope variables
|
||||
};
|
||||
|
||||
enum hQueueOpt {
|
||||
HQO_NONE,
|
||||
HQO_onLogOut,
|
||||
HQO_OnDeath,
|
||||
HQO_OnMapChange,
|
||||
HQO_MAX,
|
||||
};
|
||||
|
||||
/* [Ind/Hercules] */
|
||||
struct hQueue {
|
||||
int id;
|
||||
int *item;
|
||||
int items;
|
||||
/* events */
|
||||
char onLogOut[EVENT_NAME_LENGTH];
|
||||
char onDeath[EVENT_NAME_LENGTH];
|
||||
char onMapChange[EVENT_NAME_LENGTH];
|
||||
};
|
||||
|
||||
struct hQueueIterator {
|
||||
int *item;
|
||||
int items;
|
||||
int pos;
|
||||
};
|
||||
|
||||
//
|
||||
// Script state
|
||||
|
|
@ -129,6 +155,7 @@ struct script_state {
|
|||
int instance_id;
|
||||
//For backing up purposes
|
||||
struct script_state *bk_st;
|
||||
unsigned char hIterator;
|
||||
int bk_npcid;
|
||||
unsigned freeloop : 1;// used by buildin_freeloop
|
||||
unsigned op2ref : 1;// used by op_2
|
||||
|
|
@ -291,8 +318,14 @@ struct script_function {
|
|||
char *name;
|
||||
char *arg;
|
||||
};
|
||||
|
||||
/* script.c interface (incomplete) */
|
||||
struct script_interface {
|
||||
/* */
|
||||
struct hQueue *hq;
|
||||
struct hQueueIterator *hqi;
|
||||
int hqs, hqis;
|
||||
int hqe[HQO_MAX];
|
||||
/* */
|
||||
char **buildin;
|
||||
unsigned int buildin_count;
|
||||
|
|
@ -304,6 +337,11 @@ struct script_interface {
|
|||
bool (*addScript) (char *name, char *args, bool (*func)(struct script_state *st));
|
||||
int (*conv_num) (struct script_state *st,struct script_data *data);
|
||||
const char* (*conv_str) (struct script_state *st,struct script_data *data);
|
||||
/* */
|
||||
struct hQueue *(*queue) (int idx);
|
||||
bool (*queue_add) (int idx, int var);
|
||||
bool (*queue_del) (int idx);
|
||||
bool (*queue_remove) (int idx, int var);
|
||||
} script_s;
|
||||
|
||||
struct script_interface *script;
|
||||
|
|
|
|||
|
|
@ -14464,7 +14464,7 @@ void skill_unitsetmapcell (struct skill_unit *src, uint16 skill_id, uint16 skill
|
|||
|
||||
for( y = src->bl.y - range; y <= src->bl.y + range; ++y )
|
||||
for( x = src->bl.x - range; x <= src->bl.x + range; ++x )
|
||||
map_setcell(src->bl.m, x, y, cell, flag);
|
||||
map[src->bl.m].setcell(src->bl.m, x, y, cell, flag);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
|
|
|
|||
|
|
@ -6079,14 +6079,15 @@ void status_set_viewdata(struct block_list *bl, int class_)
|
|||
|
||||
/// Returns the status_change data of bl or NULL if it doesn't exist.
|
||||
struct status_change *status_get_sc(struct block_list *bl) {
|
||||
if( bl )
|
||||
switch (bl->type) {
|
||||
case BL_PC: return &((TBL_PC*)bl)->sc;
|
||||
case BL_MOB: return &((TBL_MOB*)bl)->sc;
|
||||
case BL_NPC: return &((TBL_NPC*)bl)->sc;
|
||||
case BL_HOM: return &((TBL_HOM*)bl)->sc;
|
||||
case BL_MER: return &((TBL_MER*)bl)->sc;
|
||||
case BL_ELEM: return &((TBL_ELEM*)bl)->sc;
|
||||
if( bl ) {
|
||||
switch (bl->type) {
|
||||
case BL_PC: return &((TBL_PC*)bl)->sc;
|
||||
case BL_MOB: return &((TBL_MOB*)bl)->sc;
|
||||
case BL_NPC: return NULL;
|
||||
case BL_HOM: return &((TBL_HOM*)bl)->sc;
|
||||
case BL_MER: return &((TBL_MER*)bl)->sc;
|
||||
case BL_ELEM: return &((TBL_ELEM*)bl)->sc;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ struct unit_data* unit_bl2ud(struct block_list *bl)
|
|||
if( bl->type == BL_PC) return &((struct map_session_data*)bl)->ud;
|
||||
if( bl->type == BL_MOB) return &((struct mob_data*)bl)->ud;
|
||||
if( bl->type == BL_PET) return &((struct pet_data*)bl)->ud;
|
||||
if( bl->type == BL_NPC) return &((struct npc_data*)bl)->ud;
|
||||
if( bl->type == BL_NPC) return ((struct npc_data*)bl)->ud;
|
||||
if( bl->type == BL_HOM) return &((struct homun_data*)bl)->ud;
|
||||
if( bl->type == BL_MER) return &((struct mercenary_data*)bl)->ud;
|
||||
if( bl->type == BL_ELEM) return &((struct elemental_data*)bl)->ud;
|
||||
|
|
@ -678,10 +678,12 @@ int unit_setdir(struct block_list *bl,unsigned char dir)
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint8 unit_getdir(struct block_list *bl)
|
||||
{
|
||||
uint8 unit_getdir(struct block_list *bl) {
|
||||
struct unit_data *ud;
|
||||
nullpo_ret(bl );
|
||||
nullpo_ret(bl);
|
||||
|
||||
if( bl->type == BL_NPC )
|
||||
return ((TBL_NPC*)bl)->dir;
|
||||
ud = unit_bl2ud(bl);
|
||||
if (!ud) return 0;
|
||||
return ud->dir;
|
||||
|
|
@ -1961,8 +1963,7 @@ int unit_skillcastcancel(struct block_list *bl,int type)
|
|||
}
|
||||
|
||||
// unit_data initialization process
|
||||
void unit_dataset(struct block_list *bl)
|
||||
{
|
||||
void unit_dataset(struct block_list *bl) {
|
||||
struct unit_data *ud;
|
||||
nullpo_retv(ud = unit_bl2ud(bl));
|
||||
|
||||
|
|
@ -2121,8 +2122,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
|
|||
npc_touchnext_areanpc(sd,true);
|
||||
|
||||
// Check if warping and not changing the map.
|
||||
if ( sd->state.warping && !sd->state.changemap )
|
||||
{
|
||||
if ( sd->state.warping && !sd->state.changemap ) {
|
||||
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
|
||||
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
|
||||
}
|
||||
|
|
@ -2163,18 +2163,15 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
|
|||
sd->state.active, sd->state.connect_new, sd->state.rewarp, sd->state.changemap, sd->state.debug_remove_map,
|
||||
map[bl->m].name, map[bl->m].users,
|
||||
sd->debug_file, sd->debug_line, sd->debug_func, file, line, func);
|
||||
}
|
||||
else
|
||||
if (--map[bl->m].users == 0 && battle_config.dynamic_mobs) //[Skotlex]
|
||||
} else if (--map[bl->m].users == 0 && battle_config.dynamic_mobs) //[Skotlex]
|
||||
map_removemobs(bl->m);
|
||||
if( !(sd->sc.option&OPTION_INVISIBLE) )
|
||||
{// decrement the number of active pvp players on the map
|
||||
--map[bl->m].users_pvp;
|
||||
}
|
||||
if( map[bl->m].instance_id )
|
||||
{
|
||||
instance[map[bl->m].instance_id].users--;
|
||||
instance_check_idle(map[bl->m].instance_id);
|
||||
if( map[bl->m].instance_id >= 0 ) {
|
||||
instances[map[bl->m].instance_id].users--;
|
||||
instance->check_idle(map[bl->m].instance_id);
|
||||
}
|
||||
sd->state.debug_remove_map = 1; // temporary state to track double remove_map's [FlavioJS]
|
||||
sd->debug_file = file;
|
||||
|
|
@ -2356,9 +2353,19 @@ int unit_free(struct block_list *bl, clr_type clrtype)
|
|||
ers_free(pc_sc_display_ers, sd->sc_display[i]);
|
||||
}
|
||||
sd->sc_display_count = 0;
|
||||
}
|
||||
if( sd->sc_display != NULL ) {
|
||||
aFree(sd->sc_display);
|
||||
sd->sc_display = NULL;
|
||||
}
|
||||
if( sd->instance != NULL ) {
|
||||
aFree(sd->instance);
|
||||
sd->instance = NULL;
|
||||
}
|
||||
if( sd->queues != NULL ) {
|
||||
aFree(sd->queues);
|
||||
sd->queues = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL_PET:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue