From 73169ee3002dc038f8556c74df250f6fbc029f1f Mon Sep 17 00:00:00 2001 From: Sirius Date: Sun, 26 May 2013 02:53:06 -0700 Subject: * Poring War: Added missing barrier resets [Euphy's rAthena fix based on my report] * Added support for Baby Novices in the Novice's Quest Skills * Hotfix for the Blacksmith Rank bugreport: http://hercules.ws/board/tracker/issue-7288-max-refine-blacksmith-rank/ * Added duplicates from pre-re Mage Quest required in Sage Quest Skill. --- npc/other/poring_war.txt | 29 ++++++++++--------- npc/quests/skills/novice_skills.txt | 4 +-- npc/re/quests/skills/sage_skills.txt | 55 ++++++++++++++++++++++++++++++++++++ src/map/script.c | 2 +- 4 files changed, 74 insertions(+), 16 deletions(-) create mode 100644 npc/re/quests/skills/sage_skills.txt diff --git a/npc/other/poring_war.txt b/npc/other/poring_war.txt index f81b54f89..6e701b398 100644 --- a/npc/other/poring_war.txt +++ b/npc/other/poring_war.txt @@ -1,17 +1,20 @@ -//===== Hercules Script ====================================== +//===== rAthena Script ======================================= //= Poring War //===== By: ================================================== //= Kisuka //===== Current Version: ===================================== -//= 1.1b +//= 1.2 +//===== Compatible With: ===================================== +//= rAthena SVN //===== Description: ========================================= -//= [Aegis Conversion] +//= [Official Conversion] //= Poring War //===== Additional Comments: ================================= //= 1.0 First version. [Kisuka][5511] //= 1.1 Fixed some typos/bugs. [CalciumKid] //= 1.1a Fixed Waiting rooms witht he default MAX_LEVEL [Slim] //= 1.1b Fixed incorrect label calls. [Euphy] +//= 1.2 Added missing barrier resets, credits to Zopokx. [Euphy] //============================================================ // Poring War Recruiter @@ -929,23 +932,23 @@ OnStop: end; OnAngelingWin: - removemapflag "poring_w02",mf_partylock; - removemapflag "poring_w02",mf_pvp; - removemapflag "poring_w02",mf_pvp_noguild; - removemapflag "poring_w02",mf_pvp_nocalcrank; - mapannounce "poring_w02","Mr. Doppel: Angeling Team of party " + getpartyname($@wop_team_a) + " won the battle!",0,0xf08080; - donpcevent "Deviruchi#wop_endmaster::OnEnable"; - stopnpctimer; - end; - + set .@i,1; OnDevilingWin: removemapflag "poring_w02",mf_partylock; removemapflag "poring_w02",mf_pvp; removemapflag "poring_w02",mf_pvp_noguild; removemapflag "poring_w02",mf_pvp_nocalcrank; - mapannounce "poring_w02","Mr. Doppel: Deviling Team of party " + getpartyname($@wop_team_d) + " won the battle!",0,0xf08080; + if (.@i) + mapannounce "poring_w02","Mr. Doppel: Angeling Team of party " + getpartyname($@wop_team_a) + " won the battle!",0,0xf08080; + else + mapannounce "poring_w02","Mr. Doppel: Deviling Team of party " + getpartyname($@wop_team_d) + " won the battle!",0,0xf08080; donpcevent "Deviruchi#wop_endmaster::OnEnable"; stopnpctimer; + // Reset Barriers + donpcevent "#aroom_ingate_wop::OnDisable"; + donpcevent "#aroom_outgate_wop::OnDisable"; + donpcevent "#droom_ingate_wop::OnDisable"; + donpcevent "#droom_outgate_wop::OnDisable"; end; OnTimer5000: diff --git a/npc/quests/skills/novice_skills.txt b/npc/quests/skills/novice_skills.txt index 92cc797e6..17a670eed 100644 --- a/npc/quests/skills/novice_skills.txt +++ b/npc/quests/skills/novice_skills.txt @@ -15,7 +15,7 @@ //============================================================ prt_in,234,133,4 script Nami 66,{ - if ((Class == Job_Novice) && (JobLevel > 3 || BaseLevel > 11) && (skill_nov < 3)) { + if ((Class == Job_Novice || Class == Job_Baby) && (JobLevel > 3 || BaseLevel > 11) && (skill_nov < 3)) { mes "[Nami]"; mes "Hello!"; mes "I want to be a nurse so bad!"; @@ -189,7 +189,7 @@ prt_in,234,133,4 script Nami 66,{ } prt_in,73,87,4 script Chivalry Member 65,{ - if ((Class == Job_Novice) && (JobLevel > 6) && ((skill_nov >= 3) && (skill_nov <= 5))) { + if ((Class == Job_Novice || Class == Job_Baby) && (JobLevel > 6) && ((skill_nov >= 3) && (skill_nov <= 5))) { mes "[Bulma]"; mes "Yeah. . . I look great. . ."; mes "I am a knight in the knight's"; diff --git a/npc/re/quests/skills/sage_skills.txt b/npc/re/quests/skills/sage_skills.txt new file mode 100644 index 000000000..2c92d7bd9 --- /dev/null +++ b/npc/re/quests/skills/sage_skills.txt @@ -0,0 +1,55 @@ +//===== Hercules Script ======================================= +//= Sage Quest Skill's related NPCs +//===== By: ================================================== +//= Zopokx +//===== Current Version: ===================================== +//= 1.0 +//===== Compatible With: ===================================== +//= Hercules +//===== Description: ========================================= +//= Morocc/Payon Solution duplicate NPCs for Sage Quest Skill +//===== Additional Comments: ================================= +//= 1.0 First version. [Zopokx] +//============================================================ + +moc_ruins,91,150,0 script Ponka-Hontas 93,{ + mes "[Mage Guildsman]"; + mes "Would you like a Solution? Then please give me 50 Zeny and at least 1 Empty Testtube."; + next; + if (select("Alright, Deal.:Nah, forget it.") == 1) { + mes "[Mage Guildsman]"; + if (zeny < 50) { + mes "I'm sorry, but you don't have enough money to cover the 50 Zeny fee."; + close; + } + if (countitem(1092) == 0) { + mes "You can't carry liquids without using a bottle. Bring an Empty Test Tube the next time you see me."; + close; + } + delitem 1092,1; //Empty_Cylinder + set zeny,zeny-50; + getitem 1088,1; //Morocc_Potion + } + close; +} + +pay_arche,122,100,0 script Dollshoi 88,{ + mes "[Mage Guildsman]"; + mes "You want a Solution? Hmm, give me 50 Zeny and at least 1 Empty Test Tube."; + next; + if (select("Alright, Deal.:Nah, forget it.") == 1) { + mes "[Mage Guildsman]"; + if (Zeny < 50) { + mes "Hey! You don't have enough money to cover my 50 Zeny charge."; + close; + } + if (countitem(1092) == 0) { + mes "You can't carry solutions without a bottle! Bring me an Empty Test Tube."; + close; + } + delitem 1092,1; //Empty_Cylinder + set zeny,zeny-50; + getitem 1089,1; //Payon_Potion + } + close; +} diff --git a/src/map/script.c b/src/map/script.c index 9a123705b..c1b3cbf70 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -7272,7 +7272,7 @@ BUILDIN(successrefitem) clif->additem(sd,i,1,0); pc_equipitem(sd,i,ep); clif->misceffect(&sd->bl,3); - if(sd->status.inventory[i].refine == MAX_REFINE && + if(sd->status.inventory[i].refine == 10 && sd->status.inventory[i].card[0] == CARD0_FORGE && sd->status.char_id == (int)MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3]) ){ // Fame point system [DracoRPG] -- cgit v1.2.3-70-g09d2 From 053a678f040a7b52c67c193abdeb2e20e3d93382 Mon Sep 17 00:00:00 2001 From: Sirius Date: Sun, 26 May 2013 03:20:17 -0700 Subject: Header scripts adapted to Hercules --- npc/other/poring_war.txt | 6 ++---- npc/re/quests/skills/sage_skills.txt | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/npc/other/poring_war.txt b/npc/other/poring_war.txt index 6e701b398..95a17d241 100644 --- a/npc/other/poring_war.txt +++ b/npc/other/poring_war.txt @@ -1,13 +1,11 @@ -//===== rAthena Script ======================================= +//===== Hercules Script ====================================== //= Poring War //===== By: ================================================== //= Kisuka //===== Current Version: ===================================== //= 1.2 -//===== Compatible With: ===================================== -//= rAthena SVN //===== Description: ========================================= -//= [Official Conversion] +//= [Aegis Conversion] //= Poring War //===== Additional Comments: ================================= //= 1.0 First version. [Kisuka][5511] diff --git a/npc/re/quests/skills/sage_skills.txt b/npc/re/quests/skills/sage_skills.txt index 2c92d7bd9..64ebe20e3 100644 --- a/npc/re/quests/skills/sage_skills.txt +++ b/npc/re/quests/skills/sage_skills.txt @@ -1,15 +1,13 @@ -//===== Hercules Script ======================================= +//===== Hercules Script ====================================== //= Sage Quest Skill's related NPCs //===== By: ================================================== //= Zopokx //===== Current Version: ===================================== //= 1.0 -//===== Compatible With: ===================================== -//= Hercules //===== Description: ========================================= //= Morocc/Payon Solution duplicate NPCs for Sage Quest Skill //===== Additional Comments: ================================= -//= 1.0 First version. [Zopokx] +//= 1.0 First version //============================================================ moc_ruins,91,150,0 script Ponka-Hontas 93,{ -- cgit v1.2.3-70-g09d2 From 26ba1adce14d46a7e7a800cf2cf8e28567b7f931 Mon Sep 17 00:00:00 2001 From: Sirius Date: Sun, 26 May 2013 08:09:42 -0700 Subject: Eden EXP Quests 56-70 script rewritten and optimised --- npc/re/quests/eden/56-70.txt | 1379 ++++++++++-------------------------------- 1 file changed, 320 insertions(+), 1059 deletions(-) diff --git a/npc/re/quests/eden/56-70.txt b/npc/re/quests/eden/56-70.txt index d4599c557..c735bde2a 100644 --- a/npc/re/quests/eden/56-70.txt +++ b/npc/re/quests/eden/56-70.txt @@ -3,7 +3,7 @@ //===== By: ================================================== //= L0ne_W0lf //===== Current Version: ===================================== -//= 1.4 +//= 2.0 //===== Description: ========================================= //= Repetable Quests for Players between Baselevel 56 - 70. //===== Additional Comments: ================================= @@ -12,1076 +12,337 @@ //= 1.2 Added checkquest confirmation for -1. [Euphy] //= 1.3 Fixed Puppet Master's Agony Quest (12217 -> 3259). [Joseph] //= 1.4 Fixed invalid check (Magic Wand Quest). [Joseph] +//= 2.0 Optimised [Zopokx] //============================================================ -moc_para01,42,38,3 script Mission [56 - 70] 857,{ - if (checkquest(12217) > -1) erasequest 12217; - if (countitem(6219)) { - mes "Here is the list of various adventures for level 55~70 adventurers."; - next; - mes "Lots of missions such as a Monster Hunting, Delivery Goods, Finding People."; - next; - switch (select("Mission Numbers 1~5:Mission Numbers 6~10:Mission Numbers 11~15")) { +moc_para01,42,38,3 script MisiĆ³n [56 - 70] 857,{ + if (countitem(6219) < 1) { + mes "To get these missions, I need to Join the Eden Group first. I must find Secretary Lime Evenor and become a member."; + close; + } + if ((BaseLevel < 56) && (BaseLevel > 70)) { + mes "These missions are not fit for my level. I should look for other missions."; + close; + } + mes "Here is the list of various adventures for level 56~70 adventurers."; + next; + mes "Lots of missions such as a Monster Hunting, Delivery Goods, Finding People."; + next; + switch (select("Mission Numbers 1~5:Mission Numbers 6~10:Mission Numbers 11~15")) { case 1: switch (select("What is this Bandage?:Dangerous Alligators.:That wasn't a mermaid...:My country is calling me!")) { - case 1: - if (checkquest(3250) <= 0) { - mes "This mission is assigned by the Rekenber corporation from Lighthalzen. Below are the details."; - next; - mes "Rekenber corporation is about to launch a new project called 'Green Medical Center'. For the first product of the project, we are preparing well-being Bandages."; - next; - mes "Regarding the project, we need to research monster's reactions when they are wrapped with Rotten Bandages."; - next; - mes "If you are interested, please hunt 30 Mummies and bring 30 Rotten Bandages. You can find them in the Pyramid West of Morroc."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "- Rekenber corporation chief director 'Julie E Delph' -"; - next; - mes " "; - next; - mes "Would you like to accept this mission?"; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3250; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - if (checkquest(3250,HUNTING) == 1) { - mes "You have an on-going mission. Would you like to check the details?"; - next; - switch (select("Check the details.:Cancel.")) { - case 1: - mes "This mission is assigned by the Rekenber corporation from Lighthalzen. Below are the details."; - next; - mes "Rekenber corporation is about to launch a new project called 'Green Medical Center'. For the first product of the project, we are preparing well-being Bandages."; - next; - mes "Regarding the project, we need to research monster's reactions when they are wrapped with Rotten Bandages."; - next; - mes "If you are interested, please hunt 30 Mummies and bring 30 Rotten Bandages. You can find them in the Pyramid West of Morroc."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "- Rekenber corporation chief director 'Julie E Delph' -"; - close; - case 2: - close; - } - } - if ((checkquest(3250,HUNTING) == 2) && (countitem(930) > 19)) { - mes "I have done pretty well for the mission. Should I report it now?"; - next; - switch (select("Report the mission.:Do not report it yet.")) { - case 1: - delitem 930,20; //Rotten_Bandage - getexp 15000,5000; - erasequest 3250; - mes "You have completed the mission. Get rewards."; - close; - case 2: - close; - } - } - case 2: - if (checkquest(3251) <= 0) { - mes "This mission is assigned by the Comodo cooperative society. Below are the details."; - next; - mes "Alligators have gone wild these days, they attack women and drunken people who hang out near the beach."; - next; - mes "This is a very shameful situation for us, the most wonderful vacation spot in Rune-Midgard."; - next; - mes "So, it would be very helpful if you hunt 30 Alligators to clean out this situation."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes " "; - next; - mes "Would you like to accept this mission?"; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3251; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - if (checkquest(3251,HUNTING) == 1) { - mes "You have an on-going mission. Would you like to check the details?"; - next; - switch (select("Check the details.:Cancel.")) { - case 1: - mes "This mission is assigned by the Comodo cooperative society. Below are the details."; - next; - mes "Alligators have gone wild these days, they attack women and drunken people who hang out near the beach."; - next; - mes "This is a very shameful situation for us, the most wonderful vacation spot in Rune-Midgard."; - next; - mes "So, it would be very helpful if you hunt 30 Alligators to clean out this situation."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - close; - case 2: - close; - } - } - if (checkquest(3251,HUNTING) == 2) { - mes "I have done pretty well for the mission. Should I report it now?"; - next; - switch (select("Report the mission.:Do not report it yet.")) { - case 1: - getexp 16000,6000; - erasequest 3251; - mes "You have completed the mission. Get rewards."; - close; - case 2: - close; - } - } - case 3: - if (checkquest(3252) <= 0) { - mes "This mission is assigned by an unknown client from Izlude."; - next; - mes "I have admired the beach of Izlude, ever since I was born."; - next; - mes "When I was young, I found a mysterious creature in the Izlude dungeon, I had never seen something like that before..."; - next; - mes "I instantly thought it was a mermaid. I was so supprised, I have studied about mermaids in whole my life."; - next; - mes "But, as I studied harder, I found that the creature was not a mermaid... yes, It wasn't beautiful at all like other mermaids..."; - next; - mes "I finally tracked down the fact that it was a Merman, not a Mermaid!"; - next; - mes "Merman... I have wasted my life studying this monster! So please hunt 30 Mermans to make me feel better."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Izlude 'The Lost dream mermaid' --"; - next; - mes " "; - next; - mes "Would you like to accept this mission?"; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3252; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - if (checkquest(3252,HUNTING) == 1) { - mes "You have an on-going mission. Would you like to check the details?"; - next; - switch (select("Check the details.:Cancel.")) { - case 1: - mes "This mission is assigned by an unknown client from Izlude."; - next; - mes "I have admired the beach of Izlude, ever since I was born."; - next; - mes "When I was young, I found a mysterious creature in the Izlude dungeon, I had never seen something like that before."; - next; - mes "I instantly thought it was a mermaid. I was so supprised, I have studied about mermaids in whole my life."; - next; - mes "But, as I studied harder, I found that the creature was not a mermaid... yes, It wasn't beautiful at all like other mermaids..."; - next; - mes "I finally tracked down the fact that it was a Merman, not a Mermaid!"; - next; - mes " Merman... I have wasted my life studying this monster! So please hunt 30 Mermans to make me feel better."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Izlude 'The Lost dream mermaid' --"; - close; - case 2: - close; - } - } - if (checkquest(3252,HUNTING) == 2) { - mes "I have done pretty well for the mission. Should I report it now?"; - next; - switch (select("Report the mission.:Do not report it yet.")) { - case 1: - getexp 17000,8000; - erasequest 3252; - mes "You have completed the mission. Get rewards."; - close; - case 2: - close; - } - } - case 4: - if (checkquest(3254) <= 0) { - mes "This mission is assigned by the government officer of the Rune-Midgarts Kingdom."; - next; - mes "To prevent a flood in Prontera, we decided to build a huge dam to regulate the water supply."; - next; - mes "But, we are shorthanded on supplies and we need to collect Fine Sand and Grit."; - next; - mes "So, we would like to ask for help. People, please bring us 10 Fine Sand and 30 Grit each so we can build the dam."; - next; - mes "You can get those materials from Sand Man, I wish you good luck!"; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Government officer of the Rune-Midgarts Kingdom, Dufre Kent --"; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3254; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - if ((checkquest(3254) == 1) && (countitem(7043) < 10) && (countitem(1056) < 30)) { - mes "You have an on-going mission. Would you like to check the details?"; - next; - switch (select("Check the details.:Cancel.")) { - case 1: - mes "This mission is assigned by the government officer of the Rune-Midgarts Kingdom."; - next; - mes "To prevent a flood in Prontera, we decided to build a huge dam to regulate the water supply."; - next; - mes "But, we are shorthanded on supplies and we need to collect Fine Sand and Grit."; - next; - mes "So, we would like to ask for help. People, please bring us 10 Fine Sand and 30 Grit each so we can build the dam."; - next; - mes "You can get those materials from Sand Man, I wish you good luck!"; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Government officer of the Rune-Midgarts Kingdom, Dufre Kent --"; - close; - case 2: - close; - } - } - if ((checkquest(3254) == 1) && (countitem(7043) > 9) && (countitem(1056) > 29)) { - mes "I have done pretty well for the mission. Should I report it now?"; - next; - switch (select("Report the mission.:Do not report it yet.")) { - case 1: - delitem 7043,10; //Fine_Sand - delitem 1056,30; //Grit - getexp 18000,8000; - erasequest 3254; - mes "You have completed the mission. Get rewards."; - close; - case 2: - close; - } - } - if (checkquest(3254) == 2) { - mes "This mission is assigned by the government officer of the Rune-Midgarts Kingdom."; - next; - mes "To prevent a flood in Prontera, we decided to build a huge dam to regulate the water supply."; - next; - mes "But, we are shorthanded on supplies and we need to collect Fine Sand and Grit."; - next; - mes "So, we would like to ask for help. People, please bring us 10 Fine Sand and 30 Grit each so we can build the dam."; - next; - mes "You can get those materials from Sand Man, I wish you good luck!"; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Government officer of the Rune-Midgarts Kingdom, Dufre Kent --"; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3254; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - close; + case 1: callsub L_HuntingQuest,3250,15000,5000,930,20; break; + case 2: callsub L_HuntingQuest,3251,16000,6000; break; + case 3: callsub L_HuntingQuest,3252,17000,8000; break; + case 4: callsub L_Quest,3254,18000,8000,7043,10,1056,30; break; } + break; case 2: switch (select("Hunt Wild Boar:Preparing the Summer:A Woman's Grudge:Special ingredients:Puppet Master's Agony")) { - case 1: - if (checkquest(3255) <= 0) { - mes "This mission is assigned by the Payon town hall."; - next; - mes "Wild animals are always annoyances to farmers."; - next; - mes "They attack our farm and ruin whole crops!! We can't stand it anymore!"; - next; - mes "So, we would like to ask for the help from brave adventurers."; - next; - mes "Please, hunt 30 Savages to save our crops!"; - next; - mes "You can easily find those monsters around our town and field."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Payon town hall members --"; - next; - mes " "; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3255; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - if (checkquest(3255,HUNTING) == 1) { - mes "You have an on-going mission. Would you like to check the details?"; - next; - switch (select("Check the details.:Cancel.")) { - case 1: - mes "This mission is assigned by the Payon town hall."; - next; - mes "Wild animals are always an annoyance to farmers."; - next; - mes "They attack our farm and ruin whole crops!! We can't stand it anymore!"; - next; - mes "So, we would like to ask for the help from brave adventurers."; - next; - mes "Please, hunt 30 Savages to save our crops!"; - next; - mes "You can easily find those monsters around our town and field."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Payon town hall members --"; - close; - case 2: - close; - } - } - if (checkquest(3255,HUNTING) == 2) { - mes "I have done pretty well for the mission. Should I report it now?"; - next; - switch (select("Report the mission.:Do not report it yet.")) { - case 1: - getexp 16000,7000; - erasequest 3255; - mes "You have completed the mission. Get rewards."; - close; - case 2: - close; - } - } - case 2: - if (checkquest(3256) <= 0) { - mes "This mission is assigned by the Morroc blacksmith Aragham."; - next; - mes "Hello~~~~, Adventurers! This is Aragham, the hottest blacksmith in Morroc!"; - next; - mes "Anyway, I have a son named Aragam Junior, the cute one. Haha."; - next; - mes "He will be attending summer camp this summer, but he doesn't know how to swim."; - next; - mes "I want to teach him, but as you know I am a blacksmith, a far cry from swimming! Hehe."; - next; - mes "But, I figured that if I make swim fins, it will be great for his confidence~!"; - next; - mes "To make it, I need 30 Sticky Webfoots from a Roda Frog. Can you bring them to me?"; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "PS. Do not compare me with Hollgrehenn or Antonio!!!!"; - next; - mes "-- The hottest blacksmith, Morroc blacksmith Aragham --"; - next; - mes " "; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3256; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - if ((checkquest(3256) == 1) && (countitem(918) < 30)) { - mes "You have an on-going mission. Would you like to check the details?"; - next; - switch (select("Check the details.:Cancel.")) { - case 1: - mes "This mission is assigned by the Morroc blacksmith Aragham."; - next; - mes "Hello~~~~, Adventurers! This is Aragham, the hottest blacksmith in Morroc!"; - next; - mes "Anyway, I have a son named Aragam Junior, the cute one. Haha."; - next; - mes "He will be attending summer camp this summer, but he doesn't know how to swim."; - next; - mes "I want to teach him, but as you know I am a blacksmith, a far cry from swimming! Hehe."; - next; - mes "But, I figured that if I make swim fins, it will be great for his confidence~!"; - next; - mes "To make it, I need 30 Sticky Webfoots from a Roda Frog. Can you bring them to me?"; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "PS. Do not compare me with Hollgrehenn or Antonio!!!!"; - next; - mes "-- The hottest blacksmith, Morroc blacksmith Aragham --"; - close; - case 2: - close; - } - } - if ((checkquest(3256) == 1) && (countitem(918) > 29)) { - mes "I have done pretty well for the mission. Should I report it now?"; - next; - switch (select("Report the mission.:Do not report it yet.")) { - case 1: - delitem 918,30; //Sticky_Webfoot - getexp 15000,5000; - erasequest 3256; - mes "You have completed the mission. Get rewards."; - close; - case 2: - close; - } - } - if (checkquest(3256) == 2) { - mes "This mission is assigned by the Morroc blacksmith Aragham."; - next; - mes "Hello~~~~, Adventurers! This is Aragham, the hottest blacksmith in Morroc!"; - next; - mes "Anyway, I have a son named Aragam Junior, the cute one. Haha."; - next; - mes "He will be attending summer camp this summer, but he doesn't know how to swim."; - next; - mes "I want to teach him, but as you know I am a blacksmith, a far cry from swimming! Hehe."; - next; - mes "But, I figured that if I make swim fins, it will be great for his confidence~!"; - next; - mes "To make it, I need 30 Sticky Webfoots from a Roda Frog. Can you bring them to me?"; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "PS. Do not compare me with Hollgrehenn or Antonio!!!!"; - next; - mes "-- The hottest blacksmith, Morroc blacksmith Aragham --"; - next; - mes " "; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3256; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - close; - case 3: - if (checkquest(3257) <= 0) { - mes "This mission is assigned by an inventor Dorian from Izlude."; - next; - mes "Have you heard the story that if women have a grudge on their mind, it will bring natural disasters."; - next; - mes "Wow, so guys must watch out for those sensitive women! Make sure they don't have any grudges on you."; - next; - mes "Women can bring strange phenomenons with them!"; - next; - mes "I am so intrigued with that story that I'm trying to prove that it can be true."; - next; - mes "So I need to make women upset! Haha, I know what a mean idea, right?"; - next; - mes "But this is seriously just for studying... So please hunt 30 Sohee's who seems to be revived from victimized souls."; - next; - mes "So I can keep observing the case."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Elegance inventor Dorian --"; - next; - mes " "; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3257; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - if (checkquest(3257,HUNTING) == 1) { - mes "You have an on-going mission. Would you like to check the details?"; - next; - switch (select("Check the details.:Cancel.")) { - case 1: - mes "This mission is assigned by an inventor Dorian from Izlude."; - next; - mes "Have you heard the story that if women have a grudge on their mind, it will bring natural disasters."; - next; - mes "Wow, so guys must watch out for those sensitive women! Make sure they don't have any grudges on you."; - next; - mes "Women can bring strange phenomenons with them!"; - next; - mes "I am so intrigued with that story that I'm trying to prove that it can be true."; - next; - mes "So I need to make women upset! Haha, I know what a mean idea, right?"; - next; - mes "But this is seriously just for studying... So please hunt 30 Sohee's who seems to be revived from victimized souls."; - next; - mes "So I can keep observing the case."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Elegance inventor Dorian --"; - close; - case 2: - close; - } - } - if (checkquest(3257,HUNTING) == 2) { - mes "I have done pretty well for the mission. Should I report it now?"; - next; - switch (select("Report the mission.:Do not report it yet.")) { - case 1: - getexp 17000,8000; - erasequest 3257; - mes "You have completed the mission. Get rewards."; - close; - case 2: - close; - } - } - case 4: - if (checkquest(3258) <= 0) { - mes "This mission is assigned by Wallah from Payon."; - next; - mes "Hello, adventurer. How are you? How is your health?"; - next; - mes "I am a pharmacist and I am having a hard time getting special ingredients lately."; - next; - mes "Because I am a little sensitive girl, how can I possibly get those things by myself."; - next; - mes "So, please help me. Just bring 40 Huge Leafs to me, that will be enough to complete my special medicine!"; - next; - mes "Please bring it as soon as possible, people need my medicine."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Wallah --"; - next; - mes " "; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3258; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - if ((checkquest(3258) == 1) && (countitem(7198) < 40)) { - mes "You have an on-going mission. Would you like to check the details?"; - next; - switch (select("Check the details.:Cancel.")) { - case 1: - mes "This mission is assigned by Wallah from Payon."; - next; - mes "Hello, adventurer. How are you? How is your health?"; - next; - mes "I am a pharmacist and I am having a hard time getting special ingredients lately."; - next; - mes "Because I am a little sensitive girl, how can I possibly get those things by myself."; - next; - mes "So, please help me. Just bring 40 Huge Leafs to me, that will be enough to complete my special medicine!"; - next; - mes "Please bring it as soon as possible, people need my medicine."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Wallah --"; - close; - case 2: - close; - } - } - if ((checkquest(3258) == 1) && (countitem(7198) > 39)) { - mes "I have done pretty well for the mission. Should I report it now?"; - next; - switch (select("Report the mission.:Do not report it yet.")) { - case 1: - delitem 7198,40; //Great_Leaf - getexp 16000,7000; - erasequest 3258; - mes "You have completed the mission. Get rewards."; - close; - case 2: - close; - } - } - if (checkquest(3258) == 2) { - mes "This mission is assigned by Wallah from Payon."; - next; - mes "Hello, adventurer. How are you? How is your health?"; - next; - mes "I am a pharmacist and I am having a hard time getting special ingredients lately."; - next; - mes "Because I am a little sensitive girl, how can I possibly get those things by myself."; - next; - mes "So, please help me. Just bring 40 Huge Leafs to me, that will be enough to complete my special medicine!"; - next; - mes "Please bring it as soon as possible, people need my medicine."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Wallah --"; - next; - mes " "; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3258; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - close; - case 5: - if (checkquest(3259) <= 0) { - mes "This mission is assigned by puppet master Woonute from Geffen."; - next; - mes "You know being a puppet master is kind of a hard job to satisfy people."; - next; - mes "People can search and see so many different things on their own thesedays."; - next; - mes "Their expectations are getting high, I can't satisfy them anymore."; - next; - mes "But if I can make new toy concepts, like living toys, it will be ground breaking."; - next; - mes "I heard that there are live dolls called Marionettes. Can you hunt 30 Marionettes for me? And also bring 30 Golden Hair, those will be great materials for the new toys."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Puppet Master Woonute --"; - next; - mes " "; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3259; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - if ((checkquest(3259,HUNTING) == 1) && (countitem(1060) < 30)) { - mes "You have an on-going mission. Would you like to check the details?"; - next; - switch (select("Check the details.:Cancel.")) { - case 1: - mes "This mission is assigned by puppet master Woonute from Geffen."; - next; - mes "You know being a puppet master is kind of a hard job to satisfy people."; - next; - mes "People can search and see so many different things on their own thesedays."; - next; - mes "Their expectations are getting high, I can't satisfy them anymore."; - next; - mes "But if I can make new toy concepts, like living toys, it will be ground breaking."; - next; - mes "I heard that there are live dolls called Marionettes. Can you hunt 30 Marionettes for me? And also bring 30 Golden Hair, those will be great materials for the new toys."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Puppet Master Woonute --"; - close; - case 2: - close; - } - } - if ((checkquest(3259,HUNTING) == 2) && (countitem(1060) > 29)) { - mes "I have done pretty well for the mission. Should I report it now?"; - next; - switch (select("Report the mission.:Do not report it yet.")) { - case 1: - delitem 1060,30; //Golden_Hair - getexp 17000,7000; - erasequest 3259; - mes "You have completed the mission. Get rewards."; - close; - case 2: - close; - } - } + case 1: callsub L_HuntingQuest,3255,16000,7000; break; + case 2: callsub L_Quest,3256,15000,5000,918,30; break; + case 3: callsub L_HuntingQuest,3257,17000,8000; break; + case 4: callsub L_Quest,3258,16000,7000,7198,40; break; + case 5: callsub L_HuntingQuest,3259,17000,7000,1060,30; break; } + break; case 3: switch (select("Tiresome Flies:Dangerous Munak:Make the World green:Magic Wand")) { - case 1: - if (checkquest(3260) <= 0) { - mes "This mission is assigned by an exterminator from Prontera."; - next; - mes "As the weather gets warmer, insects multiply more and more. It is already out of control."; - next; - mes "People in Prontera cannot sleep because of all the bugs in their house."; - next; - mes "So, please help us, hunt 30 Hunter Flies. Then the flies can be reduced slowly."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- The Prontera exterminator --"; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3260; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - if (checkquest(3260,HUNTING) == 1) { - mes "You have an on-going mission. Would you like to check the details?"; - next; - switch (select("Check the details.:Cancel.")) { - case 1: - mes "This mission is assigned by an exterminator from Prontera."; - next; - mes "As the weather gets warmer, insects multiply more and more. It is already out of control."; - next; - mes "People in Prontera cannot sleep because of all the bugs in their house."; - next; - mes "So, please help us, hunt 30 Hunter Flies. Then the flies can be reduced slowly."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- The Prontera exterminator --"; - close; - case 2: - close; - } - } - if (checkquest(3260,HUNTING) == 2) { - mes "I have done pretty well for the mission. Should I report it now?"; - next; - switch (select("Report the mission.:Do not report it yet.")) { - case 1: - getexp 16000,6000; - erasequest 3260; - mes "You have completed the mission. Get rewards."; - close; - case 2: - close; - } - } - case 2: - if (checkquest(3261) <= 0) { - mes "This mission is assigned by Cheese Dongja from Payon."; - next; - mes "Have you heard about Munak?"; - next; - mes "The ugly monster Munak is threatening people in Payon."; - next; - mes "So we need brave adventurers like you!"; - next; - mes "Please hunt 30 Munaks then Payon will be in peace."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "- Payon Cheese Dongja -"; - next; - mes " "; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3261; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - if (checkquest(3261,HUNTING) == 1) { - mes "You have an on-going mission. Would you like to check the details?"; - next; - switch (select("Check the details.:Cancel.")) { - case 1: - mes "This mission is assigned by Cheese Dongja from Payon."; - next; - mes "Have you heard about Munak?"; - next; - mes "The ugly monster Munak is threatening people in Payon."; - next; - mes "So we need brave adventurers like you!"; - next; - mes "Please hunt 30 Munaks then Payon will be in peace."; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "- Payon Cheese Dongja -"; - close; - case 2: - close; - } - } - if (checkquest(3261,HUNTING) == 2) { - mes "I have done pretty well for the mission. Should I report it now?"; - next; - switch (select("Report the mission.:Do not report it yet.")) { - case 1: - getexp 16000,7000; - erasequest 3261; - mes "You have completed the mission. Get rewards."; - close; - case 2: - close; - } - } - case 3: - if (checkquest(3262) <= 0) { - mes "This mission is assigned by a gem dealer, Ibraham from Morroc."; - next; - mes "A small beautiful flower in the barren desert... What an incredible scene it would be!"; - next; - mes "Planting flowers can make the world green and it will be so pretty everywhere."; - next; - mes "I plan to plant strong flowers in the Morroc desert so the soil gets better."; - next; - mes "I need 40 Maneater Blossom from Flora, I know Maneater Blossom is an ugly flower, but still it is a plant."; - next; - mes "I hope you can hunt Flora and get me 40 Maneater Blossoms. You are making the world green! Be proud!"; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Morroc Ibraham --"; - next; - mes " "; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3262; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - if ((checkquest(3262) == 1) && (countitem(1032) < 40)) { - mes "You have an on-going mission. Would you like to check the details?"; - next; - switch (select("Check the details.:Cancel.")) { - case 1: - mes "This mission is assigned by a gem dealer, Ibraham from Morroc."; - next; - mes "A small beautiful flower in the barren desert... What an incredible scene it would be!"; - next; - mes "Planting flowers can make the world green and it will be so pretty everywhere."; - next; - mes "I plan to plant strong flowers in the Morroc desert so the soil gets better."; - next; - mes "I need 40 Maneater Blossom from Flora, I know Maneater Blossom is an ugly flower, but still it is a plant."; - next; - mes "I hope you can hunt Flora and get me 40 Maneater Blossoms. You are making the world green! Be proud!"; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Morroc Ibraham --"; - close; - case 2: - close; - } - } - if ((checkquest(3262) == 1) && (countitem(1032) > 39)) { - mes "I have done pretty well for the mission. Should I report it now?"; - next; - switch (select("Report the mission.:Do not report it yet.")) { - case 1: - delitem 1032,40; //Blossom_Of_Maneater - getexp 17000,7000; - erasequest 3262; - mes "You have completed the mission. Get rewards."; - close; - case 2: - close; - } - } - case 4: - if (checkquest(3263) <= 0) { - mes "This mission is assigned by the Payon blacksmith Antonio."; - next; - mes "Magic wand! Have you heard about it? It is an incredible wand!"; - next; - mes "If you say the magic words and swing the wand, it will make your wishes come true."; - next; - mes "So, I decided to make it by myself. Then I will be rich and powerful~! Haha!!"; - next; - mes "To make the wand, I need some special materials."; - next; - mes "Please bring me 30 Dokebi Horns and 30 Bamboo Cut. If you do so, I will lend you my magic wand once. Haha, good deal?"; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Payon blacksmith Antonio --"; - next; - mes " "; - next; - switch (select("Accept the mission.:Do not accept the mission.")) { - case 1: - if ((BaseLevel > 54) && (BaseLevel < 71)) { - setquest 3263; - mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; - next; - mes "This mission doesn't have time limits."; - close; - } - mes "These missions are not fit for my level. I should look for other missions."; - close; - case 2: - close; - } - } - if ((checkquest(3263) == 1) && ((countitem(1021) < 30) || (countitem(7150) < 30))) { - mes "You have an on-going mission. Would you like to check the details?"; - next; - switch (select("Check the details.:Cancel.")) { - case 1: - mes "This mission is assigned by the Payon blacksmith Antonio."; - next; - mes "Magic wand! Have you heard about it? It is an incredible wand!"; - next; - mes "If you say the magic words and swing the wand, it will make your wishes come true."; - next; - mes "So, I decided to make it by myself. Then I will be rich and powerful~! Haha!!"; - next; - mes "To make the wand, I need some special materials."; - next; - mes "Please bring me 30 Dokebi Horns and 30 Bamboo Cut. If you do so, I will lend you my magic wand once. Haha, good deal?"; - next; - mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; - next; - mes "-- Payon blacksmith Antonio --"; - close; - case 2: - close; - } - } - if ((checkquest(3263) == 1) && (countitem(1021) > 29) && (countitem(7150) > 29)) { - mes "I have done pretty well for the mission. Should I report it now?"; - next; - switch (select("Report the mission.:Do not report it yet.")) { - case 1: - delitem 1021,30; //Dokkaebi_Horn - delitem 7150,30; //Bamboo_Cut - getexp 18000,8000; - erasequest 3263; - mes "You have completed the mission. Get rewards."; - close; - case 2: - close; - } - } + case 1: callsub L_HuntingQuest,3260,16000,6000; break; + case 2: callsub L_HuntingQuest,3261,16000,7000; break; + case 3: callsub L_Quest,3262,17000,7000,1032,40; break; + case 4: callsub L_Quest,3263,18000,8000,1021,30,7150,30; break; } + break; + } + close; + +L_Quest: + if (checkquest(getarg(0)) <= 0) { + callsub L_CheckDetails, getarg(0); + mes " "; + next; + mes "Would you like to accept this mission?"; + next; + if(select("Accept the mission.:Do not accept the mission.") == 2) { + setquest getarg(0); + mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; + next; + mes "This mission doesn't have time limits."; } } - mes "To get these missions, I need to Join the Eden Group first. I must find Secretary Lime Evenor and become a member."; + else if ((checkquest(getarg(0)) == 1) && (countitem(getarg(3)) < getarg(4)) && (countitem(getarg(5,0)) < getarg(6,1))){ + mes "You have an on-going mission. Would you like to check the details?"; + next; + if(select("Check the details.:Cancel.") == 2) { close; } + callsub L_CheckDetails, getarg(0); + } + else if ((checkquest(getarg(0)) == 1) && (countitem(getarg(3)) >= getarg(4)) && (countitem(getarg(5,0)) >= getarg(6,0))){ + mes "I have done pretty well for the mission. Should I report it now?"; + next; + if(select("Report the mission.:Do not report it yet.") == 2) { close; } + delitem getarg(3),getarg(4); + if (getarg(5,0) > 0) { delitem getarg(5),getarg(6); } + getexp getarg(1),getarg(2); + erasequest getarg(0); + mes "You have completed the mission. Get rewards."; + } close; + +L_HuntingQuest: + if (checkquest(getarg(0)) <= 0) { + callsub L_CheckDetails, getarg(0); + mes " "; + next; + mes "Would you like to accept this mission?"; + next; + if(select("Accept the mission.:Do not accept the mission.") == 2) { + setquest getarg(0); + mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; + next; + mes "This mission doesn't have time limits."; + } + } + else if (checkquest(getarg(0),HUNTING) == 1) { + mes "You have an on-going mission. Would you like to check the details?"; + next; + if(select("Check the details.:Cancel.") == 2) { close; } + callsub L_CheckDetails, getarg(0); + } + else if (checkquest(getarg(0),HUNTING) == 2) { + if (getarg(3,0)){ + if (countitem(getarg(3)) < getarg(4)) { + mes "I don't have enough "+getitemname(getarg(3))+"."; + mes "I need to gather "+getarg(4)+" "+getitemname(getarg(3))+" to complete this mission."; + close; + } + } + mes "I have done pretty well for the mission. Should I report it now?"; + next; + if(select("Report the mission.:Do not report it yet.") == 2) { close; } + if (getarg(3,0) > 0) { delitem getarg(3),getarg(4); } + getexp getarg(1),getarg(2); + erasequest getarg(0); + mes "You have completed the mission. Get rewards."; + } + close; + +L_CheckDetails: + switch(getarg(0)){ + case 3250: + mes "This mission is assigned by the Rekenber corporation from Lighthalzen. Below are the details."; + next; + mes "Rekenber corporation is about to launch a new project called 'Green Medical Center'. For the first product of the project, we are preparing well-being Bandages."; + next; + mes "Regarding the project, we need to research monster's reactions when they are wrapped with Rotten Bandages."; + next; + mes "If you are interested, please hunt 30 Mummies and bring 30 Rotten Bandages. You can find them in the Pyramid West of Morroc."; + next; + mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; + next; + mes "- Rekenber corporation chief director 'Julie E Delph' -"; + break; + case 3251: + mes "This mission is assigned by the Comodo cooperative society. Below are the details."; + next; + mes "Alligators have gone wild these days, they attack women and drunken people who hang out near the beach."; + next; + mes "This is a very shameful situation for us, the most wonderful vacation spot in Rune-Midgard."; + next; + mes "So, it would be very helpful if you hunt 30 Alligators to clean out this situation."; + next; + mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; + break; + case 3252: + mes "This mission is assigned by an unknown client from Izlude."; + next; + mes "I have admired the beach of Izlude, ever since I was born."; + next; + mes "When I was young, I found a mysterious creature in the Izlude dungeon, I had never seen something like that before..."; + next; + mes "I instantly thought it was a mermaid. I was so supprised, I have studied about mermaids in whole my life."; + next; + mes "But, as I studied harder, I found that the creature was not a mermaid... yes, It wasn't beautiful at all like other mermaids..."; + next; + mes "I finally tracked down the fact that it was a Merman, not a Mermaid!"; + next; + mes "Merman... I have wasted my life studying this monster! So please hunt 30 Mermans to make me feel better."; + next; + mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; + next; + mes "-- Izlude 'The Lost dream mermaid' --"; + break; + case 3254: + mes "This mission is assigned by the government officer of the Rune-Midgarts Kingdom."; + next; + mes "To prevent a flood in Prontera, we decided to build a huge dam to regulate the water supply."; + next; + mes "But, we are shorthanded on supplies and we need to collect Fine Sand and Grit."; + next; + mes "So, we would like to ask for help. People, please bring us 10 Fine Sand and 30 Grit each so we can build the dam."; + next; + mes "You can get those materials from Sand Man, I wish you good luck!"; + next; + mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; + next; + mes "-- Government officer of the Rune-Midgarts Kingdom, Dufre Kent --"; + break; + case 3255: + mes "This mission is assigned by the Payon town hall."; + next; + mes "Wild animals are always an annoyance to farmers."; + next; + mes "They attack our farm and ruin whole crops!! We can't stand it anymore!"; + next; + mes "So, we would like to ask for the help from brave adventurers."; + next; + mes "Please, hunt 30 Savages to save our crops!"; + next; + mes "You can easily find those monsters around our town and field."; + next; + mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; + next; + mes "-- Payon town hall members --"; + break; + case 3256: + mes "This mission is assigned by the Morroc blacksmith Aragham."; + next; + mes "Hello~~~~, Adventurers! This is Aragham, the hottest blacksmith in Morroc!"; + next; + mes "Anyway, I have a son named Aragam Junior, the cute one. Haha."; + next; + mes "He will be attending summer camp this summer, but he doesn't know how to swim."; + next; + mes "I want to teach him, but as you know I am a blacksmith, a far cry from swimming! Hehe."; + next; + mes "But, I figured that if I make swim fins, it will be great for his confidence~!"; + next; + mes "To make it, I need 30 Sticky Webfoots from a Roda Frog. Can you bring them to me?"; + next; + mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; + next; + mes "PS. Do not compare me with Hollgrehenn or Antonio!!!!"; + next; + mes "-- The hottest blacksmith, Morroc blacksmith Aragham --"; + break; + case 3257: + mes "This mission is assigned by an inventor Dorian from Izlude."; + next; + mes "Have you heard the story that if women have a grudge on their mind, it will bring natural disasters."; + next; + mes "Wow, so guys must watch out for those sensitive women! Make sure they don't have any grudges on you."; + next; + mes "Women can bring strange phenomenons with them!"; + next; + mes "I am so intrigued with that story that I'm trying to prove that it can be true."; + next; + mes "So I need to make women upset! Haha, I know what a mean idea, right?"; + next; + mes "But this is seriously just for studying... So please hunt 30 Sohee's who seems to be revived from victimized souls."; + next; + mes "So I can keep observing the case."; + next; + mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; + next; + mes "-- Elegance inventor Dorian --"; + break; + case 3258: + mes "This mission is assigned by Wallah from Payon."; + next; + mes "Hello, adventurer. How are you? How is your health?"; + next; + mes "I am a pharmacist and I am having a hard time getting special ingredients lately."; + next; + mes "Because I am a little sensitive girl, how can I possibly get those things by myself."; + next; + mes "So, please help me. Just bring 40 Huge Leafs to me, that will be enough to complete my special medicine!"; + next; + mes "Please bring it as soon as possible, people need my medicine."; + next; + mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; + next; + mes "-- Wallah --"; + break; + case 3259: + mes "This mission is assigned by puppet master Woonute from Geffen."; + next; + mes "You know being a puppet master is kind of a hard job to satisfy people."; + next; + mes "People can search and see so many different things on their own thesedays."; + next; + mes "Their expectations are getting high, I can't satisfy them anymore."; + next; + mes "But if I can make new toy concepts, like living toys, it will be ground breaking."; + next; + mes "I heard that there are live dolls called Marionettes. Can you hunt 30 Marionettes for me? And also bring 30 Golden Hair, those will be great materials for the new toys."; + next; + mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; + next; + mes "-- Puppet Master Woonute --"; + break; + case 3260: + mes "This mission is assigned by an exterminator from Prontera."; + next; + mes "As the weather gets warmer, insects multiply more and more. It is already out of control."; + next; + mes "People in Prontera cannot sleep because of all the bugs in their house."; + next; + mes "So, please help us, hunt 30 Hunter Flies. Then the flies can be reduced slowly."; + next; + mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; + next; + mes "-- The Prontera exterminator --"; + break; + case 3261: + mes "This mission is assigned by Cheese Dongja from Payon."; + next; + mes "Have you heard about Munak?"; + next; + mes "The ugly monster Munak is threatening people in Payon."; + next; + mes "So we need brave adventurers like you!"; + next; + mes "Please hunt 30 Munaks then Payon will be in peace."; + next; + mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; + next; + mes "- Payon Cheese Dongja -"; + break; + case 3262: + mes "This mission is assigned by a gem dealer, Ibraham from Morroc."; + next; + mes "A small beautiful flower in the barren desert... What an incredible scene it would be!"; + next; + mes "Planting flowers can make the world green and it will be so pretty everywhere."; + next; + mes "I plan to plant strong flowers in the Morroc desert so the soil gets better."; + next; + mes "I need 40 Maneater Blossom from Flora, I know Maneater Blossom is an ugly flower, but still it is a plant."; + next; + mes "I hope you can hunt Flora and get me 40 Maneater Blossoms. You are making the world green! Be proud!"; + next; + mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; + next; + mes "-- Morroc Ibraham --"; + break; + case 3263: + mes "This mission is assigned by the Payon blacksmith Antonio."; + next; + mes "Magic wand! Have you heard about it? It is an incredible wand!"; + next; + mes "If you say the magic words and swing the wand, it will make your wishes come true."; + next; + mes "So, I decided to make it by myself. Then I will be rich and powerful~! Haha!!"; + next; + mes "To make the wand, I need some special materials."; + next; + mes "Please bring me 30 Dokebi Horns and 30 Bamboo Cut. If you do so, I will lend you my magic wand once. Haha, good deal?"; + next; + mes "Please confirm it to us after you complete the mission, then we will give you proper rewards."; + next; + mes "-- Payon blacksmith Antonio --"; + break; + } + next; + return; } -- cgit v1.2.3-70-g09d2 From bcc26308706af5ac48953ad3904c9886752aafa2 Mon Sep 17 00:00:00 2001 From: Sirius Date: Sun, 26 May 2013 13:11:43 -0700 Subject: Fixed a not intended NPC name in the last commit. --- npc/re/quests/eden/56-70.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npc/re/quests/eden/56-70.txt b/npc/re/quests/eden/56-70.txt index c735bde2a..95b62955d 100644 --- a/npc/re/quests/eden/56-70.txt +++ b/npc/re/quests/eden/56-70.txt @@ -15,7 +15,7 @@ //= 2.0 Optimised [Zopokx] //============================================================ -moc_para01,42,38,3 script MisiĆ³n [56 - 70] 857,{ +moc_para01,42,38,3 script Mission [56 - 70] 857,{ if (countitem(6219) < 1) { mes "To get these missions, I need to Join the Eden Group first. I must find Secretary Lime Evenor and become a member."; close; -- cgit v1.2.3-70-g09d2 From f68d0c0b7c7c2285c03d9546ecf7121be3b3875c Mon Sep 17 00:00:00 2001 From: Sirius Date: Sun, 26 May 2013 16:43:46 -0700 Subject: Thanks to Euphy for pointing out a problem with the level check that shouldn't be at beginning of the script. --- npc/re/quests/eden/56-70.txt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/npc/re/quests/eden/56-70.txt b/npc/re/quests/eden/56-70.txt index 95b62955d..4bf3f9863 100644 --- a/npc/re/quests/eden/56-70.txt +++ b/npc/re/quests/eden/56-70.txt @@ -20,10 +20,6 @@ moc_para01,42,38,3 script Mission [56 - 70] 857,{ mes "To get these missions, I need to Join the Eden Group first. I must find Secretary Lime Evenor and become a member."; close; } - if ((BaseLevel < 56) && (BaseLevel > 70)) { - mes "These missions are not fit for my level. I should look for other missions."; - close; - } mes "Here is the list of various adventures for level 56~70 adventurers."; next; mes "Lots of missions such as a Monster Hunting, Delivery Goods, Finding People."; @@ -65,6 +61,10 @@ L_Quest: mes "Would you like to accept this mission?"; next; if(select("Accept the mission.:Do not accept the mission.") == 2) { + if ((BaseLevel < 56) && (BaseLevel > 70)) { + mes "These missions are not fit for my level. I should look for other missions."; + close; + } setquest getarg(0); mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; next; @@ -97,6 +97,10 @@ L_HuntingQuest: mes "Would you like to accept this mission?"; next; if(select("Accept the mission.:Do not accept the mission.") == 2) { + if ((BaseLevel < 56) && (BaseLevel > 70)) { + mes "These missions are not fit for my level. I should look for other missions."; + close; + } setquest getarg(0); mes "I have successfully accepted the mission. I have to come back and confirm my work after I complete the mission."; next; -- cgit v1.2.3-70-g09d2 From 8bc266493d752703735b5d29b89247c746255ccf Mon Sep 17 00:00:00 2001 From: Sirius Date: Sun, 26 May 2013 17:45:43 -0700 Subject: Argh! I hate the fact of having several repositories. Thanks again, Euphy! --- npc/re/quests/eden/56-70.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/npc/re/quests/eden/56-70.txt b/npc/re/quests/eden/56-70.txt index 4bf3f9863..02e66d452 100644 --- a/npc/re/quests/eden/56-70.txt +++ b/npc/re/quests/eden/56-70.txt @@ -61,7 +61,7 @@ L_Quest: mes "Would you like to accept this mission?"; next; if(select("Accept the mission.:Do not accept the mission.") == 2) { - if ((BaseLevel < 56) && (BaseLevel > 70)) { + if ((BaseLevel < 56) || (BaseLevel > 70)) { mes "These missions are not fit for my level. I should look for other missions."; close; } @@ -97,7 +97,7 @@ L_HuntingQuest: mes "Would you like to accept this mission?"; next; if(select("Accept the mission.:Do not accept the mission.") == 2) { - if ((BaseLevel < 56) && (BaseLevel > 70)) { + if ((BaseLevel < 56) || (BaseLevel > 70)) { mes "These missions are not fit for my level. I should look for other missions."; close; } -- cgit v1.2.3-70-g09d2 From 810f6e7c0ae4e4353eeeefb5c6d670ecd0ca27cd Mon Sep 17 00:00:00 2001 From: Sirius Date: Mon, 27 May 2013 01:54:58 -0700 Subject: I didn't notice this errors before. --- db/quest_db.txt | 2 +- npc/re/quests/eden/56-70.txt | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/db/quest_db.txt b/db/quest_db.txt index dc3b87d2d..ad5af4472 100644 --- a/db/quest_db.txt +++ b/db/quest_db.txt @@ -419,7 +419,7 @@ 3256,0,0,0,0,0,0,0,"Request - Ready for waiting summer" 3257,0,1170,30,0,0,0,0,"Request - A grudge of women" 3258,0,0,0,0,0,0,0,"Request - A material of delicacy" -3259,0,1143,30,0,0,0,0,"Request - A agony of a doll maste" +3259,0,1143,30,0,0,0,0,"Request - A agony of a doll master" 3260,0,1035,30,0,0,0,0,"Request - Tiresome flies" 3261,0,1026,30,0,0,0,0,"Request - Unclean girl" 3262,0,0,0,0,0,0,0,"Request - Queer hobby" diff --git a/npc/re/quests/eden/56-70.txt b/npc/re/quests/eden/56-70.txt index 02e66d452..12beeae26 100644 --- a/npc/re/quests/eden/56-70.txt +++ b/npc/re/quests/eden/56-70.txt @@ -27,31 +27,31 @@ moc_para01,42,38,3 script Mission [56 - 70] 857,{ switch (select("Mission Numbers 1~5:Mission Numbers 6~10:Mission Numbers 11~15")) { case 1: switch (select("What is this Bandage?:Dangerous Alligators.:That wasn't a mermaid...:My country is calling me!")) { - case 1: callsub L_HuntingQuest,3250,15000,5000,930,20; break; - case 2: callsub L_HuntingQuest,3251,16000,6000; break; - case 3: callsub L_HuntingQuest,3252,17000,8000; break; - case 4: callsub L_Quest,3254,18000,8000,7043,10,1056,30; break; + case 1: callsub L_HuntingQuest,3250,15000,5000,930,30; + case 2: callsub L_HuntingQuest,3251,16000,6000; + case 3: callsub L_HuntingQuest,3252,17000,8000; + case 4: callsub L_Quest,3254,18000,8000,7043,10,1056,30; } break; case 2: switch (select("Hunt Wild Boar:Preparing the Summer:A Woman's Grudge:Special ingredients:Puppet Master's Agony")) { - case 1: callsub L_HuntingQuest,3255,16000,7000; break; - case 2: callsub L_Quest,3256,15000,5000,918,30; break; - case 3: callsub L_HuntingQuest,3257,17000,8000; break; - case 4: callsub L_Quest,3258,16000,7000,7198,40; break; - case 5: callsub L_HuntingQuest,3259,17000,7000,1060,30; break; + case 1: callsub L_HuntingQuest,3255,16000,7000; + case 2: callsub L_Quest,3256,15000,5000,918,30; + case 3: callsub L_HuntingQuest,3257,17000,8000; + case 4: callsub L_Quest,3258,16000,7000,7198,40; + case 5: callsub L_HuntingQuest,3259,17000,7000,1060,30; } break; case 3: switch (select("Tiresome Flies:Dangerous Munak:Make the World green:Magic Wand")) { - case 1: callsub L_HuntingQuest,3260,16000,6000; break; - case 2: callsub L_HuntingQuest,3261,16000,7000; break; - case 3: callsub L_Quest,3262,17000,7000,1032,40; break; - case 4: callsub L_Quest,3263,18000,8000,1021,30,7150,30; break; + case 1: callsub L_HuntingQuest,3260,16000,6000; + case 2: callsub L_HuntingQuest,3261,16000,7000; + case 3: callsub L_Quest,3262,17000,7000,1032,40; + case 4: callsub L_Quest,3263,18000,8000,1021,30,7150,30; } break; } - close; + end; L_Quest: if (checkquest(getarg(0)) <= 0) { @@ -60,7 +60,7 @@ L_Quest: next; mes "Would you like to accept this mission?"; next; - if(select("Accept the mission.:Do not accept the mission.") == 2) { + if(select("Accept the mission.:Do not accept the mission.") == 1) { if ((BaseLevel < 56) || (BaseLevel > 70)) { mes "These missions are not fit for my level. I should look for other missions."; close; @@ -194,7 +194,7 @@ L_CheckDetails: case 3255: mes "This mission is assigned by the Payon town hall."; next; - mes "Wild animals are always an annoyance to farmers."; + mes "Wild animals are always annoyances to farmers."; next; mes "They attack our farm and ruin whole crops!! We can't stand it anymore!"; next; -- cgit v1.2.3-70-g09d2 From f7fa80ee689635a01c3c137f7a0611b210cc8ae0 Mon Sep 17 00:00:00 2001 From: Sirius Date: Tue, 28 May 2013 02:34:56 -0700 Subject: Fixed console error using Euphy's reference. --- npc/re/quests/eden/56-70.txt | 80 ++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/npc/re/quests/eden/56-70.txt b/npc/re/quests/eden/56-70.txt index 12beeae26..c503a274b 100644 --- a/npc/re/quests/eden/56-70.txt +++ b/npc/re/quests/eden/56-70.txt @@ -3,7 +3,7 @@ //===== By: ================================================== //= L0ne_W0lf //===== Current Version: ===================================== -//= 2.0 +//= 2.1 //===== Description: ========================================= //= Repetable Quests for Players between Baselevel 56 - 70. //===== Additional Comments: ================================= @@ -13,6 +13,7 @@ //= 1.3 Fixed Puppet Master's Agony Quest (12217 -> 3259). [Joseph] //= 1.4 Fixed invalid check (Magic Wand Quest). [Joseph] //= 2.0 Optimised [Zopokx] +//= 2.1 Fixed some errors using Euphy's reference [Zopokx] //============================================================ moc_para01,42,38,3 script Mission [56 - 70] 857,{ @@ -70,33 +71,44 @@ L_Quest: next; mes "This mission doesn't have time limits."; } + close; } - else if ((checkquest(getarg(0)) == 1) && (countitem(getarg(3)) < getarg(4)) && (countitem(getarg(5,0)) < getarg(6,1))){ - mes "You have an on-going mission. Would you like to check the details?"; - next; - if(select("Check the details.:Cancel.") == 2) { close; } - callsub L_CheckDetails, getarg(0); - } - else if ((checkquest(getarg(0)) == 1) && (countitem(getarg(3)) >= getarg(4)) && (countitem(getarg(5,0)) >= getarg(6,0))){ - mes "I have done pretty well for the mission. Should I report it now?"; - next; - if(select("Report the mission.:Do not report it yet.") == 2) { close; } - delitem getarg(3),getarg(4); - if (getarg(5,0) > 0) { delitem getarg(5),getarg(6); } - getexp getarg(1),getarg(2); - erasequest getarg(0); - mes "You have completed the mission. Get rewards."; + if (checkquest(getarg(0)) == 1) { + if (getargcount() > 5) { + if ((countitem(getarg(3)) >= getarg(4)) && (countitem(getarg(5)) >= getarg(6))) { set .@complete, 1; } + else { set .@complete, 0; } + } else { + if (countitem(getarg(3)) >= getarg(4)) { set .@complete, 1; } + else { set .@complete, 0; } + } + if (.@complete) { + mes "I have done pretty well for the mission. Should I report it now?"; + next; + if(select("Report the mission.:Do not report it yet.") == 2) { close; } + delitem getarg(3),getarg(4); + if (getarg(5,0) > 0) { delitem getarg(5),getarg(6); } + getexp getarg(1),getarg(2); + erasequest getarg(0); + mes "You have completed the mission. Get rewards."; + } else { + mes "You have an on-going mission. Would you like to check the details?"; + next; + if(select("Check the details.:Cancel.") == 1) + callsub L_CheckDetails, getarg(0); + } } close; + end; L_HuntingQuest: if (checkquest(getarg(0)) <= 0) { callsub L_CheckDetails, getarg(0); + next; mes " "; next; mes "Would you like to accept this mission?"; next; - if(select("Accept the mission.:Do not accept the mission.") == 2) { + if(select("Accept the mission.:Do not accept the mission.") == 1) { if ((BaseLevel < 56) || (BaseLevel > 70)) { mes "These missions are not fit for my level. I should look for other missions."; close; @@ -110,26 +122,29 @@ L_HuntingQuest: else if (checkquest(getarg(0),HUNTING) == 1) { mes "You have an on-going mission. Would you like to check the details?"; next; - if(select("Check the details.:Cancel.") == 2) { close; } - callsub L_CheckDetails, getarg(0); + if(select("Check the details.:Cancel.") == 1) + callsub L_CheckDetails, getarg(0); } else if (checkquest(getarg(0),HUNTING) == 2) { - if (getarg(3,0)){ - if (countitem(getarg(3)) < getarg(4)) { - mes "I don't have enough "+getitemname(getarg(3))+"."; - mes "I need to gather "+getarg(4)+" "+getitemname(getarg(3))+" to complete this mission."; - close; - } + if (getargcount() > 3) { + if (countitem(getarg(3)) >= getarg(4)) { set .@complete, 1; } + else { set .@complete, 0; } + } else { set .@complete, 1; } + if (.@complete) { + mes "I have done pretty well for the mission. Should I report it now?"; + next; + if(select("Report the mission.:Do not report it yet.") == 2) { close; } + if (getarg(3,0) > 0) { delitem getarg(3),getarg(4); } + getexp getarg(1),getarg(2); + erasequest getarg(0); + mes "You have completed the mission. Get rewards."; + } else { + mes "I don't have enough "+getitemname(getarg(3))+"."; + mes "I need to gather "+getarg(4)+" "+getitemname(getarg(3))+" to complete this mission."; } - mes "I have done pretty well for the mission. Should I report it now?"; - next; - if(select("Report the mission.:Do not report it yet.") == 2) { close; } - if (getarg(3,0) > 0) { delitem getarg(3),getarg(4); } - getexp getarg(1),getarg(2); - erasequest getarg(0); - mes "You have completed the mission. Get rewards."; } close; + end; L_CheckDetails: switch(getarg(0)){ @@ -347,6 +362,5 @@ L_CheckDetails: mes "-- Payon blacksmith Antonio --"; break; } - next; return; } -- cgit v1.2.3-70-g09d2 From 156c500bd24fe2bc11eefad5cfd9df128c6903cd Mon Sep 17 00:00:00 2001 From: Mysteries Date: Tue, 28 May 2013 20:02:30 -0400 Subject: Follow up to 0e798b4 Readded Compatibility --- npc/re/quests/quests_dicastes.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/npc/re/quests/quests_dicastes.txt b/npc/re/quests/quests_dicastes.txt index 0e114b97c..20320b078 100644 --- a/npc/re/quests/quests_dicastes.txt +++ b/npc/re/quests/quests_dicastes.txt @@ -1,9 +1,11 @@ -//===== Hercules Script ======================================= +//===== Hercules Script ====================================== //= El Dicastes Quest NPCs //===== By: ================================================== //= Gennosuke Kouga, Muad_Dib //===== Current Version: ===================================== //= 1.9a +//===== Compatible With: ===================================== +//= Hercules //===== Description: ========================================= //= Quest NPCs related to Dewata: //== Sapha's Visit, Doha's Secrect Order, Frede's Request, -- cgit v1.2.3-70-g09d2 From bd12ba5d760d9055a210e111c52f5f77ca9a8ae8 Mon Sep 17 00:00:00 2001 From: CairoLee Date: Wed, 29 May 2013 20:20:24 +0800 Subject: - remove malaya.txt from npc/scripts.conf --- npc/scripts.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/npc/scripts.conf b/npc/scripts.conf index 91c2028b1..65cfe53f5 100644 --- a/npc/scripts.conf +++ b/npc/scripts.conf @@ -51,7 +51,6 @@ npc: npc/cities/jawaii.txt npc: npc/cities/lighthalzen.txt npc: npc/cities/louyang.txt npc: npc/cities/lutie.txt -npc: npc/cities/malaya.txt npc: npc/cities/manuk.txt npc: npc/cities/morocc.txt npc: npc/cities/moscovia.txt -- cgit v1.2.3-70-g09d2 From b30c74a7733848f03e5defc238dca0e0cb044470 Mon Sep 17 00:00:00 2001 From: j-tkay Date: Thu, 30 May 2013 16:29:07 +0800 Subject: Reverted Novice Ground to 953aabf5a650d4eef506c1e620d81405f56863b6. Signed-off-by: j-tkay --- npc/jobs/novice/novice.txt | 76 -- npc/re/jobs/novice/novice.txt | 2053 ++++++++++++++++++++++++++++++++++++++++- npc/scripts_jobs.conf | 1 - 3 files changed, 2046 insertions(+), 84 deletions(-) delete mode 100644 npc/jobs/novice/novice.txt diff --git a/npc/jobs/novice/novice.txt b/npc/jobs/novice/novice.txt deleted file mode 100644 index 755cc2bbb..000000000 --- a/npc/jobs/novice/novice.txt +++ /dev/null @@ -1,76 +0,0 @@ -//===== Hercules Script ======================================= -//= New Novice Training Grounds -//===== By: ================================================== -//= Streusel -//===== Current Version: ===================================== -//= 1.0 -//===== Compatible With: ===================================== -//= Hercules -//===== Description: ========================================= -//= New Novice Training Grounds -//= [Hand Scripted (No Programs or AEGIS Scripts)] -//===== Additional Comments: ================================= -//= 1.0 First version. [Streusel] -//= Credits to whoever made Sprakki. -//============================================================ - -// Sprakki (Stard of Novice Training Ground, Outside Castle) -//============================================================ -- script ::Captain_Carew -1,{ - if(job_novice_q < 1) { - mes "[Captain Carew]"; - mes "Hello there! Welcome to the World of Ragnarok Online. My name is Captain Carew and I'm in charge of giving you basic gameplay tips."; - mes "Click on the [Next] button or press [Enter] to continue."; - next; - mes "[Captain Carew]"; - mes "First you need to learn the very basics of controlling your character."; - mes "All the basic ^4A4AFFmoves, selection of items, and attacks^000000 use the ^4A4AFFleft click of the mouse^000000."; - next; - cutin "tutorial01",3; - mes "-! Info !-"; - mes "Click on the ground to move the character."; - mes "Attacking monsters and conversations with the people of this world can be done by simply clicking on them."; - next; - cutin "",255; - mes "[Captain Carew]"; - mes "First off, try moving around."; - mes "Do you see that wooden bridge to the right?"; - next; - setquest 7117; - set job_novice_q,1; - mes "[Captain Carew]"; - mes "Walk over that bridge and there's a castle used as the Training Center."; - mes "I will be waiting for you inside of that Castle. Please come to the castle by yourself."; - next; - cutin "tutorial02",3; - mes "-! Info !-"; - mes "You've received a quest from Sprakki."; - mes "You can check the contents of the quest in the Quest Info Window."; - next; - mes "[Captain Carew]"; - mes "I will wait inside the Training Center across the bridge."; - next; - mes "-! Info !-"; - mes "You can open the Quest Info Window by pressing the ^4A4AFFALT + U^000000 keys at the same time."; - next; - cutin "",255; - mes "[Captain Carew]"; - mes "Have you checked the Quest Info Window?"; - mes "I'll be waiting in the castle across the bridge."; - close; - } - mes "[Carew]"; - mes "I'm not sure what's happening, I'm very shy."; - mes "Meet me in Izlude again."; - mes ""; - next; - mes "[Carew]"; - mes "I'm now heading to the local harbor of Izlude."; - mes "Now, sleep unti we arrive."; - close; -} - -//Official view id 639 -iz_int01,91,81,4 script ::Rumin 99,{ -end; -} diff --git a/npc/re/jobs/novice/novice.txt b/npc/re/jobs/novice/novice.txt index 8d29ce2cc..ebefaff48 100644 --- a/npc/re/jobs/novice/novice.txt +++ b/npc/re/jobs/novice/novice.txt @@ -1,17 +1,2056 @@ -//===== Hercules Script ======================================= +//===== rAthena Script ======================================= //= New Novice Training Grounds //===== By: ================================================== -//= Streusel +//= Kisuka //===== Current Version: ===================================== -//= 1.0 +//= 1.4a //===== Compatible With: ===================================== -//= Hercules +//= rAthena SVN //===== Description: ========================================= //= New Novice Training Grounds //= [Hand Scripted (No Programs or AEGIS Scripts)] //===== Additional Comments: ================================= -//= 1.0 First version. [Streusel] +//= 1.0 First version. [Kisuka] +//= 1.1 Updated warps, savepoints, NPC locations. [Kisuka] +//= 1.2 Cleaning. [Euphy] +//= 1.3 Fixed Eden Group Officer's level requirement. [Joseph] +//= 1.4 Fixed checkquest to check quest accordingly. [Joseph] +//= 1.4a Added 'npcskill' command. [Euphy] //============================================================ -iz_int01,100,91,4 duplicate(Captain_Carew) Captain Carew#iz_int 873 -iz_int01,91,81,4 duplicate(Rumin) Rumin#iz_int01 99 \ No newline at end of file +// Sprakki (Stard of Novice Training Ground, Outside Castle) +//============================================================ +new_1-1,53,114,4 script Sprakki#nv1 90,{ + if(job_novice_q < 1) { + mes "[Sprakki]"; + mes "Hello there! Welcome to the World of Ragnarok Online. My name is Sprakki and I'm in charge of giving you basic gameplay tips."; + mes "Click on the [Next] button or press [Enter] to continue."; + next; + mes "[Sprakki]"; + mes "First you need to learn the very basics of controlling your character."; + mes "All the basic ^4A4AFFmoves, selection of items, and attacks^000000 use the ^4A4AFFleft click of the mouse^000000."; + next; + cutin "tutorial01",3; + mes "-! Info !-"; + mes "Click on the ground to move the character."; + mes "Attacking monsters and conversations with the people of this world can be done by simply clicking on them."; + next; + cutin "",255; + mes "[Sprakki]"; + mes "First off, try moving around."; + mes "Do you see that wooden bridge to the right?"; + next; + setquest 7117; + set job_novice_q,1; + mes "[Sprakki]"; + mes "Walk over that bridge and there's a castle used as the Training Center."; + mes "I will be waiting for you inside of that Castle. Please come to the castle by yourself."; + next; + cutin "tutorial02",3; + mes "-! Info !-"; + mes "You've received a quest from Sprakki."; + mes "You can check the contents of the quest in the Quest Info Window."; + next; + mes "[Sprakki]"; + mes "I will wait inside the Training Center across the bridge."; + next; + mes "-! Info !-"; + mes "You can open the Quest Info Window by pressing the ^4A4AFFALT + U^000000 keys at the same time."; + next; + cutin "",255; + mes "[Sprakki]"; + mes "Have you checked the Quest Info Window?"; + mes "I'll be waiting in the castle across the bridge."; + close; + } + mes "[Sprakki]"; + mes "I will be waiting for you across the Bridge to the east."; + close; +} + +// Sprakki (Inside Castle) +//============================================================ +new_1-2,100,29,4 script Sprakki#nv2 90,{ + if(job_novice_q < 1) { + mes "[Sprakki]"; + mes "Hello there! Welcome to the World of Ragnarok Online. My name is Sprakki and I'm in charge of giving you basic gameplay tips."; + mes "Click on the [Next] button or press [Enter] to continue."; + next; + mes "[Sprakki]"; + mes "First you need to learn the very basics of controlling your character."; + mes "All the basic ^4A4AFFmoves, selection of items, and attacks^000000 use the ^4A4AFFleft click of the mouse^000000."; + next; + cutin "tutorial01",3; + mes "-! Info !-"; + mes "Click on the ground to move the character."; + mes "Attacking monsters and conversations with the people of this world can be done by simply clicking on them."; + next; + cutin "",255; + setquest 7117; + set job_novice_q,1; + mes "[Sprakki]"; + mes "Well then, I will give you a quest to talk to me."; + mes "After the conversation is over, talk to me again by left-clicking on me."; + next; + cutin "tutorial02",3; + mes "-! Info !-"; + mes "You've received a quest from Sprakki."; + mes "You can check the contents of the quest in the Quest Info Window by pressing the ^4A4AFFAlt + U^000000 keys at the same time."; + next; + cutin "",255; + mes "[Sprakki]"; + mes "Have you checked the Quest Info Window?"; + mes "Well, talk to me again."; + close; + } + if(job_novice_q == 1) { + getexp 300,0; + getexp 300,5; + completequest 7117; + set job_novice_q,2; + mes "[Sprakki]"; + mes "Great!"; + mes "Now you know how to move and talk to others, right?"; + next; + } + mes "[Sprakki]"; + mes "The training Center is prepared for novices just like you."; + mes "You are going to be trained to get used to the basics of the Game."; + next; + select("Begin Training."); + mes "[Sprakki]"; + mes "I will guide you to the Novice Training Center."; + mes "Inside, Instructor 'Brade' will be waiting to speak to you."; + next; + setquest 7118; + set job_novice_q,3; + mes "[Sprakki]"; + mes "Instructor 'Brade' will help you afterwards."; + mes "Please, Go see him."; + next; + mes "^4A4AFF- You received a quest 'Novice Training Ground-1' from Sprakki.^000000"; + mes "^4A4AFFPlease check the Quest Info Window.-^000000"; + close2; + savepoint "new_1-2",100,100; + warp "new_1-2",100,100; + end; +} + +// Instructor Brade +//============================================================ +new_1-2,100,105,4 script Brade#nv 733,{ + if(job_novice_q < 3) { + mes "[Instructor Brade]"; + mes "How did you get here?"; + close2; + warp "new_1-1",53,111; + end; + } + else if(job_novice_q == 3) { + getexp 300,0; + getexp 300,0; + getexp 300,10; + completequest 7118; + set job_novice_q,4; + mes "[Instructor Brade]"; + mes "Great."; + mes "You've completed the given quest successfully, so I will reward you with experience points."; + next; + mes "[Instructor Brade]"; + mes "Experience Points you've earned from hunting or finishing quests can be checked by tracking the EXP Bar, located at the upper-left side of the display."; + next; + mes "[Instructor Brade]"; + mes "Sigh... I will just talk roughly."; + mes "...I just can't get used to"; + mes "'politeness' you know."; + mes "Don't look at me like that!"; + next; + mes "[Instructor Brade]"; + mes "Ok look alive you maggot."; + mes "Next up is items and equipment."; + next; + mes "[Instructor Brade]"; + mes "First, take these."; + mes "These are very basic equipments and recovery potions."; + getitem 2352,1; // Novice_Plate + getitem 2510,1; // Novice_Hood + getitem 2414,1; // Novice_Boots + getitem 5055,1; // Novice_Egg_Cap + getitem 1243,1; // Novice_Knife + getitem 2112,1; // Novice_Guard + getitem 569,300; // Novice_Potion + setquest 7119; + set job_novice_q,5; + next; + mes "[Instructor Brade]"; + mes "In the upper left Basic Info Window, press the 'Item' icon to open the Item Window."; + mes "The item window has 3 sections..."; + next; + mes "[Instructor Brade]"; + mes "Consumable items, equipment, and other items."; + mes "If you want to use or equip items, double-click on the item or drag them into the Equipment Window."; + next; + mes "[Instructor Brade]"; + mes "You can see detailed info of each item by right-clicking on the item."; + mes "Do that and the info will pop-up in a separate window."; + next; + cutin "tutorial04",3; + mes "!- Info -!"; + mes "Double-click on the item to see the detailed information."; + next; + mes "!- Info -!"; + mes "Right-click on other players to show the Community Menu and you can join a party, request trades, etc."; + next; + cutin "",255; + mes "[Instructor Brade]"; + mes "Why don't you equip the items I gave you earlier?"; + mes "^4A4AFFDouble-Click^000000 on the item you want to equip. Let us continue after you are done gearing up."; + next; + cutin "tutorial03",3; + mes "!- Info -!"; + mes "Items can be easily equipped or used by simply clicking on them."; + mes "The Hot Key to open the Item Window is Alt + E."; + next; + mes "!- Info -!"; + mes "To check on the items that are currently equipped, use the hot key Alt + Q."; + mes "Or, drag the item on to the item slot you want the item to be equipped."; + next; + mes "!- Info -!"; + mes "Equip all of the equipment given by Instructor Brade."; + close2; + cutin "",255; + end; + } + else if(job_novice_q == 4) { + mes "[Instructor Brade]"; + mes "Uh... Where were we? Oh right, let's continue."; + mes "It's about items and equipments."; + next; + mes "[Instructor Brade]"; + mes "Take these."; + mes "Basic equipments and recovery potions."; + getitem 2352,1; // Novice_Plate + getitem 2510,1; // Novice_Hood + getitem 2414,1; // Novice_Boots + getitem 5055,1; // Novice_Egg_Cap + getitem 1243,1; // Novice_Knife + getitem 2112,1; // Novice_Guard + getitem 569,300; // Novice_Potion + setquest 7119; + set job_novice_q,5; + next; + mes "[Instructor Brade]"; + mes "In the upper left Basic Info Window, press the 'Item' icon to open the Item Window."; + mes "The item window is divided into..."; + next; + mes "[Instructor Brade]"; + mes "3 sections: consumable items, equipment and other items."; + mes "If you want to use or equip items, double-click on the item or drag them into the Equipment Window."; + next; + mes "[Instructor Brade]"; + mes "You can see detailed info of each item by right-clicking on the item."; + mes "Do that and the info will pop-up in a separate window."; + next; + cutin "tutorial04",3; + mes "!- Info -!"; + mes "Double-click on the item to see the detailed information."; + next; + mes "!- Info -!"; + mes "Right-click on other players to show the Community Menu and you can join a party, request trades, etc."; + next; + cutin "",255; + mes "[Instructor Brade]"; + mes "Why don't you equip the items I gave you earlier?"; + mes "^4A4AFFDouble-Click^000000 on the item you want to equip. Let us continue after you are done gearing up."; + next; + cutin "tutorial03",3; + mes "!- Info -!"; + mes "Items can be easily equipped or used by simply clicking on them."; + mes "The Hot Key to open the Item Window is Alt + E."; + next; + mes "!- Info -!"; + mes "To check on the items that are currently equipped, use the hot key Alt + Q."; + mes "Or, drag the item on to the item slot you want the item to be equipped."; + next; + mes "!- Info -!"; + mes "Equip all of the equipment given by Instructor Brade."; + close2; + cutin "",255; + end; + } + else if(job_novice_q == 5 || job_novice_q == 6) { + for(set .@i,1; .@i<7; set .@i,.@i+1) + if (getequipisequiped(.@i)) set .@EquipCheck, .@EquipCheck+1; + if(.@EquipCheck >= 4) { + if(job_novice_q == 5) { + mes "[Instructor Brade]"; + mes "You are all set."; + mes "You are coming along just fine."; + getexp 300,0; + getexp 300,0; + getexp 300,0; + getexp 300,15; + getitem 12323,50; // N_Fly_Wing + getitem 12324,20; // N_Butterfly_Wing + completequest 7119; + set job_novice_q,6; + next; + mes "[Instructor Brade]"; + mes "Here's some Fly Wings and Butterfly Wings as a reward."; + mes "You don't need these in the Training Ground, but they will come in handy later."; + next; + } + mes "[Instructor Brade]"; + mes "Next, are Hot Keys."; + mes "Press the ^4A4AFF12 key^000000 on your keyboard."; + mes "A box with 9 slots will pop up."; + next; + mes "[Instructor Brade]"; + mes "Drag on the right corner of the Hot Key Window and you will be able to see the other pages of the Hot Key."; + next; + mes "[Instructor Brade]"; + mes "The F1 to F9 keys are the designated hotkeys."; + mes "Just drag a skill or an item onto the Hot Key Window and press a corresponding key to use them right away."; + next; + cutin "tutorial05",3; + mes "!- Info -!"; + mes "You can register a skill or an item to the Hot Key Window by just dragging them onto the Hot Key Slot."; + next; + mes "!- Info -!"; + mes "Registered Skills or Items can be used/equipped by just pressing the corresponding key."; + next; + mes "!- Info -!"; + mes "You can customize the Hot Key to use any keys you please as the Hot Key by changing the Shortcut configuration in the options menu."; + next; + mes "!- Info -!"; + mes "Register skills and items that you use often so that you can use them easily"; + next; + cutin "",255; + mes "[Instructor Brade]"; + mes "The last part is how to use Skills."; + mes "But before that, you need to learn something first."; + next; + setquest 7120; + set job_novice_q,7; + mes "[Instructor Brade]"; + mes "Somewhere in this room, there's someone named ^4A4AFFJinha^000000."; + mes "Find Jinha and learn the ^4A4AFF[First Aid]^000000 skill from him."; + next; + mes "[Instructor Brade]"; + mes "Your lesson is after that."; + mes "Go find Jinha and learn the [First Aid] Skill. Then come back to me."; + close; + } + mes "[Instructor Brade]"; + mes "Try to put on at least 4 of the equipment I gave you."; + mes "Put those shoes on, wear those clothes, and arm yourself with that weapon you maggot."; + close; + } + else if(job_novice_q == 7) { + mes "[Instructor Brade]"; + mes "Somewhere in this room, there's someone named ^4A4AFFJinha^000000."; + mes "Find Jinha and learn the ^4A4AFF[First Aid]^000000 skill from him."; + close; + } + else if(job_novice_q == 8) { + mes "[Instructor Brade]"; + mes "Now you've learned the [First Aid] Skill."; + mes "Just as I told you before, by registering the First Aid Skill onto the Hot Key Window, you can use the skill fast and easy."; + next; + mes "[Instructor Brade]"; + mes "And that's it, that's all I can teach you."; + mes "You see that exit to the west?"; + mes "Move on to the next room and there will be another instructor waiting for you."; + next; + mes "[Instructor Brade]"; + mes "We will be seeing each other soon enough."; + mes "But for now, go to the room to the west and get more information."; + next; + mes "[Instructor Brade]"; + mes "You've come along fine this far."; + mes "This is not much, but that this as a reward."; + getitem 2393,1; // N_Adventurer's_Suit + completequest 7120; + set job_novice_q,9; + close; + } + else if(job_novice_q > 8) { + mes "[Instructor Brade]"; + mes "Next step of the Training is done in the room west of here."; + mes "If you are lost, I can send you there."; + next; + if(select("I can get there by myself.:Please, send me to the next room.") == 2) { + mes "[Instructor Brade]"; + mes "Oh well."; + mes "I think it's better than seeing you lost and wandering about."; + mes "Hahahaha..."; + close2; + warp "new_1-2",41,172; + end; + } + mes "[Instructor Brade]"; + mes "Good. That's the attitude you must have."; + mes "You can't just lean on others to help you."; + mes "Now, go ahead."; + close; + } + mes "[Instructor Brade]"; + mes "Why are you still here?"; + close2; + warp "prontera",156,90; + end; +} + +// Instructor Jinha +//============================================================ +new_1-2,115,120,4 script Jinha#nv 59,{ + if(job_novice_q < 7) { + mes "[Jinha]"; + mes "What can I help you with?"; + mes "Hmm? You haven't followed the curriculum correctly."; + next; + mes "[Jinha]"; + mes "You have to see Instructor Brade first before me. I will send you to Instructor Brade."; + close2; + warp "new_1-2",100,100; + end; + } + else if(job_novice_q == 7) { + mes "[Jinha]"; + mes "Hello!"; + mes "How can I help you?"; + next; + select("I want to learn the use the [First Aid] Skill."); + mes "[Jinha]"; + mes "That's right."; + mes "First Aid is the skill used to convert SP into HP when you are in danger."; + next; + specialeffect2 58; + specialeffect2 234; + mes "[Jinha]"; + mes "It's recovery amount is small."; + mes "Still, it will help you not to faint from a critical hit."; + next; + skill "NV_FIRSTAID",1,0; // NV_FIRSTAID + set job_novice_q,8; + mes "[Jinha]"; + mes "You can open the Skill Window by pressing the ^4A4AFFskill^000000 button in the Basic Window."; + mes "Hot Key is ^4A4AFFALT + S^000000."; + mes "Why don't you try the skill?"; + next; + mes "[Jinha]"; + mes "Good, now you know how to use the First Aid Skill, you have to move on to the next step."; + mes "Go back to Instructor Brade and show him what you've learned here."; + close; + } + else if(job_novice_q == 8) { + mes "[Jinha]"; + mes "Didn't you learn the First Aid Skill already?"; + mes "Have it checked by Instructor Brade."; + mes "If you don't know how to get to him, I will send you to him."; + next; + if(select("I'm good by myself.:Please, send me to him.") == 2) { + mes "[Jinha]"; + mes "I will send you to Instructor Brade."; + close2; + warp "new_1-2",100,100; + end; + } + mes "[Jinha]"; + mes "Very Good!"; + mes "That's the right attitude!"; + mes "You will be a great adventurer in the future."; + close; + } + else if(job_novice_q > 8) { + mes "[Jinha]"; + mes "What can I do for you?"; + mes "Next course will be continued in the West Room."; + mes "Go on to the west room."; + close; + } + mes "[Jinha]"; + mes "Why are you still here?"; + close2; + warp "prontera",156,90; + end; +} + +// People/Services in Ragnarok +//============================================================ +// ---------- Chocolat ---------- +new_1-2,32,172,4 script Chocolat#nv 96,{ + if(job_novice_q < 9) { + mes "[Chocolat]"; + mes "Hmm? Strange."; + mes "Let me see that Trainee ID for a sec."; + next; + mes "[Chocolat]"; + mes "You were still on the basic course."; + mes "You should go back to Instructor Brade or Jinha."; + next; + mes "[Chocolat]"; + mes "If you don't know how to find them, I can send you to Instructor Brade, How about it?"; + next; + if(select("I will go myself.:Will you do that for me?") == 2) { + mes "[Chocolat]"; + mes "Sure."; + mes "I will see you later."; + close2; + warp "new_1-2",100,100; + end; + } + mes "[Chocolat]"; + mes "Sure. Go out to the door to the right."; + close; + } + else if(job_novice_q == 9) { + mes "[Chocolat]"; + mes "I will tell you about the people you will be seeing in Town."; + mes "There are many kinds of people in town and some of them will be helpful to know."; + next; + mes "[Chocolat]"; + mes "There are a lot of people in town, but among them, these people are the most important to know."; + next; + mes "[Chocolat]"; + mes "They are [Kafra] Agents standing right behind me and their rival company the [Cool Event]."; + mes "When you visit a town for the first time, you should talk to Information [Soldier]."; + next; + mes "[Chocolat]"; + mes "Well then, let's hear from each of them."; + mes "Start by talking to the [Kafra] agent."; + setquest 7121; + set job_novice_q,10; + close; + } + else if(job_novice_q == 10) { + mes "[Chocolat]"; + mes "Here, talk to these guys standing behind me."; + mes "Start with the [Kafra] gal behind me."; + close; + } + else if(job_novice_q == 11) { + mes "[Chocolat]"; + mes "You've learned a lot about Kafra service huh?"; + mes "From now on, you can use the Kafra Server."; + next; + mes "[Chocolat]"; + mes "Next is Kafra's rival, [Cool Event] Staff!"; + mes "[Cool Event] Staff specialize in events."; + mes "Well, why don't you talk to him yourself?"; + close; + } + else if(job_novice_q == 12) { + mes "[Chocolat]"; + mes "After [Kafra] and [Cool Event], are the Information [Soldier]s."; + mes "They can seem insignificant but they can help you greatly when the time comes."; + next; + mes "[Chocolat]"; + mes "I've brought the Information Soldier from the City of Prontera."; + mes "Ask him what he actually does in town."; + close; + } + else if(job_novice_q == 13) { + mes "[Chocolat]"; + mes "How was the guide of the Information [Soldier]?"; + mes "Last is about using [Inn]s."; + mes "There's an Inn located in each town."; + next; + mes "[Chocolat]"; + mes "You can rest at Inns or Hotels for a small fee."; + mes "Your HP and SP will be recovered completely by resting there."; + mes "Can't hurt to use one, eh?"; + next; + mes "[Chocolat]"; + mes "Besides these guys, there's many merchants selling various kind of items, so go check them out."; + completequest 7121; + getexp 300,0; + getexp 300,0; + getexp 300,0; + getexp 300,0; + getexp 300,0; + getexp 300,20; + getitem 7059,20; // Cargo_Free_Ticket + getitem 7060,30; // Warp_Free_Ticket + set job_novice_q,14; + next; + mes "[Chocolat]"; + mes "You've completed all the quests I gave you."; + mes "As the reward, I will give you Free Tickets for Kafra Storage and Teleport Service."; + mes "They will come in handy."; + next; + mes "[Chocolat]"; + mes "That's all for me."; + mes "Now, it's time for real combat!"; + next; + mes "[Chocolat]"; + mes "Real Combat Training will be given by Instructor Brade. You met him earlier."; + mes "I will send you to the Real Combat Training Field."; + close2; + savepoint "new_1-3",96,21; + warp "new_1-3",96,21; + end; + } + else if(job_novice_q > 13) { + mes "[Chocolat]"; + mes "What can I do for you?"; + next; + select(""); + mes "[Chocolat]"; + mes "I will send you to the Real Combat Training Field right away."; + close2; + savepoint "new_1-3",96,21; + warp "new_1-3",96,21; + end; + } + mes "[Chocolat]"; + mes "Why are you still here?"; + close2; + warp "prontera",156,90; + end; +} + +// ---------- Kafra ---------- +new_1-2,29,176,4 script Kafra#nv 117,{ + if(job_novice_q < 10) { + mes "[Kafra Agent]"; + mes "Hello."; + mes "I don't think it's my turn yet."; + mes "Please talk to 'Chocolat' first."; + close; + } + else if(job_novice_q == 10) { + mes "[Kafra Agent]"; + mes "Hello."; + mes "I've been dispatched by the Kafra Head Office to help Trainees."; + mes "The Kafra Corporation is the world's largest company with a long and distinguished history on the Rune Midgard continent."; + mes "It's important for you adventurers to be close with us."; + next; + mes "[Kafra Agent]"; + mes "I will inform you about the Kafra Services which you will be using most frequently, [Save], [Storage], and [Teleport] Services."; + next; + mes "[Kafra Agent]"; + mes "When you talk to a Kafra Agent and ask for the Save Service, the location of where you will revive, after being defeated in battle, will be changed."; + next; + mes "[Kafra Agent]"; + mes "Your Respawn Point is always the last place where you have saved."; + mes "Using a Butterfly Wing will return you to the place where you last saved."; + mes "This service is free to use, so feel free to use the Save Service anytime you like."; + next; + mes "[Kafra Agent]"; + mes "Next is the Storage Service."; + mes "You can store and retrieve your items in any town at your convenience."; + next; + mes "[Kafra Agent]"; + mes "It's unreasonable to carry all of your items with you when you don't need them right away."; + mes "Please use our Storage and keep your items safe and secure."; + next; + mes "[Kafra Agent]"; + mes "Our convenient Storage Service is provided to our customers for a small fee which is different from town to town."; + mes "However, you must be at least ^4A4AFFBasic Skill Level 6^000000 to use the Storage."; + next; + mes "[Kafra Agent]"; + mes "There are 7 different item sections of the Storage into which items are organized: Consumable, Kafra (Item Mall), Armor, Weapons, Ammo, Cards, and Etc items."; + next; + mes "[Kafra Agent]"; + mes "There are a maximum of 600 Inventory Slots in Kafra Storage, meaning you can have up to 600 different kinds of total items in Storage."; + next; + mes "[Kafra Agent]"; + mes "If you have a Premium Subscription, the maximum Inventory Slots in Kafra Storage is 600!"; + mes "Remember though, that in the case of Equipment, each item takes up one Inventory Slot."; + mes "The maximum number of items that can be placed in Kafra Storage is 30,000."; + next; + mes "[Kafra Agent]"; + mes "Storage is shared by everyone character on one account."; + mes "Storage Fees can vary for each Town."; + mes "So please keep that in mind when you are using our storage service."; + next; + mes "[Kafra Agent]"; + mes "We also provide you with a Teleport Service to make your trips easier when you are trying to move a long distance."; + next; + mes "[Kafra Agent]"; + mes "With our veteran teleporter's skill, your trip will be safer and more comfortable."; + mes "Oh and remember that the places you can teleport to vary from town to town."; + next; + mes "[Kafra Agent]"; + mes "This is all for your never ending support. We are working hard to repay our debt to our customers."; + next; + mes "[Kafra Agent]"; + mes "Do you want to hear another explanation?"; + set job_novice_q,11; + next; + } + else { + mes "[Kafra Agent]"; + mes "Kafra Service at your service"; + mes "What can I do for you?"; + next; + select("About Kafra Service"); + mes "[Kafra Agent]"; + mes "I will explain about the Kafra Service."; + mes "Which service do you want to be informed about?"; + next; + } + + while(1) { + switch(select("About Save:About Storage:About Teleport:About Cart:No More.")) { + case 1: + mes "[Kafra Agent]"; + mes "When you are killed in battle, you can revive in the location you saved with this service."; + mes "If you save at a Kafra in a village, you can revive in the village you saved."; + next; + mes "[Kafra Agent]"; + mes "Saved location is always where you saved last, and by using a Butterfly Wing, you can teleport directly to your saved point."; + mes "So feel free to use this service."; + next; + break; + case 2: + mes "[Kafra Agent]"; + mes "Next is the Storage Service."; + mes "You can store and retrieve your items in any town at your convenience."; + next; + mes "[Kafra Agent]"; + mes "It's unreasonable to carry all of your items with you when you don't need them right away."; + mes "Please use our Storage and keep your items safe and secure."; + next; + mes "[Kafra Agent]"; + mes "Our convenient Storage Service is provided to our customers for a small fee which is different from town to town."; + mes "However, you must be at least ^4A4AFFBasic Skill Level 6^000000 to use the Storage."; + next; + mes "[Kafra Agent]"; + mes "There are 7 different item sections of the Storage into which items are organized: Consumable, Kafra (Item Mall), Armor, Weapons, Ammo, Cards, and Etc items."; + next; + mes "[Kafra Agent]"; + mes "There are a maximum of 600 Inventory Slots in Kafra Storage, meaning you can have up to 600 different kinds of total items in Storage."; + next; + mes "[Kafra Agent]"; + mes "If you have a Premium Subscription, the maximum Inventory Slots in Kafra Storage is 600!"; + mes "Remember though, that in the case of Equipment, each item takes up one Inventory Slot."; + mes "The maximum number of items that can be placed in Kafra Storage is 30,000."; + next; + mes "[Kafra Agent]"; + mes "Storage is shared by everyone character on one account."; + mes "Storage Fees can vary for each Town."; + mes "So please keep that in mind when you are using our storage service."; + next; + break; + case 3: + mes "[Kafra Agent]"; + mes "We also provide you with a Teleport Service to make your trips easier when you are trying to move a long distance."; + next; + mes "[Kafra Agent]"; + mes "With our veteran teleporter's skill, your trip will be safer and more comfortable."; + mes "Oh and remember that the places you can teleport to vary from town to town."; + next; + mes "[Kafra Agent]"; + mes "This is all for your never ending support. We are working hard to repay our debt to our customers."; + next; + break; + case 4: + mes "[Kafra Agent]"; + mes "The Kafra corporation provides Cart rental services to customers engaged in commercial business."; + mes "Originally this cart rental service had been only provided by the merchant guild in Alberta."; + next; + mes "[Kafra Agent]"; + mes "However, since we took over this service, our merchant customers have been able to rent carts from almost anywhere."; + mes "The cart rental service is available only for job classes engaged in commercial business such as ^4A4AFFMerchants, Blacksmiths, Alchemists, and Super Novices^000000."; + next; + mes "[Kafra Agent]"; + mes "Of course you should learn the 'Pushcart' skill beforehand, otherwise you will not be able to rent a cart from us."; + mes "The rental fee varies by town, please keep that in mind."; + next; + break; + case 5: + mes "[Kafra Agent]"; + mes "I hope you are satisfied with my explanation about the Kafra Service."; + close; + } + } +} + +// ---------- Cool Event Staff ---------- +new_1-2,32,176,4 script Cool Event Staff#nv 874,{ + if(job_novice_q < 11) { + mes "[Cool Event Staff]"; + mes "This is not my turn."; + mes "You finished talking to Kafra yet?"; + close; + } + else if(job_novice_q == 11) { + mes "[Cool Event Staff]"; + mes "Hello."; + mes "We are working hard to provide events on Rune Midgard similar to the Kafra service."; + next; + mes "[Cool Event Staff]"; + mes "Our staff is here to support you with [storage], [save], and [teleport] services."; + next; + mes "[Cool Event Staff]"; + mes "If there's no Kafra around you, we're around to help you."; + next; + mes "[Cool Event Staff]"; + mes "We are working hard on a network of Events to make your life better."; + mes "I hope that you can meet our staff in Alberta."; + next; + mes "[Cool Event Staff]"; + mes "Who knows, we might meet outside of this academy."; + next; + mes "[Cool Event Staff]"; + mes "Mostly all of us wear red coats in the places that the Kafra Staff don't work for."; + set job_novice_q,12; + close; + } + mes "[Cool Event Staff]"; + mes "Most of our services are similar to those of Kafra."; + close; +} + +// ---------- Soldier ---------- +new_1-2,35,176,4 script Soldier#nv 105,{ + if(job_novice_q < 12) { + mes "[Soldier]"; + mes "It isn't my turn yet."; + mes "Listen to Chocolat."; + close; + } + else if(job_novice_q == 12) { + mes "[Soldier]"; + mes "Soldiers are in each town to guide you to useful places."; + mes "Ask us where you want to go and we'll mark your mini maps with a ^4A4AFF+^000000."; + mes "Don't hesitate to ask us questions."; + next; + mes "[Soldier]"; + mes "We all don't look the same in every town but our roles are the same."; + mes "Take note of this whenever you go to a new town."; + next; + mes "[Soldier]"; + mes "If you want to go to your first town, you can do so once you have reached Base Level 11 in the training grounds."; + set job_novice_q,13; + close; + } + mes "[Soldier]"; + mes "What can I help you with?"; + mes "Need me to explain what I do again?"; + next; + if(select("Yes, I need an explanation.:Nope") == 2) { + mes "[Soldier]"; + mes "Ok well talk to Chocolat if you're done talking with us."; + close; + } + mes "[Soldier]"; + mes "Soldiers are in each town to guide you to useful places."; + mes "Ask us where you want to go and we'll mark your mini maps with a ^4A4AFF+^000000."; + mes "Don't hesitate to ask us questions."; + next; + mes "[Soldier]"; + mes "We all don't look the same in every town but our roles are the same."; + mes "Take note of this whenever you go to a new town."; + next; + mes "[Soldier]"; + mes "If you want to go to your first town, you can do so once you have reached Base Level 11 in the training grounds."; + close; +} + +// Instructor Brade (Real Combat Training) +//============================================================ +- script Brade#nv::NvBrade 733,{ + if(job_novice_q < 14) { + mes "[Brade]"; + mes "How did you get here?"; + close2; + warp "new_1-2",100,100; + end; + } + else if(job_novice_q == 14) { + mes "[Brade]"; + mes "Welcome."; + mes "Now this is real practice."; + mes "We can practice real battle here."; + next; + mes "[Brade]"; + mes "As I explained the first time, we can click on the monsters."; + mes "One attack per click."; + next; + mes "[Brade]"; + mes "For convenience,"; + mes "^4A4AFFIf you hold down the Ctrl key,^000000"; + mes "while attacking, you will automatically attack."; + next; + mes "[Brade]"; + mes "You can also set this mode before battle by typing ^4A4AFF[ /nc ]^000000."; + next; + mes "[Brade]"; + mes "Then, let's go Poring hunting."; + mes "Please hunt Poring's on Level 1 of the training grounds."; + setquest 7122; + set job_novice_q,15; + getitem 569,100; // Novice_Potion + next; + mes "^4A4AFF- You've received a quest from Instructor Brade.^000000"; + mes "^4A4AFFPlease check the quest information window. -^000000"; + close; + } + else if(job_novice_q == 15) { + if(checkquest(7122,HUNTING) == 2) { + mes "[Brade]"; + mes "You can see it is not so hard, right?"; + mes "Nice job."; + getitem 13040,1; // N_Cutter + getexp 1000,0; + getexp 1000,0; + getexp 1000,30; + completequest 7122; + set job_novice_q,16; + next; + mes "[Brade]"; + mes "Now all of the courses are almost done."; + mes "You are a Novice, and you can't get any jobs yet."; + next; + mes "[Brade]"; + mes "If you acquire all of basic skills with Job Level 10, you can change your job."; + next; + mes "[Brade]"; + mes "The first job classes are defined into 6 classes."; + next; + mes "[Brade]"; + mes "The 6 basic jobs are"; + mes "Swordman, Thief,"; + mes "Acolyte, Mage,"; + mes "Archer and Merchant."; + next; + mes "[Brade]"; + mes "Let's experience the basic 6 jobs, Swordman, Thief, Acolyte, Mage, Archer and Merchant and see what those jobs can do."; + next; + mes "[Brade]"; + mes "Behind me, there are people dispatched from each of the basic Job Guilds."; + mes "These people will give you instruction manuals that allow you to experience some limited skills of each job."; + next; + mes "[Brade]"; + mes "Equip a manual of the job which you want to experience, and you will be able to use some basic skills of that corresponding job."; + mes "Try those skills and decide which job to choose."; + close; + } + mes "[Brade]"; + mes "Kill enough Porings."; + mes "Porings are easy to deal with, so cheer up."; + mes "Try again."; + npcskill "AL_HEAL",10,99,60; + close; + } + mes "[Brade]"; + mes "Have you tried the skills in the Manuals?"; + mes "If you want to hear information about each job, talk to the people dispatched by the Job Guilds."; + next; + mes "[Brade]"; + mes "I think you've learned enough, if you want to learn more, then speak to the Eden Group girl next to the Trainers."; + next; + mes "[Brade]"; + mes "Try using the job manuals to find out the characteristics of each job's skills."; + mes "I will restore your HP and SP... Keep it up."; + npcskill "AL_HEAL",10,99,60; + close; +} + +new_1-3,96,30,4 duplicate(NvBrade) Brade#nv1 733 +new_2-3,96,30,4 duplicate(NvBrade) Brade#nv2 733 +new_3-3,96,30,4 duplicate(NvBrade) Brade#nv3 733 +new_4-3,96,30,4 duplicate(NvBrade) Brade#nv4 733 +new_5-3,96,30,4 duplicate(NvBrade) Brade#nv5 733 + +// Job Guides (Real Combat Training) +//============================================================ +// --------------------------- Deletion Function ------------------------------ +function script F_NvErase { + if (getarg(0,0)) { + if (checkquest(7123) == 0 || checkquest(7123) == 1) erasequest 7123; + if (checkquest(7124) == 0 || checkquest(7124) == 1) erasequest 7124; + if (checkquest(7126) == 0 || checkquest(7126) == 1) erasequest 7126; + if (checkquest(7127) == 0 || checkquest(7127) == 1) erasequest 7127; + } + nude; + if (countitem(2819)) delitem 2819,1; // Swordsman_Manual + if (countitem(2820)) delitem 2820,1; // Thief_Manual + if (countitem(2821)) delitem 2821,1; // Acolyte_Manual + if (countitem(2822)) delitem 2822,1; // Archer_Manual + if (countitem(2823)) delitem 2823,1; // Merchant_Manual + if (countitem(2824)) delitem 2824,1; // Mage_Manual + return; +} + +// ---------------------------- Swordman Guide ------------------------------- +- script Swordman Guide#nv::NvSwd 728,{ + if(job_novice_q < 16) { + mes "[Swordman Guildsman]"; + mes "I won't help you until you finish Brade's instructions."; + close; + } + mes "[Swordman Guildsman]"; + mes "Can I help you?"; + next; + switch(select("About Swordman Class.:Job change to Swordman.:Got any quests?:Cancel.")) { + case 1: + mes "[Swordman Guildsman]"; + mes "Literally, Swordman means one, who is specialized in wielding swords."; + mes "But they can also choose to use spears if they so choose."; + next; + mes "[Swordman Guildsman]"; + mes "We possess strong physical strength."; + mes "So naturally we can equip heavy armors and weapons."; + mes "Most weapon classes, except for bows and rods, are equippable by our class."; + next; + mes "[Swordman Guildsman]"; + mes "The only weakness of the Swordman class is that they cannot use magic spells."; + mes "But we've compensated for that by using elemental weapons."; + next; + mes "[Swordman Guildsman]"; + mes "The merits of being a Swordman is the enormous amount of HP we have."; + mes "Most of us can bear the grunt of our enemies' attacks with relative ease."; + next; + mes "[Swordman Guildsman]"; + mes "And we are unrivaled when it comes to one-on-one melee combat."; + next; + mes "[Swordman Guildsman]"; + mes "Anyone who chooses to be a Swordman will likely play the role of the tank. It is our duty to protect the weak."; + next; + mes "[Swordman Guildsman]"; + mes "As a Swordman you can advance to a ^8C2121Knight^000000 or ^8C2121Crusader^000000 class as your 2nd class profession."; + mes "And just recently third professions have been discovered."; + if(countitem(2819) == 0 && (getequipid(EQI_ACC_L) != 2819 || getequipid(EQI_ACC_R) != 2819)) { + next; + mes "[Swordman Guildsman]"; + mes "If you're interested in being a Swordman, I'll offer you this manual."; + mes "Do you want to try the skills of a Swordman?"; + next; + if(select("I'll try the Swordman skills.:No Thanks.") == 2) { + mes "[Swordman Guildsman]"; + mes "Hum. Do you think so?"; + mes "Ok, I agree with you. Choosing a job is very important in our lives."; + mes "Just talk to me whenever you want to experience Swordman skills."; + close; + } + mes "[Swordman Guildsman]"; + mes "Here is the Swordman manual."; + mes "I'll just take any manuals from any other classes you have."; + callfunc "F_NvErase"; + getitem 2819,1; // Swordsman_Manual + next; + mes "[Swordman Guildsman]"; + mes "After equipping the Manual, open your Skill menu by pressing ALT+S."; + mes "Make sure to minimize your Skill tree by clicking the '-' button on the top right corner of the Skill Tree Window."; + } + close; + case 2: + mes "[Swordman Guildsman]"; + mes "Do you really want to change your job to Swordman?"; + mes "If you want to be a Swordman, I'll send you to the Swordman Guild immediately."; + next; + mes "[Swordman Guildsman]"; + mes "I think you have enough job levels, of course, right?"; + mes "Do you want to stop your training now and go to the Swordman Guild?"; + next; + if(select("I'll consider it again.:I'll go to the Swordman Guild.") == 2) { + mes "[Swordman Guildsman]"; + mes "I see."; + mes "Then I'll end your training process and send you to the Swordman Guild."; + close2; + callfunc "F_NvErase",1; + savepoint "izlude",94,103; + warp "izlude_in",74,167; + end; + } + mes "[Swordman Guildsman]"; + mes "Please try enough instruction manuals from each job class and consider it carefully."; + mes "Of course, you're always welcomed."; + close; + case 3: + set .@quest, checkquest(7123); + if (.@quest == -1) { + mes "[Swordman Guildsman]"; + mes "You want me to give you a quest?"; + mes "Umm. Let me see."; + mes "Ok! Hunt a couple of Picky monsters around here."; + next; + mes "^4d4dffYou received a hunting request from a staff of the Swordman Guild."; + mes "You can check the contents of the quest from the quest information window.^000000"; + setquest 7123; + next; + mes "[Swordman Guildsman]"; + mes "Use the 'Bash' skill in the Swordman manual."; + mes "Open your Skill Tree by pressing ^4A4AFFAlt + S^000000 and minimize the window by pressing the '-' button on the top right corner of the window to see the available Swordman skills."; + next; + mes "[Swordman Guildsman]"; + mes "Talk to Trainer Brutus if you want to fight stronger monsters."; + mes "I'll wait for you here."; + mes "Wish you a good luck."; + close; + } + else if (.@quest == 1) { + if (checkquest(7123,HUNTING) == 2) { + mes "[Swordman Guildsman]"; + mes "Great."; + mes "I think that you're good enough to be a Swordman."; + mes "I'll give you some potions as a reward."; + completequest 7123; + getitem 569,200; // Novice_Potion + getexp 5000,100; + close; + } + mes "[Swordman Guildsman]"; + mes "Hunt two Picky monsters."; + mes "You can find them in the more difficult training grounds by talking to Trainer Brutus."; + close; + } + else if (.@quest == 2) { + mes "[Swordman Guildsman]"; + mes "I think you finished that quest already, right?"; + mes "You'll experience more of these quests as you grow as an adventurer in the world."; + next; + mes "[Swordman Guildsman]"; + mes "Your training is now complete."; + mes "If you choose to become a Swordman I wish you goodluck."; + close; + } + mes "[Swordman Guildsman]"; + mes "I'm sorry but I don't have any quests to give you right now."; + close; + case 4: + mes "[Swordman Guildsman]"; + mes "If you have any questions about the Swordman class, please ask me."; + mes "The Swordman Guild is waiting for novices like you."; + close; + } +} + +new_1-3,97,41,4 duplicate(NvSwd) Swordman Guide#nv1 728 +new_2-3,97,41,4 duplicate(NvSwd) Swordman Guide#nv2 728 +new_3-3,97,41,4 duplicate(NvSwd) Swordman Guide#nv3 728 +new_4-3,97,41,4 duplicate(NvSwd) Swordman Guide#nv4 728 +new_5-3,97,41,4 duplicate(NvSwd) Swordman Guide#nv5 728 + +// ---------------------------- Mage Guide ---------------------------------- +- script Mage Guide#nv::NvMag 123,{ + if(job_novice_q < 16) { + mes "[Mage Guild Member]"; + mes "You are still in the process of training with Instructor Brade."; + close; + } + mes "[Mage Guild Member]"; + mes "What can I help you with?"; + next; + switch(select("Tell me about Mages:I want to be a Mage:Give me a Quest:Cancel")) { + case 1: + mes "[Mage Guild Member]"; + mes "Mages are those who can use magic when they need to protect their friends."; + mes "Mages can curse enemies using the elements of fire, water, earth and thunder magic."; + next; + mes "[Mage Guild Member]"; + mes "However they cannot equip other weapons but staffs and books."; + mes "Because they are too delicate to carry heavy weapons."; + next; + mes "[Mage Guild Member]"; + mes "But they can cover this weakness by their remarkable magic skills."; + mes "That is why many people want to become a Mage!"; + next; + mes "[Mage Guild Member]"; + mes "Mages have to be in their guild for guild's power and honor."; + mes "This is one of the reasons why Mages are popular in any parties and guilds."; + mes "Why don't you become a Mage?"; + next; + mes "[Mage Guild Member]"; + mes "^8C2121Mages can transform to Wizards or Sages as their second job.^000000"; + if(countitem(2824) == 0 && (getequipid(EQI_ACC_L) != 2824 || getequipid(EQI_ACC_R) != 2824)) { + next; + mes "[Mage Guild Member]"; + mes "Do you want to register to experience how it is to be a Mage?"; + mes "Would you like to test Mage skills?"; + next; + if(select("I want to test Mage skills.:I don't want to test it.") == 2) { + mes "[Mage Guild Member]"; + mes "Hum. Do you think so."; + mes "Ok, I agree with you. Choosing a job is very important in our life."; + mes "Just talk to me whenever you want to experience Mage skills."; + close; + } + mes "[Mage Guild Member]"; + mes "Here is the Mage Manual."; + mes "I will take the other job registration forms and manuals from you."; + next; + mes "[Mage Guild Member]"; + mes "Here is the Mage Manual."; + mes "I will take the other job registration forms and manuals from you."; + callfunc "F_NvErase"; + getitem 2824,1; // Mage_Manual + next; + mes "[Mage Guild Member]"; + mes "After equipping the Manual, open your Skill menu by pressing ALT+S."; + mes "Make sure to minimize your Skill tree by clicking the '-' button on the top right corner of the Skill Tree Window."; + } + close; + case 2: + mes "[Mage Guild Member]"; + mes "You want to be a Mage?"; + mes "Ok, then, I will send you to the Mage Guild union in Geffen right away."; + next; + mes "[Mage Guild Member]"; + mes "Wait, have you checked your Job level?"; + mes "Do you want to complete your Novice training and go straight to the Mage Guild's union?"; + next; + if(select("I will think about it again.:Yes, complete my training.") == 2) { + mes "[Mage Guild Member]"; + mes "Welcome!!"; + mes "I will send you to the Mage Guilds union after you complete your Novice training."; + close2; + callfunc "F_NvErase",1; + savepoint "geffen",119,38; + warp "geffen_in",163,98; + end; + } + mes "[Mage Guild Member]"; + mes "Please test what Mage skills are all about before you decide."; + mes "We are always welcome to have you!"; + close; + case 3: + set .@quest, checkquest(7124); + if (.@quest == -1) { + mes "[Mage Guild Member]"; + mes "Huh? Quest?"; + mes "Hmm... What would be suited for you...?"; + mes "Would you like to hunt Lunatics by using Bolt skills?"; + next; + mes "^4d4dffYou have received a Hunting quest from the Mage Guide."; + mes "You can get more information about the quest from the quest window.^000000"; + setquest 7124; + next; + mes "[Mage Guild Member]"; + mes "You are able to use 'Fire Bolt' skill that is shown on the Mage manual."; + mes "I will wait for you here."; + mes "Good luck!"; + close; + } + else if (.@quest == 1) { + if (checkquest(7124,HUNTING) == 2) { + mes "[Mage Guild Member]"; + mes "You have done excellent job."; + mes "So, did you find any interests about Mages?"; + mes "Alright. I will give something..."; + mes "Here are Novice Butterfly Wings, please take them."; + completequest 7124; + getitem 12324, 30; // N_Butterfly_Wing + getexp 5000,100; + close; + } + mes "[Mage Guild Member]"; + mes "The quest is that you have to"; + mes "hunt Lunatics and bring 5 clovers."; + close; + } + else if (.@quest == 2) { + mes "[Mage Guild Member]"; + mes "You have already completed the quest."; + mes "Once you enter the main world, you can get various exciting quests there!"; + next; + mes "[Mage Guild Member]"; + mes "This should be enough for your training."; + close; + } + mes "[Mage Guild Member]"; + mes "I'm sorry but I don't have any quests to give you right now."; + close; + case 4: + mes "[Mage Guild Member]"; + mes "If you have any questions about Mages, feel free to ask me."; + mes "I think you could be a intelligent Mage..."; + close; + } +} + +new_1-3,101,41,4 duplicate(NvMag) Mage Guide#nv1 123 +new_2-3,101,41,4 duplicate(NvMag) Mage Guide#nv2 123 +new_3-3,101,41,4 duplicate(NvMag) Mage Guide#nv3 123 +new_4-3,101,41,4 duplicate(NvMag) Mage Guide#nv4 123 +new_5-3,101,41,4 duplicate(NvMag) Mage Guide#nv5 123 + +// ---------------------------- Thief Guide --------------------------------- +- script Thief Guide#nv::NvThf 118,{ + if(job_novice_q < 16) { + mes "[Thief Guild Member]"; + mes "You look like you are not done with Instructor Brade's lessons."; + close; + } + mes "[Thief Guild Member]"; + mes "How can I help you?"; + next; + switch(select("About the Thief Class.:I want to be a Thief.:Got any Quests?:Cancel.")) { + case 1: + mes "[Thief Guild Member]"; + mes "Thieves are experts at using Dagger class weapons."; + mes "They strike quickly and easily evade attacks from their enemies."; + next; + mes "[Thief Guild Member]"; + mes "Thieves can learn skills that allow them to hide from their enemies or steal items from monsters."; + mes "They are also feared for their use of poison, which slowly weakens their enemies."; + next; + mes "[Thief Guild Member]"; + mes "In jeopardy, or in the case that thieves do not want to reveal themselves, they can use their skill to hide themselves easily."; + next; + mes "[Thief Guild Member]"; + mes "Thieves can change their jobs to ^8C2121Assassins^000000 or ^8C2121Rogues.^000000"; + if(countitem(2820) == 0 && (getequipid(EQI_ACC_L) != 2820 || getequipid(EQI_ACC_R) != 2820)) { + next; + mes "[Thief Guild Member]"; + mes "If you want, I'll give you a Thief skill manual."; + mes "Would you like to experience the skills of a Thief?"; + next; + if(select("Yes, I would.:No, I don't.") == 2) { + mes "[Thief Guild Member]"; + mes "Oh, are you sure?"; + mes "Class selection is very important so please consider it carefully."; + mes "If you want to ask about Thieves, please talk to me any time."; + close; + } + mes "[Thief Guild Member]"; + mes "Here, please take the Thief manual."; + mes "I'll just take the other class manuals while I'm at it."; + next; + mes "[Thief Guild Member]"; + mes "Here, please take the Thief manual."; + mes "I'll just take the other class manuals while I'm at it."; + callfunc "F_NvErase"; + getitem 2820,1; // Thief_Manual + next; + mes "[Thief Guild Member]"; + mes "Make sure to equip the Skill Manual by double-clicking it in the Inventory Window."; + mes "Open your Skill Tree by pressing ^4A4AFFAlt + S^000000 and minimize the window by pressing the '-' button on the top right corner of the window to see the available skills."; + } + close; + + case 2: + mes "[Thief Guild Member]"; + mes "Do you really want to be a Thief?"; + mes "If so, I will send you to the Thief Guild immediately."; + next; + mes "[Thief Guild Member]"; + mes "You already reached the required job level, didn't you?"; + mes "Do you want to finish the Novice training and go to the Thief Guild?"; + next; + if(select("Let me consider it again.:Yes, I do.") == 2) { + mes "[Thief Guild Member]"; + mes "Ok, I see."; + mes "Welcome. Then your Novice training is totally complete and you will be sent to the Thief Guild immediately."; + close2; + callfunc "F_NvErase",1; + savepoint "morocc",150,100; + warp "moc_prydb1",99,185; + end; + } + mes "[Thief Guild Member]"; + mes "Have you tried all of the class manuals yet?"; + mes "If you're undecided what job to take on I suggest you try talking to all the Guides first."; + close; + case 3: + set .@quest, checkquest(7127); + if (.@quest == -1) { + mes "[Thief Guild Member]"; + mes "Quests?"; + mes "Hmm, what will be good for you?"; + mes "How about hunting some Willows."; + next; + mes "[Thief Guild Member]"; + mes "You can't cheat this so make sure to kill 5 Willows. When you're done come and talk to me again."; + mes "If you talk to Trainer Brutus, he can send you to a more difficult training ground where there are Willows to hunt."; + setquest 7127; + next; + mes "[Thief Guild Member]"; + mes "If you equip the Thief manual, you can have the effect of the skill, Double Attack."; + mes "Double Attack and Hide are the main skills of the Thief."; + close; + } + else if (.@quest == 1) { + if (checkquest(7127,HUNTING) == 2) { + mes "[Thief Guild Member]"; + mes "You are very strong."; + mes "These are not many but let me give you a reward for your effort."; + completequest 7127; + getitem 12323, 50; // N_Fly_Wing + getexp 5000,100; + close; + } + mes "[Thief Guild Member]"; + mes "Hunt 5 Willows and then come talk to me to finish your quest."; + close; + } + else if (.@quest == 2) { + mes "[Thief Guild Member]"; + mes "I think you finished that quest already, right?"; + mes "You'll experience more of these quests as you grow as an adventurer in the world."; + next; + mes "[Thief Guild Member]"; + mes "Your training is now complete."; + mes "If you choose to become a Thief I wish you goodluck."; + close; + } + mes "[Thief Guild Member]"; + mes "I'm sorry but I don't have any quests to give you right now."; + close; + case 4: + mes "[Thief Guild Member]"; + mes "If you have something to ask about the Thief job, feel free to ask me."; + close; + } +} + +new_1-3,105,41,4 duplicate(NvThf) Thief Guide#nv1 118 +new_2-3,105,41,4 duplicate(NvThf) Thief Guide#nv2 118 +new_3-3,105,41,4 duplicate(NvThf) Thief Guide#nv3 118 +new_4-3,105,41,4 duplicate(NvThf) Thief Guide#nv4 118 +new_5-3,105,41,4 duplicate(NvThf) Thief Guide#nv5 118 + +// ---------------------------- Merchant Guide ------------------------------ +- script Merchant Guide#nv::NvMer 97,{ + if(job_novice_q < 16) { + mes "[Merchant Guildsman]"; + mes "You are still in the process of training with sir Brade."; + close; + } + mes "[Merchant Guildsman]"; + mes "What can I help you with?"; + next; + switch(select("Tell me about Merchants:I want to be a Merchant.:Give me a Quest.:Cancel")) { + case 1: + mes "[Merchant Guildsman]"; + mes "Merchant? Simply put, they sell goods and make money."; + mes "That's the main focus for any Merchant."; + next; + mes "[Merchant Guildsman]"; + mes "We have special skills for making money."; + mes "We can buy goods at a lower price and sell them at a higher price."; + next; + mes "[Merchant Guildsman]"; + mes "Also Merchants can have Carts that we can store lots of items in."; + next; + mes "[Merchant Guildsman]"; + mes "^8C2121Merchants can transform to a Blacksmith or an Alchemist^000000 as their second job."; + if(countitem(2823) == 0 && (getequipid(EQI_ACC_L) != 2823 || getequipid(EQI_ACC_R) != 2823)) { + next; + mes "[Merchant Guildsman]"; + mes "Do you wan to see what it's like to be a Merchant?"; + next; + if(select("I want to test Merchant skills.:I don't want to test it.") == 2) { + mes "[Merchant Guildsman]"; + mes "Hum. Do you think so?"; + mes "Ok, I agree with you. Choosing a job is very important in our life."; + mes "Just talk to me whenever you want to experience Merchant skills."; + close; + } + mes "[Merchant Guildsman]"; + mes "Here is the Merchant skill manual."; + mes "I will take other job manuals from you while I'm at it."; + next; + mes "[Merchant Guildsman]"; + mes "Here is the Merchant skill manual."; + mes "I will take other job manuals from you while I'm at it."; + callfunc "F_NvErase"; + getitem 2823,1; // Merchant_Manual + next; + mes "[Merchant Guildsman]"; + mes "Make sure to equip the Skill Manual by double-clicking it in the Inventory Window."; + mes "Open your Skill Tree by pressing ^4A4AFFAlt + S^000000 and minimize the window by pressing the '-' button on the top right corner of the window to see the available skills."; + } + close; + + case 2: + mes "[Merchant Guildsman]"; + mes "You want to be a Merchant?"; + mes "Ok, then, I will send you to the Merchant Guild's union right away."; + next; + mes "[Merchant Guildsman]"; + mes "Wait, have you checked your Job level?"; + mes "Do you want to complete your Novice training and go straight to the Merchant Guild's union?"; + next; + if(select("I will think about it again.:Yes, I want to go to the Merchant Guild's union.") == 2) { + mes "[Merchant Guildsman]"; + mes "Welcome!!"; + mes "I will send you to the Merchant Guild's union after you complete your Novice training."; + close2; + callfunc "F_NvErase",1; + savepoint "alberta",29,231; + warp "alberta_in",62,44; + end; + } + mes "[Merchant Guildsman]"; + mes "Ok, I hope you consider being a Merchant."; + mes "We are always welcome to have you!"; + close; + case 3: + set .@quest, checkquest(7126); + if (.@quest == -1) { + mes "[Merchant Guildsman]"; + mes "Huh? Quest??"; + mes "Humm... What would be suited for you...?"; + mes "Ok, then bring me ^5d5dff300 zeny^000000 by selling some of your items to the Potato Merchant."; + next; + mes "[Merchant Guildsman]"; + mes "If you equipped the Merchant manual you have the ability to use the 'Overcharge' and 'Discount' skills."; + setquest 7126; + next; + mes "I will wait for you here."; + mes "Good luck!"; + close; + } + else if (.@quest == 1) { + if (Zeny > 299) { + mes "[Merchant Guildsman]"; + mes "Excellent!"; + mes "Zeny is the currency of Rune-Midgard."; + mes "You can make zeny by selling loot as well as through making smart business decisions."; + next; + mes "[Merchant Guildsman]"; + mes "We can use extremely powerful skills with zeny!"; + mes "Mammonite! That is our ultimate attack skill!!"; + mes "We basically paste money on the weapon and then strike the enemy. Death by Zeny! Nyahahahaha!"; + next; + mes "[Merchant Guildsman]"; + mes "By the way, you have done an excellent job. So, I should give you something... What would be good?"; + mes "Alright! What about Phracon?"; + mes "Phracon is a metallic element which you can use for refining weapons."; + completequest 7126; + getitem 1010,7; // Phracon + getexp 5000,100; + close; + } + mes "[Merchant Guildsman]"; + mes "Zeny is the currency of Rune-Midgard."; + mes "You can make zeny by selling loot as well as through making smart business decisions."; + next; + mes "[Merchant Guildsman]"; + mes "You can get loot by killing monsters. After hunting monsters, you can sell those loot to make a profit!"; + mes "What a valuable job it is! Isn't it?"; + next; + mes "[Merchant Guildsman]"; + mes "Why don't you try to be a Merchant? Making money is not easy but it will be a great experience!"; + close; + } + else if (.@quest == 2) { + mes "[Merchant Guildsman]"; + mes "You have already completed the quest."; + mes "Once you enter the main world, you can get various exciting quests there!"; + next; + mes "[Merchant Guildsman]"; + mes "I think you're strong enough now to change your job right? Hahahaha don't waste too much time here Novice."; + close; + } + mes "[Merchant Guildsman]"; + mes "I'm sorry but I don't have any quests to give you right now."; + close; + case 4: + mes "[Merchant Guildsman]"; + mes "If you have any questions about Merchants, feel free to ask me."; + mes "I think you could be a rich Merchant. AhHahaha."; + close; + } +} + +new_1-3,109,41,4 duplicate(NvMer) Merchant Guide#nv1 97 +new_2-3,109,41,4 duplicate(NvMer) Merchant Guide#nv2 97 +new_3-3,109,41,4 duplicate(NvMer) Merchant Guide#nv3 97 +new_4-3,109,41,4 duplicate(NvMer) Merchant Guide#nv4 97 +new_5-3,109,41,4 duplicate(NvMer) Merchant Guide#nv5 97 + +// ---------------------------- Archer Guide -------------------------------- +- script Archer Guide#nv::NvArc 727,{ + if(job_novice_q < 16) { + mes "[Archer Guide]"; + mes "You are still in the process of training with sir Brade."; + close; + } + mes "[Archer Guide]"; + mes "What can I help you with?"; + next; + switch(select("Tell me about Archers:I want to be an Archer:Cancel")) { + case 1: + mes "[Archer Guide]"; + mes "Archers have specialized skills by using a Bow and have a variety of powerful skills."; + mes "Archers are good at staying back and picking off their targets."; + next; + mes "[Archer Guide]"; + mes "Archers don't have great vitality so they have to keep their distance from enemies."; + next; + mes "[Archer Guide]"; + mes "On the other hand, Archers are attentive and have incredibly accurate eyes."; + mes "So once they are ready to attack, they can kill enemies before they're even aware of their presence."; + next; + mes "[Archer Guide]"; + mes "^8C2121Archers can transform to many second jobs like a Hunter.^000000"; + mes "^8C2121Besides Hunters, Archers can transform to a Bard, if they are male.^000000"; + mes "^8C2121They can transform to a Dancer, if they are female.^000000"; + if(countitem(2822) == 0 && (getequipid(EQI_ACC_L) != 2822 || getequipid(EQI_ACC_R) != 2822)) { + next; + mes "[Archer Guide]"; + mes "Do you want to register to test skill experience?"; + mes "Would you like to test Archer skills?"; + next; + if(select("I want to test Archer skills.:I don't want to test it.") == 2) { + mes "[Archer Guide]"; + mes "Hum. Do you think so."; + mes "Ok, I agree with you. Choosing a job is very important in our life."; + mes "Just talk to me whenever you want to experience Archer skills."; + close; + } + mes "[Archer Guide]"; + mes "Here is the Archer manual."; + mes "I will take the other job manuals from you while you test the Archer manual out."; + next; + mes "[Archer Guide]"; + mes "I will take the other job manuals from you while you test the Archer manual out."; + callfunc "F_NvErase"; + getitem 2822,1; // Archer_Manual + next; + mes "[Archer Guide]"; + mes "Make sure to equip the Skill Manual by double-clicking it in the Inventory Window."; + mes "Open your Skill Tree by pressing ^4A4AFFAlt + S^000000 and minimize the window by pressing the '-' button on the top right corner of the window to see the available skills."; + } + close; + case 2: + mes "[Archer Guide]"; + mes "You want to be an Archer?"; + mes "Ok, then, I will send you to the Archer Guild right away."; + next; + mes "[Archer Guide]"; + mes "Wait, have you checked your Job level?"; + mes "Do you want to complete the Novice training arena and go to the Archer Guild right now?"; + next; + if(select("I will think about it again.:Yes, I want to go to the Archer Guild's union.") == 2) { + mes "[Archer Guide]"; + mes "Welcome!!"; + mes "I will send you to the Archer Guild after you complete your Novice training."; + close2; + callfunc "F_NvErase",1; + savepoint "payon",256,242; + warp "payon_in02",64,65; + end; + } + mes "[Archer Guide]"; + mes "Test out all the jobs if you have to but choose Archer because we're the best."; + mes "We are always welcome to have you!"; + close; + case 3: + mes "[Archer Guide]"; + mes "If you have any questions about Archers, feel free to ask me."; + mes "I think you could be a strong Archer young Novice."; + close; + } +} + +new_1-3,113,41,4 duplicate(NvArc) Archer Guide#nv1 727 +new_2-3,113,41,4 duplicate(NvArc) Archer Guide#nv2 727 +new_3-3,113,41,4 duplicate(NvArc) Archer Guide#nv3 727 +new_4-3,113,41,4 duplicate(NvArc) Archer Guide#nv4 727 +new_5-3,113,41,4 duplicate(NvArc) Archer Guide#nv5 727 + +// ---------------------------- Acolyte Guide ------------------------------- +- script Acolyte Guide#nv::NvAco 95,{ + if(job_novice_q < 16) { + mes "[Prontera Acolyte]"; + mes "You look like you are not done with Instructor Brade's lessons."; + close; + } + mes "[Prontera Acolyte]"; + mes "What can I do for you?"; + next; + switch(select("What is an Acolyte?:Job change to Acolyte:Cancel")) { + case 1: + mes "[Prontera Acolyte]"; + mes "An Acolyte is someone who worships the goddess Freya sacrificing themselves to help others."; + next; + mes "[Prontera Acolyte]"; + mes "Acolytes use supportive skills to make combat easier."; + mes "It is essential to have an Acolyte in any successful party."; + next; + mes "[Prontera Acolyte]"; + mes "^8C2121As an Acolyte, you can upgrade your future job to Priest or Monk.^000000"; + next; + mes "[Prontera Acolyte]"; + if(countitem(2821) == 0 && (getequipid(EQI_ACC_L) != 2821 || getequipid(EQI_ACC_R) != 2821)) { + next; + mes "[Prontera Acolyte]"; + mes "If you want, I can give you a skill manual to experience what it is like to be an Acolyte."; + mes "Would you like to experience the skills of an Acolyte?"; + next; + if(select("Yes, please.:No I'm not interested.") == 2) { + mes "[Prontera Acolyte]"; + mes "Hum. Do you think so."; + mes "Ok, I agree with you. Choosing a job is very important in our life."; + mes "Just talk to me whenever you want to know about Acolytes."; + close; + } + mes "[Prontera Acolyte]"; + mes "Here you go, the instruction manual of an Acolyte."; + mes "I will take away those other job's manuals while you study this one."; + next; + mes "[Prontera Acolyte]"; + mes "Here you go, the instruction manual of an Acolyte."; + mes "I will take away those other job's manuals while you study this one."; + callfunc "F_NvErase"; + getitem 2821,1; // Acolyte_Manual + next; + mes "[Prontera Acolyte]"; + mes "Make sure to equip the Skill Manual by double-clicking it in the Inventory Window."; + mes "Open your Skill Tree by pressing ^4A4AFFAlt + S^000000 and minimizing the window by pressing the '-' button on the top right corner of the window to see the available skills."; + } + close; + case 2: + mes "[Prontera Acolyte]"; + mes "Of course, I assume you have enough job levels to become an Acolyte right?"; + mes "Would you like to quit the Training Process and go to the Cathedral of Prontera?"; + next; + if(select("Let me reconsider.:I will go to the Cathedral.") == 2) { + mes "[Prontera Acolyte]"; + mes "That's great."; + mes "Then I will completely end the Training Process and send you to the Cathedral of Prontera."; + close2; + callfunc "F_NvErase",1; + savepoint "prontera",117,72; + warp "prt_church",172,19; + end; + } + mes "[Prontera Acolyte]"; + mes "You should try out each job's manuals."; + mes "Go through them throughly and decide carefully."; + mes "Of course, I will welcome you anytime."; + close; + case 3: + mes "[Prontera Acolyte]"; + mes "If you have any questions about Acolytes, please ask me anytime."; + mes "Our God, Odin awaits adventurers like you"; + close; + } +} + +new_1-3,117,41,4 duplicate(NvAco) Acolyte Guide#nv1 95 +new_2-3,117,41,4 duplicate(NvAco) Acolyte Guide#nv2 95 +new_3-3,117,41,4 duplicate(NvAco) Acolyte Guide#nv3 95 +new_4-3,117,41,4 duplicate(NvAco) Acolyte Guide#nv4 95 +new_5-3,117,41,4 duplicate(NvAco) Acolyte Guide#nv5 95 + +// ---------------------------- Bruce (Extended Jobs) ----------------------- +- script Bruce#nv::NvBruce 57,{ + mes "[Bruce]"; + mes "Hello?"; + mes "I'm here to guide you about extra jobs and special classes."; + next; + mes "[Bruce]"; + mes "For special classes, there are Taekwon, Ninja, Super Novice, and Gunslinger."; + mes "Which job description do you want to hear?"; + next; + while(1) { + switch(select("Taekwon:Ninja:Super Novice:Gunslinger:End the conversation.")) { + case 1: + mes "[Bruce]"; + mes "It's a job that usually uses a lot of kicking skills."; + mes "It belongs to special class and later you can change your job into Taekwon Master which has much stronger attack skills."; + next; + mes "[Bruce]"; + mes "There is a secondary class to choose from called Soul Linker which also has strong attacks."; + mes "You can decide that later when you get stronger."; + next; + break; + case 2: + mes "[Bruce]"; + mes "Ninja's specialty is rapid movement."; + mes "They specialize in using throwing weapons."; + next; + mes "[Bruce]"; + mes "Ninjas are kind of a hybrid class that can use various dodge skills with the capability of both physical and magical attacks depending on their preference."; + next; + break; + case 3: + mes "[Bruce]"; + mes "The biggest attraction of the stronger Novice, called Super Novice, is their pull to mediocrity."; + mes "They are the proverbial Jack-of-all-Trades but Master of none."; + next; + mes "[Bruce]"; + mes "Super Novices can learn most of the 1st job class skills."; + mes "If you become a Super Novice, you cannot change your job, which is too bad, but you can grow as a very individual character."; + next; + break; + case 4: + mes "[Bruce]"; + mes "You can job change directly from Novice to a special class which is optimized for a long-distance attack with guns."; + next; + mes "[Bruce]"; + mes "Gunslingers use all kinds of guns made in 'Einbroch', the city of steel."; + mes "I recommend this for those who want to become powerful sharpshooters."; + next; + break; + case 5: + mes "[Bruce]"; + mes "If you need more information, you can always go to"; + mes "'iro.ragnarokonline.com'"; + close; + } + } +} + +new_1-3,121,41,4 duplicate(NvBruce) Bruce#nv1 57 +new_2-3,121,41,4 duplicate(NvBruce) Bruce#nv2 57 +new_3-3,121,41,4 duplicate(NvBruce) Bruce#nv3 57 +new_4-3,121,41,4 duplicate(NvBruce) Bruce#nv4 57 +new_5-3,121,41,4 duplicate(NvBruce) Bruce#nv5 57 + +//============================================================================ +// Eden Group Officer (Real Combat Training) +//============================================================================ +- script Eden Group Officer#nv::NvEdn -1,{ + if(BaseLevel < 10) { + mes "[Eden Group Officer]"; + mes "Hello, I am a representative of the Eden Group."; + mes "We are here to assist adventurers in Rune Midgard."; + next; + mes "[Eden Group Officer]"; + mes "We have agents all over the world waiting to send you to our secret headquarters where you can get some useful quests."; + next; + mes "[Eden Group Officer]"; + mes "If you take our quests we even give you weapons and equipment so be sure to visit us once you are done with your training."; + next; + mes "[Eden Group Officer]"; + mes "Speak to me again once you have reached Base Level 10 and I will send you out of the training grounds."; + mes "Have you taken the quests from all of the Guides yet?"; + close; + }else{ + mes "[Eden Group Officer]"; + mes "Great! You are ready to take on the challenges of the world."; + mes "What would you like to do?"; + next; + switch(select("I want to leave the training grounds:Tell me about the towns.:Cancel")) { + case 1: + mes "[Eden Group Officer]"; + mes "Looks like you are ready."; + mes "I guess you have made up your mind, huh?"; + next; + mes "[Eden Group Officer]"; + mes "If you know what job you want to change to, you should ask the ^4A4AFFJob Guides^000000 to send you out of the training grounds."; + mes "What town would you like to go to?"; + next; + switch(select("Prontera:Morocc:Payon:Alberta:Geffen:Cancel")) { + case 1: + mes "[Eden Group Officer]"; + mes "Prontera, the Capital city of the Rune-Midgarts Kingdom."; + mes "Take care and may Freya bless you on your journey."; + callsub S_Warp,"prontera",121,77,121,76; + case 2: + mes "[Eden Group Officer]"; + mes "The desert city of Morocc was recently destroyed."; + mes "I will send you to the camp where the survivors are."; + callsub S_Warp,"moc_ruins",71,157,70,158; + case 3: + mes "[Eden Group Officer]"; + mes "Just north of Payon you'll find the Archer Village."; + mes "Good luck on your journeys."; + callsub S_Warp,"payon",167,68,172,111; + case 4: + mes "[Eden Group Officer]"; + mes "Alberta, the Port City."; + mes "It's the main hub of all trades."; + mes "If you want to travel to other civilizations, Alberta is the only outlet."; + callsub S_Warp,"alberta",115,57,116,58; + case 5: + mes "[Eden Group Officer]"; + mes "Geffen, is known as the Magical City of Rune Midgard."; + mes "I will send you near the Fountains."; + mes "Goddess Freya bless you."; + callsub S_Warp,"geffen",118,36,128,66; + case 6: + mes "[Eden Group Officer]"; + mes "If you're still not sure what job you want, talk to the Job Guides for more help."; + close; + } + case 2: + mes "[Eden Group Officer]"; + mes "Prontera is the main capital of the Rune-Midgard Kingdom. Here you will find Merchants selling their items and is a favorite gathering point of adventurers."; + next; + mes "[Eden Group Officer]"; + mes "The Acolyte Guild is here at the Prontera Church located to the northwest. The Swordman Guild can be found at Izlude, a town just southeast of Prontera."; + next; + mes "[Eden Group Officer]"; + mes "Morocc is a city located in the desert that was recently destroyed due to an evil monster named Satan Morroc. The Thief Guild has been working to restore it to it's former glory."; + next; + mes "[Eden Group Officer]"; + mes "Payon is where the Archer Guild has made it's home. You can also find the Kafra Shop Employees selling their Item Mall items near the center of this city."; + next; + mes "[Eden Group Officer]"; + mes "Alberta is the trading hub of Rune Midgard. The Merchant Guild is located here and the docks have ships that will take you to different island cities."; + next; + mes "[Eden Group Officer]"; + mes "Geffen is known as the magical city of Rune Midgard. The Mage Guild is located here and research for new magic is always being conducted at their headquarters."; + next; + mes "[Eden Group Officer]"; + mes "If you wish to be sent directly to the Job Guilds, then speak to the Job Guides and tell them that you want to change your job."; + close; + case 3: + close; + } + } + +S_Warp: + close2; + callfunc "F_NvErase",1; + savepoint getarg(0),getarg(1),getarg(2); + warp getarg(0),getarg(3),getarg(4); + end; + +OnTouch: + emotion e_gasp; + end; +} + +new_1-3,97,50,4 duplicate(NvEdn) Eden Group Officer#nv1 729,5,5 +new_2-3,97,50,4 duplicate(NvEdn) Eden Group Officer#nv2 729,5,5 +new_3-3,97,50,4 duplicate(NvEdn) Eden Group Officer#nv3 729,5,5 +new_4-3,97,50,4 duplicate(NvEdn) Eden Group Officer#nv4 729,5,5 +new_5-3,97,50,4 duplicate(NvEdn) Eden Group Officer#nv5 729,5,5 + +// Merchant (Real Combat Training) +//============================================================ +- shop Merchant#nv::NvPotato 93,516:15 + +new_1-3,100,50,4 duplicate(NvPotato) Merchant#nv1 93 +new_2-3,100,50,4 duplicate(NvPotato) Merchant#nv2 93 +new_3-3,100,50,4 duplicate(NvPotato) Merchant#nv3 93 +new_4-3,100,50,4 duplicate(NvPotato) Merchant#nv4 93 +new_5-3,100,50,4 duplicate(NvPotato) Merchant#nv5 93 + +// Trainer (Real Combat Training) +//============================================================ +- script Level 1 Trainer#nv::NvBrutus 84,{ + mes "[Trainer Brutus]"; + mes "These monsters are all weak and easy to kill. But be careful, a lot of them are aggressive and out for blood!"; + next; + mes "[Trainer Brutus]"; + mes "If you think monsters here are too weak for you, I can send you to another training ground where the monsters are stronger than the ones over here."; + next; + mes "[Trainer Brutus]"; + mes "So would you like to try?"; + next; + switch(select("Send me to another Level:What monsters are there?:Cancel")) { + case 1: + mes "[Trainer Brutus]"; + mes "I see, then let me guide you to another level. Which level do you want to go to?"; + next; + for(set .@i,1; .@i<6; set .@i,.@i+1) { + if (!compare(strnpcinfo(2),"nv"+.@i)) + set .@menu$, .@menu$+"Send me to Level "+.@i; + set .@menu$, .@menu$+":"; + } + set .@i, select(.@menu$+"Cancel"); + if (.@i < 7) warp "new_"+.@i+"-3",96,21; + close; + case 2: + mes "[Trainer Brutus]"; + mes "You seem eager to fight."; + mes "The monster levels increase with each level of the training grounds."; + next; + mes "[Trainer Brutus]"; + mes "Level 1 has the weakest monsters."; + mes "There you'll find Poring, Drops, Lunatics, Fabres, and Chonchons."; + next; + mes "[Trainer Brutus]"; + mes "Level 2 is more challenging."; + mes "There you'll find Condors, Pickys, Willows, Fabres, and Roda Frogs."; + next; + mes "[Trainer Brutus]"; + mes "Level 3 is pretty much the same as Level 2."; + mes "There you'll find Condors, Pickys, Willows, Fabres, and Roda Frogs."; + next; + mes "[Trainer Brutus]"; + mes "Level 4 has stronger monsters."; + mes "There you'll find Rockers, Spores, and Fabres."; + next; + mes "[Trainer Brutus]"; + mes "Level 5 is the same as Level 4."; + mes "There you'll find Rockers, Spores, and Fabres."; + close; + case 3: + mes "[Trainer Brutus]"; + mes "Hmm...?"; + mes "Are you worried about going to more challenging places? That's understandable, since you're still a new adventurer. Good luck~"; + close; + } +} + +new_1-3,103,50,4 duplicate(NvBrutus) Level 1 Trainer#nv1 84 +new_2-3,103,50,4 duplicate(NvBrutus) Level 2 Trainer#nv2 84 +new_3-3,103,50,4 duplicate(NvBrutus) Level 3 Trainer#nv3 84 +new_4-3,103,50,4 duplicate(NvBrutus) Level 4 Trainer#nv4 84 +new_5-3,103,50,4 duplicate(NvBrutus) Level 5 Trainer#nv5 84 + +// Random Stuff (Guards & Bulletin Board) +//============================================================ +new_1-1,66,114,4 script Bulletin Board#nv 111,{ + mes "^FF0000=================================^000000"; + mes "^FF0000 ^000000 ^E40CAA[Welcome]^CC0000 to ^FF9000Novice^7FFF00 Training ^00FF00Grounds ^E40CAA[Welcome]^FF0000^000000"; + mes "^FF0000=================================^000000"; + close; +} + +new_1-1,144,116,2 script Guard#nv1 105,{ + mes "[Training Grounds Guard]"; + mes "Welcome to the Training Grounds."; + mes "You are now in the outer court yard. Please go inside the castle to begin your training."; + close; +} + +new_1-1,144,107,2 script Guard#nv2 105,{ + mes "[Training Grounds Guard]"; + if(rand(2)) { + mes "Come in!"; + mes "I would like to welcome you to the Training Grounds!"; + next; + mes "[Training Grounds Guard]"; + mes "In here, you can prepare yourself for your future adventures throughout the Ragnarok world!"; + } + else { + mes "Go, Novice, go!"; + mes "Fight, and grow stronger! Look towards a brighter tomorrow!"; + } + close; +} + +new_1-2,161,182,5 script Instructor#nv 92,{ + mes "[Edwin]"; + mes "Eh? Why are you still here?"; + mes "There are no more courses that you need to take."; + next; + mes "[Edwin]"; + mes "Well, I will let you out of here."; + mes "Go find the instructor, Brade."; + close2; + warp "new_1-2",100,100; + end; +} + +// Real Combat Training Mobs +//============================================================ +new_1-3,0,0,0,0 monster ChonChon 1011,10,0,0,0 +new_1-3,0,0,0,0 monster Drops 1113,10,0,0,0 +new_1-3,0,0,0,0 monster Fabre 1184,5,0,0,0 +new_1-3,0,0,0,0 monster Lunatic 1063,10,0,0,0 +new_1-3,0,0,0,0 monster Poring 1002,10,0,0,0 +new_2-3,0,0,0,0 monster Condor 1009,10,0,0,0 +new_2-3,0,0,0,0 monster Fabre 1184,5,0,0,0 +new_2-3,0,0,0,0 monster Picky 1050,10,0,0,0 +new_2-3,0,0,0,0 monster Roda Frog 1012,10,0,0,0 +new_2-3,0,0,0,0 monster Willow 1010,10,0,0,0 +new_3-3,0,0,0,0 monster Condor 1009,10,0,0,0 +new_3-3,0,0,0,0 monster Fabre 1184,5,0,0,0 +new_3-3,0,0,0,0 monster Picky 1050,10,0,0,0 +new_3-3,0,0,0,0 monster Roda Frog 1012,10,0,0,0 +new_3-3,0,0,0,0 monster Willow 1010,10,0,0,0 +new_4-3,0,0,0,0 monster Fabre 1184,5,0,0,0 +new_4-3,0,0,0,0 monster Rocker 1052,10,0,0,0 +new_4-3,0,0,0,0 monster Spore 1014,10,0,0,0 +new_4-3,0,0,0,0 monster Thief Bug 1051,10,0,0,0 +new_4-3,0,0,0,0 monster Thief Bug 1053,10,0,0,0 +new_5-3,0,0,0,0 monster Fabre 1184,5,0,0,0 +new_5-3,0,0,0,0 monster Rocker 1052,10,0,0,0 +new_5-3,0,0,0,0 monster Spore 1014,1,0,0,0 +new_5-3,0,0,0,0 monster Thief Bug 1051,1,0,0,0 +new_5-3,0,0,0,0 monster Thief Bug 1053,1,0,0,0 \ No newline at end of file diff --git a/npc/scripts_jobs.conf b/npc/scripts_jobs.conf index 966f9fbfa..61191700e 100644 --- a/npc/scripts_jobs.conf +++ b/npc/scripts_jobs.conf @@ -43,7 +43,6 @@ npc: npc/jobs/2-2a/Stalker.txt npc: npc/jobs/2-2e/SoulLinker.txt // - Novice npc: npc/jobs/novice/supernovice.txt -npc: npc/jobs/novice/novice.txt // - Transcended Quest (2-x -> High Novice) npc: npc/jobs/valkyrie.txt -- cgit v1.2.3-70-g09d2 From f1936fb677d1b86164b455c67e539db15eb92d31 Mon Sep 17 00:00:00 2001 From: CairoLee Date: Thu, 30 May 2013 20:40:56 +0800 Subject: - Merge checkhomcall Script Command from rAthena --- doc/script_commands.txt | 13 +++++++++++++ src/map/script.c | 26 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 5fbf652a4..26801c07c 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -5636,6 +5636,19 @@ IDs. Returns 1 upon success and 0 for all failures. +--------------------------------------- + +*checkhomcall() + +This function checks if the attached player's Homunculus is active, +and will return the following values: + -1: The player has no Homunculus. + 0: The player's Homunculus is active. + 1: The player's Homunculus is vaporized. + 2: The player's Homunculus is in morph state. + +--------------------------------------- + *gethominfo() This function works as a direct counterpart of 'getpetinfo': diff --git a/src/map/script.c b/src/map/script.c index 9a123705b..7e15b3372 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -9795,6 +9795,31 @@ BUILDIN(homunculus_shuffle) { return true; } +/*========================================== + * Check for homunculus state. + * Return: -1 = No homunculus + * 0 = Homunculus is active + * 1 = Homunculus is vaporized (rest) + * 2 = Homunculus is in morph state + *------------------------------------------*/ +BUILDIN(checkhomcall) +{ + TBL_PC *sd = script_rid2sd(st); + TBL_HOM *hd; + + if( sd == NULL ) + return false; + + hd = sd->hd; + + if( !hd ) + script_pushint(st, -1); + else + script_pushint(st, hd->homunculus.vaporize); + + return true; +} + //These two functions bring the eA MAPID_* class functionality to scripts. BUILDIN(eaclass) { @@ -17401,6 +17426,7 @@ void script_parse_builtin(void) { BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn] BUILDIN_DEF2(homunculus_mutate,"hommutate","?"), BUILDIN_DEF2(homunculus_shuffle,"homshuffle",""), //[Zephyrus] + BUILDIN_DEF(checkhomcall,""), BUILDIN_DEF(eaclass,"?"), //[Skotlex] BUILDIN_DEF(roclass,"i?"), //[Skotlex] BUILDIN_DEF(checkvending,"?"), -- cgit v1.2.3-70-g09d2 From 20bdc01fa687b174a732be4483ddea4982d67ce9 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 30 May 2013 21:00:22 -0300 Subject: Memory Slasher - May 30 Patch http://hercules.ws/board/topic/928-memory-slasher-may-30-patch/ Signed-off-by: shennetsind --- conf/battlegrounds.conf | 101 ++++++ npc/instances/EndlessTower.txt | 447 +++++++++++++------------- npc/instances/NydhoggsNest.txt | 82 ++--- npc/instances/OrcsMemory.txt | 88 ++--- npc/instances/SealedShrine.txt | 76 +++-- src/char/char.c | 46 ++- src/char/char.h | 2 +- src/common/console.c | 6 + src/common/malloc.c | 102 +++++- src/common/malloc.h | 2 + src/common/mmo.h | 5 +- src/common/socket.c | 60 ++-- src/common/socket.h | 14 +- src/map/atcommand.c | 2 +- src/map/battleground.c | 508 +++++++++++++++++++++++++++-- src/map/battleground.h | 66 +++- src/map/chrif.c | 7 +- src/map/clif.c | 248 ++++++++++---- src/map/clif.h | 41 ++- src/map/guild.c | 10 +- src/map/instance.c | 484 ++++++++++++++++------------ src/map/instance.h | 76 +++-- src/map/intif.c | 2 +- src/map/irc-bot.c | 6 +- src/map/map.c | 467 +++++++++++++++++---------- src/map/map.h | 31 +- src/map/mob.c | 7 +- src/map/npc.c | 327 +++++++++---------- src/map/npc.h | 12 +- src/map/packets.h | 5 +- src/map/packets_struct.h | 62 ++++ src/map/party.c | 107 ++++--- src/map/party.h | 3 +- src/map/path.c | 36 +-- src/map/pc.c | 148 ++++++--- src/map/pc.h | 15 + src/map/script.c | 709 ++++++++++++++++++++++++++++++----------- src/map/script.h | 38 +++ src/map/skill.c | 2 +- src/map/status.c | 17 +- src/map/unit.c | 37 ++- 41 files changed, 3084 insertions(+), 1420 deletions(-) create mode 100644 conf/battlegrounds.conf diff --git a/conf/battlegrounds.conf b/conf/battlegrounds.conf new file mode 100644 index 000000000..b43899dd7 --- /dev/null +++ b/conf/battlegrounds.conf @@ -0,0 +1,101 @@ +//==================================================== +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//= +//= http://hercules.ws/board/ +//==================================================== +//= Link~u! +//= 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) */ + } + ) +}) \ No newline at end of file diff --git a/npc/instances/EndlessTower.txt b/npc/instances/EndlessTower.txt index 7edbc618f..a6c330e69 100644 --- a/npc/instances/EndlessTower.txt +++ b/npc/instances/EndlessTower.txt @@ -202,7 +202,8 @@ alberta,214,77,6 script Captain Janssen 709,{ } } -e_tower,81,105,0 script Tower Protection Stone 406,{ +//e_tower,81,105,0 script Tower Protection Stone 406,{ +prontera,150,150,0 script Tower Protection Stone 952,{ set .@party_id,getcharid(1); set .@ins_mas,getpartyleader(.@party_id,2); @@ -481,7 +482,7 @@ e_tower,151,185,4 script Purification Stone#et2 844,{ } else { delitem 6000,1; //Dark_Ashes - instance_announce 0, .@move_name$ + ". You will be warped to the 26th Level.",bc_map,"0x00ff99"; + instance_announce -1, .@move_name$ + ". You will be warped to the 26th Level.",bc_map,"0x00ff99"; warp "2@tower",52,354; } break; @@ -493,7 +494,7 @@ e_tower,151,185,4 script Purification Stone#et2 844,{ } else { delitem 6000,2; //Dark_Ashes - instance_announce 0, .@move_name$ + ". You will be warped to the 51st Level.",bc_map,"0x00ff99"; + instance_announce -1, .@move_name$ + ". You will be warped to the 51st Level.",bc_map,"0x00ff99"; warp "3@tower",52,354; } break; @@ -505,7 +506,7 @@ e_tower,151,185,4 script Purification Stone#et2 844,{ } else { delitem 6000,3; //Dark_Ashes - instance_announce 0, .@move_name$ + ". You will be warped to the 76th Level.",bc_map,"0x00ff99"; + instance_announce -1, .@move_name$ + ". You will be warped to the 76th Level.",bc_map,"0x00ff99"; warp "4@tower",52,354; } break; @@ -532,11 +533,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 1 } else - instance_announce 0, "Remaining Monsters on the 1st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 1st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 1st Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 1st Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("1FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -567,11 +568,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 2 } else - instance_announce 0, "Remaining Monsters on the 2nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 2nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 2nd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 2nd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("2FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -605,11 +606,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 3 } else - instance_announce 0, "Remaining Monsters on the 3rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 3rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 3rd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 3rd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("3FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -643,11 +644,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 4 } else - instance_announce 0, "Remaining Monsters on the 4th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 4th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 4th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 4th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("4FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -680,11 +681,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 5 } else - instance_announce 0, "Remaining Monsters on the 5th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 5th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 5th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 5th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("5FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -716,11 +717,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 6 } else - instance_announce 0, "Remaining Monsters on the 6th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 6th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 6th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 6th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("6FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -752,11 +753,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 7 } else - instance_announce 0, "Remaining Monsters on the 7th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 7th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 7th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 7th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("7FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -786,11 +787,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 8 } else - instance_announce 0, "Remaining Monsters on the 8th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 8th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 8th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 8th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("8FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -821,11 +822,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 9 } else - instance_announce 0, "Remaining Monsters on the 9th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 9th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 9th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 9th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("9FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -856,11 +857,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 10 } else - instance_announce 0, "Remaining Monsters on the 10th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 10th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 10th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 10th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("10FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -892,11 +893,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 11 } else - instance_announce 0, "Remaining Monsters on the 11th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 11th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 11th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 11th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("11FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -926,11 +927,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 12 } else - instance_announce 0, "Remaining Monsters on the 12th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 12th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 12th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 12th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("12FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -961,11 +962,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 13 } else - instance_announce 0, "Remaining Monsters on the 13th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 13th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 13th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 13th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("13FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -998,11 +999,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 14 } else - instance_announce 0, "Remaining Monsters on the 14th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 14th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 14th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 14th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("14FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1037,11 +1038,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 15 } else - instance_announce 0, "Remaining Monsters on the 15th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 15th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 15th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 15th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("15FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1073,11 +1074,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 16 } else - instance_announce 0, "Remaining Monsters on the 16th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 16th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 16th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 16th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("16FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1109,11 +1110,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 17 } else - instance_announce 0, "Remaining Monsters on the 17th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 17th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 17th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 17th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("17FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1143,11 +1144,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 18 } else - instance_announce 0, "Remaining Monsters on the 18th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 18th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 18th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 18th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("18FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1179,11 +1180,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 19 } else - instance_announce 0, "Remaining Monsters on the 19th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 19th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 19th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 19th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("19FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1213,11 +1214,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 20 } else - instance_announce 0, "Remaining Monsters on the 20th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 20th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 20th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 20th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("20FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1250,11 +1251,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 21 } else - instance_announce 0, "Remaining Monsters on the 21st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 21st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 21st Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 21st Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("21FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1288,11 +1289,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 22 } else - instance_announce 0, "Remaining Monsters on the 22nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 22nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 22nd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 22nd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("22FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1325,11 +1326,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 23 } else - instance_announce 0, "Remaining Monsters on the 23rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 23rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 23rd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 23rd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("23FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1360,11 +1361,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 24 } else - instance_announce 0, "Remaining Monsters on the 24th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 24th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 24th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 24th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("24FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1395,11 +1396,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 25 } else - instance_announce 0, "Remaining Monsters on the 25th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 25th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 25th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 25th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("25FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1487,11 +1488,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 26 } else - instance_announce 0, "Remaining Monsters on the 26th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 26th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 26th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 26th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("26FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1525,11 +1526,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 27 } else - instance_announce 0, "Remaining Monsters on the 27th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 27th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 27th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 27th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("27FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1561,11 +1562,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 28 } else - instance_announce 0, "Remaining Monsters on the 28th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 28th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 28th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 28th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("28FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1599,11 +1600,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 29 } else - instance_announce 0, "Remaining Monsters on the 29th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 29th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 29th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 29th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("29FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1633,11 +1634,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 30 } else - instance_announce 0, "Remaining Monsters on the 30th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 30th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 30th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 30th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("30FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1669,11 +1670,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 31 } else - instance_announce 0, "Remaining Monsters on the 31st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 31st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 31st Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 31st Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("31FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1708,11 +1709,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 32 } else - instance_announce 0, "Remaining Monsters on the 32nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 32nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 32nd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 32nd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("32FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1745,11 +1746,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 33 } else - instance_announce 0, "Remaining Monsters on the 33rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 33rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 33rd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 33rd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("33FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1780,11 +1781,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 34 } else - instance_announce 0, "Remaining Monsters on the 34th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 34th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 34th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 34th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("34FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1817,11 +1818,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 35 } else - instance_announce 0, "Remaining Monsters on the 35th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 35th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 35th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 35th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("35FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1852,11 +1853,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 36 } else - instance_announce 0, "Remaining Monsters on the 36th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 36th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 36th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 36th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("36FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1887,11 +1888,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 37 } else - instance_announce 0, "Remaining Monsters on the 37th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 37th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 37th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 37th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("37FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1921,11 +1922,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 38 } else - instance_announce 0, "Remaining Monsters on the 38th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 38th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 38th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 38th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("38FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1958,11 +1959,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 39 } else - instance_announce 0, "Remaining Monsters on the 39th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 39th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 39th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 39th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("39FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -1996,11 +1997,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 40 } else - instance_announce 0, "Remaining Monsters on the 40th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 40th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 40th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 40th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("40FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2029,11 +2030,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 41 } else - instance_announce 0, "Remaining Monsters on the 41st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 41st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 41st Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 41st Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("41FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2066,11 +2067,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 42 } else - instance_announce 0, "Remaining Monsters on the 42nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 42nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 42nd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 42nd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("42FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2102,11 +2103,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 43 } else - instance_announce 0, "Remaining Monsters on the 43rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 43rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 43rd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 43rd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("43FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2139,11 +2140,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 44 } else - instance_announce 0, "Remaining Monsters on the 44th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 44th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 44th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 44th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("44FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2175,11 +2176,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 45 } else - instance_announce 0, "Remaining Monsters on the 45th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 45th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 45th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 45th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("45FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2209,11 +2210,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 46 } else - instance_announce 0, "Remaining Monsters on the 46th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 46th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 46th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 46th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("46FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2245,11 +2246,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 47 } else - instance_announce 0, "Remaining Monsters on the 47 Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 47 Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 47th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 47th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("47FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2280,11 +2281,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 48 } else - instance_announce 0, "Remaining Monsters on the 48th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 48th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 48th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 48th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("48FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2317,11 +2318,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 49 } else - instance_announce 0, "Remaining Monsters on the 49th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 49th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 49th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 49th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("49FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2354,11 +2355,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 50 } else - instance_announce 0, "Remaining Monsters on the 50th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 50th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 50th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 50th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("50FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2444,11 +2445,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 51 } else - instance_announce 0, "Remaining Monsters on the 51st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 51st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 51st Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 51st Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("51FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2482,11 +2483,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 52 } else - instance_announce 0, "Remaining Monsters on the 52nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 52nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 52nd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 52nd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("52FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2516,11 +2517,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 53 } else - instance_announce 0, "Remaining Monsters on the 53rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 53rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 53rd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 53rd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("53FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2551,11 +2552,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 54 } else - instance_announce 0, "Remaining Monsters on the 54th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 54th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 54th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 54th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("54FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2587,11 +2588,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 55 } else - instance_announce 0, "Remaining Monsters on the 55th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 55th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 55th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 55th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("55FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2624,11 +2625,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 56 } else - instance_announce 0, "Remaining Monsters on the 56th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 56th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 56th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 56th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("56FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2665,11 +2666,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 57 } else - instance_announce 0, "Remaining Monsters on the 57th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 57th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 57th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 57th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("57FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2702,11 +2703,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 58 } else - instance_announce 0, "Remaining Monsters on the 58th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 58th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 58th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 58th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("58FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2737,11 +2738,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 59 } else - instance_announce 0, "Remaining Monsters on the 59th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 59th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 59th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 59th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("59FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2777,11 +2778,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 60 } else - instance_announce 0, "Remaining Monsters on the 60th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 60th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 60th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 60th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("60FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2815,11 +2816,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 61 } else - instance_announce 0, "Remaining Monsters on the 61st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 61st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 61st Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 61st Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("61FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2848,11 +2849,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 62 } else - instance_announce 0, "Remaining Monsters on the 62nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 62nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 62nd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 62nd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("62FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2885,11 +2886,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 63 } else - instance_announce 0, "Remaining Monsters on the 63rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 63rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 63rd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 63rd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("63FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2923,11 +2924,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 64 } else - instance_announce 0, "Remaining Monsters on the 64th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 64th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 64th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 64th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("64FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2957,11 +2958,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 65 } else - instance_announce 0, "Remaining Monsters on the 65th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 65th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 65th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 65th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("65FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -2992,11 +2993,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 66 } else - instance_announce 0, "Remaining Monsters on the 66th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 66th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 66th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 66th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("66FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3029,11 +3030,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 67 } else - instance_announce 0, "Remaining Monsters on the 67th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 67th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 67th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 67th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("67FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3066,11 +3067,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 68 } else - instance_announce 0, "Remaining Monsters on the 68th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 68th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 68th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 68th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("68FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3103,11 +3104,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 69 } else - instance_announce 0, "Remaining Monsters on the 69th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 69th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 69th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 69th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("69FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3138,11 +3139,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 70 } else - instance_announce 0, "Remaining Monsters on the 70th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 70th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 70th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 70th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("70FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3174,11 +3175,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 71 } else - instance_announce 0, "Remaining Monsters on the 71st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 71st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 71st Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 71st Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("71FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3210,11 +3211,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 72 } else - instance_announce 0, "Remaining Monsters on the 72nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 72nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 72nd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 72nd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("72FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3248,11 +3249,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 73 } else - instance_announce 0, "Remaining Monsters on the 73rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 73rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 73rd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 73rd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("73FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3289,11 +3290,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 74 } else - instance_announce 0, "Remaining Monsters on the 74th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 74th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 74th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 74th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("74FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3325,11 +3326,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 75 } else - instance_announce 0, "Remaining Monsters on the 75th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1, "Remaining Monsters on the 75th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0, "All Monsters on the 75th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1, "All Monsters on the 75th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("75FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3415,11 +3416,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 76 } else - instance_announce 0,"Remaining Monsters on the 76th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 76th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 76th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 76th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("76FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3452,11 +3453,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 77 } else - instance_announce 0,"Remaining Monsters on the 77th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 77th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 77th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 77th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("77FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3489,11 +3490,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 78 } else - instance_announce 0,"Remaining Monsters on the 78th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 78th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the Level 78th have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the Level 78th have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("78FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3526,11 +3527,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 79 } else - instance_announce 0,"Remaining Monsters on the 79th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 79th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 79th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 79th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("79FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3560,11 +3561,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 80 } else - instance_announce 0,"Remaining Monsters on the 80th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 80th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 80th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 80th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("80FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3595,11 +3596,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 81 } else - instance_announce 0,"Remaining Monsters on the 81st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 81st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 81st Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 81st Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("81FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3632,11 +3633,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 82 } else - instance_announce 0,"Remaining Monsters on the 82nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 82nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 82nd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 82nd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("82FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3668,11 +3669,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 83 } else - instance_announce 0,"Remaining Monsters on the 83rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 83rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 83rd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 83rd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("83FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3705,11 +3706,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 84 } else - instance_announce 0,"Remaining Monsters on the 84th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 84th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 84th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 84th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("84FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3738,11 +3739,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 85 } else - instance_announce 0,"Remaining Monsters on the 85th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 85th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 85th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 85th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("85FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3774,11 +3775,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 86 } else - instance_announce 0,"Remaining Monsters on the 86th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 86th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 86th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 86th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("86FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3810,11 +3811,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 87 } else - instance_announce 0,"Remaining Monsters on the 87th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 87th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 87th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 87th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("87FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3847,11 +3848,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 88 } else - instance_announce 0,"Remaining Monsters on the 88th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 88th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 88th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 88th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("88FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3883,11 +3884,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 89 } else - instance_announce 0,"Remaining Monsters on the 89th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 89th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 89th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 89th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("89FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3919,11 +3920,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 90 } else - instance_announce 0,"Remaining Monsters on the 90th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 90th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 90th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 90th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("90FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3954,11 +3955,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 91 } else - instance_announce 0,"Remaining Monsters on the 91st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 91st Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 91st Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 91st Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("91FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -3991,11 +3992,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 92 } else - instance_announce 0,"Remaining Monsters on the 92nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 92nd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 92nd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 92nd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("92FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -4027,11 +4028,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 93 } else - instance_announce 0,"Remaining Monsters on the 93rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 93rd Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 93rd Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 93rd Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("93FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -4061,11 +4062,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 94 } else - instance_announce 0,"Remaining Monsters on the 94th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 94th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 94th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 94th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("94FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -4098,11 +4099,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 95 } else - instance_announce 0,"Remaining Monsters on the 95th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 95th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 95th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 95th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("95FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -4133,11 +4134,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 96 } else - instance_announce 0,"Remaining Monsters on the 96th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 96th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 96th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 96th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("96FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -4169,11 +4170,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 97 } else - instance_announce 0,"Remaining Monsters on the 97th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 97th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 97th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 97th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("97FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -4207,11 +4208,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 98 } else - instance_announce 0,"Remaining Monsters on the 98th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 98th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 98th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 98th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("98FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -4302,11 +4303,11 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 99 } else - instance_announce 0,"Remaining Monsters on the 99th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; + instance_announce -1,"Remaining Monsters on the 99th Level - " + .@mob_dead_num,bc_map,"0x00ff99"; end; OnTimer5000: - instance_announce 0,"All Monsters on the 99th Level have been defeated.",bc_map,"0xffff00"; + instance_announce -1,"All Monsters on the 99th Level have been defeated.",bc_map,"0xffff00"; donpcevent instance_npcname("99FGate102tower", instance_id())+"::OnEnable"; stopnpctimer; end; @@ -4488,7 +4489,7 @@ OnInstanceInit: OnMyMobDead: set .@mob_dead_num,mobcount("5@tower",instance_npcname("#102FShadowDust1", instance_id())+"::OnMyMobDead"); if (.@mob_dead_num < 1) { - instance_announce 0, "Mysterious Voice: Who are you to dare intrude upon my sanctuary?!",bc_map,"0xffff00"; + instance_announce -1, "Mysterious Voice: Who are you to dare intrude upon my sanctuary?!",bc_map,"0xffff00"; donpcevent instance_npcname("#102FShadowDust", instance_id())+"::OnDisable"; donpcevent instance_npcname("Lucid Crystal#102", instance_id())+"::OnEnable"; //SetItemPartyInMap in_102floor 100 @@ -4633,23 +4634,23 @@ OnEnable: end; OnTimer500: - instance_announce 0,"Guests, huh? I hope you've come here knowing that you'll be buried in this place. If you didn't know, well... it's too late!",bc_map,"0x00ffcc"; + instance_announce -1,"Guests, huh? I hope you've come here knowing that you'll be buried in this place. If you didn't know, well... it's too late!",bc_map,"0x00ffcc"; end; OnTimer5500: - instance_announce 0,"This is why you adventurers always end up dead.",bc_map,"0x00ffcc"; + instance_announce -1,"This is why you adventurers always end up dead.",bc_map,"0x00ffcc"; end; OnTimer10500: - instance_announce 0,"I may applaud you for your courage... Of course, I intend to play with you a little bit first.",bc_map,"0x00ffcc"; + instance_announce -1,"I may applaud you for your courage... Of course, I intend to play with you a little bit first.",bc_map,"0x00ffcc"; end; OnTimer15500: - instance_announce 0,"You know, I like watching humans running around in fear.",bc_map,"0x00ffcc"; + instance_announce -1,"You know, I like watching humans running around in fear.",bc_map,"0x00ffcc"; end; OnTimer20500: - instance_announce 0,"Let's see who runs fastest. Are you ready?",bc_map,"0x00ffcc"; + instance_announce -1,"Let's see who runs fastest. Are you ready?",bc_map,"0x00ffcc"; stopnpctimer; areamonster "6@tower",151,66,153,106,"Bone Guardian",1152,50,instance_npcname("#1st Beeper", instance_id())+"::OnMyMobDead"; areamonster "6@tower",158,66,160,106,"Bone Guardian",1152,50,instance_npcname("#1st Beeper", instance_id())+"::OnMyMobDead"; @@ -4662,7 +4663,7 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 101 } else - instance_announce 0,"Remaining Targets " + .@mob_dead_num + "ea",bc_map,"0x00ff99"; + instance_announce -1,"Remaining Targets " + .@mob_dead_num + "ea",bc_map,"0x00ff99"; end; } @@ -4674,15 +4675,15 @@ OnEnable: end; OnTimer500: - instance_announce 0,"Well, I guess they aren't too challenging for you.",bc_map,"0x00ffcc"; + instance_announce -1,"Well, I guess they aren't too challenging for you.",bc_map,"0x00ffcc"; end; OnTimer5500: - instance_announce 0,"Let's speed up a little bit, shall we?",bc_map,"0x00ffcc"; + instance_announce -1,"Let's speed up a little bit, shall we?",bc_map,"0x00ffcc"; end; OnTimer10500: - instance_announce 0,"I demand an encore!",bc_map,"0x00ffcc"; + instance_announce -1,"I demand an encore!",bc_map,"0x00ffcc"; stopnpctimer; areamonster "6@tower",151,66,153,106,"Wind Guardian",1263,30,instance_npcname("#2nd Beeper", instance_id())+"::OnMyMobDead"; areamonster "6@tower",158,66,160,106,"Wind Guardian",1263,30,instance_npcname("#2nd Beeper", instance_id())+"::OnMyMobDead"; @@ -4695,7 +4696,7 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 102 } else - instance_announce 0,"Remaining Targets " + .@mob_dead_num + "ea",bc_map,"0x00ff99"; + instance_announce -1,"Remaining Targets " + .@mob_dead_num + "ea",bc_map,"0x00ff99"; end; } @@ -4707,15 +4708,15 @@ OnEnable: end; OnTimer500: - instance_announce 0,"Yes, this is getting exciting!",bc_map,"0x00ffcc"; + instance_announce -1,"Yes, this is getting exciting!",bc_map,"0x00ffcc"; end; OnTimer5500: - instance_announce 0,"I'll remember you as one of a few that have managed to entertain me.",bc_map,"0x00ffcc"; + instance_announce -1,"I'll remember you as one of a few that have managed to entertain me.",bc_map,"0x00ffcc"; end; OnTimer10500: - instance_announce 0,"How would you like to play one more round?",bc_map,"0x00ffcc"; + instance_announce -1,"How would you like to play one more round?",bc_map,"0x00ffcc"; stopnpctimer; areamonster "6@tower",151,66,153,106,"Sword Edge Guardian",1132,20,instance_npcname("#3rd Beeper", instance_id())+"::OnMyMobDead"; areamonster "6@tower",158,66,160,106,"Sword Edge Guardian",1132,20,instance_npcname("#3rd Beeper", instance_id())+"::OnMyMobDead"; @@ -4728,7 +4729,7 @@ OnMyMobDead: //SetItemPartyInMap in_102floor 103 } else - instance_announce 0,"Remaining Targets " + .@mob_dead_num + "ea",bc_map,"0x00ff99"; + instance_announce -1,"Remaining Targets " + .@mob_dead_num + "ea",bc_map,"0x00ff99"; end; } @@ -4740,15 +4741,15 @@ OnEnable: end; OnTimer500: - instance_announce 0,"Okay, the time has come to make my appearance!",bc_map,"0x00ffcc"; + instance_announce -1,"Okay, the time has come to make my appearance!",bc_map,"0x00ffcc"; end; OnTimer5500: - instance_announce 0,"Do you want to know who I am?",bc_map,"0x00ffcc"; + instance_announce -1,"Do you want to know who I am?",bc_map,"0x00ffcc"; end; OnTimer10500: - instance_announce 0,"You'll soon know. Mine is the face of death!",bc_map,"0x00ffcc"; + instance_announce -1,"You'll soon know. Mine is the face of death!",bc_map,"0x00ffcc"; stopnpctimer; monster "6@tower",156,147,"Nacht Sieger",1956,1,instance_npcname("#4th Beeper", instance_id())+"::OnMyMobDead"; end; @@ -4825,15 +4826,15 @@ OnEnable: end; OnTimer500: - instance_announce 0,"This... This can't be happening! I can't be defeated!",bc_map,"0xffff00"; + instance_announce -1,"This... This can't be happening! I can't be defeated!",bc_map,"0xffff00"; end; OnTimer5500: - instance_announce 0,"Nooo! My soul... My shell...! Nooo~!",bc_map,"0xffff00"; + instance_announce -1,"Nooo! My soul... My shell...! Nooo~!",bc_map,"0xffff00"; end; OnTimer10500: - instance_announce 0,"Nacht Sieger's body has turned into dark ashes that scattered in the wind.",bc_map,"0x00ffcc"; + instance_announce -1,"Nacht Sieger's body has turned into dark ashes that scattered in the wind.",bc_map,"0x00ffcc"; stopnpctimer; end; } diff --git a/npc/instances/NydhoggsNest.txt b/npc/instances/NydhoggsNest.txt index fffe47227..0ad8149d4 100644 --- a/npc/instances/NydhoggsNest.txt +++ b/npc/instances/NydhoggsNest.txt @@ -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"; diff --git a/npc/instances/OrcsMemory.txt b/npc/instances/OrcsMemory.txt index a23499d7e..325b1a739 100644 --- a/npc/instances/OrcsMemory.txt +++ b/npc/instances/OrcsMemory.txt @@ -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"; diff --git a/npc/instances/SealedShrine.txt b/npc/instances/SealedShrine.txt index fe376c688..b893a1816 100644 --- a/npc/instances/SealedShrine.txt +++ b/npc/instances/SealedShrine.txt @@ -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()); diff --git a/src/char/char.c b/src/char/char.c index 00fc633df..dc5352137 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -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]); diff --git a/src/char/char.h b/src/char/char.h index b48ea359c..996a0e845 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -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 diff --git a/src/common/console.c b/src/common/console.c index ba93b8e09..33d485497 100644 --- a/src/common/console.c +++ b/src/common/console.c @@ -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; diff --git a/src/common/malloc.c b/src/common/malloc.c index 4874aa0f4..e98ec770a 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -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; diff --git a/src/common/malloc.h b/src/common/malloc.h index 34a26b56e..1b8e82bd9 100644 --- a/src/common/malloc.h +++ b/src/common/malloc.h @@ -80,5 +80,7 @@ struct malloc_interface { void (*final) (void); } malloclib_s; +void memmgr_report (int extra); + struct malloc_interface *malloclib; #endif /* _MALLOC_H_ */ diff --git a/src/common/mmo.h b/src/common/mmo.h index d45dea212..a86aba723 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.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; }; diff --git a/src/common/socket.c b/src/common/socket.c index 5126d231b..0459004cc 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -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; diff --git a/src/common/socket.h b/src/common/socket.h index 4879cb109..b58cbdccf 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -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); diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 65da7aa24..796447633 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -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 diff --git a/src/map/battleground.c b/src/map/battleground.c index 618679406..4bb6035ad 100644 --- a/src/map/battleground.c +++ b/src/map/battleground.c @@ -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; + + 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 ) */ + + 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"); + } + } -void do_init_battleground(void) -{ + 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; iguild->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; iguild->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; iguild->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; } diff --git a/src/map/battleground.h b/src/map/battleground.h index c2b74a534..8fe9f3b77 100644 --- a/src/map/battleground.h +++ b/src/map/battleground.h @@ -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_ */ diff --git a/src/map/chrif.c b/src/map/chrif.c index 06956e731..ee2e252c1 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -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; diff --git a/src/map/clif.c b/src/map/clif.c index 2f69ce2fd..99b4d8c11 100644 --- a/src/map/clif.c +++ b/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 .16B .W .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 .16B .W .W .L .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 .61B .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 .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 .61B .L .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 .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; diff --git a/src/map/clif.h b/src/map/clif.h index 3e3db98c1..4347ad743 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -8,6 +8,7 @@ #include "../common/cbasetypes.h" #include "../common/db.h" #include "../common/mmo.h" +#include "../common/socket.h" #include /** @@ -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); diff --git a/src/map/guild.c b/src/map/guild.c index b83f05f00..a6c873861 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -24,6 +24,7 @@ #include "clif.h" #include "skill.h" #include "log.h" +#include "instance.h" #include #include @@ -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); diff --git a/src/map/instance.c b/src/map/instance.c index 8ddde8b3e..7b3e2e800 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -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 #include -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 */ } - - 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; - + + ARR_FIND(0, instance->instances, i, instances[i].state == INSTANCE_FREE); + + if( i == instance->instances ) + RECREATE(instances, struct instance_data, ++instance->instances); + + 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, 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; + + ARR_FIND( instance->start_id, map_num, i, !map[i].name[0] ); // Searching for a Free Map + + 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); - - if( !instance_is_valid(instance_id) ) +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->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( 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].vars ) + db_destroy(instances[instance_id].vars); - instance[instance_id].vars = NULL; + 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( instance[instance_id].party_id && (p = party_search(instance[instance_id].party_id)) != NULL ) - p->instance_id = 0; // Update Party information + instances[instance_id].vars = NULL; - ShowInfo("[Instance] Destroyed %s.\n", instance[instance_id].name); - memset( &instance[instance_id], 0x00, sizeof(instance[0]) ); + aFree(instances[instance_id].map); + + memset( &instances[instance_id], 0x00, sizeof(struct instance_data) ); - 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( 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( 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 ) { + 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; +} diff --git a/src/map/instance.h b/src/map/instance.h index 03b0d0898..e86586e44 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -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; + +enum instance_owner_type { + IOT_NONE, + IOT_CHAR, + IOT_PARTY, + IOT_GUILD, + /* ... */ + IOT_MAX, +}; -struct s_instance { +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 diff --git a/src/map/intif.c b/src/map/intif.c index 93bb8add7..9e6403f10 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -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; diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c index 0e155011e..bfaf18af0 100644 --- a/src/map/irc-bot.c +++ b/src/map/irc-bot.c @@ -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); diff --git a/src/map/map.c b/src/map/map.c index d4c15cd6e..54646d1c3 100644 --- a/src/map/map.c +++ b/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; jchsys_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(); diff --git a/src/map/map.h b/src/map/map.h index f524e8840..850913474 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -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; diff --git a/src/map/mob.c b/src/map/mob.c index 57325ba1c..433e979f3 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -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; } diff --git a/src/map/npc.c b/src/map/npc.c index 7d0d5c6e1..bff6be30c 100644 --- a/src/map/npc.c +++ b/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;isc.option&OPTION_INVISIBLE) { + for(i=0;ioption&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;isc.option&OPTION_INVISIBLE) + for(i=0;ioption&OPTION_INVISIBLE) continue; - 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)) + 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.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 )// ,,, { 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 );// , else if( type == SCRIPT && sscanf(w4, "%d,%d,%d", &class_, &xs, &ys) == 3);// ,, else if( type != WARP ) class_ = atoi(w4);// - 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; - - 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; + 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 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; } diff --git a/src/map/npc.h b/src/map/npc.h index 8a8b14d6e..16e6fe74c 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -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 */ diff --git a/src/map/packets.h b/src/map/packets.h index 7e14305b7..92df54367 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -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 diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index c873d3ad3..9d1f9b280 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -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_ */ diff --git a/src/map/party.c b/src/map/party.c index 8a632a8ef..4462d4f07 100644 --- a/src/map/party.c +++ b/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; } diff --git a/src/map/party.h b/src/map/party.h index 12fe7a2bc..3978324e4 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -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? diff --git a/src/map/path.c b/src/map/path.c index 3bbd8d20b..8ab63d390 100644 --- a/src/map/path.c +++ b/src/map/path.c @@ -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) diff --git a/src/map/pc.c b/src/map/pc.c index 55ce993b4..241e0fbb3 100644 --- a/src/map/pc.c +++ b/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;jbl.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; diff --git a/src/map/pc.h b/src/map/pc.h index b1fa3e741..5207c4c34 100644 --- a/src/map/pc.h +++ b/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; diff --git a/src/map/script.c b/src/map/script.c index 41f8e7472..d42d3d3e3 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -816,10 +816,12 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom) func = add_word(p); if( str_data[func].type == C_FUNC ){ + char argT = 0; // buildin function add_scriptl(func); add_scriptc(C_ARG); arg = script->buildin[str_data[func].val]; + if( !arg ) arg = &argT; } else if( str_data[func].type == C_USERFUNC || str_data[func].type == C_USERFUNC_POS ){ // script defined function add_scriptl(buildin_callsub_ref); @@ -2358,8 +2360,8 @@ void get_val(struct script_state* st, struct script_data* data) } break; case '\'': - if (st->instance_id) { - data->u.str = (char*)idb_get(instance[st->instance_id].vars,reference_getuid(data)); + if ( st->instance_id >= 0 ) { + data->u.str = (char*)idb_get(instances[st->instance_id].vars,reference_getuid(data)); } else { ShowWarning("script:get_val: cannot access instance variable '%s', defaulting to \"\"\n", name); data->u.str = NULL; @@ -2423,8 +2425,8 @@ void get_val(struct script_state* st, struct script_data* data) } break; case '\'': - if( st->instance_id ) - data->u.num = (int)idb_iget(instance[st->instance_id].vars,reference_getuid(data)); + if( st->instance_id >= 0 ) + data->u.num = (int)idb_iget(instances[st->instance_id].vars,reference_getuid(data)); else { ShowWarning("script:get_val: cannot access instance variable '%s', defaulting to 0\n", name); data->u.num = 0; @@ -2484,9 +2486,9 @@ static int set_reg(struct script_state* st, TBL_PC* sd, int num, const char* nam } return 1; case '\'': - if( st->instance_id ) { - idb_remove(instance[st->instance_id].vars, num); - if( str[0] ) idb_put(instance[st->instance_id].vars, num, aStrdup(str)); + if( st->instance_id >= 0 ) { + idb_remove(instances[st->instance_id].vars, num); + if( str[0] ) idb_put(instances[st->instance_id].vars, num, aStrdup(str)); } return 1; default: @@ -2532,10 +2534,10 @@ static int set_reg(struct script_state* st, TBL_PC* sd, int num, const char* nam } return 1; case '\'': - if( st->instance_id ) { - idb_remove(instance[st->instance_id].vars, num); + if( st->instance_id >= 0 ) { + idb_remove(instances[st->instance_id].vars, num); if( val != 0 ) - idb_iput(instance[st->instance_id].vars, num, val); + idb_iput(instances[st->instance_id].vars, num, val); } return 1; default: @@ -3462,7 +3464,7 @@ void run_script_main(struct script_state *st) script_attach_state(st); nd = map_id2nd(st->oid); - if( nd && map[nd->bl.m].instance_id > 0 ) + if( nd ) st->instance_id = map[nd->bl.m].instance_id; if(st->state == RERUNLINE) { @@ -3845,9 +3847,25 @@ void do_final_script(void) { script->buildin[i] = NULL; } } - - aFree(script->buildin); + aFree(script->buildin); + + if( script->hqs ) { + for( i = 0; i < script->hqs; i++ ) { + if( script->hq[i].item != NULL ) + aFree(script->hq[i].item); + } + } + if( script->hqis ) { + for( i = 0; i < script->hqis; i++ ) { + if( script->hqi[i].item != NULL ) + aFree(script->hqi[i].item); + } + } + if( script->hq != NULL ) + aFree(script->hq); + if( script->hqi != NULL ) + aFree(script->hqi); } /*========================================== * Initialization @@ -8457,13 +8475,10 @@ BUILDIN(monster) if (sd && strcmp(mapn, "this") == 0) m = sd->bl.m; - else - { + else { m = map_mapname2mapid(mapn); - if (map[m].flag.src4instance && st->instance_id) - { // Try to redirect to the instance map, not the src map - if ((m = instance_mapid2imapid(m, st->instance_id)) < 0) - { + if (map[m].flag.src4instance && st->instance_id >= 0) { // Try to redirect to the instance map, not the src map + if ((m = instance->mapid2imapid(m, st->instance_id)) < 0) { ShowError("buildin_monster: Trying to spawn monster (%d) on instance map (%s) without instance attached.\n", class_, mapn); return false; } @@ -8528,27 +8543,22 @@ BUILDIN(areamonster) struct map_session_data* sd; int16 m; - if (script_hasdata(st,10)) - { + if (script_hasdata(st,10)) { event = script_getstr(st, 10); check_event(st, event); } - if (script_hasdata(st, 11)) - { + if (script_hasdata(st, 11)) { size = script_getnum(st, 11); - if (size > 3) - { + if (size > 3) { ShowWarning("buildin_monster: Attempted to spawn non-existing size %d for monster class %d\n", size, class_); return false; } } - if (script_hasdata(st, 12)) - { + if (script_hasdata(st, 12)) { ai = script_getnum(st, 12); - if (ai > 4) - { + if (ai > 4) { ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_); return false; } @@ -8558,13 +8568,10 @@ BUILDIN(areamonster) if (sd && strcmp(mapn, "this") == 0) m = sd->bl.m; - else - { + else { m = map_mapname2mapid(mapn); - if (map[m].flag.src4instance && st->instance_id) - { // Try to redirect to the instance map, not the src map - if ((m = instance_mapid2imapid(m, st->instance_id)) < 0) - { + if (map[m].flag.src4instance && st->instance_id >= 0) { // Try to redirect to the instance map, not the src map + if ((m = instance->mapid2imapid(m, st->instance_id)) < 0) { ShowError("buildin_areamonster: Trying to spawn monster (%d) on instance map (%s) without instance attached.\n", class_, mapn); return false; } @@ -8624,7 +8631,7 @@ BUILDIN(killmonster) if( (m=map_mapname2mapid(mapname))<0 ) return true; - if( map[m].flag.src4instance && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) + if( map[m].flag.src4instance && st->instance_id >= 0 && (m = instance->mapid2imapid(m, st->instance_id)) < 0 ) return true; if( script_hasdata(st,4) ) { @@ -8665,7 +8672,7 @@ BUILDIN(killmonsterall) if( (m = map_mapname2mapid(mapname))<0 ) return true; - if( map[m].flag.src4instance && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) + if( map[m].flag.src4instance && st->instance_id >= 0 && (m = instance->mapid2imapid(m, st->instance_id)) < 0 ) return true; if( script_hasdata(st,3) ) { @@ -11168,8 +11175,7 @@ BUILDIN(mobcount) // Added by RoVeRT return true; } - if( map[m].flag.src4instance && map[m].instance_id == 0 && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) - { + if( map[m].flag.src4instance && map[m].instance_id >= 0 && st->instance_id >= 0 && (m = instance->mapid2imapid(m, st->instance_id)) < 0 ) { script_pushint(st,-1); return true; } @@ -12491,8 +12497,7 @@ BUILDIN(jump_zero) /*========================================== * movenpc [MouseJstr] *------------------------------------------*/ -BUILDIN(movenpc) -{ +BUILDIN(movenpc) { TBL_NPC *nd = NULL; const char *npc; int x,y; @@ -12505,7 +12510,7 @@ BUILDIN(movenpc) return -1; if (script_hasdata(st,5)) - nd->ud.dir = script_getnum(st,5) % 8; + nd->dir = script_getnum(st,5) % 8; npc_movenpc(nd, x, y); return true; } @@ -12559,17 +12564,20 @@ BUILDIN(npcspeed) speed = script_getnum(st,2); nd =(struct npc_data *)map_id2bl(st->oid); - if( nd ) - { + if( nd ) { + if( nd->ud == &npc_base_ud ) { + nd->ud = NULL; + CREATE(nd->ud, struct unit_data, 1); + unit_dataset(&nd->bl); + } nd->speed = speed; - nd->ud.state.speed_changed = 1; + nd->ud->state.speed_changed = 1; } return true; } // make an npc walk to a position [Valaris] -BUILDIN(npcwalkto) -{ +BUILDIN(npcwalkto) { struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); int x=0,y=0; @@ -12577,6 +12585,12 @@ BUILDIN(npcwalkto) y=script_getnum(st,3); if(nd) { + if( nd->ud == &npc_base_ud ) { + nd->ud = NULL; + CREATE(nd->ud, struct unit_data, 1); + unit_dataset(&nd->bl); + } + if (!nd->status.hp) { status_calc_npc(nd, true); } else { @@ -15341,7 +15355,7 @@ BUILDIN(setcell) for( y = y1; y <= y2; ++y ) for( x = x1; x <= x2; ++x ) - map_setcell(m, x, y, type, flag); + map[m].setcell(m, x, y, type, flag); return true; } @@ -15865,25 +15879,28 @@ BUILDIN(bg_get_data) * Instancing Script Commands *------------------------------------------*/ -BUILDIN(instance_create) -{ +BUILDIN(instance_create) { const char *name; - int party_id, res; + int owner_id, res; + int type = IOT_PARTY; name = script_getstr(st, 2); - party_id = script_getnum(st, 3); + owner_id = script_getnum(st, 3); + if( script_hasdata(st,4) ) { + type = script_getnum(st, 4); + if( type < IOT_NONE || type >= IOT_MAX ) { + ShowError("buildin_instance_create: unknown instance type %d for '%s'\n",type,name); + return true; + } + } - res = instance_create(party_id, name); - if( res == -4 ) // Already exists - { + res = instance->create(owner_id, name, (enum instance_owner_type) type); + if( res == -4 ) { // Already exists script_pushint(st, -1); return true; - } - else if( res < 0 ) - { + } else if( res < 0 ) { const char *err; - switch(res) - { + switch(res) { case -3: err = "No free instances"; break; case -2: err = "Invalid party ID"; break; case -1: err = "Invalid type"; break; @@ -15898,44 +15915,39 @@ BUILDIN(instance_create) return true; } -BUILDIN(instance_destroy) -{ - int instance_id; - struct map_session_data *sd; - struct party_data *p; +BUILDIN(instance_destroy) { + int instance_id = -1; if( script_hasdata(st, 2) ) instance_id = script_getnum(st, 2); - else if( st->instance_id ) + else if( st->instance_id >= 0 ) instance_id = st->instance_id; - else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) - instance_id = p->instance_id; else return true; - if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) - { + if( !instance->valid(instance_id) ) { ShowError("buildin_instance_destroy: Trying to destroy invalid instance %d.\n", instance_id); return true; } - instance_destroy(instance_id); + instance->destroy(instance_id); return true; } -BUILDIN(instance_attachmap) -{ - const char *name; +BUILDIN(instance_attachmap) { + const char *name, *map_name = NULL; int16 m; - int instance_id; + int instance_id = -1; bool usebasename = false; name = script_getstr(st,2); instance_id = script_getnum(st,3); - if( script_hasdata(st,4) && script_getnum(st,4) > 0) + if( script_hasdata(st,4) && script_getnum(st,4) > 0 ) usebasename = true; - if( (m = instance_add_map(name, instance_id, usebasename)) < 0 ) // [Saithis] - { + if( script_hasdata(st, 5) ) + map_name = script_getstr(st, 5); + + if( (m = instance->add_map(name, instance_id, usebasename, map_name)) < 0 ) { // [Saithis] ShowError("buildin_instance_attachmap: instance creation failed (%s): %d\n", name, m); script_pushconststr(st, ""); return true; @@ -15945,109 +15957,81 @@ BUILDIN(instance_attachmap) return true; } -BUILDIN(instance_detachmap) -{ - struct map_session_data *sd; - struct party_data *p; +BUILDIN(instance_detachmap) { const char *str; int16 m; - int instance_id; + int instance_id = -1; str = script_getstr(st, 2); if( script_hasdata(st, 3) ) instance_id = script_getnum(st, 3); - else if( st->instance_id ) + else if( st->instance_id >= 0 ) instance_id = st->instance_id; - else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) - instance_id = p->instance_id; else return true; - if( (m = map_mapname2mapid(str)) < 0 || (m = instance_map2imap(m,instance_id)) < 0 ) - { + if( (m = map_mapname2mapid(str)) < 0 || (m = instance->map2imap(m,instance_id)) < 0 ) { ShowError("buildin_instance_detachmap: Trying to detach invalid map %s\n", str); return true; } - instance_del_map(m); + instance->del_map(m); return true; } -BUILDIN(instance_attach) -{ - int instance_id; +BUILDIN(instance_attach) { + int instance_id = -1; instance_id = script_getnum(st, 2); - if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) + if( !instance->valid(instance_id) ) return true; st->instance_id = instance_id; return true; } -BUILDIN(instance_id) -{ - int instance_id; - - if( script_hasdata(st, 2) ) - { - struct party_data *p; - struct map_session_data *sd; - int type; - type = script_getnum(st, 2); - if( type == 0 ) - instance_id = st->instance_id; - else if( type == 1 && (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL ) - instance_id = p->instance_id; - else - instance_id = 0; - } - else - instance_id = st->instance_id; - - script_pushint(st, instance_id); +BUILDIN(instance_id) { + script_pushint(st, st->instance_id); return true; } BUILDIN(instance_set_timeout) { int progress_timeout, idle_timeout; - int instance_id; - struct map_session_data *sd; - struct party_data *p; + int instance_id = -1; progress_timeout = script_getnum(st, 2); idle_timeout = script_getnum(st, 3); if( script_hasdata(st, 4) ) instance_id = script_getnum(st, 4); - else if( st->instance_id ) + else if( st->instance_id >= 0 ) instance_id = st->instance_id; - else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) - instance_id = p->instance_id; else return true; - if( instance_id > 0 ) - instance_set_timeout(instance_id, progress_timeout, idle_timeout); + if( instance_id >= 0 ) + instance->set_timeout(instance_id, progress_timeout, idle_timeout); return true; } -BUILDIN(instance_init) -{ +BUILDIN(instance_init) { int instance_id = script_getnum(st, 2); - if( instance[instance_id].state != INSTANCE_IDLE ) - { + if( !instance->valid(instance_id) ) { + ShowError("instance_init: invalid instance id %d.\n",instance_id); + return true; + } + + if( instances[instance_id].state != INSTANCE_IDLE ) { ShowError("instance_init: instance already initialized.\n"); return true; } - instance_init(instance_id); + instance->start(instance_id); return true; } -BUILDIN(instance_announce) -{ +BUILDIN(instance_announce) { int instance_id = script_getnum(st,2); const char *mes = script_getstr(st,3); int flag = script_getnum(st,4); @@ -16058,53 +16042,40 @@ BUILDIN(instance_announce) int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY int i; - struct map_session_data *sd; - struct party_data *p; - if( instance_id == 0 ) - { - if( st->instance_id ) + if( instance_id == -1 ) { + if( st->instance_id >= 0 ) instance_id = st->instance_id; - else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) - instance_id = p->instance_id; - else return true; + else + return true; } - if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) + if( !instance->valid(instance_id) ) return true; - for( i = 0; i < instance[instance_id].num_map; i++ ) - map_foreachinmap(buildin_announce_sub, instance[instance_id].map[i], BL_PC, + for( i = 0; i < instances[instance_id].num_map; i++ ) + map_foreachinmap(buildin_announce_sub, instances[instance_id].map[i], BL_PC, mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); return true; } -BUILDIN(instance_npcname) -{ +BUILDIN(instance_npcname) { const char *str; - int instance_id = 0; - - struct map_session_data *sd; - struct party_data *p; + int instance_id = -1; struct npc_data *nd; str = script_getstr(st, 2); if( script_hasdata(st, 3) ) instance_id = script_getnum(st, 3); - else if( st->instance_id ) + else if( st->instance_id >= 0 ) instance_id = st->instance_id; - else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) - instance_id = p->instance_id; - if( instance_id && (nd = npc_name2id(str)) != NULL ) - { + if( instance_id >= 0 && (nd = npc_name2id(str)) != NULL ) { static char npcname[NAME_LENGTH]; snprintf(npcname, sizeof(npcname), "dup_%d_%d", instance_id, nd->bl.id); script_pushconststr(st,npcname); - } - else - { + } else { ShowError("script:instance_npcname: invalid instance NPC (instance_id: %d, NPC name: \"%s\".)\n", instance_id, str); st->state = END; return false; @@ -16113,24 +16084,56 @@ BUILDIN(instance_npcname) return true; } -BUILDIN(has_instance) -{ +BUILDIN(has_instance) { struct map_session_data *sd; - struct party_data *p; const char *str; int16 m; - int instance_id = 0; + int instance_id = -1; str = script_getstr(st, 2); + + if( (m = map_mapname2mapid(str)) < 0 ) { + script_pushconststr(st, ""); + return true; + } + if( script_hasdata(st, 3) ) instance_id = script_getnum(st, 3); - else if( st->instance_id ) + else if( st->instance_id >= 0 ) instance_id = st->instance_id; - else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) - instance_id = p->instance_id; + else if( (sd = script_rid2sd(st)) != NULL ) { + struct party_data *p; + 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); + if( j != instances[sd->instance[i]].num_map ) + break; + } + if( i != sd->instances ) + instance_id = sd->instance[i]; + } + if( instance_id == -1 && 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); + if( j != instances[p->instance[i]].num_map ) + break; + } + if( i != p->instances ) + instance_id = p->instance[i]; + } + if( instance_id == -1 && 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); + if( j != instances[sd->guild->instance[i]].num_map ) + break; + } + if( i != sd->guild->instances ) + instance_id = sd->guild->instance[i]; + } + } - if( !instance_id || (m = map_mapname2mapid(str)) < 0 || (m = instance_map2imap(m, instance_id)) < 0 ) - { + if( !instance->valid(instance_id) || (m = instance->map2imap(m, instance_id)) < 0 ) { script_pushconststr(st, ""); return true; } @@ -16138,38 +16141,41 @@ BUILDIN(has_instance) script_pushconststr(st, map[m].name); return true; } - -BUILDIN(instance_warpall) -{ - struct map_session_data *pl_sd; - int16 m, i; - int instance_id; +static int buildin_instance_warpall_sub(struct block_list *bl,va_list ap) { + struct map_session_data *sd = ((TBL_PC*)bl); + int mapindex = va_arg(ap,int); + int x = va_arg(ap,int); + int y = va_arg(ap,int); + + pc_setpos(sd,mapindex,x,y,CLR_TELEPORT); + + return 0; +} +BUILDIN(instance_warpall) { + int16 m; + int instance_id = -1; const char *mapn; int x, y; - unsigned short mapindex; - struct party_data *p = NULL; + int mapindex; mapn = script_getstr(st,2); x = script_getnum(st,3); y = script_getnum(st,4); + if( script_hasdata(st,5) ) instance_id = script_getnum(st,5); - else if( st->instance_id ) + else if( st->instance_id >= 0 ) instance_id = st->instance_id; - else if( (pl_sd = script_rid2sd(st)) != NULL && pl_sd->status.party_id && (p = party_search(pl_sd->status.party_id)) != NULL && p->instance_id ) - instance_id = p->instance_id; - else return true; - - if( (m = map_mapname2mapid(mapn)) < 0 || (map[m].flag.src4instance && (m = instance_mapid2imapid(m, instance_id)) < 0) ) + else return true; - if( !(p = party_search(instance[instance_id].party_id)) ) + if( (m = map_mapname2mapid(mapn)) < 0 || (map[m].flag.src4instance && (m = instance->mapid2imapid(m, instance_id)) < 0) ) return true; - + mapindex = map_id2index(m); - for( i = 0; i < MAX_PARTY; i++ ) - if( (pl_sd = p->data[i].sd) && map[pl_sd->bl.m].instance_id == st->instance_id ) pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT); + map_foreachininstance(buildin_instance_warpall_sub, instance_id, BL_PC,mapindex,x,y); + return true; } @@ -16183,8 +16189,7 @@ BUILDIN(instance_warpall) * Example: instance_check_party (getcharid(1){,amount}{,min}{,max}); * Example 2: instance_check_party (getcharid(1),1,1,99); *------------------------------------------*/ -BUILDIN(instance_check_party) -{ +BUILDIN(instance_check_party) { struct map_session_data *pl_sd; int amount, min, max, i, party_id, c = 0; struct party_data *p = NULL; @@ -16298,13 +16303,12 @@ BUILDIN(areamobuseskill) int16 m; int range,mobid,skill_id,skill_lv,casttime,emotion,target,cancel; - if( (m = map_mapname2mapid(script_getstr(st,2))) < 0 ) - { + if( (m = map_mapname2mapid(script_getstr(st,2))) < 0 ) { ShowError("areamobuseskill: invalid map name.\n"); return true; } - if( map[m].flag.src4instance && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) + if( map[m].flag.src4instance && st->instance_id >= 0 && (m = instance->mapid2imapid(m, st->instance_id)) < 0 ) return true; center.m = m; @@ -16994,6 +16998,309 @@ BUILDIN(npcskill) return true; } +struct hQueue *script_hqueue_get(int idx) { + if( idx < 0 || idx >= script->hqs || script->hq[idx].items == -1 ) + return NULL; + return &script->hq[idx]; +} +/* set .@id,queue(); */ +/* creates queue, returns created queue id */ +BUILDIN(queue) { + int idx = script->hqs; + int i; + + for(i = 0; i < script->hqs; i++) { + if( script->hq[i].items == -1 ) { + break; + } + } + + if( i == script->hqs ) { + RECREATE(script->hq, struct hQueue, ++script->hqs); + script->hq[ idx ].item = NULL; + } else + idx = i; + + script->hq[ idx ].id = idx; + script->hq[ idx ].items = 0; + script->hq[ idx ].onDeath[0] = '\0'; + script->hq[ idx ].onLogOut[0] = '\0'; + script->hq[ idx ].onMapChange[0] = '\0'; + + script_pushint(st,idx); + return true; +} +/* set .@length,queuesize(.@queue_id); */ +/* returns queue length */ +BUILDIN(queuesize) { + int idx = script_getnum(st, 2); + + if( idx < 0 || idx >= script->hqs || script->hq[idx].items == -1 ) { + ShowWarning("buildin_queuesize: unknown queue id %d\n",idx); + script_pushint(st, 0); + } else + script_pushint(st, script->hq[ idx ].items ); + + return true; +} +bool script_hqueue_add(int idx, int var) { + if( idx < 0 || idx >= script->hqs || script->hq[idx].items == -1 ) { + ShowWarning("script_hqueue_add: unknown queue id %d\n",idx); + return true; + } else { + struct map_session_data *sd; + int i; + + for(i = 0; i < script->hq[idx].items; i++) { + if( script->hq[idx].item[i] == var ) { + return true; + } + } + + if( i == script->hq[idx].items ) { + + for(i = 0; i < script->hq[idx].items; i++) { + if( script->hq[idx].item[i] == 0 ) { + break; + } + } + + if( i == script->hq[idx].items ) + RECREATE(script->hq[idx].item, int, ++script->hq[idx].items); + + script->hq[idx].item[i] = var; + + if( var >= START_ACCOUNT_NUM && (sd = map_id2sd(var)) ) { + for(i = 0; i < sd->queues_count; i++) { + if( sd->queues[i] == -1 ) { + break; + } + } + + if( i == sd->queues_count ) + RECREATE(sd->queues, int, ++sd->queues_count); + + sd->queues[i] = idx; + } + + } + } + return false; +} +/* queueadd(.@queue_id,.@var_id); */ +/* adds a new entry to the queue, returns 1 if already in queue, 0 otherwise */ +BUILDIN(queueadd) { + int idx = script_getnum(st, 2); + int var = script_getnum(st, 3); + + script_pushint(st,script->queue_add(idx,var)?1:0); + + return true; +} +bool script_hqueue_remove(int idx, int var) { + if( idx < 0 || idx >= script->hqs || script->hq[idx].items == -1 ) { + ShowWarning("script_hqueue_remove: unknown queue id %d (used with var %d)\n",idx,var); + return true; + } else { + int i; + + for(i = 0; i < script->hq[idx].items; i++) { + if( script->hq[idx].item[i] == var ) { + return true; + } + } + + if( i != script->hq[idx].items ) { + struct map_session_data *sd; + script->hq[idx].item[i] = 0; + + if( var >= START_ACCOUNT_NUM && (sd = map_id2sd(var)) ) { + for(i = 0; i < sd->queues_count; i++) { + if( sd->queues[i] == var ) { + break; + } + } + + if( i != sd->queues_count ) + sd->queues[i] = -1; + } + + } + } + return false; +} +/* queueremove(.@queue_id,.@var_id); */ +/* removes a entry from the queue, returns 1 if not in queue, 0 otherwise */ +BUILDIN(queueremove) { + int idx = script_getnum(st, 2); + int var = script_getnum(st, 3); + + script_pushint(st, script->queue_remove(idx,var)?1:0); + + return true; +} + +/* queueopt(.@queue_id,optionType,); */ +/* modifies the queue's options, when val is not provided the option is removed */ +/* when OnMapChange event is triggered, it sets a temp char var @QMapChangeTo$ with the destination map name */ +/* returns 1 when fails, 0 on success */ +BUILDIN(queueopt) { + int idx = script_getnum(st, 2); + int var = script_getnum(st, 3); + + if( idx < 0 || idx >= script->hqs || script->hq[idx].items == -1 ) { + ShowWarning("buildin_queueopt: unknown queue id %d\n",idx); + script_pushint(st, 1); + } else if( var <= HQO_NONE || var >= HQO_MAX ) { + ShowWarning("buildin_queueopt: unknown optionType %d\n",var); + script_pushint(st, 1); + } else { + switch( (enum hQueueOpt)var ) { + case HQO_OnDeath: + if( script_hasdata(st, 4) ) + safestrncpy(script->hq[idx].onDeath, script_getstr(st, 4), EVENT_NAME_LENGTH); + else + script->hq[idx].onDeath[0] = '\0'; + break; + case HQO_onLogOut: + if( script_hasdata(st, 4) ) + safestrncpy(script->hq[idx].onLogOut, script_getstr(st, 4), EVENT_NAME_LENGTH); + else + script->hq[idx].onLogOut[0] = '\0'; + break; + case HQO_OnMapChange: + if( script_hasdata(st, 4) ) + safestrncpy(script->hq[idx].onMapChange, script_getstr(st, 4), EVENT_NAME_LENGTH); + else + script->hq[idx].onMapChange[0] = '\0'; + break; + default: + ShowWarning("buildin_queueopt: unsupported optionType %d\n",var); + script_pushint(st, 1); + break; + } + } + + return true; +} +bool script_hqueue_del(int idx) { + if( idx < 0 || idx >= script->hqs || script->hq[idx].items == -1 ) { + ShowWarning("script_queue_del: unknown queue id %d\n",idx); + return true; + } else { + struct map_session_data *sd; + int i; + + for(i = 0; i < script->hq[idx].items; i++) { + if( script->hq[idx].item[i] >= START_ACCOUNT_NUM && (sd = map_id2sd(script->hq[idx].item[i])) ) { + int j; + for(j = 0; j < sd->queues_count; j++) { + if( sd->queues[j] == script->hq[idx].item[i] ) { + break; + } + } + + if( j != sd->queues_count ) + sd->queues[j] = -1; + } + } + + script->hq[idx].items = -1; + } + return false; +} +/* queuedel(.@queue_id); */ +/* deletes queue of id .@queue_id, returns 1 if id not found, 0 otherwise */ +BUILDIN(queuedel) { + int idx = script_getnum(st, 2); + + script_pushint(st,script->queue_del(idx)?1:0); + + return true; +} + +/* set .@id, queueiterator(.@queue_id); */ +/* creates a new queue iterator, returns its id */ +BUILDIN(queueiterator) { + int qid = script_getnum(st, 2); + struct hQueue *queue = NULL; + int idx = script->hqis; + int i; + + if( qid < 0 || qid >= script->hqs || script->hq[idx].items == -1 || !(queue = script->queue(qid)) ) { + ShowWarning("queueiterator: invalid queue id %d\n",qid); + return true; + } + + for(i = 0; i < script->hqis; i++) { + if( script->hqi[i].items == -1 ) { + break; + } + } + + if( i == script->hqis ) + RECREATE(script->hqi, struct hQueueIterator, ++script->hqis); + else + idx = i; + + RECREATE(script->hqi[ idx ].item, int, queue->items); + + memcpy(&script->hqi[idx].item, &queue->item, sizeof(int)*queue->items); + + script->hqi[ idx ].items = queue->items; + script->hqi[ idx ].pos = 0; + + script_pushint(st,idx); + return true; +} +/* Queue Iterator Get Next */ +/* returns next/first member in the iterator, 0 if none */ +BUILDIN(qiget) { + int idx = script_getnum(st, 2); + + if( idx < 0 || idx >= script->hqis ) { + ShowWarning("buildin_qiget: unknown queue iterator id %d\n",idx); + script_pushint(st, 0); + } else if ( script->hqi[idx].pos == script->hqi[idx].items ) { + script_pushint(st, 0); + } else { + struct hQueueIterator *it = &script->hqi[idx]; + script_pushint(st, it->item[it->pos++]); + } + + return true; +} +/* Queue Iterator Check */ +/* returns 1:0 if there is a next member in the iterator */ +BUILDIN(qicheck) { + int idx = script_getnum(st, 2); + + if( idx < 0 || idx >= script->hqis ) { + ShowWarning("buildin_qicheck: unknown queue iterator id %d\n",idx); + script_pushint(st, 0); + } else if ( script->hqi[idx].pos == script->hqi[idx].items ) { + script_pushint(st, 0); + } else { + script_pushint(st, 1); + } + + return true; +} +/* Queue Iterator Check */ +BUILDIN(qiclear) { + int idx = script_getnum(st, 2); + + if( idx < 0 || idx >= script->hqis ) { + ShowWarning("buildin_qiclear: unknown queue iterator id %d\n",idx); + script_pushint(st, 1); + } else { + script->hqi[idx].items = -1; + script_pushint(st, 0); + } + + return true; +} + // declarations that were supposed to be exported from npc_chat.c #ifdef PCRE_SUPPORT BUILDIN(defpattern); @@ -17442,12 +17749,12 @@ void script_parse_builtin(void) { BUILDIN_DEF(bg_updatescore,"sii"), // Instancing - BUILDIN_DEF(instance_create,"si"), + BUILDIN_DEF(instance_create,"si?"), BUILDIN_DEF(instance_destroy,"?"), - BUILDIN_DEF(instance_attachmap,"si?"), + BUILDIN_DEF(instance_attachmap,"si??"), BUILDIN_DEF(instance_detachmap,"s?"), BUILDIN_DEF(instance_attach,"i"), - BUILDIN_DEF(instance_id,"?"), + BUILDIN_DEF(instance_id,""), BUILDIN_DEF(instance_set_timeout,"ii?"), BUILDIN_DEF(instance_init,"i"), BUILDIN_DEF(instance_announce,"isi?????"), @@ -17492,6 +17799,20 @@ void script_parse_builtin(void) { BUILDIN_DEF(checkquest, "i?"), BUILDIN_DEF(changequest, "ii"), BUILDIN_DEF(showevent, "ii"), + + /** + * hQueue [Ind/Hercules] + **/ + BUILDIN_DEF(queue,""), + BUILDIN_DEF(queuesize,"i"), + BUILDIN_DEF(queueadd,"ii"), + BUILDIN_DEF(queueremove,"ii"), + BUILDIN_DEF(queueopt,"ii?"), + BUILDIN_DEF(queuedel,"i"), + BUILDIN_DEF(queueiterator,"i"), + BUILDIN_DEF(qicheck,"i"), + BUILDIN_DEF(qiget,"i"), + BUILDIN_DEF(qiclear,"i"), }; int i,n, len = ARRAYLENGTH(BUILDIN), start = script->buildin_count; char* p; @@ -17545,6 +17866,11 @@ void script_parse_builtin(void) { void script_defaults(void) { script = &script_s; + script->hq = NULL; + script->hqi = NULL; + script->hqs = script->hqis = 0; + memset(&script->hqe, 0, sizeof(script->hqe)); + script->buildin_count = 0; script->buildin = NULL; @@ -17555,4 +17881,9 @@ void script_defaults(void) { script->addScript = script_hp_add; script->conv_num = conv_num; script->conv_str = conv_str; + + script->queue = script_hqueue_get; + script->queue_add = script_hqueue_add; + script->queue_del = script_hqueue_del; + script->queue_remove = script_hqueue_remove; } diff --git a/src/map/script.h b/src/map/script.h index a0d282bfe..70ced5d43 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -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; diff --git a/src/map/skill.c b/src/map/skill.c index 06bfca5f8..911410727 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -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); } /*========================================== diff --git a/src/map/status.c b/src/map/status.c index b7e906910..30adf0d0f 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -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; } diff --git a/src/map/unit.c b/src/map/unit.c index cbc695c4a..3ab1008cb 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -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: -- cgit v1.2.3-70-g09d2 From f6bca33e1524354a28223f14e45d4765fcb06c92 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 30 May 2013 22:20:57 -0300 Subject: Memory Slasher | May 30 Patch http://hercules.ws/board/topic/928-memory-slasher-may-30-patch/ Signed-off-by: shennetsind --- doc/script_commands.txt | 122 +++++++++++++++++++++++++++++++++--------------- src/map/map.h | 32 ++++++------- 2 files changed, 100 insertions(+), 54 deletions(-) diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 5fbf652a4..af3d90262 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -7610,10 +7610,9 @@ This will open a book item at the specified page. ======================== --------------------------------------- -*instance_create("",); +*instance_create("",{,}); -Create an instance using the name "" for the Party of -. +Create an instance using the name "" for the of owner_type (when not provided, defaults to IOT_PARTY) Most instance_* commands are used in conjunction with this command and depend on the ID this command returns. @@ -7644,30 +7643,32 @@ Example: *instance_destroy {}; Destroys instance with the ID . If no ID is specified, the -instance the script is attached to is used. If the script is not attached -to an instance, the instance of the currently attached player's party is -used. If no player is currently attached, the command fails and causes the -script to halt. +instance the script is attached to is used. If in the end no instance_id, +is found the command halts the script execution. --------------------------------------- -*instance_attachmap("",{,}); +*instance_attachmap("",{,{,""}}); Attaches the map "" to the instance specified with . The optional parameter specifies, whether a map requires -emulation for instancing (1) or not (0 = default). +emulation for instancing (1) or not (0 = default). if use base name is specified, +and "" too the server will instance the map under the "", +name. Returns the resulting map name on success or an empty string on failure. +Example: + instance_attachmap("prontera", .@instance_id,1,"via"); +^ the above creates a instance (or clone) of prontera, on a map called "via" + --------------------------------------- *instance_detachmap ""{,}; Detach the map "" to the instance with the . If no -ID is specified, the instance the script is attached to is used. If the -script is not attached to an instance, the instance of the currently -attached player's party is used. If no player is currently attached, the -command fails and causes the script to halt. +ID is specified, the instance the script is attached to is used. If in the +end no instance_id is found the command halts the script execution. --------------------------------------- @@ -7681,10 +7682,8 @@ the source maps to the instanced maps. *instance_announce ,"",{,{,{,{,{,}}}}}; Works like announce, but has the parameter. If instance id -is 0, the instance the script is attached to is used. If the script is not -attached to an instance, the instance of the currently attached player's -party is used. If no player is currently attached, the command fails and -causes the script to halt. +is -1, the instance the script is attached to is used. If in the +end no instance_id is found the command halts the script execution. --------------------------------------- @@ -7698,10 +7697,8 @@ Attaches the current script to the instance given by . Retrieves the unique name given to a copy of an NPC given by "" in an instance specified . If no ID is specified, the -instance the script is attached to is used. If the script is not attached -to an instance, the instance of the currently attached player's party is -used. If no player is currently attached, the command fails and causes the -script to halt. +instance the script is attached to is used. If in the end no instance_id, +is found the command halts the script execution. --------------------------------------- @@ -7709,22 +7706,18 @@ script to halt. Checks whether or not the given map belongs to specified instance. If no ID is specified, the instance the script is attached to is used. If the -script is not attached to an instance, the instance of the currently -attached player's party is used. If no player is currently attached, the -command fails and causes the script to halt. +script is not attached to an instance, it'll try to check whether the, +player attached to the script possesses an instance with a map matching +"". If in the end no instance_id is found the command halts the, +script execution. Returns name of the instanced map on success, otherwise an empty string. --------------------------------------- -*instance_id({}); +*instance_id(); -Retrieves the instance id, depending on . If type is not given, it -defaults to 0. - -Type: - 0 - Instance ID the script is attached to. - 1 - Instance ID of the currently attached player's party. +Retrieves the instance id of the script it is being run on. --------------------------------------- @@ -7732,19 +7725,16 @@ Type: Warps all players in the instance to at given coordinates. If no ID is specified, the instance the script is attached to -is used. If the script is not attached to an instance, the instance of the -currently attached player's party is used. If no player is currently -attached, the command fails and causes the script to halt. +is used. If in the end no instance_id is found the command halts the, +script execution. --------------------------------------- *instance_set_timeout ,{,}; Sets the timeout values for an instance given by . If no ID -is specified, the instance the script is attached to is used. If the -script is not attached to an instance, the instance of the currently -attached player's party is used. If no player is currently attached, the -command fails and causes the script to halt. +is specified, the instance the script is attached to is used. If in the end, +no instance_id is found the command halts the script execution. Parameter specifies the total amount of time the instance will exist. Parameter specifies how long players have, when @@ -8080,3 +8070,59 @@ If the character does not have a mercenary, the command returns "" for name and 0 for all other types. ---------------------------------------- + +========================== +|11.- Queue Commands .| +========================== +--------------------------------------- +Queue Author's note: the following sucks, probably breaks formatting, please fix if you're willing to (you may remove this note) +--------------------------------------- +*queue() +creates a new queue instance, returns created queue id + +--------------------------------------- +*queuesize() +returns the amount of entries in queue instance of . + +--------------------------------------- +*queueadd(,) +adds to queue of , returns 1 if is already present in the queue, 0 otherwise. + +--------------------------------------- +*queueremove(,) +removes from queue of , returns 1 if is not present in the queue, 0 otherwise. + +--------------------------------------- +*queueopt(,,{Optional